'POST', 'permission_callback' => array( $this, 'can_embed' ), 'callback' => array( $this, 'handle' ), 'args' => array( 'player' => array( 'type' => 'integer', 'required' => true, 'sanitize_callback' => 'absint', 'validate_callback' => 'rest_validate_request_arg', ), 'page_id' => array( 'type' => 'integer', 'sanitize_callback' => 'absint', 'validate_callback' => 'rest_validate_request_arg', ), 'title' => array( 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field', 'validate_callback' => 'rest_validate_request_arg', ), 'status' => array( 'type' => 'string', 'enum' => array( 'draft', 'publish' ), ), 'position' => array( 'type' => 'string', 'enum' => array( 'append', 'prepend' ), ), ), ) ); } /** * REST permission: add a player to a page (users who can edit pages). * * @return bool */ public function can_embed() { return current_user_can( 'edit_pages' ); } /** * Block markup (or the shortcode when the block is not registered). * * @param int $player_id Player. * @return string */ public static function markup( $player_id ) { $player_id = absint( $player_id ); if ( class_exists( '\WP_Block_Type_Registry' ) && \WP_Block_Type_Registry::get_instance()->is_registered( 'streamsera/player' ) ) { return ''; } return '[streamsera id="' . $player_id . '"]'; } /** * Whether the current user may publish posts of a type (publish_pages for pages). * * @param string $post_type Post type. * @return bool */ private static function can_publish( $post_type ) { $type = get_post_type_object( $post_type ); $cap = $type && isset( $type->cap->publish_posts ) ? $type->cap->publish_posts : ( 'page' === $post_type ? 'publish_pages' : 'publish_posts' ); return current_user_can( $cap ); } /** * Add the player to a page or create one. * * @param WP_REST_Request $request Request. * @return WP_REST_Response|WP_Error */ public function handle( WP_REST_Request $request ) { $player_id = absint( $request['player'] ); $player = $player_id ? get_post( $player_id ) : null; // Published players, or drafts / private players the user may edit; never someone else's draft. if ( ! $player || 'streamsera_player' !== $player->post_type || ( 'publish' !== $player->post_status && ! current_user_can( 'edit_post', $player_id ) ) ) { return new WP_Error( 'streamsera_no_player', __( 'Player not found.', 'streamsera' ), array( 'status' => 404 ) ); } $position = 'prepend' === $request['position'] ? 'prepend' : 'append'; $markup = self::markup( $player_id ); $page_id = absint( $request['page_id'] ); if ( $page_id ) { $page = get_post( $page_id ); if ( ! $page || ! in_array( $page->post_type, array( 'page', 'post' ), true ) ) { return new WP_Error( 'streamsera_no_page', __( 'Page not found.', 'streamsera' ), array( 'status' => 404 ) ); } if ( ! current_user_can( 'edit_post', $page_id ) ) { return new WP_Error( 'streamsera_forbidden', __( 'You cannot edit that page.', 'streamsera' ), array( 'status' => 403 ) ); } // Changing live content needs the publish capability of that post type too. if ( 'publish' === $page->post_status && ! self::can_publish( $page->post_type ) ) { return new WP_Error( 'streamsera_forbidden', __( 'You cannot change published content.', 'streamsera' ), array( 'status' => 403 ) ); } $content = (string) $page->post_content; if ( false !== strpos( $content, '"playerId":' . $player_id . '}' ) || false !== strpos( $content, 'id="' . $player_id . '"' ) ) { // Already there: don't add it twice. $already = true; } else { $already = false; $content = 'prepend' === $position ? $markup . "\n\n" . $content : rtrim( $content ) . "\n\n" . $markup; // wp_update_post() expects slashed data (it unslashes): keep backslashes in the page content. $result = wp_update_post( wp_slash( array( 'ID' => $page_id, 'post_content' => $content, ) ), true ); if ( is_wp_error( $result ) ) { return $result; } } $status = $page->post_status; } else { $title = sanitize_text_field( (string) $request['title'] ); $status = 'draft' === $request['status'] ? 'draft' : 'publish'; if ( 'publish' === $status && ! self::can_publish( 'page' ) ) { return new WP_Error( 'streamsera_forbidden', __( 'You cannot publish pages. Create the page as a draft instead.', 'streamsera' ), array( 'status' => 403 ) ); } if ( '' === $title ) { $title = streamsera_plain_title( $player ); } $page_id = wp_insert_post( wp_slash( array( 'post_type' => 'page', 'post_title' => $title, 'post_status' => $status, 'post_content' => $markup, ) ), true ); if ( is_wp_error( $page_id ) ) { return $page_id; } $already = false; } /** * Fires after a player was added to a page from the Embed dialog. * * @param int $page_id Page. * @param int $player_id Player. * @param string $position append|prepend. */ do_action( 'streamsera_embed_added_to_page', $page_id, $player_id, $position ); return new WP_REST_Response( array( 'id' => (int) $page_id, 'title' => streamsera_plain_title( $page_id ), 'status' => $status, 'already' => $already, 'edit_link' => get_edit_post_link( $page_id, 'raw' ), 'view_link' => 'publish' === $status ? get_permalink( $page_id ) : get_preview_post_link( $page_id ), ) ); } }