Symfony2 command and tcpdf whiteoctober - symfony

I use symfony and I have installed whiteoctober TCPDF with success.
It works if I use it in a controller, my PDF is generated.
However I want to use it in a command.
So I have a command called "CronInvoicesCommand" in a command folder and of course I have this error:
Attempted to call method "get" on class "OandP\boBundle\Command\CronInvoicesCommand" in C:\wamp\www\OandPlocal\src\OandP\boBundle\Command\CronInvoicesCommand.php line 187. Did you mean to call: "getAliases", "getApplication", "getDefinition", "getDescription", "getHelp", "getHelper", "getHelperSet", "getName", "getNativeDefinition", "getProcessedHelp", "getSynopsis"?
So my question is how can I load all those method in a command.
Thank you se much for your help

you can use a container aware commmand :
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
class MyCommand extends ContainerAwareCommand
{
protected function execute(InputInterface $input, OutputInterface $output)
{
$em = $this->getContainer()->get('doctrine')->getEntityManager();
// ...

Probably you are trying to get a service from a container similar to the controller method get. In a Command you can access to the container with the getContainer() method, so try to substitute something like:
$this->get('service_name');
with
$this->getContainer()->get('service_name');
More info here in the doc.
Hope this help

Related

Executing Symfony 4 Custom Command in fixtures

I have a custom command in my symfony project to populate the database with the default data that the application need to work in both dev and prod environments.
For the dev environment I have a fixture script that depends on these default common data.
I'm trying to call my custom Symfony command in the fixture script so that I'm sure to have the required data to properly load my fixtures.
This is my custom command app:db:populate in "pseudo script", just creating a bunch of entities, persit & flush. My custom command works fine when I call it through php bin/console app:db:populate
protected function execute(InputInterface $input, OutputInterface $output)
{
// Creating a bunch of default entities, persist them and flush
$data = new MyDefaultEntity();
// ...
$this->manager->persist($data);
// ...
$this->manager->flush();
}
Then, in my fixture script, I want to call app:db:populate first, because fixtures depends on these data. So I tried to use the Process class to execute my script this way :
public function load(ObjectManager $manager)
{
// Execute the custom command
$cmd = 'php bin/console app:db:populate';
$process = new Process($cmd);
$process->run(function ($type, $buffer) {
if (Process::ERR === $type) {
echo 'ERR > '.$buffer;
} else {
echo 'OUT > '.$buffer;
}
});
// Then load the fixtures !
// ...
}
The custom command seems to execute well until the $this->manager->flush();
I have the following error in my console (Data is obfuscated for the post):
In AbstractMySQLDriver.php line 36:
An exception occurred while executing 'INSERT INTO ....(..., ..., ...) VALUES (?, ?, ?)' with params ["...", "...", "..."]:
SQLSTATE[HY000]: General error: 1205 Lock wait timeout exceeded; try restarting transaction
I don't know what to do regarding this error ... Why the command is working normally when used through a classic console call and why it is not working in a Process?
So, the short answer is
Quoting Symfony documentation :
You may have the need to execute some function that is only available in a console command. Usually, you should refactor the command and move some logic into a service that can be reused in the controller.
I ended up making a service class that handles all the app:db:populate logic (read a json file and insert basic app entities in the database). Then I call this service in both app:db:populate execute methods and AppFixtures load methods.
Hope this will help someone.

Symfony Process Eats Terminal Control Codes

So I'm running a Symfony Process for some commands, and I noticed that when I write those to Symfony's OutputInterface it is not showing colors or progress bars. I think that the commands (npm, artisan, ls, etc) are using terminal control codes, and one of those classes is eating the non-standard ASCII characters.
EDIT:
I've done some digging and I belive Symfony uses its StreamOutput class by default. It appears to be able to output in color, and I've tried telling it to OUTPUT_RAW. No beans there. Perhaps the problem is somewhere else...
Is there a built-in way to tell these classes not to do that? How can I get my pretty output back?
Colors availability depends on the program you are calling.
You may try to set the tty/pty:
protected function execute(InputInterface $input, OutputInterface $output)
{
$process = new Process('ls -l --color="always"');
$process->setTty(true); // or $process->setPty(true);
$process->run();
$output->write($process->getOutput());
}
See related issue.
I don't think that a command output removes the escape codes. Next example works well (for me):
protected function execute(InputInterface $input, OutputInterface $output)
{
$output->write(shell_exec('ls -l --color="always"')); // ok, output is colored
}
Hope this helps.

Trouble running unit test - got undefined method error

I followed the instructions on this page but couldn't get my unit test working.
http://framework.zend.com/manual/2.2/en/tutorials/unittesting.html
My initial code was like this:
<?php
namespace ApplicationTest\Controller;
use Zend\Http\Request;
use Zend\Http\Response;
use Zend\Test\PHPUnit\Controller\AbstractHttpControllerTestCase;
class IndexControllerTest extends AbstractHttpControllerTestCase {
protected $controller;
protected $request;
protected $response;
protected $routeMatch;
protected $event;
protected $traceError = true;
public function setUp() {
$this->setApplicationConfig(
include '../../../config/application.config.php'
);
parent::setUp();
}
public function testIndexActionCanBeAccessed() {
$this->dispatch('/');
$this->assertResponseStatusCode(200);
}
}
And when I ran phpunit, I got the following error message:
PHPUnit 3.7.21 by Sebastian Bergmann.
Configuration read from /usr/share/php/tool/module/Application/test/phpunit.xml
onDispatch called.
E
Time: 1 second, Memory: 14.50Mb
There was 1 error:
1) ApplicationTest\Controller\IndexControllerTest::testIndexActionCanBeAccessed
Zend\ServiceManager\Exception\ServiceNotFoundException: Zend\ServiceManager\ServiceManager::get was unable to fetch or create an instance for Zend\Db\Adapter\Adapter
Then I followed the second set of instructions to configure the service manager.
public function testIndexActionCanBeAccessed() {
$albumTableMock = $this->getMockBuilder('User\Model\UserData')
->disableOriginalConstructor()
->getMock();
$albumTableMock->expects($this->once())
->method('getUserSessionArray')
->will($this->returnValue(array()));
$serviceManager = $this->getApplicationServiceLocator();
$serviceManager->setAllowOverride(true);
$serviceManager->setService('User\Model\UserData', $albumTableMock);
$this->dispatch('/');
$this->assertResponseStatusCode(200);
}
And this time, I got the following error:
PHPUnit 3.7.21 by Sebastian Bergmann.
Configuration read from /usr/share/php/tool/module/Application/test/phpunit.xml
onDispatch called.
PHP Fatal error: Call to undefined method Mock_UserData_ae821217::getUserSessionArray() in /usr/share/php/tool/module/User/Module.php on line 95
PHP Stack trace:
PHP 1. {main}() /usr/local/pear/bin/phpunit:0
…
Could someone help me on this please?
We are using Zend Framework 2.2.0.
Thank you so much.
EC
Your mock isn't quite setup right. You don't set any methods for the mock to have and so your expects isn't really being set. You need to create your mock like this:
$albumTableMock = $this->getMockBuilder('User\Model\UserData')
->disableOriginalConstructor()
->setMethods(array('getUserSessionArray')) //ADD this line
->getMock();
Your User\Model\UserData class doesn't exist and so PHPUnit did not create the method to get mocked. And when you ran your tests the function was not defined.

Symfony 2 Service Error on unit Testing

I make some functional test with Symfony 2 and phpunit.
But i've some trouble with a Service.
Let me explain.
During my run test, i want to use some service used by the application. So i juste set my setUp function for setting the kernel :
static::$kernel = static::createKernel();
static::$kernel->boot();
$this->objectFactory = static::$kernel->getContainer()->get('some.application.objectfactory');
So i've this and in my function i need to used a service that return an object so i call my service like that
$var = $this->objectFactory->getObject($id);
and obviously in my tearDown function i just :
protected function tearDown()
{
$this->client->restart();
unset($this->client, $this->objectFactory);
}
So my problem is when i run a test i've this message :
Symfony\Component\DependencyInjection\Exception\InactiveScopeException: You cannot create a service ("request") of an inactive scope ("request").
And i can't find a way to solve this.
Did someone have any idea ??
My version of Symfony is 2.2.1 and my version of phpunit is 3.7.19
If someone can help me, i could be very happy.
I'm sorry if my English isn't so good.
EDIT
Maybe it could help someone, in the service i used that : :
$request = $this->container->get('request');
It seems to be the reason why it dosen't work, when i remove it, it doesn't say the error, but they still doesn't work.
EDIT
#Cyprian
According to you have change my code for what i want.
So i just add to my service, in the function that i want, the client (Client web test case), and then inside the function i just add this :
if (isset($client)) {
$request = $client->getRequest();
} else {
$request = $this->container->get('request');
}
So in my function where i call the service i've just this :
public function getObject($id)
{
//Get the service from the kernel
$service = static::$kernel->getContainer()->get('service');
$object = $service->getObject($id, $this->client);
}
and it works fine like this
#nifr
Your idea doesn't work for me, but i think your idea wasn't wrong, they just not works in my case
However Thanks for your help, i'm happy i works now, and i expect that post could help someone else
Try get request from the client, not service container:
$request = $this->client->getRequest();
In that way you can also get kernel and/or container:
$kernel = $this->client->getKernel();
$container = $this->client->getContainer();
One more useful tip: kernel from the client is rebooted between each two requests. So, for example if you pass your mock to client's container and do some request, in next request (after the first one) the container will not contain your mock.
There is no request available in phpUnit as long as you don't construct one.
If you want to test a request. create it like this:
use Symfony\Component\HttpFoundation\Request;
protected $request;
public function setUp()
{
// ...
$this->request = new Request();
// ... modify your request acccording to your needs
}
and add/call a setter in your Service using the request.
$service = $this->kernel->getContainer()->get('your_service')
$service->setRequest($this->request);
or create a Functional Test with WebtestCase.

Is it possible to mock our own service?

I want to mock a service that is required in a class constructor. I have an exception of PHPUnit : MyService is required, Mock_MyService_0afc7fc1 given.
But with the Request, EntityManager or other Symfony 2 component, I haven't this issue.
Here is my Class's construct :
use Acme\Bundle\Service\MyService;
use Symfony\Component\HttpFoundation\Request;
...
public function __construct(MyService $service, Request $request)
{
and my mock :
...
$service = $this->getMock('MyService');
$class = new Class($service, $request);
It's impossible to mock our own service ? Only Symfony 2 component ?
PS : If I delete MyServicelike that : public function __construct($service, Request $request), this works. But I want to define my variable with it :(
The issue is that PHPUnit at the time of the test execution can't find (or autoload) your MyService class.
That means that you'll probably run into the same issues with other Mocking libraries as all of them require the original class to exist to scan it and create the mock.
It happens because you need to tell PHPUnit the Fully-Qualified Class Name.
Change your code to $this->getMock("\Acme\Bundle\Service\MyService"); and it should work out.
(Still, give mockery a try. It's a nice library)

Resources