How to upload file with Guzzle client? - symfony

I'm trying to do BDD testing on an upload method. I'm using Behat with Mink in a symfony2 project.
Now I'm able to do simple request with this client:
$this->client = $this->mink->getSession('goutte')->getDriver()->getClient();
and
$this->client->request("POST", $url, array('content-type' => 'application/json'), array(), array(), $fields);
without any issue.
How to do a request with a file? I tried this:
$file = new \Symfony\Component\HttpFoundation\File\UploadedFile($path, "video");
$fields = json_encode($table->getColumnsHash()[0]);
$this->client->request("POST", $url, array('content-type' => 'multipart/form-data'), array($file), array(), $fields);
And the error I receive is:
PHP Fatal error: Call to undefined method
GuzzleHttp\Stream\Stream::addFile()
What is the mistake?
Thanks!

Ok finally I found the answer. Hope that helps someone.
To upload a file, the correct way is:
$fields = $table->getColumnsHash()[0]; //array('name' => 'test', 'surname' => 'test');
$fields["file"] = fopen($path, 'rb');
$this->client->request("POST", $url, array('Content-Type => multipart/form-data'), array(), array(), $fields);
The trick is that you must not use the fourth parameter of the Goutte request, but you have to pass all fields as body raw data.

I don't know about Guzzle upload but simple upload works like below. You can remove unnecessary bits.
Note: I would suggest you to keep dummy image files in project folder because if there are a lot of developers work on same project they would have exactly same folder structure so image would be accessible. I've seen some guys selecting an image from their desktop which differs from person to person so tests fail.
files_path below must point to your project directory and it should exist as e.g. /var/www/html/myproject/test/build/dummy/
behat.yml
default:
context:
class: Site\FrontendBundle\Features\Context\FeatureContext
parameters:
output_path: %behat.paths.base%/build/behat/output/
screen_shot_path: %behat.paths.base%/build/behat/screenshot/
extensions:
Behat\Symfony2Extension\Extension:
mink_driver: true
kernel:
env: test
debug: true
Behat\MinkExtension\Extension:
base_url: 'http://localhost/local/symfony/web/app_test.php/'
files_path: %behat.paths.base%/build/dummy/
javascript_session: selenium2
browser_name: firefox
goutte: ~
selenium2: ~
paths:
features: %behat.paths.base%/src
bootstrap: %behat.paths.features%/Context
Assuming that you have jpg.jpg under /var/www/html/myproject/test/build/dummy/ folder as below.
Example feature for upload:
Feature: Create League
In order to upload a file
As a user
I should be able to select and upload a file
#javascript
Scenario: I can create league
Given I am on "/"
When I attach the file "jpg.jpg" to "league_flag"
And I press "Submit"
Then I should see "Succeeded."

Related

WordPress - Verifying nonce with navigator.sendBeacon

I am working on a very simple tracking plugin. I am using the visibilitychange event to send tracking data to a PHP script included in the plugin using navigator.sendBeacon.
However, unlike a simple WordPress AJAX request, the PHP file doesn't have access to any of the WordPress core files. Therefore the check_ajax_referer function throws an error.
I can't figure out a way of ensuring the PHP file has access to the WordPress core files, or even any of the files I have included in the plugin.
Is it possible to set this up like is normally done with WP and AJAX, or do I need to include all of the WP core files in the PHP script? And, if the second option is the only option, which files do I need to include?
Example code:
Enqueuing the JS script and localizing the PHP script path and nonce:
wp_enqueue_script( $this->plugin_name, plugin_dir_url( __FILE__ ) . 'dist/scripts/main.js', array( 'jquery' ), $this->version, true );
wp_localize_script( $this->plugin_name, 'OBJECT_NAME', array('PHP_SCRIPT_PATH' => PATH, 'ajax_nonce' => wp_create_nonce('TRACKING_NONCE')));
Send the data
document.addEventListener("visibilitychange", function () {
if (document.visibilityState === 'hidden') {
var data = new FormData();
data.append('tracking_data', JSON.stringify(form_data));
navigator.sendBeacon(OBJECT_NAME.PHP_SCRIPT_PATH, data);
}
});
Receive and process the data:
if (!empty($_POST)) {
$security_check = check_ajax_referer( 'TRACKING_NONCE', 'security' ); //Error thrown: Uncaught Error: Call to undefined function check_ajax_referer()
//Process data....
}

Symfony validator translations

I just started using symfony validator and i really like it except translation part, currently it uses my own translator lib, but i found validator.LOCALE.xlf files where are translations for almost all languages stored, and i can't figure out how to use them.
My current validator registering code is
$container->register('validator', \Symfony\Component\Validator\Validator\ValidatorInterface::class)
->setFactory(
[
new Reference('validator.builder'),
'getValidator'
]
);
$container->register('validator.builder', \Symfony\Component\Validator\ValidatorBuilderInterface::class)
->setFactory(
[
\Symfony\Component\Validator\Validation::class,
'createValidatorBuilder'
]
)
->addMethodCall(
'setTranslator',
[
new Reference('translator') // Symfony translatorInterface
]
)
->addMethodCall(
'setTranslationDomain',
[
'messages'
]
);
It looks like i checked already whole validator structure, like RecursiveValidator, ContextualValidator, Contexts and etc, but just somewhere missing one single param, on another hand ConstraintViolationBuilder just simply takes passed translator and trying to translate constraint message through it, no attempts to use any xlf files.
Just force search through all validator library files gave no result too.
Symfony guilde didn't helped too, because it offers to use default error sentences as a translation key, and use this "keys" in your own translations files, but why copy already translated sentences to your own file, and also create a mess with keys pattern (for example i use snake case) when there is already structured files exists (i am talking about .xlf)?
Solution is to add xlf file loader to your translator, and pass it .xlf translations as a resource.
Something like that
$container->register('translator.xlf_file_loader', \Symfony\Component\Translation\Loader\XliffFileLoader::class);
$container->register('translator.php_file_loader', \Symfony\Component\Translation\Loader\PhpFileLoader::class);
$container->register('translator', \Project\Framework\Translation\Translator::class)
->addArgument(
new Reference('service_container')
)
->addMethodCall(
'addLoader',
[
'php',
new Reference('translator.php_file_loader')
]
)
->addMethodCall(
'addLoader',
[
'xlf',
new Reference('translator.xlf_file_loader')
]
)
->addMethodCall('addResource', ['php', __DIR__ . '/../translation/lt.php', 'lt'])
->addMethodCall('addResource', ['php', __DIR__ . '/../translation/en.php', 'en'])
->addMethodCall('addResource', ['php', __DIR__ . '/../translation/ru.php', 'ru'])
->addMethodCall('addResource', ['xlf', __DIR__ . '/../../vendor/symfony/validator/Resources/translations/validators.lt.xlf', 'lt'])
->addMethodCall(
'setFallbackLocales',
[
['lt']
]
);
Have you simply tried to either
change the locale in the app configuration:
# config/packages/translation.yaml
framework:
default_locale: 'en'
translator:
fallbacks: ['en']
Documentation
change the locale based on (user) input:
public function onKernelRequest(GetResponseEvent $event)
{
$request = $event->getRequest();
// some logic to determine the $locale
$request->setLocale($locale);
}
Documentation

Open pdf from server path in Symfony3

I would like to open the pdf file in the window browser but I have "The file "\\servername\20\2016080.pdf" does not exist"
If I copy this path in a browser, it's work.
Edit: I have found in the logs
CRITICAL - Uncaught PHP Exception Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException: "The file "\\servername\20\2016080.pdf" does not exist" at C:\wamp64\www\his\vendor\symfony\symfony\src\Symfony\Component\HttpFoundation\File\File.php line 37
Thank you.
$response = new BinaryFileResponse($result = $ServerModel->getDocument($request-> get('id'));
$response->headers->set('Content-Type', 'application/pdf');
return $response;
If you're using symfony 3.2 or later (which you should be), you can use the new file helper to serve binary files.
from the symfony docs
$pdfPath = $this->getParameter('dir.downloads').'/sample.pdf';
return $this->file($pdfPath);
how you go about getting the path of the file may differ depending on your implementation. But if its a straight SplFileInfo:: object php docs then you can just use:
$file->getPathname();
The file helper will automagically do much of heavy lifting for you.
Make sure the file is accessible, either by a route or by an un-firewalled path.
/**
* #Route("/show-pdf", name="show-pdf")
*/
public function showPdf(Request $request) {
ini_set('display_errors', 'On');
$pdf = file_get_contents('path/to/file.pdf');
return new Response($pdf, 200, [
'Content-Type' => 'application/pdf',
'Content-Disposition' => 'inline; filename="file.pdf"'
]);
}

laravel development environment sqlite database does not exist

Trying to use sqlite in development environment. It seems to detect the environment correctly but when I try to migrate to development.sqlite I get exception thrown "database does not exist"
artisan command
php artisan migrate --env=development
bootstrap/start.php
$env = $app->detectEnvironment(array(
'development' => array('localhost'),
));
app/config/development/database.php
<?php
return array(
'default' => 'sqlite',
'connections' => array(
'sqlite' => array(
'driver' => 'sqlite',
'database' => __DIR__.'/../database/development.sqlite',
'prefix' => '',
)
)
);
As far as I know laravel is supposed to create the file if it does not exist but since it didn't I tried manually creating the file and still get the exception thrown.
UPDATE: Maybe something not right with the env because the same thing happens if I try ':memory' for the database.
UPDATE 2: I tried running the sample unit test but add to TestCase.php
/**
* Default preparation for each test
*
*/
public function setUp()
{
parent::setUp(); // Don't forget this!
$this->prepareForTests();
}
/**
* Creates the application.
*
* #return Symfony\Component\HttpKernel\HttpKernelInterface
*/
public function createApplication()
{
$unitTesting = true;
$testEnvironment = 'testing';
return require __DIR__.'/../../bootstrap/start.php';
}
/**
* Migrates the database and set the mailer to 'pretend'.
* This will cause the tests to run quickly.
*
*/
private function prepareForTests()
{
Artisan::call('migrate');
Mail::pretend(true);
}
And this too gives the same exception though the testing env is already shipped with laravel. So I'll see if I can find any new issues on that.
Wow, typos and wrong paths.
Copying the sqlite array from config/database.php into config/development/database.php I forgot to change the path to the development.sqlite file from
__DIR__.'/../database/development.sqlite'
to
__DIR__.'/../../database/development.sqlite'
And for the in memory test it should have been
':memory:'
instead of
':memory'
I noticed that my database.php file had the following
'sqlite' => [
'driver' => 'sqlite',
'database' => env('DB_DATABASE', database_path('database.sqlite')),
'prefix' => '',
],
I changed it to read the following, and it worked just fine.
'sqlite' => [
'driver' => 'sqlite',
'database' => database_path('database.sqlite'),
'prefix' => '',
],
One of the problem which I faced was I use "touch storage/database.sqlite" in terminal, so database is created in Storage folder instead of database folder.
in my config/database.php path is database_path('database.sqlite')
'sqlite' => [
'driver' => 'sqlite',
'database' => database_path('database.sqlite'),
'prefix' => '',
],
than I use command "php artisan migrate" which gave me error "Database (/Applications/MAMP/htdocs/FOLDER_NAME/database/database.sqlite) does
not exist."
so it's obvious database file is not in database folder as It was generated in Storage folder, so copy "database.sqlite" from storage folder or run command "touch database/database.sqlite"
Hope that helps.!!
Well, my answer is kinda outdated, but anyway. I faced the same problem, but with Laravel 5, I am using Windows 7 x64. First I manually created SQLite database called 'db' and placed it into storage directory, then fixed my .env file like this:
APP_ENV=local
APP_DEBUG=true
APP_KEY=oBxQMkpqbENPb07bLccw6Xv7opAiG3Jp
DB_HOST=localhost
DB_DATABASE='db'
DB_USERNAME=''
DB_PASSWORD=''
CACHE_DRIVER=file
SESSION_DRIVER=file
QUEUE_DRIVER=sync
MAIL_DRIVER=smtp
MAIL_HOST=mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null`
I thought it would fix my problems, but the command line keeps telling me that database doesn't exist. And then I just checked the path to db in my database.php file and this is why I put database file into storage directory. But nothing changed. And finally I checked db's extension and it was .db, not .sqlite as default extension you see in your sqlite block in database.php. So this is how I reconfigured sqlite piece:
'sqlite' => [
'driver' => 'sqlite',
'database' => storage_path().'/db.db',
'prefix' => '',
],
And of course don't forget to set sqlite as default database in your database.php file. Good luck!
For me it was that path to database had to be '/var/www/html' + location to the database in your project. In my case database was stored in database/db.sqlite so DB_DATABASE='/var/www/html/database/db.sqlite'
I had the same error while running a GitHub action test workflow.
For me the solution was to define the relative path to the database archive into the workflow file:
on:
...
env:
DB_CONNECTION: sqlite
DB_DATABASE: database/database.sqlite
jobs:
laravel-tests:
...
I think that the previous answers reduce the importance of the config and most likely the developers wanted to get the database file like this:
'sqlite' => [
'driver' => 'sqlite',
'url' => env('DATABASE_URL'),
'database' => database_path(env('DB_DATABASE', 'database').'.sqlite'), // <- like this
'prefix' => '',
'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true),
],
Tested on Laravel 9.x

Must manually load PHP ActiveRecord models

I'm drawing a blank. I have code working locally (which is MAMP). When moving to a nginx ubuntu box (running php-fpm), for some reason, phpactiverecord is acting up.
I finally traced it down to this - All of my model classes, I have to load manually. If I add a require_once() underneath my code, then it works fine. If I don't, then I get errors like:
PHP Fatal Error: Class not found ... on the models I've created..
Does anyone have ANY idea what direction I could troubleshoot this in? I checked permissions to the models folder (which is not in the public root), echo'd out the path that is sent over to cfg->set_model_directory is correct, etc..
This sound like a nginx or php thing? I'm guessing nginx since this works on my MAMP?
Doesn't work:
ActiveRecord\Config::initialize(
function ($cfg) {
$cfg->set_model_directory(BASE_PATH . '/models');
$cfg->set_connections(
array(
'development' => 'mysql://blah:removed#localhost/com_dbname'
)
);
}
);
Works:
ActiveRecord\Config::initialize(
function ($cfg) {
$cfg->set_model_directory(BASE_PATH . '/models');
$cfg->set_connections(
array(
'development' => 'mysql://blah:removed#localhost/com_dbname'
)
);
}
);
require_once(BASE_PATH . '/models/model1.php');
require_once(BASE_PATH . '/models/model2.php');
Update
Adding in actual code to help identify issue:
require_once ('../lib/php-activerecord/ActiveRecord.php');
ActiveRecord\Config::initialize(
function ($cfg) {
$cfg->set_model_directory('/var/www/uc1/models');
$cfg->set_connections(
array(
'development' => 'mysql://test_usr:test_pwd#localhost/test_db'
)
);
}
);
require_once ('/var/www/uc1/models/ucurls.php'); //Name of model file. Must manually include to get this to work on my nginx server.
$_record = UCUrls::find_by_urlkey('example.com/123');
echo "urlkey=" . $_record->urlkey;
I solved this issue in windows adding a line in the file ActiveRecord.php,
in the function activerecord_autoload($class_name)
at the line 39 or 40
$file = "$root/$class_name.php";
//add this line
$file = strtolower($file);
Set trace in ActiveRecord.php too look where are ActiveRecord is searching for models.
But I think your issue is in filesystem - Mac OS X by default uses Case Insensitive filesystem, while Ubuntu's Case Sensitive filesystem.
So your model UCUrls should be in file /var/www/uc1/models/UCUrls.php, not in /var/www/uc1/models/ucurls.php

Resources