Retrieve all controller action that have a specific annotation - Symfony2 - symfony

I have created an annotation class called #Module, and a command GenerateModulesCommand. What I want is to find all controller actions that have the #Module annotation.
Example :
/**
*
* #Module(name='sidebar', enabled=true')
*/
public function sidebarAction($name) {
$ape = new ArrayParamsExtension ();
return $this->render('ModuleManagerBundle:Default:sidebar.html.twig', $ape->getArrayParams($name));
}
I want to be able to look at the specific properties in the #Module (name, enabled, etc...)
So far, this is my execute method from my Command :
protected function execute(InputInterface $input, OutputInterface $output) {
$path = $this->getApplication()->getKernel()->locateResource('#ModuleManagerBundle');
$driver = new PHPDriver($path);
$classes = $driver->getAllClassNames();
foreach ($classes as $key => $class) {
$reader = new AnnotationReader();
$annotationReader = new CachedReader(
$reader, new ArrayCache()
);
$reflClass = new ReflectionClass("\Controller\\" . $reportableClass);
$annotation = $annotationReader->getClassAnnotation(
$reflClass, 'Custom_Annotation'
);
if (is_null($annotation)) {
unset($classes[$key]);
}
}
$output->writeln($path);
}
I found this code on sof, but I don't know how to search all Controller classes and all the Actions inside them..

You can try this in your function
use Doctrine\Common\Annotations\AnnotationReader;
your function
public function getControllersWithAnnotationModules()
{
$allAnnotations = new AnnotationReader();
$controllers = array();
foreach ($this->container->get('router')->getRouteCollection()->all() as $route) {
$defaults = $route->getDefaults();
if (isset($defaults['_controller'])) {
$controllerAction = explode(':', $defaults['_controller']);
$controller = $controllerAction[0];
if (!isset($controllers[$controller]) && class_exists($controller)) {
$controllers[$controller] = $controller;
}
}
}
$controllersWithModules = array();
foreach($controllers as $controller){
$reflectionClass = new \ReflectionClass($controller);
$module = $allAnnotations->getClassAnnotation($reflectionClass,'Acme\YourBundle\Module');
if($module)
$controllersWithModules[] = $controller;
}
return $controllersWithModules ;
}

Related

phpUnit equalTo won't look inside my objects

I'm writing this test:
public function update_emails_in_gmail(): void
{
$emailId = new EmailId(self::EMAIL_ID);
$sender = new EmailAddress(self::SENDER_ADDRESS);
$sentAt = new DateTimeImmutable();
$email = new Email($emailId, $sender, $sentAt);
$labelToAdd = new Label(self::LABEL_ADD_THIS, self::LABEL_ADD_THIS);
$labelToRemove = new Label(self::LABEL_REMOVE_THIS, self::LABEL_REMOVE_THIS);
$removeLabel = new RemoveLabel($labelToRemove);
$addLabel = new AddLabel($labelToAdd);
$this->gmailService
->expects($this->once())
->method('modifyMessage')
->with($this->equalTo($emailId), $this->equalTo([$addLabel, $removeLabel]))
;
$email
->addLabel($labelToAdd)
->removeLabel($labelToRemove)
;
$this
->gmailRepository
->updateEmail($email);
}
And this is the code for updateEmail:
/**
* #param Email $email
* #return void
*/
public function updateEmail(Email $email): void
{
$this
->gmail
->modifyMessage($email->id(), [new AddLabel(new Label("", "")), new RemoveLabel(new Label("", ""))]);
}
I was expecting the test to fail, since self::LABEL_ADD_THIS and self::LABEL_REMOVE_THIS are both not empty but phpUnit is saying the test passed...
Any idea what I'm doing wrong?

Codeception improve readiness unit test

I'm new to test, I'm using codeception and phpunit to do some TDD.
However, my methods have a lot of code. Do I used best practices ? Is there a way to improve the readiness of my code, can it be more clean ?
class NewsFormHandlerTest extends \Codeception\Test\Unit
{
/**
* #var \UnitTester
*/
protected $tester;
protected function _before()
{
}
protected function _after()
{
}
private function getFormMock(){
return $this->getMockBuilder(FormInterface::class)
->disableOriginalConstructor()
->getMock();
}
private function getNewsManagerMock(){
return $this->getMockBuilder(INewsManager::class)
->disableOriginalConstructor()
->getMock();
}
// tests
public function testShouldHandleASuccessfulFormSubmissionForAddANews()
{
// prepare
$request = new \Symfony\Component\HttpFoundation\Request();
$news = new News();
$form = $this->getFormMock();
$form->expects($this->once())
->method('isValid')
->will($this->returnValue(true));
$form->expects($this->once())
->method('submit');
$form->expects($this->once())
->method('getData')
->will($this->returnValue($news));
$newsManager = $this->getNewsManagerMock();
$newsManager->expects($this->once())
->method('add');
$user = Stub::make(WebserviceUser::class, []);
// test
$handler = new NewsFormHandler($newsManager, $user);
$newsReturned = $handler->handle($form, $request, NewsFormHandler::ADD);
// assert
$this->assertInstanceOf(News::class, $newsReturned);
$this->assertEquals($news, $newsReturned);
}
public function testShouldHandleASuccessfulFormSubmissionForEditANews()
{
// prepare
$request = new \Symfony\Component\HttpFoundation\Request();
$news = new News();
$form = $this->getFormMock();
$form->expects($this->once())
->method('isValid')
->will($this->returnValue(true));
$form->expects($this->once())
->method('submit');
$form->expects($this->once())
->method('getData')
->will($this->returnValue($news));
$newsManager = $this->getNewsManagerMock();
$newsManager->expects($this->once())
->method('edit');
$user = Stub::make(WebserviceUser::class, []);
// test
$handler = new NewsFormHandler($newsManager, $user);
$newsReturned = $handler->handle($form, $request, NewsFormHandler::EDIT);
// assert
$this->assertInstanceOf(News::class, $newsReturned);
$this->assertEquals($news, $newsReturned);
}
public function testFailFormWithInvalidData()
{
// prepare
$request = new \Symfony\Component\HttpFoundation\Request();
$form = $this->getFormMock();
$form->expects($this->once())
->method('isValid')
->will($this->returnValue(false));
$newsManager = $this->getNewsManagerMock();
$newsManager->expects($this->never())
->method('edit');
$this->expectException(InvalidFormException::class);
$user = Stub::make(WebserviceUser::class, []);
// test
$handler = new NewsFormHandler($newsManager, $user);
$newsReturned = $handler->handle($form, $request, NewsFormHandler::ADD);
// assert
$this->assertNull($newsReturned);
}
}
You can probably extract body of testShouldHandleASuccessfulFormSubmissionForAddANews and testShouldHandleASuccessfulFormSubmissionForEditANews to other method with parameter like $action = 'add'|'edit' (or use your defined contants NewsFormHandler::EDIT etc), as they're almost the same.
You can extract mock creation from above methods to a single parametrized method, as the process is almost the same (pass the differences as method arguments and let it do the dirty work).
You can also add some readability by using BDD style, as in example in page http://codeception.com/docs/05-UnitTests#BDD-Specification-Testing

Create my own entity generator on symfony using doctrine generator

I am building an entity generator in order to update my DB's structure and data according to a distant one (DB), via SOAP WS...
I get the structure from an array, and am currently writing my entity classes by myself, with a file_put_content().
But as I advance, I can't help noticing that the Doctrine\ORM\Tools\EntityGenerator already does what I intend to do, way better I would ever be able to!!
So i was wondering if there was a way to use this implemented generator from my controller?
I mean, this is what Symfony is all about right? Using existing classes & bundles from anywhere in my code? :)
Any idea someOne?
Thx :)
You can use this code:
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpKernel\Bundle\BundleInterface;
use Sensio\Bundle\GeneratorBundle\Generator\DoctrineEntityGenerator;
use Sensio\Bundle\GeneratorBundle\Command\Validators;
class MyController extends Controller
{
private $generator;
public function generateEntityAction()
{
$format = "annotation"; //it can also be yml/php/xml
$fields = "title:string(255) body:text";
$withRepository = false; //true/false
$entity = Validators::validateEntityName("MyBundle:EntityName");
list($bundle, $entity) = $this->parseShortcutNotation($entity);
$format = Validators::validateFormat($format);
$fields = $this->parseFields($fields);
$bundle = $this->get('service_container')->get('kernel')->getBundle($bundle);
$generator = $this->getGenerator();
$generator->generate($bundle, $entity, $format, array_values($fields), $withRepository);
}
protected function createGenerator()
{
return new DoctrineEntityGenerator($this->get('service_container')->get('filesystem'), $this->get('service_container')->get('doctrine'));
}
protected function getSkeletonDirs(BundleInterface $bundle = null)
{
$skeletonDirs = array();
if (isset($bundle) && is_dir($dir = $bundle->getPath() . '/Resources/SensioGeneratorBundle/skeleton')) {
$skeletonDirs[] = $dir;
}
if (is_dir($dir = $this->get('service_container')->get('kernel')->getRootdir() . '/Resources/SensioGeneratorBundle/skeleton')) {
$skeletonDirs[] = $dir;
}
$skeletonDirs[] = __DIR__ . '/../Resources/skeleton';
$skeletonDirs[] = __DIR__ . '/../Resources';
return $skeletonDirs;
}
protected function getGenerator(BundleInterface $bundle = null)
{
if (null === $this->generator) {
$this->generator = $this->createGenerator();
$this->generator->setSkeletonDirs($this->getSkeletonDirs($bundle));
}
return $this->generator;
}
protected function parseShortcutNotation($shortcut)
{
$entity = str_replace('/', '\\', $shortcut);
if (false === $pos = strpos($entity, ':')) {
throw new \InvalidArgumentException(sprintf('The entity name must contain a : ("%s" given, expecting something like AcmeBlogBundle:Blog/Post)', $entity));
}
return array(substr($entity, 0, $pos), substr($entity, $pos + 1));
}
private function parseFields($input)
{
if (is_array($input)) {
return $input;
}
$fields = array();
foreach (explode(' ', $input) as $value) {
$elements = explode(':', $value);
$name = $elements[0];
if (strlen($name)) {
$type = isset($elements[1]) ? $elements[1] : 'string';
preg_match_all('/(.*)\((.*)\)/', $type, $matches);
$type = isset($matches[1][0]) ? $matches[1][0] : $type;
$length = isset($matches[2][0]) ? $matches[2][0] : null;
$fields[$name] = array('fieldName' => $name, 'type' => $type, 'length' => $length);
}
}
return $fields;
}
}
Mostly, it comes from Sensio\Bundle\GeneratorBundle\Command\GenerateDoctrineEntityCommand and Sensio\Bundle\GeneratorBundle\Command\GeneratorCommand

Symfony 2.1 form unit testing on bind event

I am trying to test a method on the bind event of a custom form type.
Here is the code
public function bind(DataEvent $event)
{
$form = $event->getForm();
if($form->getNormData() instanceof BaseFileInterface && !$event->getData() instanceof UploadedFile) {
$event->setData($form->getNormData());
}
if($event->getData() instanceof UploadedFile) {
$hander = $this->handlerManager->getHandler(
$form->getParent()->getConfig()->getDataClass(),
$form->getName()
);
$datas = $hander->createBaseFile($event->getData());
$event->setData($datas);
}
if(is_string($event->getData())) {
$event->setData(null);
}
}
and the form builder of the type :
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->addEventSubscriber(new BaseFileListener($this->handlerManager))
->addViewTransformer(new BaseFileToStringTransformer())
;
}
My test class inherits from Symfony\Component\Form\Tests\FormIntegrationTestCase and is doing this :
protected function setUp()
{
parent::setUp();
$this->handlerManager = $this->getHandlerManagerMock();
$this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
$this->builder = new FormBuilder(null, null, $this->dispatcher, $this->factory);
$this->form = $this->factory->create('my_file');
$this->form->setParent($this->getFormMock())->setData(new DummyEntity());
}
protected function getFormMock()
{
$mock = $this
->getMockBuilder('Symfony\Component\Form\Tests\FormInterface')
->disableOriginalConstructor()
->getMock()
;
return $mock;
}
public function testBindHandleNewFileWithNonEmptyField()
{
$data = $file = new UploadedFile(
__DIR__.'/../Fixtures/test.gif',
'original.gif',
'image/gif',
filesize(__DIR__.'/../Fixtures/test.gif'),
null
);
$event = new FormEvent($this->form, $data);
$listener = new BaseFileListener($this->handlerManager);
$listener->bind($event);
$this->assertInstanceOf('My\FooBundle\Entity\BaseFileInterface', $event->getData());
$this->assertNotEquals($event->getData(), $this->form->getNormData());
}
The probleme is that the $form->getParent()->getConfig()->getDataClass() throws an exception on getDataClass ().
The question is how to build the form correctly to perform the bind test ?
Ok, answering my self :)
Here is the good mocking in phpunit :
protected function setUp()
{
parent::setUp();
$this->handlerManager = $this->getHandlerManagerMock();
$this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
$this->builder = new FormBuilder(null, null, $this->dispatcher, $this->factory);
$this->form = $this->factory->create('my_file');
$this->form->setParent($this->getFormMock());
}
protected function getFormMock()
{
$mock = $this->getMock('Symfony\Component\Form\Tests\FormInterface');
$mock
->expects($this->any())
->method('getConfig')
->will($this->returnValue($this->getFormConfigMock()))
;
return $mock;
}
protected function getFormConfigMock()
{
$mock = $this->getMockBuilder('Symfony\Component\Form\FormConfigInterface')
->disableOriginalConstructor()
->getMock();
$mock
->expects($this->any())
->method('getDataClass')
->will($this->returnValue('My\FooBundle\Tests\DummyEntity'))
;
return $mock;
}
I thought I could manage to rebuild the entire form without using mock, but it seems impossible.
If someone has a better solution to offer I'm interested.

Call form values in form handler

Here is my problem.
I am curently learning Symfony and I have created a form with a formType file and a formHandler.
I'd like now to use values of the form in my handler but I can't figure how to call those values, which method can I use? I've tried many method of the request class but it doesn't work.
Could you help me please?
Here is my handler. Some of my try are still in it commented, it's quiet simple, I'm just trying to do an echo.
class adminFormHandler
{
protected $form;
protected $request;
protected $em;
public function __construct(Form $form, Request $request, EntityManager $em)
{
$this->form = $form;
$this->request = $request;
$this->em = $em;
}
public function process()
{
if( $this->request->getMethod() == 'POST' )
{
$this->form->bindRequest($this->request);
//if( $this->form->isValid() )
//{
//echo $this->request->get('nom');
//$param = $this->request->request->keys();
//$param = $this->form->getData(nom);
//echo $param;
$myfield = $form->getAttribute('nom');
echo $myfield->getData();
//echo $param;//$this->form->get('nom')->getText();
//$this->onSuccess($this->form->getData());
return true;
//}
}
return false;
}
public function onSuccess1(/*Students $students*/)
{
//$this->em->persist($students);
//$this->em->flush();
echo'on success 1';
}
public function onSuccess2()
{
//$this->em->persist($students);
//$this->em->flush();
echo'on success 2';
}
}
You can use:
$data = $this->form->getData();
$myfield = $data['nom'];
or
$myfield = $this->form->get('nom')->getData();

Resources