Trying to retrieve file from request with Silex/Symfony2 - symfony

I'm retrieving a POSTed file with:
$this->app->post(Extension::API_PREFIX . "profile/picture", array($this, 'post_profile_pic'))
->bind('post_profile_pic');
public function post_profile_pic(Request $request) {
$response = $this->app->json(array(
'file' => $request
));
return $response;
}
I'm using Postman to upload the file (see screenshot), but the request is empty:
{
"file": {
"attributes": { },
"request": { },
"query": { },
"server": { },
"files": { },
"cookies": { },
"headers": { }
}
}
Yet it obviously knows that there should be a file there. So how do I access the file?

Uploaded files in PHP are not sent with $_POST but in a separate variable called $_FILES ( http://php.net/manual/en/features.file-upload.post-method.php ) - so in your case you should take a look at
$this->app->files
If you use the default form components from symfony the documentation is at http://symfony.com/doc/current/reference/forms/types/file.html#basic-usage
In the simpleforms module files are retrieved by the lines following
$files = $this->app['request']->files->get($form->getName());
Which is using the basic structure that the Bolt, Silex and Symfony components provide.
(See also https://github.com/jadwigo/SimpleForms/blob/master/Extension.php#L505)

Related

Nested pages in Hygraph (GraphCMS) with Nextjs dynamic routing

I am trying to create nested pages using Hygraph (GraphCMS) and Nextjs. I thought about using [..slug].js
But the problem I have is that writing my slug-like this "page/subpage" the GraphCMS returns the following structure which is not an array or nested
{
"data": {
"pages": [
{
"slug": "page/subpage"
}
]
}
}
And if I try to get static paths Nextjs simply will find nothing at page/subpage, it will always be 400 not found because it is a string and only will work as http://localhost:3000/page%2Fsubpage
Does anyone know how to create subpages in GraphCMS (Hygraph)? Really need your help.
Right now I have the following code to get static paths
export async function getStaticPaths() {
const client = graphcmsClient()
const { pages } = await client.request(`
query {
pages(where: {slug_not_in: ["home"]}) {
slug
}
}
`)
return {
paths: pages.map(({ slug }) => ({
params: { slug },
})),
fallback: false
}
}

Spring Cloud Contract with multiple requestparts

I'm trying to write a contract to test the following providers endpoint
#PostMapping(value = "/api/{id}/addFiles", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
ResponseEntity<Void> addFiles(#PathVariable(value = "id") String id, #RequestPart("name") String name, #RequestPart("test") String test, #RequestPart("files") MultiPartFile[] files)
I'm struggling to write a contract that works with multiple RequestParts such as this. If I change the two String RequestParts to RequestParams I can get the test to pass with the following contract:
Contract.make {
description "Add Files"
request {
urlPath("/api/idString/addFiles") {
queryParameters {
parameter 'name': value(consumer(regex(nonEmpty())), producer('name'))
parameter 'test': value(consumer(regex(nonEmpty())), producer('test'))
}
}
method POST()
headers {
contentType multipartFormData()
}
multipart(
files: named(
name: value(consumer(regex(nonEmpty())), producer('fileName')),
content: value(consumer(regex(nonEmpty())), producer('fileContent'))
)
)
}
response {
status ACCEPTED()
}
}
But is there a way of writing this contract whilst keeping everything as RequestParts? Nothing I've tried so far has come close to working!
Answering my own question since I realised the small error I had been making. The following contract appears to work, I had tried something similar but had not included the square brackets inside the multipart:
Contract.make {
description "Add Files"
request {
urlPath("/api/idString/addFiles")
method POST()
headers {
contentType multipartFormData()
}
multipart([
name: named(
name: value(consumer(regex(nonEmpty())), producer('name')),
content: value(consumer(regex(nonEmpty())), producer('name'))
),
test: named(
name: value(consumer(regex(nonEmpty())), producer('test')),
content: value(consumer(regex(nonEmpty())), producer('testName'))
),
files: named(
name: value(consumer(regex(nonEmpty())), producer('fileName')),
content: value(consumer(regex(nonEmpty())), producer('fileContent'))
)
])
}
response {
status ACCEPTED()
}
}

Uncaught (in promise) Error: Missing host permission for the tab

I have declared <all_urls> permission inside my manifest.json file and I'm using the tabs.insertCSS() to inject some css code inside a page when needed. I'm facing the error Uncaught (in promise) Error: Missing host permission for the tab in firefox extension debugger, how I can fix?
{
"manifest_version": 2,
"name": "myExtension",
"description": "",
"default_locale": "en",
"permissions": [
"<all_urls>",
"tabs",
"activeTab",
"contextMenus",
"notifications",
"webRequest",
"webRequestBlocking"
],
"icons": {
"16": "icons/16.png",
"48": "icons/48.png",
"128": "icons/128.png"
},
"background": {
"scripts": [
"js/background.js"
],
"persistent": true
}
}
background:
const checkRequest = (details) => {
console.log(details)
var blocked = ["https://www.example.com/", "https://www.example2.com/"]
var isBlocked = blocked.includes(details.url)
console.log(isBlocked)
return { cancel: isBlocked }
}
const redirectAfterBlock = (details) => {
console.log(details)
if( details.error == "NS_ERROR_ABORT" ){
browser.tabs.insertCSS({
file: browser.runtime.getURL('content-replace.css')
})
console.log("blocked")
}
}
browser.webRequest.onBeforeRequest.addListener(
checkRequest,
{
urls: ["<all_urls>"],
types: ["main_frame"]
},["blocking"])
browser.webRequest.onErrorOccurred.addListener(
redirectAfterBlock,
{
urls: ["<all_urls>"]
})
Looks like I fixed it by inserting my CSS in webRequest.onCompleted instead of onBeforeRequest:
browser.webRequest.onCompleted.addListener(
function (details) {
extensionApi.tabs
.insertCSS(
details.tabId,
{ file: "content.css" }
)
},
{ urls: ["<all_urls>"] }
);
Downside is there's a flash of unstyled page.

Using Gatsby `createResolvers` to set default image if GraphQL returns null?

I'm working on a gatsby site using gatsby-source-wordpress to source posts for the blog. However, if any of the WordPress posts do not include a featured image this causes the build to fail. I understand that this is expected behavior.
Here is the build error I am seeing:
29 | {posts.map(({ node: post }, index) => (
30 | <li key={post.id} {...post}>
> 31 | <Img fixed={post.featured_media.localFile.childImageSharp.fixed} />
| ^
32 | <p>
33 | <Link to={`/insights/${post.slug}`}>
34 | {post.title}
WebpackError: TypeError: Cannot read property 'localFile' of null
This is caused by the resulting query, which is returning a null result in the second node because there is no featured image on the post:
{
"data": {
"allWordpressPost": {
"edges": [
{
"node": {
"id": "28ec9054-5b05-5f94-adcb-dcbfc14659b1",
"featured_media": {
"id": "f12d613b-e544-560b-a86f-cd0a7f87801e",
"localFile": {
"id": "7fca2893-ff80-5270-9765-d17d3dc21ac2",
"url": "https://www.mycustomdomain.com/wp-content/uploads/2020/01/some-featured-image.jpg"
}
}
}
},
{
"node": {
"id": "91a236ed-39d5-5efc-8bed-290d8344b660",
"featured_media": null
}
}
]
}
}
}
How I would like to fix:
As an ideal solution, I would like to use schema customization to set a default image if there is no featured image in WordPress. But I am at a total loss how to correctly do so. I am working from this documentation to guide me, but I'm just not getting my head wrapped around it properly.
A similar working example:
Tag data is similar to featured images in that the query returns null if the post has no tags. However I am able to set a default undefined tag using createResolvers like so:
exports.createResolvers = ({ createResolvers }) => {
const resolvers = {
wordpress__POST: {
tags: {
resolve(source, args, context, info) {
const { tags } = source
if (tags === null || (Array.isArray(tags) && !tags.length)) {
return [
{
id: 'undefined',
name: 'undefined',
slug: 'undefined',
}
]
} else {
return info.originalResolver(source, args, context, info)
}
},
},
},
}
createResolvers(resolvers)
}
And this works as shown in the following query results:
{
"data": {
"allWordpressPost": {
"edges": [
{
"node": {
"id": "28ec9054-5b05-5f94-adcb-dcbfc14659b1",
"tags": [
{
"id": "undefined"
}
]
}
},
{
"node": {
"id": "91a236ed-39d5-5efc-8bed-290d8344b660",
"tags": [
{
"id": "50449e18-bef7-566a-a3eb-9f7990084afb"
},
{
"id": "8635ff58-2997-510a-9eea-fe2b88f30781"
},
{
"id": "97029bee-4dec-5198-95af-8464393f71e3"
}
]
}
}
]
}
}
}
What I tried for images (isn't working...)
When it comes to nested nodes and image files I'm at a total loss. I am heading in the following direction based on this article and this code example, but so far it isn't working:
exports.createResolvers = ({
actions,
cache,
createNodeId,
createResolvers,
store,
reporter,
}) => {
const { createNode } = actions
const resolvers = {
wordpress__POST: {
featured_media: {
type: `File`,
resolve(source, args, context, info) {
return createRemoteFileNode({
url: 'https://www.mycustomdomain.com/wp-content/uploads/2017/05/placeholder.png',
store,
cache,
createNode,
createNodeId,
reporter,
})
},
},
},
}
createResolvers(resolvers)
}
I realize the above code does not have an if else statement, so the expectation is that all featured images would be replaced by the placeholder image. However the resulting GraphQL query is unaffected (as shown at top).
Can anyone point me in the right direction here? I can't seem to wrap my head around what information I can find out there.
WebpackError: TypeError: Cannot read property 'localFile' of null
'localFile' of null means that nulled is a parent of localfile - featured_media ... you can see that in results:
"featured_media": null
... so you're trying to fix localfile while you should work on featured_media level
why?
You can easily render conditionally [in react] what you need (placeholde, component) on nulled nodes ... why at all you're trying to fix graphql response?

Duplicate default WP REST API (v2) endpoints

How can i duplicate default wp rest api V2 endpoints? I would like to keep default endpoints and routs intact, but would like to use simplified responses for my application.
Wordpress v4.7
My code for now:
function register_custom_routes()
{
$controller = new MY_REST_Posts_Controller;
$controller->register_routes();
}
add_action( 'rest_api_init', 'register_custom_routes', 1 );
class MY_REST_Posts_Controller extends WP_REST_Controller {
// this is a copy of default class WP_REST_Posts_Controller
}
Calling http://localhost/wp/wp-json/ list my namespace ( /myrest ), also
http://localhost/wp/wp-json/myrest/gives me:
{
"namespace": "myrest",
"routes": {
"/myrest": {
"namespace": "myrest",
"methods": [
"GET"
],
...
"/myrest/(?P<id>[\\d]+)": {
"namespace": "myrest",
"methods": [
"GET",
"POST",
"PUT",
"PATCH",
"DELETE"
],
...
}
but when i try to list posts with http://localhost/wp/wp-json/myrest/posts (like with default api route call) it does not work:
{
"code": "rest_no_route",
"message": "No route was found matching the URL and request method",
"data": {
"status": 404
}
}
I need simplified version of get posts response for android app but also want to keep default rest endpoints and routs as is.
Here is the solution. I've wrapped code in wp plugin.
class WP_REST_custom_controller extends WP_REST_Controller {
// this is a copy of default class WP_REST_Posts_Controller
// Edited constructor for cutom namespace and endpoint url
/**
* Constructor.
*
* #since 4.7.0
* #access public
*
* #param string $post_type Post type.
*/
public function __construct() {
$this->post_type = 'post';
$this->namespace = 'custom_namespace/v1';
$obj = get_post_type_object( $post_type );
$this->rest_base = ! empty( $obj->rest_base ) ? $obj->rest_base : $obj->name;
$this->resource_name = 'posts';
$this->meta = new WP_REST_Post_Meta_Fields( $this->post_type );
}
// this is a copy of default class WP_REST_Posts_Controller with necessary edits
}
// Function to register our new routes from the controller.
function register_custom_rest_routes() {
$controller = new WP_REST_custom_controller();
$controller->register_routes();
}
add_action( 'rest_api_init', 'register_custom_rest_routes');

Resources