how can i edit services.yaml after overriding FOUserBundle - symfony-4.2

I integrated FOSUserBundle to my project in Symfony 4, everything is ok.
My goal : add 2 attributes in user.php (name and firstname).
My steps:
i added these 2 attributes in User.php (src Entity User.php) -- ok
i move to my terminal to genrate the migration -- ok
i created new folder Form (src Form) and new file inside RegistrationFormTYpe.php (see background)
i edited services.yaml (see background)
i edited fos_user.yaml in (config fos_user.yaml)..maybe it's the wrong file..cause config.yaml doesn't exist in symfony 3 (see background)
see console error in background...
Does anyone have a solution ? must i give up to integrate fosuser in symfony 4 ?
//src\Form;
namespace src\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use FOS\UserBundle\Form\Type\RegistrationFormType as BaseRegistrationFormType;
class RegistrationFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name',TextType::class,array(
'label' => 'Nom',
'required' => TRUE,
'attr' =>array(
'class='=>'form-group form-control'
)
))
->add('firstname',TextType::class,array(
'label' => 'Prénom',
'required' => TRUE,
'attr' =>array(
'class='=>'form-group form-control'
)
))
;
}
public function getParent(){
return BaseRegistrationFormType::class;
}
public function getBlockPrefix()
{
return 'app_user_registration';
}
}
// config\services.yaml
# This file is the entry point to configure your own services.
# Files in the packages/ subdirectory configure your dependencies.
# Put parameters here that don't need to change on each machine where the app is deployed
# https://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
parameters:
locale: 'fr'
services:
app.form.registration:
class: AppBundle\Form\RegistrationFormType
tags:
- { name: form.type }
- { firstname: form.type }
# default configuration for services in *this* file
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
App\:
resource: '../src/*'
exclude: '../src/{DependencyInjection,Entity,EventListener,Migrations,Tests,Kernel.php}'
# controllers are imported separately to make sure services can be injected
# as action arguments even if you don't extend any base controller class
App\Controller\:
resource: '../src/Controller'
tags: ['controller.service_arguments']
// config\fos_user.yaml
fos_user:
db_driver: orm
user_class: App\Entity\User
firewall_name: main
service:
mailer: fos_user.mailer.noop
from_email:
address: "sebvrg#gmail.com"
sender_name: "sebvrg#gmail.com"
registration:
form:
type: AppBundle\Form\RegistrationFormType
// output in console :
In FileLoader.php line 166:
A "tags" entry is missing a "name" key for service "app.form.registration" in C:\Users\sebvr\Desktop\Projets\SELT\selt\config/services.yaml in C:\Users\sebvr\Deskt
op\Projets\SELT\selt\config/services.yaml (which is loaded in resource "C:\Users\sebvr\Desktop\Projets\SELT\selt\config/services.yaml").
In YamlFileLoader.php line 489:
A "tags" entry is missing a "name" key for service "app.form.registration" in C:\Users\sebvr\Desktop\Projets\SELT\selt\config/services.yaml.

Did you extend your User entity aswell?
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use FOS\UserBundle\Model\User as BaseUser;
/**
* #ORM\Entity
* #ORM\Table(name="`user`")
*/
class User extends BaseUser
{
/**
* #ORM\Column(type="string")
*/
private $name;
/**
* #ORM\Column(type="string")
*/
private $firstname;
public function getName()
{
return $this->name;
}
public function setName($name)
{
$this->name = $name;
}
public function getFirstname()
{
return $this->firstname;
}
public function setFirstname($firstname)
{
$this->firstname = $firstname;
}
}
And did you register the form in app/config/config.yml?
fos_user:
registration:
form:
type: AppBundle\Form\RegistrationFormType
Also your tag says Symfony 4.2 but you are using the structure of symfony 3 (AppBundle) instead of (App)

Related

How can I use the current login user in a symfony form?

I trying to do a form that use the login user to fill a EntityType and use it like the 'author'
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('Title')
>add('Comment')
->add('Author', EntityType::class, [
'class' => User::class,
'choice_label' => ['name']
]);
}
I tried to do it but I can't find the way to do it
This can be done on the individual action basis, from your controller as mentioned by SubCore. However, if you want it always work automatically from anywhere you persist the entity use an event listener.
Here is one I used in a Symfony 4.4.8 project that sets the current user in an entity's createdBy/editedBy field:
namespace App\EventListener;
use App\Application\Sonata\UserBundle\Entity\User;
use App\Entity\CMSPage;
use Doctrine\Persistence\Event\LifecycleEventArgs;
use Symfony\Component\Security\Core\Security;
class CMSPageListener
{
private $security;
public function __construct(Security $security)
{
// Avoid calling getUser() in the constructor: auth may not
// be complete yet. Instead, store the entire Security object.
$this->security = $security;
}
// the entity listener methods receive two arguments:
// the entity instance and the lifecycle event
public function preUpdate(CMSPage $page, LifecycleEventArgs $event)
{
// returns User object or null if not authenticated
$user = $this->fetchCurrentUser($event);
$page
->setEditedBy($user)
->setUpdatedAt(new \DateTime())
;
}
public function prePersist(CMSPage $page, LifecycleEventArgs $event)
{
$now = new \DateTime();
if (null === $page->getCreatedBy()) {
$page->setCreatedBy($this->fetchCurrentUser($event));
}
$page
->setCreatedAt($now)
->setUpdatedAt($now)
;
}
public function fetchCurrentUser(LifecycleEventArgs $event)
{
// returns User object or null if not authenticated
$coreUser = $this->security->getUser();
/** #var User $user */
$user = $event->getObjectManager()->getRepository(User::class)->findOneBy([
'username' => $coreUser->getUsername(),
])
;
return $user;
}
}
And here is the config/services.yaml
App\EventListener\CMSPageListener:
tags:
-
# these are the basic options that define the entity listener
name: 'doctrine.orm.entity_listener'
event: 'preUpdate'
entity: 'App\Entity\CMSPage'
# set the 'lazy' option to TRUE to only instantiate listeners when they are used
lazy: true
# you can also associate an entity listener to a specific entity manager
#entity_manager: 'custom'
# by default, Symfony looks for a method called after the event (e.g. postUpdate())
# if it doesn't exist, it tries to execute the '__invoke()' method, but you can
# configure a custom method name with the 'method' option
#method: 'checkUserChanges'
- { name: 'doctrine.orm.entity_listener', event: 'prePersist', entity: 'App\Entity\CMSPage', lazy: true }

TYPO3 routeEnhancers with suffix '.html' on rootpage

Is there still no option to have the baseurl like 'www.mysite.com' if routeEnhancers are configured with '.html' suffix?
In my opinion this should be a basic feature but I can't find any solution. Redirecting the Homepage Link is not an option, as canonicals are still pointing to the wrong URL (www.mysite.com/index.html)
Is there any solution?
My configuration looks like this:
routeEnhancers:
PageTypeSuffix:
type: PageType
default: '.html'
index: index
map:
.html: 0
The reported issue on forge.typo3.org is still open (as of September 2019).
For the time beeing, you can provide a custom PageType decorator which achieves the desired result. Daniel Dorndorf, the developer who reported the issue, kindly posted the source code for this:
/Classes/Routing/Enhancer/CustomPageTypeDecorator.php
<?php
namespace Brand\Extensionname\Classes\Routing\Enhancer;
use TYPO3\CMS\Core\Routing\Enhancer\PageTypeDecorator;
use TYPO3\CMS\Core\Routing\RouteCollection;
/**
* Class CustomPageTypeDecorator
*/
class CustomPageTypeDecorator extends PageTypeDecorator
{
public const IGNORE_INDEX = [
'/index.html',
'/index/',
];
public const ROUTE_PATH_DELIMITERS = ['.', '-', '_', '/'];
/**
* #param \TYPO3\CMS\Core\Routing\RouteCollection $collection
* #param array $parameters
*/
public function decorateForGeneration(RouteCollection $collection, array $parameters): void
{
parent::decorateForGeneration($collection, $parameters);
/**
* #var string $routeName
* #var \TYPO3\CMS\Core\Routing\Route $route
*/
foreach ($collection->all() as $routeName => $route) {
$path = $route->getPath();
if (true === \in_array($path, self::IGNORE_INDEX, true)) {
$route->setPath('/');
}
}
}
}
ext_localconf.php
<?php
defined('TYPO3_MODE') or die();
// Register custom PageTypeDecorator:
$GLOBALS['TYPO3_CONF_VARS']['SYS']['routing']['enhancers'] += ['CustomPageType' => \Brand\Extensionname\Classes\Routing\Enhancer\CustomPageTypeDecorator::class];
Add this to your template extension, adjust the PHP namespace (\Brand\Extensionname\) and you're done.
config.yaml
PageTypeSuffix:
type: CustomPageType
default: '.html'
index: 'index'
map:
'.html': 0

Symfony 4.x ROLE_USER error when rendering a form with $form->createView()

I'm creating a blog with Symfony 4 and generate forms with :
php bin/console make:form
when I try to render it like this :
/**
* Require ROLE_USER for only this controller method.
* #Route("/create", name="post.create")
* #return Response
*/
public function create(): Response
{
$post = new Post();
$form = $this->createForm(CreatePostType::class, $post);
return new Response($this->twig->render('pages/create.html.twig'), [
'form' => $form->createView()
]);
}
I get this error
Could not convert database value "'ROLE_USER'" to Doctrine Type json
for this line
'form' => $form->createView()
Here is my getRoles :
/**
* #see UserInterface
*/
public function getRoles(): array
{
$roles = $this->roles;
// guarantee every user at least has ROLE_USER
$roles[] = 'ROLE_USER';
return array_unique($roles);
}
and my security.yaml
security:
# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
providers:
in_memory: { memory: ~ }
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
anonymous: ~
I'm searching for 3 days and restarted my project in a 2nd directory without the security management, I don't understand were it's from and how to solve it
thanks
I guess the roles property is not stored as json-type in your database. Can you check the type of the roles field in the database?
As a sidenote, you can rewrite the response to:
return $this->render('pages/create.html.twig', [
'form' => $form->createView(),
]);

Create a custom resource form on Sylius (Symfony3) : "Expected scalar, but got array"

I try to create a custom form for my Sylius Resource "article" using the Sylius doc. Without creating custom form, everything works well, but if I want to make a custom form, I have this error "Invalid type for path "sylius_resource.resources.blog.article.classes.form". Expected scalar, but got array."
Here is my ArticleType class :
<?php
namespace BlogAdminBundle\Form\Type;
use Symfony\Component\Form\FormBuilderInterface;
use Sylius\Bundle\ResourceBundle\Form\Type\AbstractResourceType;
class ArticleType extends AbstractResourceType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
// Build your custom form!
$builder->add('id', HiddenType::class)
->add('titre', TextType::class)
->add('date', DateType::class, array('html5' => true))
->add('contenu', CKEditorType::class)
->add('tags', TextType::class)
->add('resume', TextareaType::class)
->add('save', SubmitType::class, array('label' => 'Enregistrer l\'article'));
}
public function getName()
{
return 'admin_article';
}
}
And the declaration of my resource :
sylius_resource:
resources:
blog.article:
driver: doctrine/orm
classes:
model: BlogBundle\Entity\Article
form:
default: BlogAdminBundle\Form\Type\ArticleType
Does anyone know what is the problem ?
Thanks everyone !
you have to register your form as form.type service. And you have to send argument of your form class. You should do something like this:
services:
app.form.type.article:
class: BlogAdminBundle\Form\Type\ArticleType
arguments: [BlogBundle\Entity\Article]
tags:
- { name: form.type }
You can check what classes are used for your Article by using this command:
php bin/console debug:container | grep article

Using OAuth2 and ZF3-MVC to protect REST API

I'm trying to get https://github.com/zfcampus/zf-oauth2 working with my ZF3-MVC Application (ok, one solution could be to wait Apigility update).
I have successfully implemented the oauth2-server-php (https://github.com/bshaffer/oauth2-server-php), its zf-oauth2 module support (https://github.com/zfcampus/zf-oauth2) and adapted zf-oauth2 client for ZF3 (https://github.com/API-Skeletons/zf-oauth2-client).
However, I'm totaly stuck now trying to protect my API y following zf-oauth2 module's recommandation:
You can protect your API using the following code (for instance, at the top of a controller):
if (!$this->server->verifyResourceRequest(OAuth2Request::createFromGlobals()))
{
// Not authorized return 401 error
$this->getResponse()->setStatusCode(401);
return;
}
where $this->server is an instance of OAuth2\Server (see the AuthController.php).
I've read this post (Using ZF2 Oauth2) but it's not compliant with ZF3. I guess there's a more efficient way rather than copying/pasting zf-oauth2 module's controller and factory to instantiate the server from scratch.
Would anyone have a clue on how to implement the instance of OAuth2\Server in my API controller?
I finally did it by my own. As I spent a significant amount time on this and saw that others where also looking for a solution, here is how I did it.
At first, I suggest you read https://docs.zendframework.com/tutorials/in-depth-guide/models-and-servicemanager/ if you're not familiar with Dependency Injection and Factories (this was my case).
module.config.php
// In module/YourModule/config/module.config.php:
namespace YourAppNamespace;
use Zend\ServiceManager\Factory\InvokableFactory;
return [
'controllers' => [
'factories' => [
Controller\YourController::class => Factory\YourControllerFactory::class,
],
],
'service_manager' => [ /** Your Service Manager Config **/ ]
'router' => [ /** Your Router Config */ ]
'view_manager' => [ /** Your ViewManager Config */ ],
];
YourControllerFactory.php
// In module/YourModule/src/Controller/YourControllerFactory.php:
namespace YourAppNamespace\Factory;
use YourAppNamespace\Controller\YourController;
use Interop\Container\ContainerInterface;
use Zend\ServiceManager\Factory\FactoryInterface;
class YourControllerFactory implements FactoryInterface
{
/**
* #param ContainerInterface $container
* #param string $requestedName
* #param null|array $options
*
* #return YourController
*/
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
$controllerPluginManager = $container;
$serviceManager = $controllerPluginManager->get('ServiceManager');
// Requires zf-campus/zf-oauth2
$server = $serviceManager->get('ZF\OAuth2\Service\OAuth2Server');
$provider = $serviceManager->get('ZF\OAuth2\Provider\UserId');
return new YourController($server, $provider);
}
}
YourController.php
// In module/YourModule/src/Controller/YourController.php:
namespace YourAppNamespace\Controller;
use ZF\OAuth2\Controller\AuthController;
use OAuth2\Request as OAuth2Request;
use ZF\OAuth2\Provider\UserId\UserIdProviderInterface;
class YourController extends AuthController
{
public function __construct($serverFactory, UserIdProviderInterface $userIdProvider)
{
parent::__construct($serverFactory, $userIdProvider);
}
public function indexAction()
{
$server = call_user_func($this->serverFactory, "oauth");
if (!$server->verifyResourceRequest(OAuth2Request::createFromGlobals())) {
// Failure
$response = $server->getResponse();
return $this->getApiProblemResponse($response);
}
// Success
echo json_encode(array('success' => true, 'message' => 'It works!'));
}
}
Hope it helps!