first commit
This commit is contained in:
@@ -0,0 +1,195 @@
|
||||
<?php
|
||||
namespace Elementor\Modules\CloudKitLibrary\Connect;
|
||||
|
||||
use Elementor\Core\Common\Modules\Connect\Apps\Library;
|
||||
use Elementor\Core\Utils\Exceptions;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
class Cloud_Kits extends Library {
|
||||
const THRESHOLD_UNLIMITED = -1;
|
||||
const FAILED_TO_FETCH_QUOTA_KEY = 'failed-to-fetch-quota';
|
||||
const INSUFFICIENT_QUOTA_KEY = 'insufficient-quota';
|
||||
|
||||
public function get_title() {
|
||||
return esc_html__( 'Cloud Kits', 'elementor' );
|
||||
}
|
||||
|
||||
protected function get_api_url(): string {
|
||||
return 'https://cloud-library.prod.builder.elementor.red/api/v1/cloud-library';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|\WP_Error
|
||||
*/
|
||||
public function get_all( $args = [] ) {
|
||||
return $this->http_request( 'GET', 'kits', [], [
|
||||
'return_type' => static::HTTP_RETURN_TYPE_ARRAY,
|
||||
] );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|\WP_Error
|
||||
*/
|
||||
public function get_quota() {
|
||||
return $this->http_request( 'GET', 'quota/kits', [], [
|
||||
'return_type' => static::HTTP_RETURN_TYPE_ARRAY,
|
||||
] );
|
||||
}
|
||||
|
||||
public function validate_quota() {
|
||||
$quota = $this->get_quota();
|
||||
|
||||
if ( is_wp_error( $quota ) ) {
|
||||
throw new \Error( static::FAILED_TO_FETCH_QUOTA_KEY ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
|
||||
}
|
||||
|
||||
$is_unlimited = self::THRESHOLD_UNLIMITED === $quota['threshold'];
|
||||
$has_quota = $quota['currentUsage'] < $quota['threshold'];
|
||||
|
||||
if ( ! $is_unlimited && ! $has_quota ) {
|
||||
throw new \Error( static::INSUFFICIENT_QUOTA_KEY ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
|
||||
}
|
||||
}
|
||||
|
||||
public function check_eligibility() {
|
||||
$quota = $this->get_quota();
|
||||
|
||||
if ( is_wp_error( $quota ) ) {
|
||||
return [
|
||||
'is_eligible' => false,
|
||||
'subscription_id' => '',
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'is_eligible' => isset( $quota['threshold'] ) && 0 !== $quota['threshold'],
|
||||
'subscription_id' => ! empty( $quota['subscriptionId'] ) ? $quota['subscriptionId'] : '',
|
||||
];
|
||||
}
|
||||
|
||||
public function create_kit( $title, $description, $content_file_data, $preview_file_data, array $includes ) {
|
||||
$this->validate_quota();
|
||||
|
||||
$endpoint = 'kits';
|
||||
|
||||
$boundary = wp_generate_password( 24, false );
|
||||
|
||||
$headers = [
|
||||
'Content-Type' => 'multipart/form-data; boundary=' . $boundary,
|
||||
];
|
||||
|
||||
$body = $this->create_multipart_body(
|
||||
[
|
||||
'title' => $title,
|
||||
'description' => $description,
|
||||
'includes' => wp_json_encode( $includes ),
|
||||
],
|
||||
[
|
||||
'previewFile' => [
|
||||
'filename' => 'preview.png',
|
||||
'content' => $preview_file_data,
|
||||
'content_type' => 'image/png',
|
||||
],
|
||||
],
|
||||
$boundary
|
||||
);
|
||||
|
||||
$payload = [
|
||||
'headers' => $headers,
|
||||
'body' => $body,
|
||||
'timeout' => 120,
|
||||
];
|
||||
|
||||
$response = $this->http_request( 'POST', $endpoint, $payload, [
|
||||
'return_type' => static::HTTP_RETURN_TYPE_ARRAY,
|
||||
] );
|
||||
|
||||
if ( empty( $response['id'] ) ) {
|
||||
$error_message = esc_html__( 'Failed to create kit: Invalid response', 'elementor' );
|
||||
throw new \Exception( $error_message, Exceptions::INTERNAL_SERVER_ERROR ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
|
||||
}
|
||||
|
||||
if ( empty( $response['uploadUrl'] ) ) {
|
||||
$this->delete_kit( $response['id'] );
|
||||
$error_message = esc_html__( 'Failed to create kit: No upload URL provided', 'elementor' );
|
||||
throw new \Exception( $error_message, Exceptions::INTERNAL_SERVER_ERROR ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
|
||||
}
|
||||
|
||||
$upload_success = $this->upload_content_file( $response['uploadUrl'], $content_file_data );
|
||||
|
||||
if ( ! $upload_success ) {
|
||||
$this->delete_kit( $response['id'] );
|
||||
$error_message = esc_html__( 'Failed to create kit: Content upload failed', 'elementor' );
|
||||
throw new \Exception( $error_message, Exceptions::INTERNAL_SERVER_ERROR ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
private function upload_content_file( $upload_url, $content_file_data ) {
|
||||
$upload_response = wp_remote_request( $upload_url, [
|
||||
'method' => 'PUT',
|
||||
'body' => $content_file_data,
|
||||
'headers' => [
|
||||
'Content-Type' => 'application/zip',
|
||||
'Content-Length' => strlen( $content_file_data ),
|
||||
],
|
||||
'timeout' => 120,
|
||||
] );
|
||||
|
||||
if ( is_wp_error( $upload_response ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$response_code = wp_remote_retrieve_response_code( $upload_response );
|
||||
|
||||
return $response_code >= 200 && $response_code < 300;
|
||||
}
|
||||
|
||||
public function get_kit( array $args ) {
|
||||
$args = array_merge_recursive( $args, [
|
||||
'timeout' => 60, // just in case if zip is big
|
||||
] );
|
||||
|
||||
return $this->http_request( 'GET', 'kits/' . $args['id'], $args, [
|
||||
'return_type' => static::HTTP_RETURN_TYPE_ARRAY,
|
||||
] );
|
||||
}
|
||||
|
||||
public function delete_kit( int $id ) {
|
||||
return $this->http_request( 'DELETE', 'kits/' . $id, [], [
|
||||
'return_type' => static::HTTP_RETURN_TYPE_ARRAY,
|
||||
] );
|
||||
}
|
||||
|
||||
private function create_multipart_body( $fields, $files, $boundary ): string {
|
||||
$eol = "\r\n";
|
||||
$body = '';
|
||||
|
||||
foreach ( $fields as $name => $value ) {
|
||||
$body .= "--{$boundary}{$eol}";
|
||||
$body .= "Content-Disposition: form-data; name=\"{$name}\"{$eol}{$eol}";
|
||||
$body .= "{$value}{$eol}";
|
||||
}
|
||||
|
||||
foreach ( $files as $name => $file ) {
|
||||
$filename = basename( $file['filename'] );
|
||||
$content_type = $file['content_type'];
|
||||
$content = $file['content'];
|
||||
|
||||
$body .= "--{$boundary}{$eol}";
|
||||
$body .= "Content-Disposition: form-data; name=\"{$name}\"; filename=\"{$filename}\"{$eol}";
|
||||
$body .= "Content-Type: {$content_type}{$eol}{$eol}";
|
||||
$body .= $content . $eol;
|
||||
}
|
||||
|
||||
$body .= "--{$boundary}--{$eol}";
|
||||
|
||||
return $body;
|
||||
}
|
||||
|
||||
protected function init() {}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
namespace Elementor\Modules\CloudKitLibrary\Data;
|
||||
|
||||
use Elementor\Modules\CloudKitLibrary\Connect\Cloud_Kits;
|
||||
use Elementor\Modules\CloudKitLibrary\Module as CloudKitLibrary;
|
||||
use Elementor\App\Modules\KitLibrary\Data\Base_Controller;
|
||||
use Elementor\Core\Utils\Collection;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
class Controller extends Base_Controller {
|
||||
|
||||
public function get_name() {
|
||||
return 'cloud-kits';
|
||||
}
|
||||
|
||||
public function get_items( $request ) {
|
||||
$data = $this->get_app()->get_all();
|
||||
|
||||
if ( is_wp_error( $data ) ) {
|
||||
return [
|
||||
'data' => [],
|
||||
];
|
||||
}
|
||||
|
||||
$kits = ( new Collection( $data ) )->map( function ( $kit ) {
|
||||
return [
|
||||
'id' => $kit['id'],
|
||||
'title' => $kit['title'],
|
||||
'thumbnail_url' => $kit['thumbnailUrl'],
|
||||
'created_at' => $kit['createdAt'],
|
||||
'updated_at' => $kit['updatedAt'],
|
||||
];
|
||||
} );
|
||||
|
||||
return [
|
||||
'data' => $kits->values(),
|
||||
];
|
||||
}
|
||||
|
||||
public function delete_item( $request ) {
|
||||
return [
|
||||
'data' => $this->get_app()->delete_kit( $request->get_param( 'id' ) ),
|
||||
];
|
||||
}
|
||||
|
||||
public function get_item( $request ) {
|
||||
return [
|
||||
'data' => $this->get_app()->get_kit( [ 'id' => $request->get_param( 'id' ) ] ),
|
||||
];
|
||||
}
|
||||
|
||||
public function register_endpoints() {
|
||||
$this->index_endpoint->register_item_route( \WP_REST_Server::DELETABLE, [
|
||||
'id' => [
|
||||
'description' => 'Unique identifier for the object.',
|
||||
'type' => 'integer',
|
||||
'required' => true,
|
||||
],
|
||||
] );
|
||||
|
||||
$this->register_endpoint( new Endpoints\Eligibility( $this ) );
|
||||
}
|
||||
|
||||
public function get_permission_callback( $request ) {
|
||||
return current_user_can( 'manage_options' );
|
||||
}
|
||||
|
||||
protected function get_app(): Cloud_Kits {
|
||||
return CloudKitLibrary::get_app();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
namespace Elementor\Modules\CloudKitLibrary\Data\Endpoints;
|
||||
|
||||
use Elementor\Modules\CloudKitLibrary\Data\Controller;
|
||||
use Elementor\Modules\CloudKitLibrary\Module as CloudKitLibrary;
|
||||
use Elementor\Data\V2\Base\Endpoint;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* @property Controller $controller
|
||||
*/
|
||||
class Eligibility extends Endpoint {
|
||||
public function get_name() {
|
||||
return 'eligibility';
|
||||
}
|
||||
|
||||
public function get_format() {
|
||||
return 'cloud-kits/eligibility';
|
||||
}
|
||||
|
||||
public function get_items( $request ) {
|
||||
return CloudKitLibrary::get_app()->check_eligibility();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
<?php
|
||||
namespace Elementor\Modules\CloudKitLibrary;
|
||||
|
||||
use Elementor\Modules\CloudKitLibrary\Data\Controller as Cloud_Kits_Controller;
|
||||
use Elementor\Core\Utils\Exceptions;
|
||||
use Elementor\Plugin;
|
||||
use Elementor\Core\Base\Module as BaseModule;
|
||||
use Elementor\Modules\CloudKitLibrary\Connect\Cloud_Kits;
|
||||
use Elementor\Core\Common\Modules\Connect\Module as ConnectModule;
|
||||
use Elementor\App\Modules\ImportExport\Module as ImportExport_Module;
|
||||
use Elementor\App\Modules\KitLibrary\Connect\Kit_Library as Kit_Library_Api;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
class Module extends BaseModule {
|
||||
|
||||
public function get_name(): string {
|
||||
return 'cloud-kit-library';
|
||||
}
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
|
||||
add_action( 'elementor/connect/apps/register', function ( ConnectModule $connect_module ) {
|
||||
$connect_module->register_app( 'cloud-kits', Cloud_Kits::get_class_name() );
|
||||
} );
|
||||
|
||||
add_filter( 'elementor/export/kit/export-result', [ $this, 'handle_export_kit_result' ], 10, 5 );
|
||||
add_filter( 'elementor/import/kit/result/cloud', [ $this, 'handle_import_kit_from_cloud' ], 10, 1 );
|
||||
add_filter( 'elementor/import/kit_thumbnail', [ $this, 'handle_import_kit_thumbnail' ], 10, 3 );
|
||||
|
||||
add_action( 'elementor/kit_library/registered', function () {
|
||||
Plugin::$instance->data_manager_v2->register_controller( new Cloud_Kits_Controller() );
|
||||
} );
|
||||
}
|
||||
|
||||
public function handle_import_kit_thumbnail( $thumbnail, $kit_id, $referrer ) {
|
||||
if ( ImportExport_Module::REFERRER_KIT_LIBRARY === $referrer ) {
|
||||
|
||||
if ( empty( $kit_id ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$api = new Kit_Library_Api();
|
||||
$kit = $api->get_by_id( $kit_id );
|
||||
|
||||
if ( is_wp_error( $kit ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $kit->thumbnail;
|
||||
}
|
||||
|
||||
if ( ImportExport_Module::REFERRER_CLOUD === $referrer ) {
|
||||
if ( empty( $kit_id ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$kit = self::get_app()->get_kit( [ 'id' => $kit_id ] );
|
||||
|
||||
if ( is_wp_error( $kit ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $kit['thumbnailUrl'] ?? '';
|
||||
}
|
||||
|
||||
return $thumbnail;
|
||||
}
|
||||
|
||||
public function handle_export_kit_result( $result, $source, $export, $settings, $file ) {
|
||||
if ( ImportExport_Module::EXPORT_SOURCE_CLOUD !== $source ) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
unset( $result['file'] );
|
||||
|
||||
$raw_screen_shot = base64_decode( substr( $settings['screenShotBlob'], strlen( 'data:image/png;base64,' ) ) );
|
||||
$title = $export['manifest']['title'];
|
||||
$description = $export['manifest']['description'];
|
||||
|
||||
$kit = self::get_app()->create_kit(
|
||||
$title,
|
||||
$description,
|
||||
$file,
|
||||
$raw_screen_shot,
|
||||
$settings['include'],
|
||||
);
|
||||
|
||||
if ( is_wp_error( $kit ) ) {
|
||||
return $kit;
|
||||
}
|
||||
|
||||
$result['kit'] = $kit;
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function handle_import_kit_from_cloud( $args ) {
|
||||
$kit = self::get_app()->get_kit( [
|
||||
'id' => $args['kit_id'],
|
||||
] );
|
||||
|
||||
if ( is_wp_error( $kit ) ) {
|
||||
return $kit;
|
||||
}
|
||||
|
||||
if ( empty( $kit['downloadUrl'] ) ) {
|
||||
throw new \Error( ImportExport_Module::KIT_LIBRARY_ERROR_KEY ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
|
||||
}
|
||||
|
||||
return [
|
||||
'file_name' => self::get_remote_kit_zip( $kit['downloadUrl'] ),
|
||||
'referrer' => ImportExport_Module::REFERRER_CLOUD,
|
||||
'file_url' => $kit['downloadUrl'],
|
||||
'kit' => $kit,
|
||||
];
|
||||
}
|
||||
|
||||
public static function get_remote_kit_zip( $url ) {
|
||||
$remote_zip_request = wp_safe_remote_get( $url );
|
||||
|
||||
if ( is_wp_error( $remote_zip_request ) ) {
|
||||
Plugin::$instance->logger->get_logger()->error( $remote_zip_request->get_error_message() );
|
||||
throw new \Error( ImportExport_Module::KIT_LIBRARY_ERROR_KEY ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
|
||||
}
|
||||
|
||||
if ( 200 !== $remote_zip_request['response']['code'] ) {
|
||||
Plugin::$instance->logger->get_logger()->error( $remote_zip_request['response']['message'] );
|
||||
throw new \Error( ImportExport_Module::KIT_LIBRARY_ERROR_KEY ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
|
||||
}
|
||||
|
||||
return Plugin::$instance->uploads_manager->create_temp_file( $remote_zip_request['body'], 'kit.zip' );
|
||||
}
|
||||
|
||||
public static function get_app(): Cloud_Kits {
|
||||
$cloud_kits_app = Plugin::$instance->common->get_component( 'connect' )->get_app( 'cloud-kits' );
|
||||
|
||||
if ( ! $cloud_kits_app ) {
|
||||
$error_message = esc_html__( 'Cloud-Kits is not instantiated.', 'elementor' );
|
||||
|
||||
throw new \Exception( $error_message, Exceptions::FORBIDDEN ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
|
||||
}
|
||||
|
||||
return $cloud_kits_app;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user