Generate URL in a symfony 1.4 task - php

I have to generate an URL in a task but I get an incorrect url of type:
./symfony/user/edit/id
when I need
/user/edit/id
My first try was:
protected function execute($arguments = array(), $options = array())
{
$configuration = ProjectConfiguration::getApplicationConfiguration('frontend', $options['env'], true);
$this->context = sfContext::createInstance($configuration);
$baseurl = $this->context->getController()->genUrl(array('module' => 'user','action' => 'edit', 'id' => $id));
// ...
}
My second try, following this answer gives the same incorrect url:
protected function execute($arguments = array(), $options = array())
{
$configuration = ProjectConfiguration::getApplicationConfiguration('frontend', $options['env'], true);
$this->context = sfContext::createInstance($configuration);
$routing = $this->context->getRouting();
$baseurl = $routing->generate('user_edit', array('id' => $id));
// ...
}
How can I get the correct URL ?

Have you tried the solution from the snippet? I use this one in many projects.
I was also using almost the same second solution you describe but a bit different:
// you get the context the same way
$context = sfContext::createInstance($configuration);
$this->controller = $context->getController();
$baseurl = $this->controller->genUrl('user_edit?id='.$id);
Check parameters for genUrl, you can give true/false as second argument for absolute url.

I solved adding the --application option!
protected function configure()
{
$this->addOptions(array(
new sfCommandOption('env', null, sfCommandOption::PARAMETER_REQUIRED, 'The environment', 'dev'),
new sfCommandOption('application', null, sfCommandOption::PARAMETER_REQUIRED, 'The application name', 'frontend'),
));
//...
}
I didn't know that it was required even if I write directly its name in the getApplicationConfiguration params.
$configuration = ProjectConfiguration::getApplicationConfiguration('frontend', $options['env'], true);

Related

Laravel TDD ignored URL query params when trying to catch them in Controller with request

I would like to write a test to be sure my query parameters in URL are working fine. But whenever I do a request()->all(), I got an empty array.
Here is my test part:
public function test_it_should_paginate_the_results_when_perPage_query_is_used()
{
// Given
factory('App\Order', 17)->create();
// When
// $request = $this->call('GET', route('api.orders.index'), ['perPage' => '5']);
// $request = $this->call('GET', route('api.orders.index') . '?perPage=5', ['perPage' => '5']);
$request = $this->get(route('api.orders.index') . '?perPage=5');
// Then
$request->assertJsonCount(5);
}
And here is the basic method in OrderController:
public function index()
{
dd(request()->all());
$orders = Order::all();
return $orders;
}
Did I miss something ?
I've forgot to mention that it picks up the parameters in the browser, but not in PHPUnit test tool
UPDATED QUESTION
So I found out a problem. It does not working when you are testing with php artisan test command. It works only when you are using phpunit command.
No idea why.
You can pass the data as the second argument to route() or as the third argument to call():
$request = $this->get(route('api.orders.index', ['perPage' => 5]));
$request = $this->call('GET', route('api.orders.index', ['perPage' => 5]));
$request = $this->call('GET', route('api.orders.index'), ['perPage' => 5]);
Here are the defintions:
function route($name, $parameters = [], $absolute = true)
public function call($method, $uri, $parameters = [], $cookies = [], $files = [], $server = [], $content = null)

Laravel phpunit testing get with parameters

I am writing some tests for my controllers but one of my tests doesn't work. It's supossed to search and get the results back to the page. But it's actually redirecting to the home page. Here is my code:
use DatabaseMigrations;
protected $user;
public function setUp()
{
parent::setUp();
$this->seed();
$this->user = factory(User::class)->create(['role_id' => 3]);
}
/** #test */
public function test_manage_search_user()
{
$response = $this->followingRedirects()->actingAs($this->user)->get('/manage/users/search', [
'choices' => 'username',
'search' => $this->user->username,
]);
$response->assertViewIs('manage.users');
$response->assertSuccessful();
$response->assertSee($this->user->email);
}
The URL you should get to make it work look like this:
http://localhost/manage/users/search?choices=username&search=Test
I checked again and it looks like it's not given in the parameters with the get request. How can I fix this?
I had the same issue trying to test GET Requests, you actually can't pass parameter with the $this->get('uri', [header]) but you can by using $this->call, if you check in MakesHttpRequests.php you can see that this->get() is actually using call method.
By adding an array to get method, you are changing the request headers, this is why you are not getting your parameters.
public function get($uri, array $headers = [])
{
$server = $this->transformHeadersToServerVars($headers);
return $this->call('GET', $uri, [], [], [], $server);
}
public function call($method, $uri, $parameters = [], $cookies = [], $files = [], $server = [], $content = null)
{
$kernel = $this->app->make(HttpKernel::class);
$files = array_merge($files, $this->extractFilesFromDataArray($parameters));
$symfonyRequest = SymfonyRequest::create(
$this->prepareUrlForRequest($uri), $method, $parameters,
$cookies, $files, array_replace($this->serverVariables, $server), $content
);
$response = $kernel->handle(
$request = Request::createFromBase($symfonyRequest)
);
if ($this->followRedirects) {
$response = $this->followRedirects($response);
}
$kernel->terminate($request, $response);
return $this->createTestResponse($response);
}
So if you want to test a GET Request you will have to do this:
$request = $this->call('GET', '/myController', ["test"=>"test"]);
In your controller you should be able to get theses parameters like so:
public function myController(Request $request)
{
$requestContent = $request->all();
$parameter = $requestContent['test'];
}
I'm using Laravel 5.X (more precisely 5.6), you can pass custom parameters using:
$response = $this->json('GET', '/url/endpoint',['params'=>'value']);
You can use the route helper to build a url with query string. in your case i would do something like this. Assuming the route name is manage.users.search
$route = route('manage.users.search', [
'choices'=> 'username',
'search' => $this->user->username,
]);
$response = $this->followingRedirects()
->actingAs($this->user)
->get($route);
In order to send parameters with GET requests.
If you use the route() method then you can pass the data as the second parameter.
$response = $this->get(route('route_name', ['key' => value]));
If you using URL directly, you could use like this
$response = $this->get('url?' . Arr::query(['key' => value]));
Do whatever you want to do with $response.
You could use the request helper to merge in http get parameters as such:
/** #var \Illuminate\Http\Request $request */
$request = request();
$request->merge([
'choices' => 'username',
'search' => 'Test'
]);
This worked for me simply pass the parameter as part of the url as follows:
$response = $this->get('api/endpoint?parameter1='.$this->dynamicParam);
Add a helper function:
if (!function_exists('extend_url_with_query_data')) {
function extend_url_with_query_data(string $url, array $queryData): string
{
if ($queryData == []) {
return $url;
}
$glue = mb_strpos($url, '?') === false ? '?' : '&';
$queryString = http_build_query($queryData);
return "{$url}{$glue}{$queryString}";
}
}
Usage:
$queryData = [
'works' => true,
];
$this->get(
extend_url_with_query_data('/api/v1/example', $queryData)
);
I would do it like this:
$this->actingAs($this->user);
$response = $this->get('/manage/users/search', [
'choices' => 'username',
'search' => $this->user->username,
]);
$response->assertViewIs('manage.users');
$response->assertSuccessful();
$response->assertSee($this->user->email);

Only append parameter to class when condition true

I was looking at this code and noticed it seemed a lot of code just to run 2 checks, and I remembered coding in C# and there was a way to shorten the code to just one check but add a (something ? something) in it, is there a way to do something like this in PHP?
if ($config->get('core:twig.caching.enabled')) {
$this->twig = new \Twig_Environment($loader, array(
'cache' => $config->get('core:template.cache_directory'),
));
}
else {
$this->twig = new \Twig_Environment($loader);
}
I would do it this way:
$cache = $config->get('core:twig.caching.enabled');
$arr = ($cache) ? array('cache' => $cache) : array();
$this->twig = new \Twig_Environment($loader, $arr);
Because I'm not 100% sure what $config->get('core:twig.caching.enabled'); do return the above solution will work as your original one.
But if the return value is only true or false and if its ok to hand over array('cache' => true) or array('cache' => false) than you can reduce this furthermore:
$this->twig = new \Twig_Environment($loader, array(
'cache' => $config->get('core:twig.caching.enabled')
));

CakePHP change DATABASE_CONFIG variables, based on user input for custom datasource

I am looking for a way to access and change the DATABASE_CONFIG variables, based on user input. Using CakePHP I created a custom datasource, based on the one provided in the docs, to access an external API. The API returns a JSON string containing the 12 most recent objects. I need to be able to change the page number in the API request to get the next 12 results, as well as accept a free text query entered by the user.
app/Config/Database.php
class DATABASE_CONFIG {
public $behance = array(
'datasource' => 'BehanceDatasource',
'api_key' => '123456789',
'page' => '1',
'text_query' => 'foo'
);
}
app/Model/Datasource/BehanceDataSource.php
App::uses('HttpSocket', 'Network/Http');
class BehanceDatasource extends DataSource {
public $description = 'Beehance datasource';
public $config = array(
'api_key' => '',
'page' => '',
'text_query' => ''
);
public function __construct($config) {
parent::__construct($config);
$this->Http = new HttpSocket();
}
public function listSources($data = null) {
return null;
}
public function describe($model) {
return $this->_schema;
}
public function calculate(Model $model, $func, $params = array()) {
return 'COUNT';
}
public function read(Model $model, $queryData = array(), $recursive = null) {
if ($queryData['fields'] === 'COUNT') {
return array(array(array('count' => 1)));
}
$queryData['conditions']['api_key'] = $this->config['api_key'];
$queryData['conditions']['page'] = $this->config['page'];
$queryData['conditions']['page'] = $this->config['text_query'];
$json = $this->Http->get('http://www.behance.net/v2/projects', $queryData['conditions']);
$res = json_decode($json, true);
if (is_null($res)) {
$error = json_last_error();
throw new CakeException($error);
}
return array($model->alias => $res);
}
}
Is there anyway to access and change the $behance array, or is there another way to go about accessing an external API with cakePHP that I am totally missing?

Twig sandboxing not working for me

Playing around with twig templates (not a part of Symfony, in CodeIgniter) and it doesn't look like I can get a global sandbox to work correctly. I'm pretty sure I'm just doing something stupid, but I really can't see it.
Functions to make twig work:
public function twig_setup($configs = NULL)
{
Twig_Autoloader::register();
$env = array(
'cache' => config_item('cache_dir'),
'strict_variables' => TRUE,
'auto_reload' => TRUE,
'extension' => 'php',
'filesystem' => NULL
);
if (!is_null($configs))
{
$env = array_merge($env, $configs);
}
$this->set_extension($env['extension']);
if (is_null($env['filesystem']))
{
$env['filesystem'] = VIEWPATH;
}
else
{
$env['filesystem'] = VIEWPATH .'/'. ltrim($env['filesystem'],'/');
}
$this->set_filesystem($env['filesystem']);
// These two things should not get set to the environment
unset($env['extension']);
unset($env['filesystem']);
$this->set_environment($env);
}
public function set_sandbox($tags, $filters, $methods, $properties, $functions, $is_global = TRUE)
{
$user_policy = new Twig_Sandbox_SecurityPolicy($tags, $filters, $methods, $properties, $functions);
$user_sandbox = new Twig_Extension_Sandbox($user_policy, $is_global);
$this->twig->addExtension($user_sandbox);
}
public function disable_logic()
{
$tags = array('for', 'block', 'include');
$filters = array();
$methods = array();
$properties = array();
$functions = array('parent', 'block');
$this->set_sandbox($tags, $filters, $methods, $properties, $functions);
}
Usage:
$twig = new TwigThing();
$twig->twig_setup();
$twig->disable_logic();
Now, once I render a template, I should not be able to use something like raw or url_encode
{{ my_var|url_encode }}
That should kick out an error, or something, but it just encodes the var...wtf am I doing wrong here?

Categories