Skip to content

Commit

Permalink
Add PDF Download endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
jakejackson1 committed Aug 30, 2024
1 parent c721a04 commit 7660ea1
Show file tree
Hide file tree
Showing 4 changed files with 273 additions and 8 deletions.
259 changes: 259 additions & 0 deletions src/Rest/Rest_Download_Pdf.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,259 @@
<?php

namespace GFPDF\Rest;

use GFPDF\Helper\Helper_Data;
use GFPDF\Helper\Helper_Form;
use GFPDF\Model\Model_PDF;
use GPDFAPI;
use WP_Error;
use WP_REST_Request;
use WP_REST_Response;
use WP_REST_Server;

/**
* @package Gravity PDF
* @copyright Copyright (c) 2024, Blue Liquid Designs
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
*/

/* Exit if accessed directly */
if ( ! defined( 'ABSPATH' ) ) {
exit;
}

/**
* @since 6.12
*/
class Rest_Download_Pdf {

/**
* @var string
* @since 6.12
*/
public const NAMESPACE = Helper_Data::REST_API_BASENAME . 'v1';

/**
* @var string
* @since 6.12
*/
public const API_BASE = '/download';

/**
* @var string[]
* @since 6.12
*/
public static $endpoints = [
'download-pdf' => self::API_BASE . '/(?P<entry>[\d]+)/(?P<pdf>[a-fA-F0-9]{13})',
];

/**
* @var Helper_Form
* @since 6.12
*/
protected $gform;

/**
* @param Helper_Form $gform
*
* @since 6.12
*/
public function __construct( $gform ) {
$this->gform = $gform;
}

/**
* @return void
* @since 6.12
*/
public function init() {
add_action( 'rest_api_init', [ $this, 'register_routes' ] );
}

/**
* Register the routes for the API
*
* @return void
* @since 6.12
*/
public function register_routes() {

/*
* Routes to list all form PDF settings, or create a new one
*/
register_rest_route(
static::NAMESPACE,
static::$endpoints['download-pdf'],
[
'args' => [
'entry' => [
'description' => __( 'The unique identifier for the Gravity Forms entry.', 'gravity-forms-pdf-extended' ),
'type' => 'integer',
'required' => true,
'validate_callback' => function( $param, $request ) {
$entry = $this->gform->get_entry( $param );

if ( ! is_wp_error( $entry ) ) {
return true;
}

return new WP_Error(
'rest_invalid_param',
sprintf( __( 'Invalid entry ID %d provided.', 'gravity-forms-pdf-extended' ), $param ),
[ 'status' => 400 ]
);
},
],

'pdf' => [
'description' => __( 'The identifier for the PDF', 'gravity-forms-pdf-extended' ),
'type' => 'string',
'required' => true,
'validate_callback' => function( $param, $request ) {

/* Get all active PDFs for the entry */
$pdfs = GPDFAPI::get_entry_pdfs( $request->get_param( 'entry' ) );

/* PDF ID is valid if in $pdfs array */
if ( isset( $pdfs[ $param ] ) ) {
return true;
}

/* translators: 1: Parameter, 2: List of valid values. */

return new WP_Error( 'rest_not_in_enum', wp_sprintf( __( '%1$s is not one of %2$l.', 'default' ), $param, ! is_wp_error( $pdfs ) ? array_keys( $pdfs ) : '""' ) );
},
],
],

[
'methods' => WP_REST_Server::CREATABLE,
'callback' => [ $this, 'get_item' ],
'permission_callback' => [ $this, 'get_item_permissions_check' ],
],
],
);
}

/**
* Generate and return PDF
*
* @param WP_REST_Request $request
*
* @return WP_Error|WP_REST_Response
*/
public function get_item( $request ) {
$path_to_pdf = \GPDFAPI::create_pdf( $request->get_param( 'entry' ), $request->get_param( 'pdf' ) );

if ( is_wp_error( $path_to_pdf ) ) {
/*
* Both entry and PDF IDs have been validated by this point.
* If an error occurred it was in the PDF generator, and why the 500 server error.
*/
$path_to_pdf->add_data( [ 'status' => 500 ] );

return $path_to_pdf;
}

$response = new WP_REST_Response(
[
'filename' => wp_basename( $path_to_pdf ),
'size' => filesize( $path_to_pdf ),
'data' => base64_encode( file_get_contents( $path_to_pdf ) ), //phpcs:ignore
]
);

$response->add_links( $this->prepare_links( $request ) );

return $response;
}

/**
* Add links for PDF
*
* @param WP_REST_Request $request
*
* @return array[]
*
* @since 6.12.0
*/
protected function prepare_links( $request ) {

$pdf_id = $data['id'] ?? $request->get_param( 'pdf' );
$entry_id = $data['entry'] ?? $request->get_param( 'entry' );

$entry = $this->gform->get_entry( $entry_id );
$form_id = $entry['form_id'];

$links = [
'self' => [
'href' => rest_url( sprintf( '%s/%d/%s', static::get_route_basepath(), $entry_id, $pdf_id ) ),
],

'pdf' => [
'href' => rest_url( sprintf( '%s/%d/%s', Rest_Form_Settings::get_route_basepath(), $form_id, $pdf_id ) ),
'embeddable' => true,
],
];

if ( ! class_exists( 'GFWebAPI' ) ) {
return $links;
}

/* If GF REST API enabled, include direct links to form endpoint */
$gfwebapi = \GFWebAPI::get_instance();
if ( ! $gfwebapi->is_v2_enabled( $gfwebapi->get_plugin_settings() ) ) {
return $links;
}

$links['form'] = [
'href' => rest_url( sprintf( 'gf/v2/forms/%d', $form_id ) ),
'embeddable' => true,
];

if ( ! empty( $entry_id ) ) {
$links['entry'] = [
'href' => rest_url( sprintf( 'gf/v2/entries/%d', $entry_id ) ),
'embeddable' => true,
];
}

return $links;
}

/**
* @return string
*
* @since 6.12
*/
public static function get_route_basepath() {
return static::NAMESPACE . static::API_BASE;
}

/**
* Ensure current user is allowed to access PDF
*
* @param WP_REST_Request $request
*
* @return bool
*/
public function get_item_permissions_check( $request ) {
/* Check if the current user has appropriate capability to view document */
/** @var Model_PDF $model_pdf */
$model_pdf = \GPDFAPI::get_pdf_class( 'model' );
if ( $model_pdf->can_user_view_pdf_with_capabilities() ) {
return true;
}

/* check if the current user is the owner and owner access is not disabled in the PDF settings */
$entry = $this->gform->get_entry( $request->get_param( 'entry' ) );
$pdf = \GPDFAPI::get_pdf( $entry['form_id'] ?? 0, $request->get_param( 'pdf' ) );

$is_owner_restricted = $pdf['restrict_owner'] ?? 'No';
if ( $is_owner_restricted !== 'Yes' && (int) $entry['created_by'] === get_current_user_id() ) {
return true;
}

return false;
}
}
14 changes: 8 additions & 6 deletions src/Rest/Rest_Form_Settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -176,15 +176,17 @@ public function register_routes() {
'validate_callback' => function( $param, $request ) {
$pdf = GPDFAPI::get_pdf( $request->get_param( 'form' ), $param );

/* PDF found, PDF ID is valid */
if ( ! is_wp_error( $pdf ) ) {
return true;
}

/* Get list of valid IDs and include in error */
$pdfs = GPDFAPI::get_form_pdfs( $request->get_param( 'form' ) );

/* translators: 1: Parameter, 2: List of valid values. */

return new WP_Error( 'rest_not_in_enum', wp_sprintf( __( '%1$s is not one of %2$l.', 'default' ), $param, ! is_wp_error( $pdfs ) ? array_keys( $pdfs ) : '' ) );
return new WP_Error( 'rest_not_in_enum', wp_sprintf( __( '%1$s is not one of %2$l.', 'default' ), $param, ! is_wp_error( $pdfs ) ? array_keys( $pdfs ) : '""' ) );
},
],
],
Expand Down Expand Up @@ -371,7 +373,7 @@ public function check_form_is_valid( $form_id ) {
* @since 6.12.0
*/
public function check_entry_is_valid( $entry_id, $request ) {
$entry = \GFAPI::get_entry( $entry_id );
$entry = $this->gform->get_entry( $entry_id );
if ( is_wp_error( $entry ) ) {
return new WP_Error(
'rest_invalid_param',
Expand Down Expand Up @@ -890,23 +892,23 @@ public function get_item_schema() {
'id' => [
'description' => __( 'Unique identifier for the PDF.', 'gravity-forms-pdf-extended' ),
'type' => 'string',
'context' => [ 'edit' ],
'context' => [ 'edit', 'embed' ],
'readonly' => true,
'pattern' => '[a-fA-F0-9]{13}',
],

'form' => [
'description' => __( 'The Gravity Forms ID the PDF is configured on.', 'gravity-forms-pdf-extended' ),
'type' => 'integer',
'context' => [ 'edit' ],
'context' => [ 'edit', 'embed' ],
'readonly' => true,
],

'active' => [
'description' => __( 'The current state of the PDF.', 'gravity-forms-pdf-extended' ),
'type' => 'boolean',
'default' => true,
'context' => [ 'edit' ],
'context' => [ 'edit', 'embed' ],
],
],
];
Expand Down Expand Up @@ -1014,7 +1016,7 @@ protected function get_section_schema( $settings, $group ) {
'description' => ! empty( $value['desc'] ) ? wp_strip_all_tags( $value['desc'] ) : $generic_description,
'type' => 'string',
'default' => $default,
'context' => [ 'edit', $group ],
'context' => [ 'edit', 'embed', $group ],
'arg_options' => [
'sanitize_callback' => function( $param, $request, $key ) {
return is_array( $param ) ? array_map( 'sanitize_text_field', $param ) : sanitize_text_field( $param );
Expand Down
4 changes: 2 additions & 2 deletions src/Rest/Rest_Pdf_Preview.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ public function register_routes() {
* @since 6.12
*/
public function create_item( $request ) {
$form = \GFAPI::get_form( $request->get_param( 'form' ) );
$form = $this->gform->get_form( $request->get_param( 'form' ) );
$entry = $this->get_entry( $request, $form );

/* Prepare request for previewing */
Expand Down Expand Up @@ -114,7 +114,7 @@ public function create_item( $request ) {
protected function get_entry( $request, $form ) {
/* user requested a specific entry to preview */
if ( $request->get_param( 'entry' ) ) {
return \GFAPI::get_entry( $request->get_param( 'entry' ) );
return $this->gform->get_entry( $request->get_param( 'entry' ) );
}

/* try to get the last form submission */
Expand Down
4 changes: 4 additions & 0 deletions src/bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -702,9 +702,13 @@ public function rest_api() {
$pdf_preview_controller = new Rest\Rest_Pdf_Preview( $this->options, $this->gform, $this->misc, $this->templates );
$pdf_preview_controller->init();

$download_pdf_controller = new Rest\Rest_Download_Pdf( $this->gform );
$download_pdf_controller->init();

/* Add to our singleton controller */
$this->singleton->add_class( $form_setting_controller );
$this->singleton->add_class( $pdf_preview_controller );
$this->singleton->add_class( $download_pdf_controller );

/* Log any errors for PDF endpoints */
$rest_request_after_callback = function( $response, $handle, $request ) {
Expand Down

0 comments on commit 7660ea1

Please sign in to comment.