2012-10-26 1 views
4

Peut-être quelque chose de similaire à la commande generate: bundle (qui, après avoir généré l'invite de groupe pour mettre à jour AppKernel) ou à Composer (qui met à jour votre autocharge avec les dépendances que vous installez). Je veux obtenir une fonctionnalité similaire à generate: bundle, mais au lieu de créer un nouveau bundle, je veux ajouter un bundle que je viens de télécharger sans avoir à modifier manuellement AppKernel.Existe-t-il un moyen de mettre à jour automatiquement AppKernel dans symfony2?

Répondre

4

Je ne pouvais pas trouver un moyen d'étendre une commande existante, donc ma pensée va créer une nouvelle commande de console dans un ensemble existant.

namespace Your\OriginalBundle\Command; 

use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; 
use Symfony\Component\Console\Input\ArrayInput; 
use Symfony\Component\Console\Input\InputArgument; 
use Symfony\Component\Console\Input\InputInterface; 
use Symfony\Component\Console\Input\InputOption; 
use Symfony\Component\Console\Output\OutputInterface; 

class AppendNewBundleCommand extends ContainerAwareCommand 
{ 
    protected $appKernel; 

    protected function configure() 
    { 
     $this 
      ->setName('yourbundle:appendnewbundle') 
      ->setDescription('Append a new bundle to the AppKernel.php') 
      ->addArgument('namespace', InputArgument::REQUIRED, 'Define your new bundle/namespace') 
     ; 
     $this->appKernel = __DIR__.'/../../../../app/AppKernel.php'; 
    } 

    protected function execute(InputInterface $input, OutputInterface $output) 
    { 
     if (!file_exists($this->appKernel)) { 
      throw new \ErrorException(sprintf("Could not locate file %s",$this->appKernel)); 
     } 
     if (!is_writable($this->appKernel)) { 
      throw new \ErrorException(sprintf('Cannot write into AppKernel (%s)',$this->appKernel)); 
     } 

     $namespace = $input->getArgument('namespace'); 
     $appContent = file_get_contents($this->appKernel); 

     $bundle = str_replace("/","\\",$namespace)."\\".str_replace("/","",$namespace); 
     $newBundle = "new {$bundle}(),"; 

     $pattern = '/\$bundles\s?=\s?array\((.*?)\);/is'; 
     preg_match($pattern, $appContent,$matches); 

     $bList = rtrim($matches[1],"\n "); 
     $e = explode(",",$bList); 
     $firstBundle = array_shift($e); 
     $tabs = substr_count($firstBundle,' '); 

     $newBList = "\$bundles = array(" 
          .$bList."\n" 
          .str_repeat(' ', $tabs).$newBundle."\n" 
         .str_repeat(' ',$tabs-1).");"; 

     file_put_contents($this->appKernel,preg_replace($pattern,$newBList,$appContent)); 
    } 
} 

Vous pouvez maintenant exécuter, juste après la génération de votre paquet en faisant

php app/console yourbundle:appendnewbundle Your/SecondBundle 

Ceci ajoutera ceci à la liste des ensembles existants

new Your\SecondBundle\YourSecondBundle(), 

Cela fonctionne si vous avez un standard (symfony2) AppKernel. Ex:

<?php 

use Symfony\Component\HttpKernel\Kernel; 
use Symfony\Component\Config\Loader\LoaderInterface; 

class AppKernel extends Kernel 
{ 
    public function registerBundles() 
    { 
     $bundles = array(
      new Symfony\Bundle\FrameworkBundle\FrameworkBundle(), 
      new Symfony\Bundle\SecurityBundle\SecurityBundle(), 
      new Symfony\Bundle\TwigBundle\TwigBundle(), 
      new Symfony\Bundle\MonologBundle\MonologBundle(), 
      new Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle(), 
      new Symfony\Bundle\DoctrineBundle\DoctrineBundle(), 
      new Symfony\Bundle\AsseticBundle\AsseticBundle(), 
      new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(), 
      new JMS\SecurityExtraBundle\JMSSecurityExtraBundle(), 
      new Ornicar\ApcBundle\OrnicarApcBundle(), 
      new Your\OriginalBundle\YourOriginalBundle(), 
     ); 

     if (in_array($this->getEnvironment(), array('dev', 'test'))) { 
      $bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle(); 
      $bundles[] = new Sensio\Bundle\DistributionBundle\SensioDistributionBundle(); 
      $bundles[] = new Sensio\Bundle\GeneratorBundle\SensioGeneratorBundle(); 
     } 

     return $bundles; 
    } 

    public function registerContainerConfiguration(LoaderInterface $loader) 
    { 
     $loader->load(__DIR__.'/config/config_'.$this->getEnvironment().'.yml'); 
    } 
} 
+0

Merci. J'étais sur le point de faire quelque chose comme ça. J'allais copier le code du code generate: bundle existant dans une commande séparée. – Jens

+1

Cool! Cette commande doit être incluse avec le framework Symfony. – caligari

+0

Wow! +1 pour l'effort mais -1000 pour ce que vous faites là! C'est le noyau de votre application! Je ne veux pas offenser mais parfois nous nous emportons pour trouver une solution pour n'importe quoi (et je m'inclure ici aussi) - mais nous oublions de vérifier si le petit avantage que nous avons gagné (en ajoutant une ligne de code automatiquement) ne en fait créer plus de problèmes. Si nous parlons ici de générer un bundle - ce qui signifie très certainement qu'il y aura du codage de toute façon - ajouter une ligne manuellement dans le noyau n'est pas un gros travail à faire. – jakabadambalazs

-2

Techniquement c'est bien sûr possible, quelqu'un doit le faire.

1

je n'ai pas tester

use Symfony\Component\HttpKernel\KernelInterface; 
use Sensio\Bundle\GeneratorBundle\Manipulator\KernelManipulator; 
use RuntimeException; 

class SomeClass { 
    /** 
    * Register bundle in Kernel 
    * @param KernelInterface $kernel 
    * @param sting   $namespace 
    * @param sting   $bundle 
    * @return boolean 
    * @throws RuntimeException   When bundle already defined in <comment>AppKernel::registerBundles()</comment> 
    */ 
    protected function registerBundle(KernelInterface $kernel, $namespace, $bundle) 
    { 
     $manip = new KernelManipulator($kernel); 

     return $manip->addBundle($namespace.'\\'.$bundle); 
    } 
} 
Questions connexes