Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 20 additions & 12 deletions admin/class-convertkit-admin-tinymce.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,23 +44,27 @@ public function register_routes() {
// Register route to return all blocks registered by the Plugin.
register_rest_route(
'kit/v1',
'/tinymce/output-modal',
'/editor/tinymce/modal/(?P<shortcode>[a-zA-Z0-9-_]+)/(?P<editor_type>[a-zA-Z0-9-_]+)',
array(
'methods' => WP_REST_Server::CREATABLE,
'methods' => WP_REST_Server::READABLE,
'args' => array(
'shortcode' => array(
'required' => true,
'validate_callback' => function ( $param ) {
return is_string( $param ) && in_array( $param, array_keys( convertkit_get_shortcodes() ), true );
},
'sanitize_callback' => 'sanitize_text_field',
),
'editor_type' => array(
'required' => true,
'validate_callback' => function ( $param ) {
return is_string( $param ) && in_array( $param, array( 'tinymce', 'quicktags' ), true );
},
'sanitize_callback' => 'sanitize_text_field',
),
),
'callback' => function ( $request ) {
ob_start();
$this->output_modal( $request['shortcode'], $request['editor_type'] );
return ob_get_clean();
return rest_ensure_response( $this->output_modal( $request['shortcode'], $request['editor_type'] ) );
},

// Only refresh resources for users who can edit posts.
Expand All @@ -79,16 +83,20 @@ public function register_routes() {
*
* @param string $shortcode_name Shortcode Name.
* @param string $editor_type Editor Type (tinymce|quicktags).
* @return string
*/
public function output_modal( $shortcode_name, $editor_type ) { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed

// Get shortcodes.
$shortcodes = convertkit_get_shortcodes();

// Start output buffering.
ob_start();

// If the shortcode is not registered, return a view in the modal to tell the user.
if ( ! isset( $shortcodes[ $shortcode_name ] ) ) {
require_once CONVERTKIT_PLUGIN_PATH . '/views/backend/tinymce/modal-missing.php';
die();
return ob_get_clean();
}

// Define shortcode.
Expand All @@ -98,25 +106,25 @@ public function output_modal( $shortcode_name, $editor_type ) { // phpcs:ignore
if ( array_key_exists( 'has_access_token', $shortcode ) && ! $shortcode['has_access_token'] ) {
$notice = $shortcode['no_access_token'];
require_once CONVERTKIT_PLUGIN_PATH . '/views/backend/tinymce/modal-notice.php';
die();
return ob_get_clean();
}

// Show a message in the modal if no resources exist.
if ( array_key_exists( 'has_resources', $shortcode ) && ! $shortcode['has_resources'] ) {
$notice = $shortcode['no_resources'];
require_once CONVERTKIT_PLUGIN_PATH . '/views/backend/tinymce/modal-notice.php';
die();
return ob_get_clean();
}

// If we have less than two panels defined in the shortcode properties, output a basic modal.
if ( count( $shortcode['panels'] ) < 2 ) {
require_once CONVERTKIT_PLUGIN_PATH . '/views/backend/tinymce/modal.php';
die();
return ob_get_clean();
}

// Output tabbed view.
require_once CONVERTKIT_PLUGIN_PATH . '/views/backend/tinymce/modal-tabbed.php';
die();
return ob_get_clean();

}

Expand Down Expand Up @@ -146,7 +154,7 @@ public function register_quicktags() {
'convertkit-admin-quicktags',
'convertkit_admin_tinymce',
array(
'ajaxurl' => rest_url( 'kit/v1/tinymce/output-modal' ),
'ajaxurl' => rest_url( 'kit/v1/editor/tinymce/modal' ),
'nonce' => wp_create_nonce( 'wp_rest' ),
)
);
Expand Down Expand Up @@ -189,7 +197,7 @@ public function register_tinymce_plugins( $plugins ) {
'convertkit-admin-editor',
'convertkit_admin_tinymce',
array(
'ajaxurl' => rest_url( 'kit/v1/tinymce/output-modal' ),
'ajaxurl' => rest_url( 'kit/v1/editor/tinymce/modal' ),
'nonce' => wp_create_nonce( 'wp_rest' ),
)
);
Expand Down
26 changes: 14 additions & 12 deletions resources/backend/js/editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,19 +55,21 @@ function convertKitTinyMCERegisterPlugin(block) {
});

// Perform an AJAX call to load the modal's view.
fetch(convertkit_admin_tinymce.ajaxurl, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'X-WP-Nonce': convertkit_admin_tinymce.nonce,
},
body: new URLSearchParams({
editor_type: 'tinymce',
shortcode: block.name,
}),
})
fetch(
convertkit_admin_tinymce.ajaxurl +
'/' +
block.name +
'/' +
'tinymce',
{
method: 'GET',
headers: {
'X-WP-Nonce': convertkit_admin_tinymce.nonce,
},
}
)
.then(function (response) {
return response.text();
return response.json();
})
.then(function (result) {
// Inject HTML into modal.
Expand Down
26 changes: 14 additions & 12 deletions resources/backend/js/quicktags.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,21 @@ for (const block in convertkit_quicktags) {
function convertKitQuickTagRegister(block) {
QTags.addButton('convertkit-' + block.name, block.title, function () {
// Perform an AJAX call to load the modal's view.
fetch(convertkit_admin_tinymce.ajaxurl, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'X-WP-Nonce': convertkit_admin_tinymce.nonce,
},
body: new URLSearchParams({
editor_type: 'quicktags',
shortcode: block.name,
}),
})
fetch(
convertkit_admin_tinymce.ajaxurl +
'/' +
block.name +
'/' +
'quicktags',
{
method: 'GET',
headers: {
'X-WP-Nonce': convertkit_admin_tinymce.nonce,
},
}
)
.then(function (response) {
return response.text();
return response.json();
})
.then(function (result) {
// Show Modal.
Expand Down
180 changes: 180 additions & 0 deletions tests/Integration/RESTAPIEditorTinyMCEModalTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
<?php

namespace Tests;

use lucatume\WPBrowser\TestCase\WPRestApiTestCase;

/**
* Tests for the REST API Editor TinyMCE Modal routes.
*
* @since 3.1.9
*/
class RESTAPIEditorTinyMCEModalTest extends WPRestApiTestCase
{
/**
* The testing implementation.
*
* @var \IntegrationTester
*/
protected $tester;

/**
* Holds the ConvertKit Settings class.
*
* @since 3.1.9
*
* @var ConvertKit_Settings
*/
private $settings;

/**
* Performs actions before each test.
*
* @since 3.1.9
*/
public function setUp(): void
{
parent::setUp();

// Activate Plugin, to include the Plugin's constants in tests.
activate_plugins('convertkit/wp-convertkit.php');

// Store Credentials in Plugin's settings.
$this->settings = new \ConvertKit_Settings();
$this->settings->save(
array(
'access_token' => $_ENV['CONVERTKIT_OAUTH_ACCESS_TOKEN'],
'refresh_token' => $_ENV['CONVERTKIT_OAUTH_REFRESH_TOKEN'],
'token_expires' => ( time() + 10000 ),
)
);

// Tell WordPress that we're making REST API requests.
// This constant isn't set by the WP_REST_Server class in tests.
if ( ! defined( 'REST_REQUEST' ) ) {
define( 'REST_REQUEST', true );
}
}

/**
* Performs actions after each test.
*
* @since 3.1.9
*/
public function tearDown(): void
{
// Delete Credentials from Plugin's settings.
$this->settings->delete_credentials();
parent::tearDown();
}

/**
* Test that the /wp-json/kit/v1/editor/tinymce/modal REST API route returns a 401 when the user is not authorized.
*
* @since 3.1.9
*/
public function testWhenUnauthorized()
{
// Make request.
$request = new \WP_REST_Request( 'GET', '/kit/v1/editor/tinymce/modal/form/tinymce' );
$response = rest_get_server()->dispatch( $request );

// Assert response is unsuccessful.
$this->assertSame( 401, $response->get_status() );
}

/**
* Test that the /wp-json/kit/v1/editor/tinymce/modal REST API route returns a 404 when no shortcode or editor type is provided.
*
* @since 3.1.9
*/
public function testWhenMissingParams()
{
// Create and become editor.
$this->actAsEditor();

// Make request.
$request = new \WP_REST_Request( 'GET', '/kit/v1/editor/tinymce/modal' );
$response = rest_get_server()->dispatch( $request );

// Assert response is unsuccessful.
$this->assertSame( 404, $response->get_status() );
}

/**
* Test that the /wp-json/kit/v1/editor/tinymce/modal REST API route returns a 404 when no shortcode or editor type is provided.
*
* @since 3.1.9
*/
public function testWhenInvalidParams()
{
// Create and become editor.
$this->actAsEditor();

// Make request.
$request = new \WP_REST_Request( 'GET', '/kit/v1/editor/tinymce/modal/invalid-shortcode/tinymce' );
$response = rest_get_server()->dispatch( $request );
$data = $response->get_data();

// Assert response is unsuccessful.
$this->assertSame( 400, $response->get_status() );
$this->assertEquals( 'rest_invalid_param', $data['code'] );
$this->assertEquals( 'Invalid parameter(s): shortcode', $data['message'] );

// Make request.
$request = new \WP_REST_Request( 'GET', '/kit/v1/editor/tinymce/modal/form/invalid-editor-type' );
$response = rest_get_server()->dispatch( $request );
$data = $response->get_data();

// Assert response is unsuccessful.
$this->assertSame( 400, $response->get_status() );
$this->assertEquals( 'rest_invalid_param', $data['code'] );
$this->assertEquals( 'Invalid parameter(s): editor_type', $data['message'] );
}

/**
* Test that the /wp-json/kit/v1/editor/tinymce/modal REST API route returns a 200 when the shortcode and editor type are valid.
*
* @since 3.1.9
*/
public function testWhenValidParams()
{
// Create and become editor.
$this->actAsEditor();

// Define the shortcodes and editor types to test.
$shortcodes = [
'broadcasts',
'content',
'formtrigger',
'form',
'product',
];
$editor_types = [
'tinymce',
'quicktags',
];

// Iterate through the shortcodes and editor types and make a request for each combination.
foreach ( $shortcodes as $shortcode ) {
foreach ( $editor_types as $editor_type ) {
$request = new \WP_REST_Request( 'GET', '/kit/v1/editor/tinymce/modal/' . $shortcode . '/' . $editor_type );
$response = rest_get_server()->dispatch( $request );

// Assert response is successful.
$this->assertSame( 200, $response->get_status() );
}
}
}

/**
* Act as an editor user.
*
* @since 3.1.9
*/
private function actAsEditor()
{
$editor_id = static::factory()->user->create( [ 'role' => 'editor' ] );
wp_set_current_user( $editor_id );
}
}