-
Notifications
You must be signed in to change notification settings - Fork 441
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature/#17 Adding mediaItem mutations. #189
Changes from 25 commits
9fc2256
51e81be
06a6cfa
c717e11
ee7ab0e
4a4f57f
dfed277
c03dbff
f48b55d
6a1fd48
2cf1b04
6c84219
e4c1471
aba78fa
605ed38
0cd6beb
7a5b928
598668c
424dc47
e703053
7e4aba7
fbba5fb
989c1de
c08d852
6110808
8351a52
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
<?php | ||
|
||
namespace WPGraphQL\Type\Enum; | ||
|
||
use WPGraphQL\Type\WPEnumType; | ||
|
||
/** | ||
* Class MediaItemStatusEnumType | ||
* | ||
* This defines an EnumType with allowed post stati for attachments in WordPress. | ||
* Attachments do not have the same status capabilities as other post types, see here | ||
* for reference: https://github.com/WordPress/WordPress/blob/master/wp-includes/post.php#L3072 | ||
* | ||
* @package WPGraphQL\Type\Enum | ||
*/ | ||
class MediaItemStatusEnumType extends WPEnumType { | ||
|
||
/** | ||
* This holds the enum values array | ||
* | ||
* @var array $values | ||
*/ | ||
private static $values; | ||
|
||
public function __construct() { | ||
$config = [ | ||
'name' => 'mediaItemStatus', | ||
'description' => __( 'The status of the media item object.', 'wp-graphql' ), | ||
'values' => self::values(), | ||
]; | ||
parent::__construct( $config ); | ||
} | ||
|
||
/** | ||
* values | ||
* Creates a list of post_stati that can be used to query by. | ||
* | ||
* @return array | ||
*/ | ||
private static function values() { | ||
|
||
/** | ||
* Set the default, if no values are built dynamically | ||
* | ||
*/ | ||
self::$values = [ | ||
'name' => 'inherit', | ||
'value' => 'inherit', | ||
]; | ||
|
||
/** | ||
* Get the dynamic list of post_stati | ||
*/ | ||
$post_stati = [ | ||
'inherit', | ||
'private', | ||
'trash', | ||
'auto-draft', | ||
]; | ||
|
||
/** | ||
* If there are $post_stati, create the $values based on them | ||
*/ | ||
if ( ! empty( $post_stati ) && is_array( $post_stati ) ) { | ||
/** | ||
* Reset the array | ||
*/ | ||
self::$values = []; | ||
/** | ||
* Loop through the post_stati | ||
*/ | ||
foreach ( $post_stati as $status ) { | ||
self::$values[ $status ] = [ | ||
'name' => strtoupper( preg_replace( '/[^A-Za-z0-9]/i', '_', $status ) ), | ||
'description' => sprintf( __( 'Objects with the %1$s status', 'wp-graphql' ), $status ), | ||
'value' => $status, | ||
]; | ||
} | ||
} | ||
|
||
/** | ||
* Return the $values | ||
*/ | ||
return self::$values; | ||
|
||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,221 @@ | ||
<?php | ||
|
||
namespace WPGraphQL\Type\MediaItem\Mutation; | ||
|
||
use GraphQLRelay\Relay; | ||
use WPGraphQL\Types; | ||
|
||
/** | ||
* Class MediaItemCreate | ||
* | ||
* @package WPGraphQL\Type\MediaItem\Mutation | ||
*/ | ||
class MediaItemCreate { | ||
|
||
/** | ||
* Holds the mutation field definition | ||
* | ||
* @var array mutation | ||
*/ | ||
private static $mutation = []; | ||
|
||
/** | ||
* Defines the create mutation for MediaItems | ||
* | ||
* @var \WP_Post_Type $post_type_object | ||
* | ||
* @return array|mixed | ||
*/ | ||
public static function mutate( \WP_Post_Type $post_type_object ) { | ||
|
||
/** | ||
* Set the name of the mutation being performed | ||
*/ | ||
$mutation_name = 'createMediaItem'; | ||
|
||
self::$mutation['mediaItem'] = Relay::mutationWithClientMutationId( [ | ||
'name' => esc_html( $mutation_name ), | ||
'description' => __( 'Create mediaItems', 'wp-graphql' ), | ||
'inputFields' => self::input_fields( $post_type_object ), | ||
'outputFields' => [ | ||
'mediaItem' => [ | ||
'type' => Types::post_object( $post_type_object->name ), | ||
'resolve' => function( $payload ) { | ||
return get_post( $payload['id'] ); | ||
}, | ||
], | ||
], | ||
'mutateAndGetPayload' => function( $input ) use ( $post_type_object, $mutation_name ) { | ||
|
||
/** | ||
* Stop now if a user isn't allowed to upload a mediaItem | ||
*/ | ||
if ( ! current_user_can( 'upload_files' ) ) { | ||
throw new \Exception( __( 'Sorry, you are not allowed to upload mediaItems', 'wp-graphql' ) ); | ||
} | ||
|
||
/** | ||
* If the mediaItem being created is being assigned to another user that's not the current user, make sure | ||
* the current user has permission to edit others mediaItems | ||
*/ | ||
if ( ! empty( $input['authorId'] ) && get_current_user_id() !== $input['authorId'] && ! current_user_can( $post_type_object->cap->edit_others_posts ) ) { | ||
throw new \Exception( __( 'Sorry, you are not allowed to create mediaItems as this user', 'wp-graphql' ) ); | ||
} | ||
|
||
/** | ||
* Set the file name, whether it's a local file or from a URL. | ||
* Then set the url for the uploaded file | ||
*/ | ||
$file_name = basename( $input['filePath'] ); | ||
$uploaded_file_url = $input['filePath']; | ||
|
||
/** | ||
* Require the file.php file from wp-admin. This file includes the | ||
* download_url and wp_handle_sideload methods | ||
*/ | ||
require_once( ABSPATH . 'wp-admin/includes/file.php' ); | ||
|
||
/** | ||
* If the mediaItem file is from a local server, use wp_upload_bits before saving it to the uploads folder | ||
*/ | ||
if ( 'file' === parse_url( $input['filePath'], PHP_URL_SCHEME) ) { | ||
$uploaded_file = wp_upload_bits( $file_name, null, file_get_contents( $input['filePath'] ) ); | ||
$uploaded_file_url = $uploaded_file['url']; | ||
} | ||
|
||
/** | ||
* URL data for the mediaItem, timeout value is the default, see: | ||
* https://developer.wordpress.org/reference/functions/download_url/ | ||
*/ | ||
$timeout_seconds = 300; | ||
$temp_file = download_url( $uploaded_file_url, $timeout_seconds ); | ||
/** | ||
* Handle the error from download_url if it occurs | ||
*/ | ||
if ( is_wp_error( $temp_file ) ) { | ||
throw new \Exception( __( 'Sorry, the URL for this file is invalid, it must be a valid URL', 'wp-graphql' ) ); | ||
} | ||
|
||
/** | ||
* Build the file data for side loading | ||
*/ | ||
$file_data = [ | ||
'name' => $file_name, | ||
'type' => $input['fileType'], | ||
'tmp_name' => $temp_file, | ||
'error' => 0, | ||
'size' => filesize( $temp_file ), | ||
]; | ||
|
||
/** | ||
* Tells WordPress to not look for the POST form fields that would normally be present as | ||
* we downloaded the file from a remote server, so there will be no form fields | ||
* The default is true | ||
*/ | ||
$overrides = [ | ||
'test_form' => false, | ||
]; | ||
|
||
/** | ||
* Insert the mediaItem and retrieve it's data | ||
*/ | ||
$file = wp_handle_sideload( $file_data, $overrides ); | ||
/** | ||
* Handle the error from wp_handle_sideload if it occurs | ||
*/ | ||
if ( ! empty( $file['error'] ) ) { | ||
throw new \Exception( __( 'Sorry, the URL for this file is invalid, it must be a path to the mediaItem file', 'wp-graphql' ) ); | ||
} | ||
|
||
/** | ||
* Insert the mediaItem object and get the ID | ||
*/ | ||
$media_item_args = MediaItemMutation::prepare_media_item( $input, $post_type_object, $mutation_name, $file ); | ||
|
||
/** | ||
* Get the post parent and if it's not set, set it to false | ||
*/ | ||
$attachment_parent_id = ( ! empty( $media_item_args['post_parent'] ) ? $media_item_args['post_parent'] : false ); | ||
|
||
/** | ||
* Stop now if a user isn't allowed to edit the parent post | ||
*/ | ||
// Attaching media to a post requires ability to edit said post. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the mixed use of comment styles here is weird, and the second one is maybe slightly misplaced? |
||
$parent = get_post( $attachment_parent_id ); | ||
|
||
if ( null !== get_post( $attachment_parent_id ) ) { | ||
$post_parent_type = get_post_type_object( $parent->post_type ); | ||
if ( ! current_user_can( $post_parent_type->cap->edit_post, $attachment_parent_id ) ) { | ||
throw new \Exception( __( 'Sorry, you are not allowed to upload mediaItems to this post', 'wp-graphql' ) ); | ||
} | ||
} | ||
|
||
/** | ||
* Insert the mediaItem | ||
*/ | ||
$attachment_id = wp_insert_attachment( $media_item_args, $file['file'], $attachment_parent_id ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. line break |
||
/** | ||
* Handle the error from wp_insert_attachment if it occurs | ||
*/ | ||
if ( 0 === $attachment_id ) { | ||
throw new \Exception( __( 'Sorry, the mediaItem failed to create', 'wp-graphql' ) ); | ||
} | ||
|
||
/** | ||
* Check if the wp_generate_attachment_metadata method exists and include it if not | ||
*/ | ||
require_once( ABSPATH . 'wp-admin/includes/image.php' ); | ||
|
||
/** | ||
* Generate and update the mediaItem's metadata | ||
*/ | ||
$attachment_data = wp_generate_attachment_metadata( $attachment_id, $file['file'] ); | ||
$attachment_data_update = wp_update_attachment_metadata( $attachment_id, $attachment_data ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. line break |
||
/** | ||
* Handle the error from wp_update_attachment_metadata if it occurs | ||
*/ | ||
if ( false === $attachment_data_update ) { | ||
throw new \Exception( __( 'Sorry, the mediaItem metadata failed to update', 'wp-graphql' ) ); | ||
} | ||
|
||
/** | ||
* Update alt text postmeta for mediaItem | ||
*/ | ||
MediaItemMutation::update_additional_media_item_data( $attachment_id, $input, $post_type_object, $mutation_name ); | ||
|
||
return [ | ||
'id' => $attachment_id, | ||
]; | ||
|
||
}, | ||
|
||
] ); | ||
|
||
return ! empty( self::$mutation['mediaItem'] ) ? self::$mutation['mediaItem'] : null; | ||
} | ||
|
||
/** | ||
* Add the filePath as a nonNull field for create mutations as its required | ||
* to create a media item | ||
* | ||
* @param \WP_Post_Type $post_type_object | ||
* | ||
* @return array | ||
*/ | ||
private static function input_fields( $post_type_object ) { | ||
|
||
/** | ||
* Update mutations require an filePath to be passed | ||
*/ | ||
return array_merge( | ||
[ | ||
'filePath' => [ | ||
'type' => Types::non_null( Types::string() ), | ||
'description' => __( 'The URL or file path to the mediaItem', 'wp-graphql' ), | ||
], | ||
], | ||
MediaItemMutation::input_fields( $post_type_object ) | ||
); | ||
|
||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not a big deal, but I'd prefer a line break between this and the next code comment block