2012-07-21 11 views
11

¿Es posible anular los comandos de la aplicación/consola symfony2? Por ejemplo, en el UserBundle de FOS me gustaría agregar unos cuantos campos más cuando se pregunta cuándo crea un usuario con su consola crear un comando de usuario. ¿Es esto posible o necesito crear mi propio comando de consola en mi propio paquete?¿Anula los comandos de la consola symfony2?

+0

material útil sobre esta cuestión. Debe marcar una respuesta como correcta;) –

Respuesta

5

Puede anular los comandos de la consola del paquete si crea (o ya tiene) su propio paquete que es hijo de ese paquete (consulte Bundle Inheritance). Luego, al colocar una clase en su paquete con la misma ubicación/nombre que el comando original, lo anula de manera efectiva.

Así, por ejemplo, para anular FOS/UserBundle/Comando/CreateUserCommand.php, crear MyCompany/UserBundle/Comando/CreateUserCommand donde MyCompanyUserBundle tiene FOSUserBundle ya que es de los padres.

Su clase de comando podría extender la clase de comando de FOS para reutilizar (bits) de ella. Sin embargo, después de haber examinado FOS CreateUserCommand creo que necesitaría anular todos los métodos para agregar más campos de entrada, en cuyo caso no hay ningún beneficio al hacerlo. Por supuesto, esto también significa que puede crear su propio comando en cualquier paquete, pero en mi opinión, es mejor mantener la personalización de FOSUserBundle en un paquete secundario.

14

Todo el proceso para añadir más campos para el comando es:

1.In su clase AcmeDemoBundle debe establecer FOSUser como padre:

<?php 

namespace Acme\UserBundle; 

use Symfony\Component\HttpKernel\Bundle\Bundle; 
use Symfony\Component\DependencyInjection\ContainerBuilder; 

class AcmeUserBundle extends Bundle 
{ 
    public function getParent() 
    { 
     return 'FOSUserBundle'; 
    } 
} 

2. Una vez que se hace eso puede volver a crear la CreateUserCommand en su paquete:

<?php 

namespace Acme\UserBundle\Command; 

use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; 
use Symfony\Component\Console\Input\InputArgument; 
use Symfony\Component\Console\Input\InputOption; 
use Symfony\Component\Console\Input\InputInterface; 
use Symfony\Component\Console\Output\OutputInterface; 
use FOS\UserBundle\Model\User; 

/** 
* @author Matthieu Bontemps <[email protected]> 
* @author Thibault Duplessis <[email protected]> 
* @author Luis Cordova <[email protected]> 
*/ 
class CreateUserCommand extends ContainerAwareCommand 
{ 
    /** 
    * @see Command 
    */ 
    protected function configure() 
    { 
     $this 
      ->setName('fos:user:create') 
      ->setDescription('Create a user.') 
      ->setDefinition(array(
       new InputArgument('username', InputArgument::REQUIRED, 'The username'), 
       new InputArgument('email', InputArgument::REQUIRED, 'The email'), 
       new InputArgument('password', InputArgument::REQUIRED, 'The password'), 
       new InputArgument('name', InputArgument::REQUIRED, 'The name'), 
       new InputOption('super-admin', null, InputOption::VALUE_NONE, 'Set the user as super admin'), 
       new InputOption('inactive', null, InputOption::VALUE_NONE, 'Set the user as inactive'), 
      )) 
      ->setHelp(<<<EOT 
The <info>fos:user:create</info> command creates a user: 

    <info>php app/console fos:user:create matthieu</info> 

This interactive shell will ask you for an email and then a password. 

You can alternatively specify the email and password as the second and third arguments: 

    <info>php app/console fos:user:create matthieu [email protected] mypassword</info> 

You can create a super admin via the super-admin flag: 

    <info>php app/console fos:user:create admin --super-admin</info> 

You can create an inactive user (will not be able to log in): 

    <info>php app/console fos:user:create thibault --inactive</info> 

EOT 
      ); 
    } 

    /** 
    * @see Command 
    */ 
    protected function execute(InputInterface $input, OutputInterface $output) 
    { 
     $username = $input->getArgument('username'); 
     $email  = $input->getArgument('email'); 
     $password = $input->getArgument('password'); 
     $name  = $input->getArgument('name'); 
     $inactive = $input->getOption('inactive'); 
     $superadmin = $input->getOption('super-admin'); 

     $manipulator = $this->getContainer()->get('acme.util.user_manipulator'); 
     $manipulator->create($username, $password, $email, $name, !$inactive, $superadmin); 

     $output->writeln(sprintf('Created user <comment>%s</comment>', $username)); 
    } 

    /** 
    * @see Command 
    */ 
    protected function interact(InputInterface $input, OutputInterface $output) 
    { 
     if (!$input->getArgument('username')) { 
      $username = $this->getHelper('dialog')->askAndValidate(
       $output, 
       'Please choose a username:', 
       function($username) { 
        if (empty($username)) { 
         throw new \Exception('Username can not be empty'); 
        } 

        return $username; 
       } 
      ); 
      $input->setArgument('username', $username); 
     } 

     if (!$input->getArgument('email')) { 
      $email = $this->getHelper('dialog')->askAndValidate(
       $output, 
       'Please choose an email:', 
       function($email) { 
        if (empty($email)) { 
         throw new \Exception('Email can not be empty'); 
        } 

        return $email; 
       } 
      ); 
      $input->setArgument('email', $email); 
     } 

     if (!$input->getArgument('password')) { 
      $password = $this->getHelper('dialog')->askAndValidate(
       $output, 
       'Please choose a password:', 
       function($password) { 
        if (empty($password)) { 
         throw new \Exception('Password can not be empty'); 
        } 

        return $password; 
       } 
      ); 
      $input->setArgument('password', $password); 
     } 

     if (!$input->getArgument('name')) { 
      $name = $this->getHelper('dialog')->askAndValidate(
       $output, 
       'Please choose a name:', 
       function($name) { 
        if (empty($name)) { 
         throw new \Exception('Name can not be empty'); 
        } 

        return $name; 
       } 
      ); 
      $input->setArgument('name', $name); 
     } 
    } 
} 

Nota he añadido un nuevo argumento de entrada llamado nombre y en el interior del comando que estoy utilizando un servicio en lugar de acme.util.user_manipulator el sistema operativo original allí voy a procesar también el nombre del usuario.

3.Create su propia UserManipulator:

<?php 

namespace Acme\UserBundle\Util; 

use FOS\UserBundle\Model\UserManagerInterface; 

/** 
* Executes some manipulations on the users 
* 
* @author Christophe Coevoet <[email protected]> 
* @author Luis Cordova <[email protected]> 
*/ 
class UserManipulator 
{ 
    /** 
    * User manager 
    * 
    * @var UserManagerInterface 
    */ 
    private $userManager; 

    public function __construct(UserManagerInterface $userManager) 
    { 
     $this->userManager = $userManager; 
    } 

    /** 
    * Creates a user and returns it. 
    * 
    * @param string $username 
    * @param string $password 
    * @param string $email 
    * @param string $name 
    * @param Boolean $active 
    * @param Boolean $superadmin 
    * 
    * @return \FOS\UserBundle\Model\UserInterface 
    */ 
    public function create($username, $password, $email, $name, $active, $superadmin) 
    { 
     $user = $this->userManager->createUser(); 
     $user->setUsername($username); 
     $user->setEmail($email); 
     $user->setName($name); 
     $user->setPlainPassword($password); 
     $user->setEnabled((Boolean)$active); 
     $user->setSuperAdmin((Boolean)$superadmin); 
     $this->userManager->updateUser($user); 

     return $user; 
    } 
} 

En esta clase solo me falta la función de crear lo que el resto de comandos como promover, degradar .. no sabe nada de nuevas propiedades de sus usuarios así que no hago necesita crear un CompilerPass para anular todo el servicio.

4.Finally, definir este nuevo servicio UserManipulator en el directorio Resources/config y añadirlo a la extensión DependencyInjection:

services: 
    acme.util.user_manipulator: 
     class:  Acme\UserBundle\Util\UserManipulator 
     arguments: [@fos_user.user_manager] 

Hecho !!!

+0

¡Hola @ nass600! Gracias por su respuesta detallada, pero podría detallar también la última parte: "agréguela a DependencyInjection Extension". Muchas gracias – Reveclair

0

En Symfony (3.3) puede anular los comandos de la consola siguiendo estos enlaces. https://symfony.com/doc/current/console/calling_commands.html y las opciones en https://symfony.com/doc/current/console/input.html

Código de Doc Symfony:

use Symfony\Component\Console\Input\ArrayInput; 
// ... 

protected function execute(InputInterface $input, OutputInterface $output) 
{ 
    $command = $this->getApplication()->find('demo:greet'); 

    $arguments = array(
     'command' => 'demo:greet', 
     'name' => 'Fabien', 
     '--yell' => true, 
    ); 

    $greetInput = new ArrayInput($arguments); 
    $returnCode = $command->run($greetInput, $output); 

    // ... 
} 
Cuestiones relacionadas