Add a header when sending a message with php-enqueue and RabbitMQ - symfony

I am trying to send a header using php-enqueue bundle
I'm trying this:
public function __construct(
ProducerInterface $producer
)
{
parent::__construct();
$this->producer = $producer;
}
//... Inside function...
$m = new Message(
'message to send',
[],
[
'm' => 1
]
);
$this->producer->sendCommand('newMessageFromApi', $m);
But the header does not reach the consumer.
These are the only headers that arrive.
[
"content_type" => "text/plain",
"delivery_mode" => 2,
"message_id" => "38f96af0-64de-4a31-9315-6b51dd5f8baf",
"timestamp" => 1652027271
]

Try this
$m = new Message('message to send',['m' => 1]);

Related

Running a report on a GA4 property using segments with google-analytics-api

I know that segments are not supported in the current v1Beta api (https://analyticsdata.googleapis.com/v1beta/properties/{property_id}:runReport).
Is there a workaround to get segmented data from using this api?
Reference: https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta/properties/runReport
I was working with google analytics API GA4 using PHP hope this helps you
<?php
class analytics{
private $property_id =null;
private $client = null;
public $propertys;
public function setPropertyId($propertyid)
{
return $this->property_id = $propertyid;
}
private function getCredentials()
{
return DIR.'PATH/credentials.json');
}
private function getClient(): BetaAnalyticsDataClient
{
return $this->client= new BetaAnalyticsDataClient([
'credentials' => $this->getCredentials(),
]);
}
public function get($propertyid,$startdate,$enddate,dimensions,$metrics)
{
$response = $this->getClient()->runReport([
'property' => 'properties/' . $this->setPropertyId($propertyid),
'dateRanges' => [
new DateRange([
'start_date' => $startdate,
'end_date' => $enddate,
]),
],
'dimensions' => [new Dimension(
[
'name' => $dimensions,
]
),
],
'metrics' => [new Metric(
[
'name' => $metrics,
]
)
]
]);
foreach ($response->getRows() as $row) {
return $row->getMetricValues()[0]->getValue();
}
}
}
then you can use the get function with dates range and dimensions metrics you want

How can I pass my UploadedFile data via http guzzle request?

I have two different website : my application and my backoffice (in Laravel)
I create an API route to store a document on my application. I made a request with Guzzle on my backoffice to store a document.
My guzzle http request on backoffice website :
public static function storeDocument($token, $request)
{
$client = new \GuzzleHttp\Client([
'Content-Type' => 'multipart/form-data'
]);
$headers = [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
];
$datas = [
'document' => $request->file('document'),
'doc_name' => $request->doc_name ?? '',
];
$request = $client->post(env('API_URL') . '/api/document/store/', ['headers' => $headers, 'form_params' => $datas]);
$result = json_decode($request->getBody()->getContents());
return $result;
}
And there is my API route method on application website :
public function store(Request $request) {
$validator = Validator::make($request->all(), [
'document' => 'bail|required|mimes:pdf,doc,docs,csv,txt|max:2048',
'doc_name' => 'bail|string|max:80|nullable',
]);
if($validator->fails()){
return response()->json($validator->errors());
};
$document = $request->document;
$fileName = '';
if(isset($request->doc_name)) {
$fileName = $request->doc_name . '.' . $document->extension();
} else {
$fileName = $document->getClientOriginalName();
}
$result = Storage::putFileAs(
'documentations',
$document,
$fileName,
'public'
);
if($result) {
return response()->json(['success' => 'Le fichier a bien été enregistré'], 201);
} else {
return response()->json(['error' => $errors], 400);
};
}
It seems that my datas aren't sent correctly because storeDocument() gives me an error : 'This field is required'. So it looks like it can't find $request->document which is required...
And with Insomnia I have no error, my file is correctly save.
I want to specify that I pass correct datas to storeDocument.
That is the result of $request->file('document') :
Illuminate\Http\UploadedFile {#1354 ▼
-test: false
-originalName: "test.pdf"
-mimeType: "application/pdf"
-error: 0
#hashName: null
path: "/tmp"
filename: "phpPOxtfN"
basename: "phpPOxtfN"
pathname: "/tmp/phpPOxtfN"
extension: ""
realPath: "/tmp/phpPOxtfN"
aTime: 2022-08-25 14:30:14
mTime: 2022-08-25 14:30:13
cTime: 2022-08-25 14:30:13
inode: 4856076
size: 48632
perms: 0100600
owner: 33
group: 33
type: "file"
writable: true
readable: true
executable: false
file: true
dir: false
link: false
}
I'm stuck since several hours on this, does anyone has any idea to help me?
Thanks ;)
EDIT: I finally found that I have to pass 'multipart' instead of 'form_params' on my http request.
Moreover I found that I have to use fopen or file_get_contents to send raw datas...
So my storeDocument function looks like this now :
public static function storeDocument($token, $request)
{
$client = new \GuzzleHttp\Client([
'Content-Type' => 'multipart/form-data'
]);
$headers = [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
];
$datas = [
[
'name' => 'document',
'contents' => file_get_contents($request->file('document')),
],
[
'name' => 'doc_name',
'contents' => $request->doc_name ?? '',
]
];
$request = $client->post(env('API_URL') . '/api/document/store/', ['headers' => $headers, 'multipart' => $datas]);
$result = json_decode($request->getBody()->getContents());
return $result;
}
But it still doesn't work...
Continue searching...

How can I Unit Test GraphQL file Upload with API Platform?

In addition to my other tests against my GraphQL API Platform backend, I am attempting to test file uploads. I'm not quite sure whether the ApiPlatform\Core\Bridge\Symfony\Bundle\Test\Client class has the ability to facilitate this test, or if Symfony\Component\HttpFoundation\File\UploadedFile should be used to provide the test file as it is for a REST operation.
Here is roughly where I am at in terms of putting together this test. (With some irrelevant parts removed for simplification)
public function testCreateMediaObject(): void {
$file = new UploadedFile('fixtures/files/logo.png', 'logo.png');
$client = self::createClient();
$gql = <<<GQL
mutation UploadMediaObject(\$file: Upload!) {
uploadMediaObject(input: {file: \$file}) {
mediaObject {
id
contentUrl
}
}
}
GQL;
$response = $client->request('POST', '/api/graphql', [
'headers' => ['Content-Type' => 'application/json'],
'json' => [
'query' => $gql,
'variables' => ["file" => null],
'map' => ['0' => ['variables.file']],
'0' => $file,
]
]);
dd($response);
}
The response I get seems to indicate that the file isn't being included as expected. Something like...
Variable "$file" of non-null type "Upload!" must not be null.
Or.. if I try to attach the file by simply assigning it directly in the variables property...
$response = $client->request('POST', '/api/graphql', [
'headers' => ['Content-Type' => 'application/json'],
'json' => [
'query' => $gql,
'variables' => ["file" => $file],
]
]);
then...
Variable "$file" got invalid value []; Expected type Upload; Could not get uploaded file, be sure to conform to GraphQL multipart request specification. Instead got: []
In my most recent attempt, I changed things up quite a bit after sifting through the graphql code...
$formFields = [
'operations' => '{ "query": "mutation ($file: Upload!) { uploadMediaObject(input: {file: $file}) { mediaObject { id contentUrl } } }", "variables": { "file": null } }',
'map' => "{'0': ['variables.file']}",
'0' => DataPart::fromPath(__DIR__.'/../../fixtures/files/logo.png'),
];
$formData = new FormDataPart($formFields);
$response = $client->request('POST', '/api/graphql', [
'headers' => $formData->getPreparedHeaders()->toArray(),
'body' => $formData->bodyToString(),
]);
The problem with this last attempt is that the server isn't seeing any body parameters. So I receiving the exception
'GraphQL multipart request does not respect the specification.'
Which is found in /api-platform/core/src/GraphQl/Action/EntrypointAction.php within the parseMultipartRequest method.
After a few hours of debugging I found this solution:
$formData = new FormDataPart();
$file = new UploadedFile('src/DataFixtures/files/test.txt', 'test.txt');
$response = $this->$client->request('POST', 'api/graphql', [
'headers' => $formData->getPreparedHeaders()->toArray(),
'extra' => [
'parameters' => [
'operations' => '{ "query": "mutation UploadMediaObject($file: Upload!) { uploadMediaObject(input: {file: $file}) { mediaObject { id contentUrl } } }", "variables": { "file": null } }',
'map' => '{ "0": ["variables.file"] }',
'0' => #$file,
],
'files' => [
$file,
],
],
]);
Refrence:
https://github.com/jaydenseric/graphql-multipart-request-spec
https://api-platform.com/docs/core/graphql/

How to document custom POST Action in API Platform through Swagger Decorator?

In the docs there is this example, but it shows only how to add one GET operation.
I would like to know how can I add a custom POST route to the documentation.
I am having trouble to show the example body request, with the expected values to be sent (username and email, in this example)
My attempt
<?php
// api/src/Swagger/SwaggerDecorator.php
namespace App\Swagger;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
final class SwaggerDecorator implements NormalizerInterface
{
private $decorated;
public function __construct(NormalizerInterface $decorated)
{
$this->decorated = $decorated;
}
public function normalize($object, $format = null, array $context = [])
{
$docs = $this->decorated->normalize($object, $format, $context);
$customDefinition = [
'tags' => [
'default'
],
'name' => 'fields',
'description' => 'Testing decorator',
'default' => 'id',
'in' => 'query',
'requestBody' =>
[
'content' => [
'application/json' => [
'schema' => [
'description' => 'abcd',
'required' => [
'username', 'email'
],
'properties' => [
'username', 'email'
],
]
]
],
'description' => 'testing'
],
];
$docs['paths']['/testing']['post']['parameters'][] = $customDefinition;
return $docs;
}
public function supportsNormalization($data, $format = null)
{
return $this->decorated->supportsNormalization($data, $format);
}
}
But it doesn't work.
you should not put the whole route declaration inside the parameters array, you should create smth like this:
$docs['paths']['/testing']['post'] = $customDefinition;

PHP Unit Test for Function having call to another function using $this Keyword

In PHP i have function like this in which it has a call to another function searchDateOperator() with in the same class using $this keyword. How to write a Unit test for this?
public static function segmetDateRangeFilter($searchField, $startDate, $endDate, $dateRange)
{
$filter = [];
if ($startDate && !$endDate) {
$filter = [
'range' => [
$this->searchDateOperator($searchField) => [
'gte' => strtotime($startDate),
]
]
];
}
if ($endDate && !$startDate) {
$filter = [
'range' => [
$this->searchDateOperator($searchField) => [
'lte' => strtotime($endDate)
]
]
];
}
if ($startDate && $endDate) {
$filter = [
'range' => [
$this->searchDateOperator($searchField) => [
'gte' => strtotime($startDate),
'lte' => strtotime($endDate)
]
]
];
}
if ($dateRange !== '') {
// $endTime upto current Time
$endTime = Carbon::now()->timestamp;
// Start Time . substract the date range days. and in timestamp
$startTime = Carbon::now()->subDays($dateRange)->timestamp;
$filter = [
'range' => [
$this->searchDateOperator($searchField) => [
'gte' => $startTime,
'lte' => $endTime
]
]
];
}
if ($filter) {
return $filter;
}
}
Your problem is that the method is declared static but you are using $this. If the method you are calling is static as well you should use self or static, like this:
$filter = [
'range' => [
self::searchDateOperator($searchField) => [
'gte' => $startTime,
'lte' => $endTime
]
]
];
Alternatively you could remove static from segmetDateRangeFilter and use it in a test like this:
public function testSomething()
{
$filterFactory = new DateFilterFactory();
// ...
$result = $filterFactory->segmetDateRangeFilter(...);
// Assertions against result
}
The class name DateFilterFactory you have to replace with whatever you use.

Resources