Search
Search
Search
Search
Information
Information
Light
Dark
Open actions menu
Basic upload method
Bypass upload method
Tips!
If you encounter an error (by firewall) while uploading using both methods,
try changing extension of the file before uploading it and rename it right after.
This uploader supports multiple file upload.
Submit
~
var
www
nea-dev.wpress.dk
httpdocs
wp-content
plugins
wp-graphql
src
Mutation
File Content:
PostObjectCreate.php
<?php namespace WPGraphQL\Mutation; use GraphQL\Error\UserError; use GraphQL\Type\Definition\ResolveInfo; use WPGraphQL\AppContext; use WPGraphQL\Data\PostObjectMutation; use WPGraphQL\Utils\Utils; use WP_Post_Type; /** * Class PostObjectCreate * * @package WPGraphQL\Mutation */ class PostObjectCreate { /** * Registers the PostObjectCreate mutation. * * @param \WP_Post_Type $post_type_object The post type of the mutation. * * @return void */ public static function register_mutation( WP_Post_Type $post_type_object ) { $mutation_name = 'create' . ucwords( $post_type_object->graphql_single_name ); register_graphql_mutation( $mutation_name, [ 'inputFields' => self::get_input_fields( $post_type_object ), 'outputFields' => self::get_output_fields( $post_type_object ), 'mutateAndGetPayload' => self::mutate_and_get_payload( $post_type_object, $mutation_name ), ] ); } /** * Defines the mutation input field configuration. * * @param \WP_Post_Type $post_type_object The post type of the mutation. * * @return array<string,array<string,mixed>> */ public static function get_input_fields( $post_type_object ) { $fields = [ 'date' => [ 'type' => 'String', 'description' => static function () { return __( 'The date of the object. Preferable to enter as year/month/day (e.g. 01/31/2017) as it will rearrange date as fit if it is not specified. Incomplete dates may have unintended results for example, "2017" as the input will use current date with timestamp 20:17 ', 'wp-graphql' ); }, ], 'menuOrder' => [ 'type' => 'Int', 'description' => static function () { return __( 'A field used for ordering posts. This is typically used with nav menu items or for special ordering of hierarchical content types.', 'wp-graphql' ); }, ], 'password' => [ 'type' => 'String', 'description' => static function () { return __( 'The password used to protect the content of the object', 'wp-graphql' ); }, ], 'slug' => [ 'type' => 'String', 'description' => static function () { return __( 'The slug of the object', 'wp-graphql' ); }, ], 'status' => [ 'type' => 'PostStatusEnum', 'description' => static function () { return __( 'The status of the object', 'wp-graphql' ); }, ], ]; if ( post_type_supports( $post_type_object->name, 'author' ) ) { $fields['authorId'] = [ 'type' => 'ID', 'description' => static function () { return __( 'The userId to assign as the author of the object', 'wp-graphql' ); }, ]; } if ( post_type_supports( $post_type_object->name, 'comments' ) ) { $fields['commentStatus'] = [ 'type' => 'String', 'description' => static function () { return __( 'The comment status for the object', 'wp-graphql' ); }, ]; } if ( post_type_supports( $post_type_object->name, 'editor' ) ) { $fields['content'] = [ 'type' => 'String', 'description' => static function () { return __( 'The content of the object', 'wp-graphql' ); }, ]; } if ( post_type_supports( $post_type_object->name, 'excerpt' ) ) { $fields['excerpt'] = [ 'type' => 'String', 'description' => static function () { return __( 'The excerpt of the object', 'wp-graphql' ); }, ]; } if ( post_type_supports( $post_type_object->name, 'title' ) ) { $fields['title'] = [ 'type' => 'String', 'description' => static function () { return __( 'The title of the object', 'wp-graphql' ); }, ]; } if ( post_type_supports( $post_type_object->name, 'trackbacks' ) ) { $fields['pinged'] = [ 'type' => [ 'list_of' => 'String', ], 'description' => static function () { return __( 'URLs that have been pinged.', 'wp-graphql' ); }, ]; $fields['pingStatus'] = [ 'type' => 'String', 'description' => static function () { return __( 'The ping status for the object', 'wp-graphql' ); }, ]; $fields['toPing'] = [ 'type' => [ 'list_of' => 'String', ], 'description' => static function () { return __( 'URLs queued to be pinged.', 'wp-graphql' ); }, ]; } if ( $post_type_object->hierarchical || in_array( $post_type_object->name, [ 'attachment', 'revision', ], true ) ) { $fields['parentId'] = [ 'type' => 'ID', 'description' => static function () { return __( 'The ID of the parent object', 'wp-graphql' ); }, ]; } if ( 'attachment' === $post_type_object->name ) { $fields['mimeType'] = [ 'type' => 'MimeTypeEnum', 'description' => static function () { return __( 'If the post is an attachment or a media file, this field will carry the corresponding MIME type. This field is equivalent to the value of WP_Post->post_mime_type and the post_mime_type column in the "post_objects" database table.', 'wp-graphql' ); }, ]; } $allowed_taxonomies = \WPGraphQL::get_allowed_taxonomies( 'objects' ); foreach ( $allowed_taxonomies as $tax_object ) { // If the taxonomy is in the array of taxonomies registered to the post_type if ( in_array( $tax_object->name, get_object_taxonomies( $post_type_object->name ), true ) ) { $fields[ $tax_object->graphql_plural_name ] = [ 'description' => static function () use ( $post_type_object, $tax_object ) { return sprintf( // translators: %1$s is the post type GraphQL name, %2$s is the taxonomy GraphQL name. __( 'Set connections between the %1$s and %2$s', 'wp-graphql' ), $post_type_object->graphql_single_name, $tax_object->graphql_plural_name ); }, 'type' => ucfirst( $post_type_object->graphql_single_name ) . ucfirst( $tax_object->graphql_plural_name ) . 'Input', ]; } } return $fields; } /** * Defines the mutation output field configuration. * * @param \WP_Post_Type $post_type_object The post type of the mutation. * * @return array<string,array<string,mixed>> */ public static function get_output_fields( WP_Post_Type $post_type_object ) { return [ $post_type_object->graphql_single_name => [ 'type' => $post_type_object->graphql_single_name, 'description' => static function () { return __( 'The Post object mutation type.', 'wp-graphql' ); }, 'resolve' => static function ( $payload, $_args, AppContext $context ) { if ( empty( $payload['postObjectId'] ) || ! absint( $payload['postObjectId'] ) ) { return null; } return $context->get_loader( 'post' )->load_deferred( $payload['postObjectId'] ); }, ], ]; } /** * Defines the mutation data modification closure. * * @param \WP_Post_Type $post_type_object The post type of the mutation. * @param string $mutation_name The mutation name. * * @return callable(array<string,mixed>$input,\WPGraphQL\AppContext $context,\GraphQL\Type\Definition\ResolveInfo $info):array<string,mixed> */ public static function mutate_and_get_payload( $post_type_object, $mutation_name ) { return static function ( $input, AppContext $context, ResolveInfo $info ) use ( $post_type_object, $mutation_name ) { /** * Throw an exception if there's no input */ if ( ( empty( $post_type_object->name ) ) || ( empty( $input ) || ! is_array( $input ) ) ) { throw new UserError( esc_html__( 'Mutation not processed. There was no input for the mutation or the post_type_object was invalid', 'wp-graphql' ) ); } /** * Stop now if a user isn't allowed to create a post */ if ( ! isset( $post_type_object->cap->create_posts ) || ! current_user_can( $post_type_object->cap->create_posts ) ) { // translators: the $post_type_object->graphql_plural_name placeholder is the name of the object being mutated throw new UserError( esc_html( sprintf( __( 'Sorry, you are not allowed to create %1$s', 'wp-graphql' ), $post_type_object->graphql_plural_name ) ) ); } /** * If the post being created is being assigned to another user that's not the current user, make sure * the current user has permission to edit others posts for this post_type */ if ( ! empty( $input['authorId'] ) ) { // Ensure authorId is a valid databaseId. $input['authorId'] = Utils::get_database_id_from_id( $input['authorId'] ); $author = ! empty( $input['authorId'] ) ? get_user_by( 'ID', $input['authorId'] ) : false; if ( false === $author ) { throw new UserError( esc_html__( 'The provided `authorId` is not a valid user', 'wp-graphql' ) ); } if ( get_current_user_id() !== $input['authorId'] && ( ! isset( $post_type_object->cap->edit_others_posts ) || ! current_user_can( $post_type_object->cap->edit_others_posts ) ) ) { // translators: the $post_type_object->graphql_plural_name placeholder is the name of the object being mutated throw new UserError( esc_html( sprintf( __( 'Sorry, you are not allowed to create %1$s as this user', 'wp-graphql' ), $post_type_object->graphql_plural_name ) ) ); } } /** * @todo: When we support assigning terms and setting posts as "sticky" we need to check permissions * @see :https://github.com/WordPress/WordPress/blob/e357195ce303017d517aff944644a7a1232926f7/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php#L504-L506 * @see : https://github.com/WordPress/WordPress/blob/e357195ce303017d517aff944644a7a1232926f7/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php#L496-L498 */ /** * Insert the post object and get the ID */ $post_args = PostObjectMutation::prepare_post_object( $input, $post_type_object, $mutation_name ); /** * Filter the default post status to use when the post is initially created. Pass through a filter to * allow other plugins to override the default (for example, Edit Flow, which provides control over * customizing stati or various E-commerce plugins that make heavy use of custom stati) * * @param string $default_status The default status to be used when the post is initially inserted * @param \WP_Post_Type $post_type_object The Post Type that is being inserted * @param string $mutation_name The name of the mutation currently in progress */ $default_post_status = apply_filters( 'graphql_post_object_create_default_post_status', 'draft', $post_type_object, $mutation_name ); /** * We want to cache the "post_status" and set the status later. We will set the initial status * of the inserted post as the default status for the site, allow side effects to process with the * inserted post (set term object connections, set meta input, sideload images if necessary, etc) * Then will follow up with setting the status as what it was declared to be later */ $intended_post_status = ! empty( $post_args['post_status'] ) ? $post_args['post_status'] : $default_post_status; /** * If the current user cannot publish posts but their intent was to publish, * default the status to pending. */ if ( ( ! isset( $post_type_object->cap->publish_posts ) || ! current_user_can( $post_type_object->cap->publish_posts ) ) && ! in_array( $intended_post_status, [ 'draft', 'pending', ], true ) ) { $intended_post_status = 'pending'; } /** * Set the post_status as the default for the initial insert. The intended $post_status will be set after * side effects are complete. */ $post_args['post_status'] = $default_post_status; $clean_args = wp_slash( (array) $post_args ); if ( ! is_array( $clean_args ) || empty( $clean_args ) ) { throw new UserError( esc_html__( 'The object failed to create', 'wp-graphql' ) ); } /** * Insert the post and retrieve the ID */ $post_id = wp_insert_post( $clean_args, true ); /** * Throw an exception if the post failed to create */ if ( is_wp_error( $post_id ) ) { $error_message = $post_id->get_error_message(); if ( ! empty( $error_message ) ) { throw new UserError( esc_html( $error_message ) ); } throw new UserError( esc_html__( 'The object failed to create but no error was provided', 'wp-graphql' ) ); } /** * This updates additional data not part of the posts table (postmeta, terms, other relations, etc) * * The input for the postObjectMutation will be passed, along with the $new_post_id for the * postObject that was created so that relations can be set, meta can be updated, etc. */ PostObjectMutation::update_additional_post_object_data( $post_id, $input, $post_type_object, $mutation_name, $context, $info, $default_post_status, $intended_post_status ); /** * Determine whether the intended status should be set or not. * * By filtering to false, the $intended_post_status will not be set at the completion of the mutation. * * This allows for side-effect actions to set the status later. For example, if a post * was being created via a GraphQL Mutation, the post had additional required assets, such as images * that needed to be sideloaded or some other semi-time-consuming side effect, those actions could * be deferred (cron or whatever), and when those actions complete they could come back and set * the $intended_status. * * @param bool $should_set_intended_status Whether to set the intended post_status or not. Default true. * @param \WP_Post_Type $post_type_object The Post Type Object for the post being mutated * @param string $mutation_name The name of the mutation currently in progress * @param \WPGraphQL\AppContext $context The AppContext passed down to all resolvers * @param \GraphQL\Type\Definition\ResolveInfo $info The ResolveInfo passed down to all resolvers * @param string $intended_post_status The intended post_status the post should have according to the mutation input * @param string $default_post_status The default status posts should use if an intended status wasn't set */ $should_set_intended_status = apply_filters( 'graphql_post_object_create_should_set_intended_post_status', true, $post_type_object, $mutation_name, $context, $info, $intended_post_status, $default_post_status ); /** * If the intended post status and the default post status are not the same, * update the post with the intended status now that side effects are complete. */ if ( $intended_post_status !== $default_post_status && true === $should_set_intended_status ) { /** * If the post was deleted by a side effect action before getting here, * don't proceed. */ $new_post = get_post( $post_id ); if ( empty( $new_post ) ) { throw new UserError( esc_html__( 'The status of the post could not be set', 'wp-graphql' ) ); } /** * If the $intended_post_status is different than the current status of the post * proceed and update the status. */ if ( $intended_post_status !== $new_post->post_status ) { $update_args = [ 'ID' => $post_id, 'post_status' => $intended_post_status, // Prevent the post_date from being reset if the date was included in the create post $args // see: https://core.trac.wordpress.org/browser/tags/4.9/src/wp-includes/post.php#L3637 'edit_date' => ! empty( $post_args['post_date'] ) ? $post_args['post_date'] : false, ]; wp_update_post( $update_args ); } } /** * Return the post object */ return [ 'postObjectId' => $post_id, ]; }; } }
Edit
Download
Unzip
Chmod
Delete