welcome back to dyb-tech

This commit is contained in:
Daniel Guzman
2024-05-18 02:28:01 +02:00
parent 9513cdba09
commit 9f30bc98c7
6149 changed files with 668407 additions and 0 deletions
@@ -0,0 +1,159 @@
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<defaults public="false" />
<service id="maker.maker.make_authenticator" class="Symfony\Bundle\MakerBundle\Maker\MakeAuthenticator">
<argument type="service" id="maker.file_manager" />
<argument type="service" id="maker.security_config_updater" />
<argument type="service" id="maker.generator" />
<argument type="service" id="maker.doctrine_helper" />
<argument type="service" id="maker.security_controller_builder" />
<tag name="maker.command" />
</service>
<service id="maker.maker.make_command" class="Symfony\Bundle\MakerBundle\Maker\MakeCommand">
<argument type="service" id="maker.php_compat_util" />
<tag name="maker.command" />
</service>
<service id="maker.maker.make_twig_component" class="Symfony\Bundle\MakerBundle\Maker\MakeTwigComponent">
<tag name="maker.command" />
</service>
<service id="maker.maker.make_controller" class="Symfony\Bundle\MakerBundle\Maker\MakeController">
<argument type="service" id="maker.php_compat_util" />
<tag name="maker.command" />
</service>
<service id="maker.maker.make_crud" class="Symfony\Bundle\MakerBundle\Maker\MakeCrud">
<argument type="service" id="maker.doctrine_helper" />
<argument type="service" id="maker.renderer.form_type_renderer" />
<tag name="maker.command" />
</service>
<service id="maker.maker.make_docker_database" class="Symfony\Bundle\MakerBundle\Maker\MakeDockerDatabase">
<argument type="service" id="maker.file_manager" />
<tag name="maker.command" />
</service>
<service id="maker.maker.make_entity" class="Symfony\Bundle\MakerBundle\Maker\MakeEntity">
<argument type="service" id="maker.file_manager" />
<argument type="service" id="maker.doctrine_helper" />
<argument>null</argument>
<argument type="service" id="maker.generator" />
<argument type="service" id="maker.entity_class_generator" />
<argument type="service" id="maker.php_compat_util" />
<tag name="maker.command" />
</service>
<service id="maker.maker.make_fixtures" class="Symfony\Bundle\MakerBundle\Maker\MakeFixtures">
<tag name="maker.command" />
</service>
<service id="maker.maker.make_form" class="Symfony\Bundle\MakerBundle\Maker\MakeForm">
<argument type="service" id="maker.doctrine_helper" />
<argument type="service" id="maker.renderer.form_type_renderer" />
<tag name="maker.command" />
</service>
<service id="maker.maker.make_functional_test" class="Symfony\Bundle\MakerBundle\Maker\MakeFunctionalTest">
<tag name="maker.command" />
<deprecated package="symfony/maker-bundle" version="1.29">The "%service_id%" service is deprecated, use "maker.maker.make_test" instead.</deprecated>
</service>
<service id="maker.maker.make_listener" class="Symfony\Bundle\MakerBundle\Maker\MakeListener">
<tag name="maker.command" />
<argument type="service" id="maker.event_registry" />
</service>
<service id="maker.maker.make_message" class="Symfony\Bundle\MakerBundle\Maker\MakeMessage">
<argument type="service" id="maker.file_manager" />
<tag name="maker.command" />
</service>
<service id="maker.maker.make_messenger_middleware" class="Symfony\Bundle\MakerBundle\Maker\MakeMessengerMiddleware">
<tag name="maker.command" />
</service>
<service id="maker.maker.make_registration_form" class="Symfony\Bundle\MakerBundle\Maker\MakeRegistrationForm">
<argument type="service" id="maker.file_manager" />
<argument type="service" id="maker.renderer.form_type_renderer" />
<argument type="service" id="maker.doctrine_helper" />
<argument type="service" id="router" on-invalid="ignore" />
<tag name="maker.command" />
</service>
<service id="maker.maker.make_reset_password" class="Symfony\Bundle\MakerBundle\Maker\MakeResetPassword">
<argument type="service" id="maker.file_manager" />
<argument type="service" id="maker.doctrine_helper" />
<argument type="service" id="maker.entity_class_generator" />
<tag name="maker.command" />
</service>
<service id="maker.maker.make_serializer_encoder" class="Symfony\Bundle\MakerBundle\Maker\MakeSerializerEncoder">
<tag name="maker.command" />
</service>
<service id="maker.maker.make_serializer_normalizer" class="Symfony\Bundle\MakerBundle\Maker\MakeSerializerNormalizer">
<tag name="maker.command" />
</service>
<service id="maker.maker.make_subscriber" class="Symfony\Bundle\MakerBundle\Maker\MakeSubscriber">
<tag name="maker.command" />
<argument type="service" id="maker.event_registry" />
<deprecated package="symfony/maker-bundle" version="1.51">The "%service_id%" service is deprecated, use "maker.maker.make_listener" instead.</deprecated>
</service>
<service id="maker.maker.make_twig_extension" class="Symfony\Bundle\MakerBundle\Maker\MakeTwigExtension">
<tag name="maker.command" />
</service>
<service id="maker.maker.make_test" class="Symfony\Bundle\MakerBundle\Maker\MakeTest">
<tag name="maker.command" />
</service>
<service id="maker.maker.make_unit_test" class="Symfony\Bundle\MakerBundle\Maker\MakeUnitTest">
<tag name="maker.command" />
<deprecated package="symfony/maker-bundle" version="1.29">The "%service_id%" service is deprecated, use "maker.maker.make_test" instead.</deprecated>
</service>
<service id="maker.maker.make_validator" class="Symfony\Bundle\MakerBundle\Maker\MakeValidator">
<tag name="maker.command" />
</service>
<service id="maker.maker.make_voter" class="Symfony\Bundle\MakerBundle\Maker\MakeVoter">
<tag name="maker.command" />
</service>
<service id="maker.maker.make_user" class="Symfony\Bundle\MakerBundle\Maker\MakeUser">
<argument type="service" id="maker.file_manager" />
<argument type="service" id="maker.user_class_builder" />
<argument type="service" id="maker.security_config_updater" />
<argument type="service" id="maker.entity_class_generator" />
<argument type="service" id="maker.doctrine_helper" />
<tag name="maker.command" />
</service>
<service id="maker.maker.make_migration" class="Symfony\Bundle\MakerBundle\Maker\MakeMigration">
<argument>%kernel.project_dir%</argument>
<argument type="service" id="maker.file_link_formatter" />
<tag name="maker.command" />
</service>
<service id="maker.maker.make_stimulus_controller" class="Symfony\Bundle\MakerBundle\Maker\MakeStimulusController">
<tag name="maker.command" />
</service>
<service id="maker.maker.make_form_login" class="Symfony\Bundle\MakerBundle\Maker\Security\MakeFormLogin">
<argument type="service" id="maker.file_manager" />
<argument type="service" id="maker.security_config_updater" />
<argument type="service" id="maker.security_controller_builder" />
<tag name="maker.command" />
</service>
</services>
</container>
@@ -0,0 +1,20 @@
<?php
/*
* This file is part of the Symfony MakerBundle package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
return (new PhpCsFixer\Config())
->setRules([
'@Symfony' => true,
'@Symfony:risky' => true,
'native_function_invocation' => false,
'blank_line_before_statement' => ['statements' => ['break', 'case', 'continue', 'declare', 'default', 'do', 'exit', 'for', 'foreach', 'goto', 'if', 'include', 'include_once', 'phpdoc', 'require', 'require_once', 'return', 'switch', 'throw', 'try', 'while', 'yield', 'yield_from']],
])
->setRiskyAllowed(true)
;
@@ -0,0 +1,85 @@
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<defaults public="false" />
<service id="maker.file_manager" class="Symfony\Bundle\MakerBundle\FileManager">
<argument type="service" id="filesystem" />
<argument type="service" id="maker.autoloader_util" />
<argument type="service" id="maker.file_link_formatter" />
<argument>%kernel.project_dir%</argument>
<argument>%twig.default_path%</argument>
</service>
<service id="maker.autoloader_finder" class="Symfony\Bundle\MakerBundle\Util\ComposerAutoloaderFinder" >
<argument /> <!-- root namespace -->
</service>
<service id="maker.autoloader_util" class="Symfony\Bundle\MakerBundle\Util\AutoloaderUtil">
<argument type="service" id="maker.autoloader_finder" />
</service>
<service id="maker.file_link_formatter" class="Symfony\Bundle\MakerBundle\Util\MakerFileLinkFormatter" >
<argument type="service" id="debug.file_link_formatter" on-invalid="ignore" />
</service>
<service id="maker.event_registry" class="Symfony\Bundle\MakerBundle\EventRegistry">
<argument type="service" id="event_dispatcher" />
</service>
<service id="maker.console_error_listener" class="Symfony\Bundle\MakerBundle\Event\ConsoleErrorSubscriber">
<tag name="kernel.event_subscriber" />
</service>
<service id="maker.doctrine_helper" class="Symfony\Bundle\MakerBundle\Doctrine\DoctrineHelper">
<argument /> <!-- entity namespace -->
<argument type="service" id="doctrine" on-invalid="ignore" />
</service>
<service id="maker.template_linter" class="Symfony\Bundle\MakerBundle\Util\TemplateLinter">
<argument>%env(default::string:MAKER_PHP_CS_FIXER_BINARY_PATH)%</argument>
<argument>%env(default::string:MAKER_PHP_CS_FIXER_CONFIG_PATH)%</argument>
</service>
<service id="maker.auto_command.abstract" class="Symfony\Bundle\MakerBundle\Command\MakerCommand" abstract="true">
<argument /> <!-- maker -->
<argument type="service" id="maker.file_manager" />
<argument type="service" id="maker.generator" />
<argument type="service" id="maker.template_linter" />
</service>
<service id="maker.generator" class="Symfony\Bundle\MakerBundle\Generator">
<argument type="service" id="maker.file_manager" />
<argument /> <!-- root namespace -->
<argument>null</argument> <!-- PhpCompatUtil -->
<argument type="service" id="maker.template_component_generator" />
</service>
<service id="maker.entity_class_generator" class="Symfony\Bundle\MakerBundle\Doctrine\EntityClassGenerator">
<argument type="service" id="maker.generator" />
<argument type="service" id="maker.doctrine_helper" />
</service>
<service id="maker.user_class_builder" class="Symfony\Bundle\MakerBundle\Security\UserClassBuilder" />
<service id="maker.security_config_updater" class="Symfony\Bundle\MakerBundle\Security\SecurityConfigUpdater" />
<service id="maker.renderer.form_type_renderer" class="Symfony\Bundle\MakerBundle\Renderer\FormTypeRenderer">
<argument type="service" id="maker.generator" />
</service>
<service id="maker.security_controller_builder" class="Symfony\Bundle\MakerBundle\Security\SecurityControllerBuilder">
</service>
<service id="maker.php_compat_util" class="Symfony\Bundle\MakerBundle\Util\PhpCompatUtil">
<argument type="service" id="maker.file_manager" />
</service>
<service id="maker.template_component_generator" class="Symfony\Bundle\MakerBundle\Util\TemplateComponentGenerator">
</service>
</services>
</container>
+108
View File
@@ -0,0 +1,108 @@
The Symfony MakerBundle
=======================
Symfony Maker helps you create empty commands, controllers, form classes,
tests and more so you can forget about writing boilerplate code. This bundle
assumes you're using a standard Symfony 5 directory structure, but many
commands can generate code into any application.
Installation
------------
Run this command to install and enable this bundle in your application:
.. code-block:: terminal
$ composer require --dev symfony/maker-bundle
Usage
-----
This bundle provides several commands under the ``make:`` namespace. List them
all executing this command:
.. code-block:: terminal
$ php bin/console list make
make:command Creates a new console command class
make:controller Creates a new controller class
make:entity Creates a new Doctrine entity class
[...]
make:validator Creates a new validator and constraint class
make:voter Creates a new security voter class
The names of the commands are self-explanatory, but some of them include
optional arguments and options. Check them out with the ``--help`` option:
.. code-block:: terminal
$ php bin/console make:controller --help
Linting Generated Code
______________________
MakerBundle uses php-cs-fixer to enforce coding standards when generating ``.php``
files. When running a ``make`` command, MakerBundle will use a ``php-cs-fixer``
version and configuration that is packaged with this bundle.
You can explicitly set a custom path to a php-cs-fixer binary and/or configuration
file by their respective environment variables:
- ``MAKER_PHP_CS_FIXER_BINARY_PATH`` e.g. tools/vendor/bin/php-cs-fixer
- ``MAKER_PHP_CS_FIXER_CONFIG_PATH`` e.g. .php-cs-fixer.config.php
.. tip::
Is PHP-CS-Fixer installed globally? To avoid needing to set these in every
project, you can instead set these on your operating system.
Configuration
-------------
This bundle doesn't require any configuration. But, you *can* configure
the root namespace that is used to "guess" what classes you want to generate:
.. code-block:: yaml
# config/packages/dev/maker.yaml
# create this file if you need to configure anything
maker:
# tell MakerBundle that all of your classes live in an
# Acme namespace, instead of the default App
# (e.g. Acme\Entity\Article, Acme\Command\MyCommand, etc)
root_namespace: 'Acme'
Creating your Own Makers
------------------------
In case your applications need to generate custom boilerplate code, you can
create your own ``make:...`` command reusing the tools provided by this bundle.
To do that, you should create a class that extends
`AbstractMaker`_ in your ``src/Maker/``
directory. And this is really it!
For examples of how to complete your new maker command, see the `core maker commands`_.
Make sure your class is registered as a service and tagged with ``maker.command``.
If you're using the standard Symfony ``services.yaml`` configuration, this
will be done automatically.
Overriding the Generated Code
-----------------------------
Generated code can never be perfect for everyone. The MakerBundle tries to balance
adding "extension points" with keeping the library simple so that existing commands
can be improved and new commands can be added.
For that reason, in general, the generated code cannot be modified. In many cases,
adding your *own* maker command is so easy, that we recommend that. However, if there
is some extension point that you'd like, please open an issue so we can discuss!
.. _`SensioGeneratorBundle`: https://github.com/sensiolabs/SensioGeneratorBundle
.. _`AbstractMaker`: https://github.com/symfony/maker-bundle/blob/main/src/Maker/AbstractMaker.php
.. _`core maker commands`: https://github.com/symfony/maker-bundle/tree/main/src/Maker
@@ -0,0 +1,8 @@
The <info>%command.name%</info> command generates various authentication systems,
by asking questions.
It can provide an empty authenticator, or a full login form authentication process.
In both cases it also updates your <info>security.yaml</info>.
For the login form, it also generates a controller and the twig template.
<info>php %command.full_name%</info>
@@ -0,0 +1,5 @@
The <info>%command.name%</info> command generates a new command:
<info>php %command.full_name% app:do-something</info>
If the argument is missing, the command will ask for the command name interactively.
@@ -0,0 +1,9 @@
The <info>%command.name%</info> command generates a new controller class.
<info>php %command.full_name% CoolStuffController</info>
If the argument is missing, the command will ask for the controller class name interactively.
You can also generate the controller alone, without template with this option:
<info>php %command.full_name% --no-template</info>
@@ -0,0 +1,5 @@
The <info>%command.name%</info> command generates crud controller with templates for selected entity.
<info>php %command.full_name% BlogPost</info>
If the argument is missing, the command will ask for the entity class name interactively.
@@ -0,0 +1,5 @@
The <info>%command.name%</info> command generates or updates databases services in compose.yaml
<info>php %command.full_name%</info>
Supports MySQL, MariaDB and PostgreSQL
@@ -0,0 +1,24 @@
The <info>%command.name%</info> command creates or updates an entity and repository class.
<info>php %command.full_name% BlogPost</info>
If the argument is missing, the command will ask for the entity class name interactively.
You can also mark this class as an API Platform resource. A hypermedia CRUD API will
automatically be available for this entity class:
<info>php %command.full_name% --api-resource</info>
Symfony can also broadcast all changes made to the entity to the client using Symfony
UX Turbo.
<info>php %command.full_name% --broadcast</info>
You can also generate all the getter/setter/adder/remover methods
for the properties of existing entities:
<info>php %command.full_name% --regenerate</info>
You can also *overwrite* any existing methods:
<info>php %command.full_name% --regenerate --overwrite</info>
@@ -0,0 +1,5 @@
The <info>%command.name%</info> command generates a new Doctrine fixtures class.
<info>php %command.full_name% AppFixtures</info>
If the argument is missing, the command will ask for a class interactively.
@@ -0,0 +1,16 @@
The <info>%command.name%</info> command generates a new form class.
<info>php %command.full_name% UserType</info>
If the argument is missing, the command will ask for the form class interactively.
You can optionally specify the bound class in a second argument.
This can be the name of an entity like <info>User</info>
<info>php %command.full_name% UserType User</info>
You can also specify a fully qualified name to another class like <info>\App\Dto\UserData</info>.
Slashes must be escaped in the argument.
<info>php %command.full_name% UserType \\App\\Dto\\UserData</info>
@@ -0,0 +1,5 @@
The <info>%command.name%</info> command generates a new functional test class.
<info>php %command.full_name% DefaultControllerTest</info>
If the argument is missing, the command will ask for the class name interactively.
@@ -0,0 +1,5 @@
The <info>%command.name%</info> command generates a new event subscriber class or a new event listener class.
<info>php %command.full_name% ExceptionListener</info>
If the argument is missing, the command will ask for the class name interactively.
@@ -0,0 +1,5 @@
The <info>%command.name%</info> command generates a new message class & handler.
<info>php %command.full_name% EmailMessage</info>
If the argument is missing, the command will ask for the message class interactively.
@@ -0,0 +1,5 @@
The <info>%command.name%</info> command generates a new Middleware class.
<info>php %command.full_name% CustomMiddleware</info>
If the argument is missing, the command will ask for the message class interactively.
@@ -0,0 +1,3 @@
The <info>%command.name%</info> command generates a new migration:
<info>php %command.full_name%</info>
@@ -0,0 +1,5 @@
The <info>%command.name%</info> command generates a complete registration form, controller & template.
<info>php %command.full_name%</info>
The command will ask for several pieces of information to build your form.
@@ -0,0 +1,18 @@
The <info>%command.name%</info> command generates all the files needed to implement
a fully-functional & secure password reset system.
The SymfonycastsResetPasswordBundle is required and can be added using composer:
<info>composer require symfonycasts/reset-password-bundle</info>
For more information on the <info>reset-password-bundle</info> check out:
<href=https://github.com/symfonycasts/reset-password-bundle>https://github.com/symfonycasts/reset-password-bundle</>
<info>%command.name%</info> requires a user entity with an email property,
email getter method, and a password setter method. Maker will ask for these
interactively if they cannot be guessed.
Maker will also update your <info>reset-password.yaml</info> configuration file
if one exists. If you have customized the configuration file, maker will attempt
to modify it accordingly but preserve your customizations.
<info>php %command.full_name%</info>
@@ -0,0 +1,5 @@
The <info>%command.name%</info> command generates a new serializer encoder class.
<info>php %command.full_name% YamlEncoder</info>
If the argument is missing, the command will ask for the class name interactively.
@@ -0,0 +1,5 @@
The <info>%command.name%</info> command generates a new serializer normalizer class.
<info>php %command.full_name% UserNormalizer</info>
If the argument is missing, the command will ask for the class name interactively.
@@ -0,0 +1,5 @@
The <info>%command.name%</info> command generates new Stimulus Controller.
<info>php %command.full_name% hello</info>
If the argument is missing, the command will ask for the controller name interactively.
@@ -0,0 +1,5 @@
The <info>%command.name%</info> command generates a new event subscriber class.
<info>php %command.full_name% ExceptionSubscriber</info>
If the argument is missing, the command will ask for the class name interactively.
@@ -0,0 +1,7 @@
The <info>%command.name%</info> command generates a new test class.
<info>php %command.full_name% TestCase BlogPostTest</info>
If the first argument is missing, the command will ask for the test type interactively.
If the second argument is missing, the command will ask for the class name interactively.
@@ -0,0 +1,5 @@
The <info>%command.name%</info> command generates a new twig extension with its runtime class.
<info>php %command.full_name% AppExtension</info>
If the argument is missing, the command will ask for the class name interactively.
@@ -0,0 +1,5 @@
The <info>%command.name%</info> command generates a new unit test class.
<info>php %command.full_name% UtilTest</info>
If the argument is missing, the command will ask for the class name interactively.
@@ -0,0 +1,7 @@
The <info>%command.name%</info> command generates a new user class for security
and updates your security.yaml file for it. It will also generate a user provider
class if your situation needs a custom class.
<info>php %command.full_name% User</info>
If the argument is missing, the command will ask for the class name interactively.
@@ -0,0 +1,5 @@
The <info>%command.name%</info> command generates a new validation constraint.
<info>php %command.full_name% EnabledValidator</info>
If the argument is missing, the command will ask for the constraint class name interactively.
@@ -0,0 +1,5 @@
The <info>%command.name%</info> command generates a new security voter.
<info>php %command.full_name% BlogPostVoter</info>
If the argument is missing, the command will ask for the class name interactively.
@@ -0,0 +1,9 @@
The <info>%command.name%</info> command generates a controller and twig template
to allow users to login using the form_login authenticator.
The controller name, and logout ability can be customized by answering the
questions asked when running <info>%command.name%</info>.
This will also update your <info>security.yaml</info> for the new authenticator.
<info>php %command.full_name%</info>
@@ -0,0 +1,7 @@
<?= "<?php\n" ?>
namespace <?= $namespace; ?>;
class <?= $class_name."\n" ?>
{
}
@@ -0,0 +1,39 @@
<?= "<?php\n" ?>
namespace <?= $namespace ?>;
<?= $use_statements; ?>
class <?= $class_name ?> extends AbstractAuthenticator
{
public function supports(Request $request): ?bool
{
// TODO: Implement supports() method.
}
public function authenticate(Request $request): Passport
{
// TODO: Implement authenticate() method.
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
{
// TODO: Implement onAuthenticationSuccess() method.
}
public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response
{
// TODO: Implement onAuthenticationFailure() method.
}
// public function start(Request $request, AuthenticationException $authException = null): Response
// {
// /*
// * If you would like this class to control what happens when an anonymous user accesses a
// * protected page (e.g. redirect to /login), uncomment this method and make this class
// * implement Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface.
// *
// * For more details, see https://symfony.com/doc/current/security/experimental_authenticators.html#configuring-the-authentication-entry-point
// */
// }
}
@@ -0,0 +1,9 @@
<?= "<?php\n" ?>
namespace <?= $namespace ?>;
<?= $use_statements; ?>
class <?= $class_name; ?> extends AbstractController
{
}
@@ -0,0 +1,48 @@
<?= "<?php\n" ?>
namespace <?= $namespace ?>;
<?= $use_statements; ?>
class <?= $class_name; ?> extends AbstractLoginFormAuthenticator
{
use TargetPathTrait;
public const LOGIN_ROUTE = 'app_login';
public function __construct(private UrlGeneratorInterface $urlGenerator)
{
}
public function authenticate(Request $request): Passport
{
$<?= $username_field_var ?> = $request->request->get('<?= $username_field ?>', '');
$request->getSession()->set(SecurityRequestAttributes::LAST_USERNAME, $<?= $username_field_var ?>);
return new Passport(
new UserBadge($<?= $username_field_var ?>),
new PasswordCredentials($request->request->get('password', '')),
[
new CsrfTokenBadge('authenticate', $request->request->get('_csrf_token')),<?= $remember_me_badge ? "
new RememberMeBadge(),\n" : "" ?>
]
);
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
{
if ($targetPath = $this->getTargetPath($request->getSession(), $firewallName)) {
return new RedirectResponse($targetPath);
}
// For example:
// return new RedirectResponse($this->urlGenerator->generate('some_route'));
throw new \Exception('TODO: provide a valid redirect inside '.__FILE__);
}
protected function getLoginUrl(Request $request): string
{
return $this->urlGenerator->generate(self::LOGIN_ROUTE);
}
}
@@ -0,0 +1,41 @@
{% extends 'base.html.twig' %}
{% block title %}Log in!{% endblock %}
{% block body %}
<form method="post">
{% if error %}
<div class="alert alert-danger">{{ error.messageKey|trans(error.messageData, 'security') }}</div>
{% endif %}
<?php if ($logout_setup): ?>
{% if app.user %}
<div class="mb-3">
You are logged in as {{ app.user.userIdentifier }}, <a href="{{ path('app_logout') }}">Logout</a>
</div>
{% endif %}
<?php endif; ?>
<h1 class="h3 mb-3 font-weight-normal">Please sign in</h1>
<label for="input<?= ucfirst($username_field); ?>"><?= $username_label; ?></label>
<input type="<?= $username_is_email ? 'email' : 'text'; ?>" value="{{ last_username }}" name="<?= $username_field; ?>" id="input<?= ucfirst($username_field); ?>" class="form-control" autocomplete="<?= $username_is_email ? 'email' : 'username'; ?>" required autofocus>
<label for="inputPassword">Password</label>
<input type="password" name="password" id="inputPassword" class="form-control" autocomplete="current-password" required>
<input type="hidden" name="_csrf_token"
value="{{ csrf_token('authenticate') }}"
>
<?php if($support_remember_me && !$always_remember_me): ?>
<div class="checkbox mb-3">
<label>
<input type="checkbox" name="_remember_me"> Remember me
</label>
</div>
<?php endif; ?>
<button class="btn btn-lg btn-primary" type="submit">
Sign in
</button>
</form>
{% endblock %}
@@ -0,0 +1,44 @@
<?= "<?php\n"; ?>
namespace <?= $namespace; ?>;
<?= $use_statements; ?>
#[AsCommand(
name: '<?= $command_name; ?>',
description: 'Add a short description for your command',
)]
class <?= $class_name; ?> extends Command
{
public function __construct()
{
parent::__construct();
}
protected function configure(): void
{
$this
<?= $set_description ? " ->setDescription(self::\$defaultDescription)\n" : '' ?>
->addArgument('arg1', InputArgument::OPTIONAL, 'Argument description')
->addOption('option1', null, InputOption::VALUE_NONE, 'Option description')
;
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
$arg1 = $input->getArgument('arg1');
if ($arg1) {
$io->note(sprintf('You passed an argument: %s', $arg1));
}
if ($input->getOption('option1')) {
// ...
}
$io->success('You have a new command! Now make it your own! Pass --help to see your options.');
return Command::SUCCESS;
}
}
@@ -0,0 +1,24 @@
<?= "<?php\n" ?>
namespace <?= $namespace; ?>;
<?= $use_statements; ?>
class <?= $class_name; ?> extends AbstractController
{
<?= $generator->generateRouteForControllerMethod($route_path, $route_name); ?>
public function <?= $method_name ?>(): <?php if ($with_template) { ?>Response<?php } else { ?>JsonResponse<?php } ?>
{
<?php if ($with_template) { ?>
return $this->render('<?= $template_name ?>', [
'controller_name' => '<?= $class_name ?>',
]);
<?php } else { ?>
return $this->json([
'message' => 'Welcome to your new controller!',
'path' => '<?= $relative_path; ?>',
]);
<?php } ?>
}
}
@@ -0,0 +1,18 @@
<?= $helper->getHeadPrintCode("Hello $class_name!"); ?>
{% block body %}
<style>
.example-wrapper { margin: 1em auto; max-width: 800px; width: 95%; font: 18px/1.5 sans-serif; }
.example-wrapper code { background: #F5F5F5; padding: 2px 6px; }
</style>
<div class="example-wrapper">
<h1>Hello {{ controller_name }}! ✅</h1>
This friendly message is coming from:
<ul>
<li>Your controller at <code><?= $root_directory ?>/<?= $controller_path ?></code></li>
<li>Your template at <code><?= $root_directory ?>/<?= $relative_path ?></code></li>
</ul>
</div>
{% endblock %}
@@ -0,0 +1,87 @@
<?= "<?php\n" ?>
namespace <?= $namespace ?>;
<?= $use_statements; ?>
#[Route('<?= $route_path ?>')]
class <?= $class_name ?> extends AbstractController
{
<?= $generator->generateRouteForControllerMethod('/', sprintf('%s_index', $route_name), ['GET']) ?>
<?php if (isset($repository_full_class_name)): ?>
public function index(<?= $repository_class_name ?> $<?= $repository_var ?>): Response
{
return $this->render('<?= $templates_path ?>/index.html.twig', [
'<?= $entity_twig_var_plural ?>' => $<?= $repository_var ?>->findAll(),
]);
}
<?php else: ?>
public function index(EntityManagerInterface $entityManager): Response
{
$<?= $entity_var_plural ?> = $entityManager
->getRepository(<?= $entity_class_name ?>::class)
->findAll();
return $this->render('<?= $templates_path ?>/index.html.twig', [
'<?= $entity_twig_var_plural ?>' => $<?= $entity_var_plural ?>,
]);
}
<?php endif ?>
<?= $generator->generateRouteForControllerMethod('/new', sprintf('%s_new', $route_name), ['GET', 'POST']) ?>
public function new(Request $request, EntityManagerInterface $entityManager): Response
{
$<?= $entity_var_singular ?> = new <?= $entity_class_name ?>();
$form = $this->createForm(<?= $form_class_name ?>::class, $<?= $entity_var_singular ?>);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$entityManager->persist($<?= $entity_var_singular ?>);
$entityManager->flush();
return $this->redirectToRoute('<?= $route_name ?>_index', [], Response::HTTP_SEE_OTHER);
}
return $this->render('<?= $templates_path ?>/new.html.twig', [
'<?= $entity_twig_var_singular ?>' => $<?= $entity_var_singular ?>,
'form' => $form,
]);
}
<?= $generator->generateRouteForControllerMethod(sprintf('/{%s}', $entity_identifier), sprintf('%s_show', $route_name), ['GET']) ?>
public function show(<?= $entity_class_name ?> $<?= $entity_var_singular ?>): Response
{
return $this->render('<?= $templates_path ?>/show.html.twig', [
'<?= $entity_twig_var_singular ?>' => $<?= $entity_var_singular ?>,
]);
}
<?= $generator->generateRouteForControllerMethod(sprintf('/{%s}/edit', $entity_identifier), sprintf('%s_edit', $route_name), ['GET', 'POST']) ?>
public function edit(Request $request, <?= $entity_class_name ?> $<?= $entity_var_singular ?>, EntityManagerInterface $entityManager): Response
{
$form = $this->createForm(<?= $form_class_name ?>::class, $<?= $entity_var_singular ?>);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$entityManager->flush();
return $this->redirectToRoute('<?= $route_name ?>_index', [], Response::HTTP_SEE_OTHER);
}
return $this->render('<?= $templates_path ?>/edit.html.twig', [
'<?= $entity_twig_var_singular ?>' => $<?= $entity_var_singular ?>,
'form' => $form,
]);
}
<?= $generator->generateRouteForControllerMethod(sprintf('/{%s}', $entity_identifier), sprintf('%s_delete', $route_name), ['POST']) ?>
public function delete(Request $request, <?= $entity_class_name ?> $<?= $entity_var_singular ?>, EntityManagerInterface $entityManager): Response
{
if ($this->isCsrfTokenValid('delete'.$<?= $entity_var_singular ?>->get<?= ucfirst($entity_identifier) ?>(), $request->request->get('_token'))) {
$entityManager->remove($<?= $entity_var_singular ?>);
$entityManager->flush();
}
return $this->redirectToRoute('<?= $route_name ?>_index', [], Response::HTTP_SEE_OTHER);
}
}
@@ -0,0 +1,4 @@
<form method="post" action="{{ path('<?= $route_name ?>_delete', {'<?= $entity_identifier ?>': <?= $entity_twig_var_singular ?>.<?= $entity_identifier ?>}) }}" onsubmit="return confirm('Are you sure you want to delete this item?');">
<input type="hidden" name="_token" value="{{ csrf_token('delete' ~ <?= $entity_twig_var_singular ?>.<?= $entity_identifier ?>) }}">
<button class="btn">Delete</button>
</form>
@@ -0,0 +1,4 @@
{{ form_start(form) }}
{{ form_widget(form) }}
<button class="btn">{{ button_label|default('Save') }}</button>
{{ form_end(form) }}
@@ -0,0 +1,11 @@
<?= $helper->getHeadPrintCode('Edit '.$entity_class_name) ?>
{% block body %}
<h1>Edit <?= $entity_class_name ?></h1>
{{ include('<?= $templates_path ?>/_form.html.twig', {'button_label': 'Update'}) }}
<a href="{{ path('<?= $route_name ?>_index') }}">back to list</a>
{{ include('<?= $templates_path ?>/_delete_form.html.twig') }}
{% endblock %}
@@ -0,0 +1,35 @@
<?= $helper->getHeadPrintCode($entity_class_name.' index'); ?>
{% block body %}
<h1><?= $entity_class_name ?> index</h1>
<table class="table">
<thead>
<tr>
<?php foreach ($entity_fields as $field): ?>
<th><?= ucfirst($field['fieldName']) ?></th>
<?php endforeach; ?>
<th>actions</th>
</tr>
</thead>
<tbody>
{% for <?= $entity_twig_var_singular ?> in <?= $entity_twig_var_plural ?> %}
<tr>
<?php foreach ($entity_fields as $field): ?>
<td>{{ <?= $helper->getEntityFieldPrintCode($entity_twig_var_singular, $field) ?> }}</td>
<?php endforeach; ?>
<td>
<a href="{{ path('<?= $route_name ?>_show', {'<?= $entity_identifier ?>': <?= $entity_twig_var_singular ?>.<?= $entity_identifier ?>}) }}">show</a>
<a href="{{ path('<?= $route_name ?>_edit', {'<?= $entity_identifier ?>': <?= $entity_twig_var_singular ?>.<?= $entity_identifier ?>}) }}">edit</a>
</td>
</tr>
{% else %}
<tr>
<td colspan="<?= (count($entity_fields) + 1) ?>">no records found</td>
</tr>
{% endfor %}
</tbody>
</table>
<a href="{{ path('<?= $route_name ?>_new') }}">Create new</a>
{% endblock %}
@@ -0,0 +1,9 @@
<?= $helper->getHeadPrintCode('New '.$entity_class_name) ?>
{% block body %}
<h1>Create new <?= $entity_class_name ?></h1>
{{ include('<?= $templates_path ?>/_form.html.twig') }}
<a href="{{ path('<?= $route_name ?>_index') }}">back to list</a>
{% endblock %}
@@ -0,0 +1,22 @@
<?= $helper->getHeadPrintCode($entity_class_name) ?>
{% block body %}
<h1><?= $entity_class_name ?></h1>
<table class="table">
<tbody>
<?php foreach ($entity_fields as $field): ?>
<tr>
<th><?= ucfirst($field['fieldName']) ?></th>
<td>{{ <?= $helper->getEntityFieldPrintCode($entity_twig_var_singular, $field) ?> }}</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<a href="{{ path('<?= $route_name ?>_index') }}">back to list</a>
<a href="{{ path('<?= $route_name ?>_edit', {'<?= $entity_identifier ?>': <?= $entity_twig_var_singular ?>.<?= $entity_identifier ?>}) }}">edit</a>
{{ include('<?= $templates_path ?>/_delete_form.html.twig') }}
{% endblock %}
@@ -0,0 +1,121 @@
<?= "<?php\n" ?>
<?php use Symfony\Bundle\MakerBundle\Str; ?>
namespace <?= $namespace ?>;
<?= $use_statements; ?>
class <?= $class_name ?> extends WebTestCase<?= "\n" ?>
{
private KernelBrowser $client;
private EntityManagerInterface $manager;
private EntityRepository $repository;
private string $path = '<?= $route_path; ?>/';
protected function setUp(): void
{
$this->client = static::createClient();
$this->manager = static::getContainer()->get('doctrine')->getManager();
$this->repository = $this->manager->getRepository(<?= $entity_class_name; ?>::class);
foreach ($this->repository->findAll() as $object) {
$this->manager->remove($object);
}
$this->manager->flush();
}
public function testIndex(): void
{
$crawler = $this->client->request('GET', $this->path);
self::assertResponseStatusCodeSame(200);
self::assertPageTitleContains('<?= ucfirst($entity_var_singular); ?> index');
// Use the $crawler to perform additional assertions e.g.
// self::assertSame('Some text on the page', $crawler->filter('.p')->first());
}
public function testNew(): void
{
$this->markTestIncomplete();
$this->client->request('GET', sprintf('%snew', $this->path));
self::assertResponseStatusCodeSame(200);
$this->client->submitForm('Save', [
<?php foreach ($form_fields as $form_field => $typeOptions): ?>
'<?= $form_field_prefix; ?>[<?= $form_field; ?>]' => 'Testing',
<?php endforeach; ?>
]);
self::assertResponseRedirects('/sweet/food/');
self::assertSame(1, $this->getRepository()->count([]));
}
public function testShow(): void
{
$this->markTestIncomplete();
$fixture = new <?= $entity_class_name; ?>();
<?php foreach ($form_fields as $form_field => $typeOptions): ?>
$fixture->set<?= ucfirst($form_field); ?>('My Title');
<?php endforeach; ?>
$this->manager->persist($fixture);
$this->manager->flush();
$this->client->request('GET', sprintf('%s%s', $this->path, $fixture->getId()));
self::assertResponseStatusCodeSame(200);
self::assertPageTitleContains('<?= ucfirst($entity_var_singular); ?>');
// Use assertions to check that the properties are properly displayed.
}
public function testEdit(): void
{
$this->markTestIncomplete();
$fixture = new <?= $entity_class_name; ?>();
<?php foreach ($form_fields as $form_field => $typeOptions): ?>
$fixture->set<?= ucfirst($form_field); ?>('Value');
<?php endforeach; ?>
$this->manager->persist($fixture);
$this->manager->flush();
$this->client->request('GET', sprintf('%s%s/edit', $this->path, $fixture->getId()));
$this->client->submitForm('Update', [
<?php foreach ($form_fields as $form_field => $typeOptions): ?>
'<?= $form_field_prefix; ?>[<?= $form_field; ?>]' => 'Something New',
<?php endforeach; ?>
]);
self::assertResponseRedirects('<?= $route_path; ?>/');
$fixture = $this->repository->findAll();
<?php foreach ($form_fields as $form_field => $typeOptions): ?>
self::assertSame('Something New', $fixture[0]->get<?= ucfirst($form_field); ?>());
<?php endforeach; ?>
}
public function testRemove(): void
{
$this->markTestIncomplete();
$fixture = new <?= $entity_class_name; ?>();
<?php foreach ($form_fields as $form_field => $typeOptions): ?>
$fixture->set<?= ucfirst($form_field); ?>('Value');
<?php endforeach; ?>
$this->manager->remove($fixture);
$this->manager->flush();
$this->client->request('GET', sprintf('%s%s', $this->path, $fixture->getId()));
$this->client->submitForm('Delete');
self::assertResponseRedirects('<?= $route_path; ?>/');
self::assertSame(0, $this->repository->count([]));
}
}
@@ -0,0 +1,27 @@
<?= "<?php\n" ?>
namespace <?= $namespace ?>;
<?= $use_statements; ?>
#[ORM\Entity(repositoryClass: <?= $repository_class_name ?>::class)]
<?php if ($should_escape_table_name): ?>#[ORM\Table(name: '`<?= $table_name ?>`')]
<?php endif ?>
<?php if ($api_resource): ?>
#[ApiResource]
<?php endif ?>
<?php if ($broadcast): ?>
#[Broadcast]
<?php endif ?>
class <?= $class_name."\n" ?>
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
public function getId(): ?int
{
return $this->id;
}
}
@@ -0,0 +1,16 @@
<?= "<?php\n" ?>
namespace <?= $namespace; ?>;
<?= $use_statements; ?>
class <?= $class_name ?> extends Fixture
{
public function load(ObjectManager $manager): void
{
// $product = new Product();
// $manager->persist($product);
$manager->flush();
}
}
@@ -0,0 +1,67 @@
<?= "<?php\n"; ?>
namespace <?= $namespace; ?>;
<?= $use_statements; ?>
/**
* @extends ServiceEntityRepository<<?= $entity_class_name; ?>>
<?= $with_password_upgrade ? " * @implements PasswordUpgraderInterface<$entity_class_name>\n" : "" ?>
*
* @method <?= $entity_class_name; ?>|null find($id, $lockMode = null, $lockVersion = null)
* @method <?= $entity_class_name; ?>|null findOneBy(array $criteria, array $orderBy = null)
* @method <?= $entity_class_name; ?>[] findAll()
* @method <?= $entity_class_name; ?>[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class <?= $class_name; ?> extends ServiceEntityRepository<?= $with_password_upgrade ? " implements PasswordUpgraderInterface\n" : "\n" ?>
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, <?= $entity_class_name; ?>::class);
}
<?php if ($include_example_comments): // When adding a new method without existing default comments, the blank line is automatically added.?>
<?php endif; ?>
<?php if ($with_password_upgrade): ?>
/**
* Used to upgrade (rehash) the user's password automatically over time.
*/
public function upgradePassword(<?= sprintf('%s ', $password_upgrade_user_interface->getShortName()); ?>$user, string $newHashedPassword): void
{
if (!$user instanceof <?= $entity_class_name ?>) {
throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', $user::class));
}
$user->setPassword($newHashedPassword);
$this->getEntityManager()->persist($user);
$this->getEntityManager()->flush();
}
<?php endif ?>
<?php if ($include_example_comments): ?>
// /**
// * @return <?= $entity_class_name ?>[] Returns an array of <?= $entity_class_name ?> objects
// */
// public function findByExampleField($value): array
// {
// return $this->createQueryBuilder('<?= $entity_alias; ?>')
// ->andWhere('<?= $entity_alias; ?>.exampleField = :val')
// ->setParameter('val', $value)
// ->orderBy('<?= $entity_alias; ?>.id', 'ASC')
// ->setMaxResults(10)
// ->getQuery()
// ->getResult()
// ;
// }
// public function findOneBySomeField($value): ?<?= $entity_class_name."\n" ?>
// {
// return $this->createQueryBuilder('<?= $entity_alias ?>')
// ->andWhere('<?= $entity_alias ?>.exampleField = :val')
// ->setParameter('val', $value)
// ->getQuery()
// ->getOneOrNullResult()
// ;
// }
<?php endif; ?>
}
@@ -0,0 +1,22 @@
{# Learn how to use Turbo Streams: https://github.com/symfony/ux-turbo#broadcast-doctrine-entities-update #}
{% block create %}
<turbo-stream action="append" target="<?= $class_name_plural ?>">
<template>
<div id="{{ '<?= $class_name ?>_' ~ id }}">
#{{ id }} created
</div>
</template>
</turbo-stream>
{% endblock %}
{% block update %}
<turbo-stream action="update" target="<?= $class_name ?>_{{ id }}">
<template>
#{{ id }} updated
</template>
</turbo-stream>
{% endblock %}
{% block remove %}
<turbo-stream action="remove" target="<?= $class_name ?>_{{ id }}"></turbo-stream>
{% endblock %}
@@ -0,0 +1,14 @@
<?= "<?php\n" ?>
namespace <?= $namespace; ?>;
<?= $use_statements; ?>
final class <?= $class_name."\n" ?>
{
#[AsEventListener(event: <?= $event ?>)]
public function <?= $method_name ?>(<?= $event_arg ?>): void
{
// ...
}
}
@@ -0,0 +1,20 @@
<?= "<?php\n" ?>
namespace <?= $namespace; ?>;
<?= $use_statements; ?>
class <?= $class_name ?> implements EventSubscriberInterface
{
public function <?= $method_name ?>(<?= $event_arg ?>): void
{
// ...
}
public static function getSubscribedEvents(): array
{
return [
<?= $event ?> => '<?= $method_name ?>',
];
}
}
@@ -0,0 +1,36 @@
<?= "<?php\n" ?>
namespace <?= $namespace ?>;
<?= $use_statements; ?>
class <?= $class_name ?> extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
<?php foreach ($form_fields as $form_field => $typeOptions): ?>
<?php if (null === $typeOptions['type'] && !$typeOptions['options_code']): ?>
->add('<?= $form_field ?>')
<?php elseif (null !== $typeOptions['type'] && !$typeOptions['options_code']): ?>
->add('<?= $form_field ?>', <?= $typeOptions['type'] ?>::class)
<?php else: ?>
->add('<?= $form_field ?>', <?= $typeOptions['type'] ? ($typeOptions['type'].'::class') : 'null' ?>, [
<?= $typeOptions['options_code']."\n" ?>
])
<?php endif; ?>
<?php endforeach; ?>
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
<?php if ($bounded_class_name): ?>
'data_class' => <?= $bounded_class_name ?>::class,
<?php else: ?>
// Configure your form options here
<?php endif ?>
]);
}
}
@@ -0,0 +1,23 @@
<?= "<?php\n" ?>
namespace <?= $namespace; ?>;
final class <?= $class_name."\n" ?>
{
/*
* Add whatever properties and methods you need
* to hold the data for this message class.
*/
// private $name;
// public function __construct(string $name)
// {
// $this->name = $name;
// }
// public function getName(): string
// {
// return $this->name;
// }
}
@@ -0,0 +1,14 @@
<?= "<?php\n" ?>
namespace <?= $namespace; ?>;
<?= $use_statements; ?>
#[AsMessageHandler]
final class <?= $class_name ?>
{
public function __invoke(<?= $message_class_name ?> $message)
{
// do something with your message
}
}
@@ -0,0 +1,14 @@
<?= "<?php\n" ?>
namespace <?= $namespace; ?>;
<?= $use_statements; ?>
final class <?= $class_name; ?> implements MiddlewareInterface
{
public function handle(Envelope $envelope, StackInterface $stack): Envelope
{
// ...
return $stack->next()->handle($envelope, $stack);
}
}
@@ -0,0 +1,106 @@
<?= "<?php\n" ?>
namespace <?= $namespace; ?>;
<?= $use_statements; ?>
class <?= $class_name; ?> extends AbstractController
{
<?php if ($will_verify_email): ?>
private <?= $generator->getPropertyType($email_verifier_class_details) ?>$emailVerifier;
public function __construct(<?= $email_verifier_class_details->getShortName() ?> $emailVerifier)
{
$this->emailVerifier = $emailVerifier;
}
<?php endif; ?>
<?= $generator->generateRouteForControllerMethod($route_path, $route_name) ?>
public function register(Request $request, <?= $password_hasher_class_details->getShortName() ?> $userPasswordHasher<?= $authenticator_full_class_name ? sprintf(', UserAuthenticatorInterface $userAuthenticator, %s $authenticator', $authenticator_class_name) : '' ?>, EntityManagerInterface $entityManager): Response
{
$user = new <?= $user_class_name ?>();
$form = $this->createForm(<?= $form_class_name ?>::class, $user);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
// encode the plain password
$user->set<?= ucfirst($password_field) ?>(
$userPasswordHasher->hashPassword(
$user,
$form->get('plainPassword')->getData()
)
);
$entityManager->persist($user);
$entityManager->flush();
<?php if ($will_verify_email): ?>
// generate a signed url and email it to the user
$this->emailVerifier->sendEmailConfirmation('app_verify_email', $user,
(new TemplatedEmail())
->from(new Address('<?= $from_email ?>', '<?= $from_email_name ?>'))
->to($user-><?= $email_getter ?>())
->subject('Please Confirm your Email')
->htmlTemplate('registration/confirmation_email.html.twig')
);
<?php endif; ?>
// do anything else you need here, like send an email
<?php if ($authenticator_full_class_name): ?>
return $userAuthenticator->authenticateUser(
$user,
$authenticator,
$request
);
<?php else: ?>
return $this->redirectToRoute('<?= $redirect_route_name ?>');
<?php endif; ?>
}
return $this->render('registration/register.html.twig', [
'registrationForm' => $form->createView(),
]);
}
<?php if ($will_verify_email): ?>
<?= $generator->generateRouteForControllerMethod('/verify/email', 'app_verify_email') ?>
public function verifyUserEmail(Request $request<?php if ($translator_available): ?>, TranslatorInterface $translator<?php endif ?><?= $verify_email_anonymously ? sprintf(', %s %s', $repository_class_name, $repository_var) : null ?>): Response
{
<?php if (!$verify_email_anonymously): ?>
$this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY');
<?php else: ?>
$id = $request->query->get('id');
if (null === $id) {
return $this->redirectToRoute('app_register');
}
<?php if ('$manager' === $repository_var): ?>
$repository = $manager->getRepository(<?= $user_class_name ?>::class);
$user = $repository->find($id);
<?php else: ?>
$user = <?= $repository_var; ?>->find($id);
<?php endif; ?>
if (null === $user) {
return $this->redirectToRoute('app_register');
}
<?php endif; ?>
// validate email confirmation link, sets User::isVerified=true and persists
try {
$this->emailVerifier->handleEmailConfirmation($request, <?= $verify_email_anonymously ? '$user' : '$this->getUser()' ?>);
} catch (VerifyEmailExceptionInterface $exception) {
$this->addFlash('verify_email_error', <?php if ($translator_available): ?>$translator->trans($exception->getReason(), [], 'VerifyEmailBundle')<?php else: ?>$exception->getReason()<?php endif ?>);
return $this->redirectToRoute('<?= $route_name ?>');
}
// @TODO Change the redirect on success and handle or remove the flash message in your templates
$this->addFlash('success', 'Your email address has been verified.');
return $this->redirectToRoute('app_register');
}
<?php endif; ?>
}
@@ -0,0 +1,11 @@
<h1>Hi! Please confirm your email!</h1>
<p>
Please confirm your email address by clicking the following link: <br><br>
<a href="{{ signedUrl|raw }}">Confirm my Email</a>.
This link will expire in {{ expiresAtMessageKey|trans(expiresAtMessageData, 'VerifyEmailBundle') }}.
</p>
<p>
Cheers!
</p>
@@ -0,0 +1,23 @@
<?= $helper->getHeadPrintCode('Register'); ?>
{% block body %}
<?php if ($will_verify_email): ?>
{% for flash_error in app.flashes('verify_email_error') %}
<div class="alert alert-danger" role="alert">{{ flash_error }}</div>
{% endfor %}
<?php endif; ?>
<h1>Register</h1>
{{ form_errors(registrationForm) }}
{{ form_start(registrationForm) }}
{{ form_row(registrationForm.<?= $username_field ?>) }}
{{ form_row(registrationForm.plainPassword, {
label: 'Password'
}) }}
{{ form_row(registrationForm.agreeTerms) }}
<button type="submit" class="btn">Register</button>
{{ form_end(registrationForm) }}
{% endblock %}
@@ -0,0 +1,48 @@
<?= "<?php\n" ?>
namespace <?= $namespace ?>;
<?= $use_statements ?>
class <?= $class_name ?> extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('plainPassword', RepeatedType::class, [
'type' => PasswordType::class,
'options' => [
'attr' => [
'autocomplete' => 'new-password',
],
],
'first_options' => [
'constraints' => [
new NotBlank([
'message' => 'Please enter a password',
]),
new Length([
'min' => 6,
'minMessage' => 'Your password should be at least {{ limit }} characters',
// max length allowed by Symfony for security reasons
'max' => 4096,
]),
],
'label' => 'New password',
],
'second_options' => [
'label' => 'Repeat Password',
],
'invalid_message' => 'The password fields must match.',
// Instead of being set onto the object directly,
// this is read and encoded in the controller
'mapped' => false,
])
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([]);
}
}
@@ -0,0 +1,160 @@
<?= "<?php\n" ?>
namespace <?= $namespace ?>;
<?= $use_statements; ?>
#[Route('/reset-password')]
class <?= $class_name ?> extends AbstractController
{
use ResetPasswordControllerTrait;
public function __construct(
private ResetPasswordHelperInterface $resetPasswordHelper,
private EntityManagerInterface $entityManager
) {
}
/**
* Display & process form to request a password reset.
*/
#[Route('', name: 'app_forgot_password_request')]
public function request(Request $request, MailerInterface $mailer<?php if ($translator_available): ?>, TranslatorInterface $translator<?php endif ?>): Response
{
$form = $this->createForm(<?= $request_form_type_class_name ?>::class);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
return $this->processSendingPasswordResetEmail(
$form->get('<?= $email_field ?>')->getData(),
$mailer<?php if ($translator_available): ?>,
$translator<?php endif ?><?= "\n" ?>
);
}
return $this->render('reset_password/request.html.twig', [
'requestForm' => $form->createView(),
]);
}
/**
* Confirmation page after a user has requested a password reset.
*/
#[Route('/check-email', name: 'app_check_email')]
public function checkEmail(): Response
{
// Generate a fake token if the user does not exist or someone hit this page directly.
// This prevents exposing whether or not a user was found with the given email address or not
if (null === ($resetToken = $this->getTokenObjectFromSession())) {
$resetToken = $this->resetPasswordHelper->generateFakeResetToken();
}
return $this->render('reset_password/check_email.html.twig', [
'resetToken' => $resetToken,
]);
}
/**
* Validates and process the reset URL that the user clicked in their email.
*/
#[Route('/reset/{token}', name: 'app_reset_password')]
public function reset(Request $request, UserPasswordHasherInterface $passwordHasher<?php if ($translator_available): ?>, TranslatorInterface $translator<?php endif ?>, string $token = null): Response
{
if ($token) {
// We store the token in session and remove it from the URL, to avoid the URL being
// loaded in a browser and potentially leaking the token to 3rd party JavaScript.
$this->storeTokenInSession($token);
return $this->redirectToRoute('app_reset_password');
}
$token = $this->getTokenFromSession();
if (null === $token) {
throw $this->createNotFoundException('No reset password token found in the URL or in the session.');
}
try {
$user = $this->resetPasswordHelper->validateTokenAndFetchUser($token);
} catch (ResetPasswordExceptionInterface $e) {
$this->addFlash('reset_password_error', sprintf(
'%s - %s',
<?php if ($translator_available): ?>$translator->trans(<?= $problem_validate_message_or_constant ?>, [], 'ResetPasswordBundle')<?php else: ?><?= $problem_validate_message_or_constant ?><?php endif ?>,
<?php if ($translator_available): ?>$translator->trans($e->getReason(), [], 'ResetPasswordBundle')<?php else: ?>$e->getReason()<?php endif ?><?= "\n" ?>
));
return $this->redirectToRoute('app_forgot_password_request');
}
// The token is valid; allow the user to change their password.
$form = $this->createForm(<?= $reset_form_type_class_name ?>::class);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
// A password reset token should be used only once, remove it.
$this->resetPasswordHelper->removeResetRequest($token);
// Encode(hash) the plain password, and set it.
$encodedPassword = $passwordHasher->hashPassword(
$user,
$form->get('plainPassword')->getData()
);
$user-><?= $password_setter ?>($encodedPassword);
$this->entityManager->flush();
// The session is cleaned up after the password has been changed.
$this->cleanSessionAfterReset();
return $this->redirectToRoute('<?= $success_redirect_route ?>');
}
return $this->render('reset_password/reset.html.twig', [
'resetForm' => $form->createView(),
]);
}
private function processSendingPasswordResetEmail(string $emailFormData, MailerInterface $mailer<?php if ($translator_available): ?>, TranslatorInterface $translator<?php endif ?>): RedirectResponse
{
$user = $this->entityManager->getRepository(<?= $user_class_name ?>::class)->findOneBy([
'<?= $email_field ?>' => $emailFormData,
]);
// Do not reveal whether a user account was found or not.
if (!$user) {
return $this->redirectToRoute('app_check_email');
}
try {
$resetToken = $this->resetPasswordHelper->generateResetToken($user);
} catch (ResetPasswordExceptionInterface $e) {
// If you want to tell the user why a reset email was not sent, uncomment
// the lines below and change the redirect to 'app_forgot_password_request'.
// Caution: This may reveal if a user is registered or not.
//
// $this->addFlash('reset_password_error', sprintf(
// '%s - %s',
// <?php if ($translator_available): ?>$translator->trans(<?= $problem_handle_message_or_constant ?>, [], 'ResetPasswordBundle')<?php else: ?><?= $problem_handle_message_or_constant ?><?php endif ?>,
// <?php if ($translator_available): ?>$translator->trans($e->getReason(), [], 'ResetPasswordBundle')<?php else: ?>$e->getReason()<?php endif ?><?= "\n" ?>
// ));
return $this->redirectToRoute('app_check_email');
}
$email = (new TemplatedEmail())
->from(new Address('<?= $from_email ?>', '<?= $from_email_name ?>'))
->to($user-><?= $email_getter ?>())
->subject('Your password reset request')
->htmlTemplate('reset_password/email.html.twig')
->context([
'resetToken' => $resetToken,
])
;
$mailer->send($email);
// Store the token object in session for retrieval in check-email route.
$this->setTokenObjectInSession($resetToken);
return $this->redirectToRoute('app_check_email');
}
}
@@ -0,0 +1,27 @@
<?= "<?php\n" ?>
namespace <?= $namespace ?>;
<?= $use_statements ?>
class <?= $class_name ?> extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('<?= $email_field ?>', EmailType::class, [
'attr' => ['autocomplete' => 'email'],
'constraints' => [
new NotBlank([
'message' => 'Please enter your email',
]),
],
])
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([]);
}
}
@@ -0,0 +1,11 @@
{% extends 'base.html.twig' %}
{% block title %}Password Reset Email Sent{% endblock %}
{% block body %}
<p>
If an account matching your email exists, then an email was just sent that contains a link that you can use to reset your password.
This link will expire in {{ resetToken.expirationMessageKey|trans(resetToken.expirationMessageData, 'ResetPasswordBundle') }}.
</p>
<p>If you don't receive an email please check your spam folder or <a href="{{ path('app_forgot_password_request') }}">try again</a>.</p>
{% endblock %}
@@ -0,0 +1,9 @@
<h1>Hi!</h1>
<p>To reset your password, please visit the following link</p>
<a href="{{ url('app_reset_password', {token: resetToken.token}) }}">{{ url('app_reset_password', {token: resetToken.token}) }}</a>
<p>This link will expire in {{ resetToken.expirationMessageKey|trans(resetToken.expirationMessageData, 'ResetPasswordBundle') }}.</p>
<p>Cheers!</p>
@@ -0,0 +1,22 @@
{% extends 'base.html.twig' %}
{% block title %}Reset your password{% endblock %}
{% block body %}
{% for flash_error in app.flashes('reset_password_error') %}
<div class="alert alert-danger" role="alert">{{ flash_error }}</div>
{% endfor %}
<h1>Reset your password</h1>
{{ form_start(requestForm) }}
{{ form_row(requestForm.<?= $email_field ?>) }}
<div>
<small>
Enter your email address, and we will send you a
link to reset your password.
</small>
</div>
<button class="btn btn-primary">Send password reset email</button>
{{ form_end(requestForm) }}
{% endblock %}
@@ -0,0 +1,12 @@
{% extends 'base.html.twig' %}
{% block title %}Reset your password{% endblock %}
{% block body %}
<h1>Reset your password</h1>
{{ form_start(resetForm) }}
{{ form_row(resetForm.plainPassword) }}
<button class="btn btn-primary">Reset password</button>
{{ form_end(resetForm) }}
{% endblock %}
@@ -0,0 +1,74 @@
<?= "<?php\n" ?>
namespace <?= $namespace; ?>;
<?= $use_statements; ?>
class <?= $class_name ?> implements UserProviderInterface, PasswordUpgraderInterface
{
/**
* Symfony calls this method if you use features like switch_user
* or remember_me.
*
* If you're not using these features, you do not need to implement
* this method.
*
* @throws UserNotFoundException if the user is not found
*/
public function loadUserByIdentifier($identifier): UserInterface
{
// Load a User object from your data source or throw UserNotFoundException.
// The $identifier argument may not actually be a username:
// it is whatever value is being returned by the getUserIdentifier()
// method in your User class.
throw new \Exception('TODO: fill in loadUserByIdentifier() inside '.__FILE__);
}
/**
* @deprecated since Symfony 5.3, loadUserByIdentifier() is used instead
*/
public function loadUserByUsername($username): UserInterface
{
return $this->loadUserByIdentifier($username);
}
/**
* Refreshes the user after being reloaded from the session.
*
* When a user is logged in, at the beginning of each request, the
* User object is loaded from the session and then this method is
* called. Your job is to make sure the user's data is still fresh by,
* for example, re-querying for fresh User data.
*
* If your firewall is "stateless: true" (for a pure API), this
* method is not called.
*/
public function refreshUser(UserInterface $user): UserInterface
{
if (!$user instanceof <?= $user_short_name ?>) {
throw new UnsupportedUserException(sprintf('Invalid user class "%s".', $user::class));
}
// Return a User object after making sure its data is "fresh".
// Or throw a UsernameNotFoundException if the user no longer exists.
throw new \Exception('TODO: fill in refreshUser() inside '.__FILE__);
}
/**
* Tells Symfony to use this provider for this User class.
*/
public function supportsClass(string $class): bool
{
return <?= $user_short_name ?>::class === $class || is_subclass_of($class, <?= $user_short_name ?>::class);
}
/**
* Upgrades the hashed password of a user, typically for using a better hash algorithm.
*/
public function upgradePassword(PasswordAuthenticatedUserInterface $user, string $newHashedPassword): void
{
// TODO: when hashed passwords are in use, this method should:
// 1. persist the new password in the user storage
// 2. update the $user object with $user->setPassword($newHashedPassword);
}
}
@@ -0,0 +1,44 @@
<?= "<?php\n" ?>
namespace <?= $namespace; ?>;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
use Symfony\Component\Security\Core\User\UserInterface;
class <?= $class_name ?> extends Voter
{
public const EDIT = 'POST_EDIT';
public const VIEW = 'POST_VIEW';
protected function supports(string $attribute, mixed $subject): bool
{
// replace with your own logic
// https://symfony.com/doc/current/security/voters.html
return in_array($attribute, [self::EDIT, self::VIEW])
&& $subject instanceof \App\Entity\<?= str_replace('Voter', null, $class_name) ?>;
}
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
{
$user = $token->getUser();
// if the user is anonymous, do not grant access
if (!$user instanceof UserInterface) {
return false;
}
// ... (check conditions and return true to grant permission) ...
switch ($attribute) {
case self::EDIT:
// logic to determine if the user can EDIT
// return true or false
break;
case self::VIEW:
// logic to determine if the user can VIEW
// return true or false
break;
}
return false;
}
}
@@ -0,0 +1,23 @@
<?= "<?php\n" ?>
namespace <?= $namespace; ?>;
<?= $use_statements; ?>
class <?= $controller_name ?> extends AbstractController
{
#[Route(path: '/login', name: 'app_login')]
public function login(AuthenticationUtils $authenticationUtils): Response
{
// get the login error if there is one
$error = $authenticationUtils->getLastAuthenticationError();
// last username entered by the user
$lastUsername = $authenticationUtils->getLastUsername();
return $this->render('<?= $template_path ?>/login.html.twig', [
'last_username' => $lastUsername,
'error' => $error,
]);
}
}
@@ -0,0 +1,44 @@
{% extends 'base.html.twig' %}
{% block title %}Log in!{% endblock %}
{% block body %}
<form method="post">
{% if error %}
<div class="alert alert-danger">{{ error.messageKey|trans(error.messageData, 'security') }}</div>
{% endif %}
<?php if ($logout_setup): ?>
{% if app.user %}
<div class="mb-3">
You are logged in as {{ app.user.userIdentifier }}, <a href="{{ path('app_logout') }}">Logout</a>
</div>
{% endif %}
<?php endif; ?>
<h1 class="h3 mb-3 font-weight-normal">Please sign in</h1>
<label for="username"><?= $username_label; ?></label>
<input type="<?= $username_is_email ? 'email' : 'text'; ?>" value="{{ last_username }}" name="_username" id="username" class="form-control" autocomplete="<?= $username_is_email ? 'email' : 'username'; ?>" required autofocus>
<label for="password">Password</label>
<input type="password" name="_password" id="password" class="form-control" autocomplete="current-password" required>
<input type="hidden" name="_csrf_token"
value="{{ csrf_token('authenticate') }}"
>
{#
Uncomment this section and add a remember_me option below your firewall to activate remember me functionality.
See https://symfony.com/doc/current/security/remember_me.html
<div class="checkbox mb-3">
<label>
<input type="checkbox" name="_remember_me"> Remember me
</label>
</div>
#}
<button class="btn btn-lg btn-primary" type="submit">
Sign in
</button>
</form>
{% endblock %}
@@ -0,0 +1,32 @@
<?= "<?php\n" ?>
namespace <?= $namespace; ?>;
<?= $use_statements; ?>
class <?= $class_name ?> implements EncoderInterface, DecoderInterface
{
public const FORMAT = '<?= $format ?>';
public function encode($data, string $format, array $context = []): string
{
// TODO: return your encoded data
return '';
}
public function supportsEncoding(string $format, array $context = []): bool
{
return self::FORMAT === $format;
}
public function decode(string $data, string $format, array $context = [])
{
// TODO: return your decoded data
return '';
}
public function supportsDecoding(string $format, array $context = []): bool
{
return self::FORMAT === $format;
}
}
@@ -0,0 +1,31 @@
<?= "<?php\n" ?>
namespace <?= $namespace; ?>;
<?= $use_statements; ?>
class <?= $class_name ?> implements NormalizerInterface, CacheableSupportsMethodInterface
{
public function __construct(private ObjectNormalizer $normalizer)
{
}
public function normalize($object, string $format = null, array $context = []): array
{
$data = $this->normalizer->normalize($object, $format, $context);
// TODO: add, edit, or delete some data
return $data;
}
public function supportsNormalization($data, string $format = null, array $context = []): bool
{
return $data instanceof \App\Entity\<?= str_replace('Normalizer', '', $class_name) ?>;
}
public function hasCacheableSupportsMethod(): bool
{
return true;
}
}
@@ -0,0 +1,18 @@
import { Controller } from '@hotwired/stimulus';
/*
* The following line makes this controller "lazy": it won't be downloaded until needed
* See https://github.com/symfony/stimulus-bridge#lazy-controllers
*/
/* stimulusFetch: 'lazy' */
export default class extends Controller {
<?= $targets ? " static targets = $targets\n" : "" ?>
<?php if ($values) { ?>
static values = {
<?php foreach ($values as $value): ?>
<?= $value['name'] ?>: <?= $value['type'] ?>,
<?php endforeach; ?>
}
<?php } ?>
// ...
}
@@ -0,0 +1,16 @@
<?= "<?php\n" ?>
namespace <?= $namespace; ?>;
use <?= $api_test_case_fqcn; ?>;
class <?= $class_name ?> extends ApiTestCase
{
public function testSomething(): void
{
$response = static::createClient()->request('GET', '/');
$this->assertResponseIsSuccessful();
$this->assertJsonContains(['@id' => '/']);
}
}
@@ -0,0 +1,31 @@
<?php /* @deprecated remove this method when removing make:unit-test and make:functional-test */ ?>
<?= "<?php\n" ?>
namespace <?= $namespace; ?>;
<?= $use_statements ?>
class <?= $class_name ?> extends <?= $panther_is_available ? 'PantherTestCase' : 'WebTestCase' ?><?= "\n" ?>
{
public function testSomething(): void
{
<?php if ($panther_is_available): ?>
$client = static::createPantherClient();
<?php else: ?>
$client = static::createClient();
<?php endif ?>
$crawler = $client->request('GET', '/');
<?php if ($web_assertions_are_available): ?>
<?php if (!$panther_is_available): ?>
$this->assertResponseIsSuccessful();
<?php endif ?>
$this->assertSelectorTextContains('h1', 'Hello World');
<?php else: ?>
<?php if (!$panther_is_available): ?>
$this->assertSame(200, $client->getResponse()->getStatusCode());
<?php endif ?>
$this->assertStringContainsString('Hello World', $crawler->filter('h1')->text());
<?php endif ?>
}
}
@@ -0,0 +1,17 @@
<?= "<?php\n" ?>
namespace <?= $namespace; ?>;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
class <?= $class_name ?> extends KernelTestCase
{
public function testSomething(): void
{
$kernel = self::bootKernel();
$this->assertSame('test', $kernel->getEnvironment());
// $routerService = static::getContainer()->get('router');
// $myCustomService = static::getContainer()->get(CustomService::class);
}
}
@@ -0,0 +1,20 @@
<?= "<?php\n" ?>
namespace <?= $namespace; ?>;
use Symfony\Component\Panther\PantherTestCase;
class <?= $class_name ?> extends PantherTestCase
{
public function testSomething(): void
{
$client = static::createPantherClient();
$crawler = $client->request('GET', '/');
<?php if ($web_assertions_are_available): ?>
$this->assertSelectorTextContains('h1', 'Hello World');
<?php else: ?>
$this->assertStringContainsString('Hello World', $crawler->filter('h1')->text());
<?php endif ?>
}
}
@@ -0,0 +1,13 @@
<?= "<?php\n" ?>
namespace <?= $namespace; ?>;
use PHPUnit\Framework\TestCase;
class <?= $class_name ?> extends TestCase
{
public function testSomething(): void
{
$this->assertTrue(true);
}
}
@@ -0,0 +1,14 @@
<?php /* @deprecated remove this method when removing make:unit-test and make:functional-test */ ?>
<?= "<?php\n" ?>
namespace <?= $namespace; ?>;
<?= $use_statements; ?>
class <?= $class_name ?> extends TestCase
{
public function testSomething(): void
{
$this->assertTrue(true);
}
}
@@ -0,0 +1,22 @@
<?= "<?php\n" ?>
namespace <?= $namespace; ?>;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
class <?= $class_name ?> extends WebTestCase
{
public function testSomething(): void
{
$client = static::createClient();
$crawler = $client->request('GET', '/');
<?php if ($web_assertions_are_available): ?>
$this->assertResponseIsSuccessful();
$this->assertSelectorTextContains('h1', 'Hello World');
<?php else: ?>
$this->assertSame(200, $client->getResponse()->getStatusCode());
$this->assertStringContainsString('Hello World', $crawler->filter('h1')->text());
<?php endif ?>
}
}
@@ -0,0 +1,10 @@
<?= "<?php\n" ?>
namespace <?= $namespace; ?>;
use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;
#[AsTwigComponent]
final class <?= $class_name."\n" ?>
{
}
@@ -0,0 +1,25 @@
<?= "<?php\n" ?>
namespace <?= $namespace; ?>;
<?= $use_statements ?>
class <?= $class_name ?> extends AbstractExtension
{
public function getFilters(): array
{
return [
// If your filter generates SAFE HTML, you should add a third
// parameter: ['is_safe' => ['html']]
// Reference: https://twig.symfony.com/doc/3.x/advanced.html#automatic-escaping
new TwigFilter('filter_name', [<?= $runtime_class_name ?>::class, 'doSomething']),
];
}
public function getFunctions(): array
{
return [
new TwigFunction('function_name', [<?= $runtime_class_name ?>::class, 'doSomething']),
];
}
}
@@ -0,0 +1,12 @@
<?= "<?php\n" ?>
namespace <?= $namespace; ?>;
use Symfony\UX\LiveComponent\Attribute\AsLiveComponent;
use Symfony\UX\LiveComponent\DefaultActionTrait;
#[AsLiveComponent]
final class <?= $class_name."\n" ?>
{
use DefaultActionTrait;
}
@@ -0,0 +1,18 @@
<?= "<?php\n" ?>
namespace <?= $namespace; ?>;
<?= $use_statements ?>
class <?= $class_name ?> implements RuntimeExtensionInterface
{
public function __construct()
{
// Inject dependencies if needed
}
public function doSomething($value)
{
// ...
}
}
@@ -0,0 +1,3 @@
<div{{ attributes }}>
<!-- component html -->
</div>
@@ -0,0 +1,20 @@
<?= "<?php\n" ?>
namespace <?= $namespace; ?>;
use Symfony\Component\Validator\Constraint;
/**
* @Annotation
*
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*/
#[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
class <?= $class_name ?> extends Constraint
{
/*
* Any public properties become valid options for the annotation.
* Then, use these in your validator class.
*/
public $message = 'The value "{{ value }}" is not valid.';
}
@@ -0,0 +1,23 @@
<?= "<?php\n" ?>
namespace <?= $namespace; ?>;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
class <?= $class_name ?> extends ConstraintValidator
{
public function validate($value, Constraint $constraint)
{
/** @var <?= $constraint_class_name ?> $constraint */
if (null === $value || '' === $value) {
return;
}
// TODO: implement the validation here
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $value)
->addViolation();
}
}
@@ -0,0 +1,51 @@
<?= "<?php\n" ?>
namespace <?= $namespace; ?>;
<?= $use_statements; ?>
class <?= $class_name; ?><?= "\n" ?>
{
public function __construct(
private VerifyEmailHelperInterface $verifyEmailHelper,
private MailerInterface $mailer,
private EntityManagerInterface $entityManager
) {
}
public function sendEmailConfirmation(string $verifyEmailRouteName, UserInterface $user, TemplatedEmail $email): void
{
$signatureComponents = $this->verifyEmailHelper->generateSignature(
$verifyEmailRouteName,
$user-><?= $id_getter ?>(),
<?php if ($verify_email_anonymously): ?>
$user-><?= $email_getter ?>(),
['id' => $user->getId()]
<?php else: ?>
$user-><?= $email_getter ?>()
<?php endif; ?>
);
$context = $email->getContext();
$context['signedUrl'] = $signatureComponents->getSignedUrl();
$context['expiresAtMessageKey'] = $signatureComponents->getExpirationMessageKey();
$context['expiresAtMessageData'] = $signatureComponents->getExpirationMessageData();
$email->context($context);
$this->mailer->send($email);
}
/**
* @throws VerifyEmailExceptionInterface
*/
public function handleEmailConfirmation(Request $request, UserInterface $user): void
{
$this->verifyEmailHelper->validateEmailConfirmation($request->getUri(), $user-><?= $id_getter ?>(), $user-><?= $email_getter?>());
$user->setIsVerified(true);
$this->entityManager->persist($user);
$this->entityManager->flush();
}
}