first commit

This commit is contained in:
User A0264400
2026-04-01 23:20:16 +03:00
commit a766acdc90
23071 changed files with 4933189 additions and 0 deletions

View File

@@ -0,0 +1,420 @@
<?php
/**
* Astra Notices
*
* An easy to use PHP Library to add dismissible admin notices in the WordPress admin.
*
* @package Astra Notices
* @since 1.0.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'Astra_Notices' ) ) :
/**
* Astra_Notices
*
* @since 1.0.0
*/
class Astra_Notices {
/**
* Notices
*
* @access private
* @var array Notices.
* @since 1.0.0
*/
private static $version = '1.1.14';
/**
* Notices
*
* @access private
* @var array Notices.
* @since 1.0.0
*/
private static $notices = array();
/**
* Instance
*
* @access private
* @var object Class object.
* @since 1.0.0
*/
private static $instance;
/**
* Initiator
*
* @since 1.0.0
* @return object initialized object of class.
*/
public static function get_instance() {
if ( ! isset( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Constructor
*
* @since 1.0.0
*/
public function __construct() {
add_action( 'admin_notices', array( $this, 'show_notices' ), 30 );
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
add_action( 'wp_ajax_astra-notice-dismiss', array( $this, 'dismiss_notice' ) );
add_filter( 'wp_kses_allowed_html', array( $this, 'add_data_attributes' ), 10, 2 );
}
/**
* Filters and Returns a list of allowed tags and attributes for a given context.
*
* @param array $allowedposttags array of allowed tags.
* @param string $context Context type (explicit).
* @since 1.0.0
* @return array
*/
public function add_data_attributes( $allowedposttags, $context ) { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed
$allowedposttags['a']['data-repeat-notice-after'] = true;
return $allowedposttags;
}
/**
* Add Notice.
*
* @since 1.0.0
* @param array $args Notice arguments.
* @return void
*/
public static function add_notice( $args = array() ) {
self::$notices[] = $args;
if ( ! isset( $args['id'] ) ) {
return;
}
$notice_id = sanitize_key( $args['id'] ); // Notice ID.
$notices = get_option( 'allowed_astra_notices', array() );
if ( ! in_array( $notice_id, $notices, true ) ) {
$notices[] = $notice_id; // Add notice id to the array.
update_option( 'allowed_astra_notices', $notices ); // Update the option.
}
}
/**
* Dismiss Notice.
*
* @since 1.0.0
* @return void
*/
public function dismiss_notice() {
$notice_id = ( isset( $_POST['notice_id'] ) ) ? sanitize_key( $_POST['notice_id'] ) : '';
$repeat_notice_after = ( isset( $_POST['repeat_notice_after'] ) ) ? absint( $_POST['repeat_notice_after'] ) : '';
$nonce = ( isset( $_POST['nonce'] ) ) ? sanitize_key( $_POST['nonce'] ) : '';
$notice = $this->get_notice_by_id( $notice_id );
$capability = isset( $notice['capability'] ) ? $notice['capability'] : 'manage_options';
if ( ! apply_filters( 'astra_notices_user_cap_check', current_user_can( $capability ) ) ) {
return;
}
$allowed_notices = get_option( 'allowed_astra_notices', array() ); // Get allowed notices.
// Define restricted user meta keys.
$wp_default_meta_keys = array(
'wp_capabilities',
'wp_user_level',
'wp_user-settings',
'account_status',
'session_tokens',
);
// if $notice_id does not start with astra-notices-id and notice_id is not from the allowed notices, then return.
if ( strpos( $notice_id, 'astra-notices-id-' ) !== 0 && ( ! in_array( $notice_id, $allowed_notices, true ) ) ) {
return;
}
if ( false === wp_verify_nonce( $nonce, 'astra-notices' ) ) {
wp_send_json_error( esc_html_e( 'WordPress Nonce not validated.', 'ultimate-addons-for-gutenberg' ) );
}
// Valid inputs?
if ( ! empty( $notice_id ) ) {
if ( in_array( $notice_id, $wp_default_meta_keys, true ) ) {
wp_send_json_error( esc_html_e( 'Invalid notice ID.', 'ultimate-addons-for-gutenberg' ) );
}
if ( ! empty( $repeat_notice_after ) ) {
set_transient( $notice_id, true, $repeat_notice_after );
} else {
update_user_meta( get_current_user_id(), $notice_id, 'notice-dismissed' );
}
wp_send_json_success();
}
wp_send_json_error();
}
/**
* Enqueue Scripts.
*
* @since 1.0.0
* @return void
*/
public function enqueue_scripts() {
wp_register_style( 'astra-notices', self::get_url() . 'notices.css', array(), self::$version );
wp_register_script( 'astra-notices', self::get_url() . 'notices.js', array( 'jquery' ), self::$version, true );
wp_localize_script(
'astra-notices',
'astraNotices',
array(
'_notice_nonce' => wp_create_nonce( 'astra-notices' ),
)
);
}
/**
* Sort the notices based on the given priority of the notice.
* This function is called from usort()
*
* @since 1.5.2
* @param array $notice_1 First notice.
* @param array $notice_2 Second Notice.
* @return array
*/
public function sort_notices( $notice_1, $notice_2 ) {
if ( ! isset( $notice_1['priority'] ) ) {
$notice_1['priority'] = 10;
}
if ( ! isset( $notice_2['priority'] ) ) {
$notice_2['priority'] = 10;
}
return $notice_1['priority'] - $notice_2['priority'];
}
/**
* Get all registered notices.
* Since v1.1.8 it is recommended to register the notices on
*
* @return array|null
*/
private function get_notices() {
usort( self::$notices, array( $this, 'sort_notices' ) );
return self::$notices;
}
/**
* Get notice by notice_id
*
* @param string $notice_id Notice id.
*
* @return array notice based on the notice id.
*/
private function get_notice_by_id( $notice_id ) {
if ( empty( $notice_id ) ) {
return array();
}
$notices = $this->get_notices();
$notice = wp_list_filter(
$notices,
array(
'id' => $notice_id,
)
);
return ( ! empty( $notice ) && isset( $notice[0] ) ) ? $notice[0] : array();
}
/**
* Display the notices in the WordPress admin.
*
* @since 1.0.0
* @return void
*/
public function show_notices() {
$defaults = array(
'id' => '', // Optional, Notice ID. If empty it set `astra-notices-id-<$array-index>`.
'type' => 'info', // Optional, Notice type. Default `info`. Expected [info, warning, notice, error].
'message' => '', // Optional, Message.
'show_if' => true, // Optional, Show notice on custom condition. E.g. 'show_if' => if( is_admin() ) ? true, false, .
'repeat-notice-after' => '', // Optional, Dismiss-able notice time. It'll auto show after given time.
'display-notice-after' => false, // Optional, Dismiss-able notice time. It'll auto show after given time.
'class' => '', // Optional, Additional notice wrapper class.
'priority' => 10, // Priority of the notice.
'display-with-other-notices' => true, // Should the notice be displayed if other notices are being displayed from Astra_Notices.
'is_dismissible' => true,
'capability' => 'manage_options', // User capability - This capability is required for the current user to see this notice.
);
// Count for the notices that are rendered.
$notices_displayed = 0;
$notices = $this->get_notices();
foreach ( $notices as $key => $notice ) {
$notice = wp_parse_args( $notice, $defaults );
// Show notices only for users with `manage_options` cap.
if ( ! current_user_can( $notice['capability'] ) ) {
continue;
}
$notice['id'] = self::get_notice_id( $notice, $key );
$notice['classes'] = self::get_wrap_classes( $notice );
// Notices visible after transient expire.
if ( isset( $notice['show_if'] ) && true === $notice['show_if'] ) {
// don't display the notice if it is not supposed to be displayed with other notices.
if ( 0 !== $notices_displayed && false === $notice['display-with-other-notices'] ) {
continue;
}
if ( self::is_expired( $notice ) ) {
self::markup( $notice );
++$notices_displayed;
}
}
}
}
/**
* Render a notice.
*
* @since 1.0.0
* @param array $notice Notice markup.
* @return void
*/
public static function markup( $notice = array() ) {
wp_enqueue_script( 'astra-notices' );
wp_enqueue_style( 'astra-notices' );
do_action( 'astra_notice_before_markup' );
do_action( "astra_notice_before_markup_{$notice['id']}" );
?>
<div id="<?php echo esc_attr( $notice['id'] ); ?>" class="<?php echo 'astra-notice-wrapper ' . esc_attr( $notice['classes'] ); ?>" data-repeat-notice-after="<?php echo esc_attr( $notice['repeat-notice-after'] ); ?>">
<div class="astra-notice-container">
<?php do_action( "astra_notice_inside_markup_{$notice['id']}" ); ?>
<?php echo wp_kses_post( $notice['message'] ); ?>
</div>
</div>
<?php
do_action( "astra_notice_after_markup_{$notice['id']}" );
do_action( 'astra_notice_after_markup' );
}
/**
* Get wrapper classes for a notice.
*
* @since 1.0.0
*
* @param array $notice Notice arguments.
* @return array Notice wrapper classes.
*/
private static function get_wrap_classes( $notice ) {
$classes = array( 'astra-notice', 'notice' );
if ( $notice['is_dismissible'] ) {
$classes[] = 'is-dismissible';
}
$classes[] = $notice['class'];
if ( isset( $notice['type'] ) && '' !== $notice['type'] ) {
$classes[] = 'notice-' . $notice['type'];
}
return esc_attr( implode( ' ', $classes ) );
}
/**
* Get HTML ID for a given notice.
*
* @since 1.0.0
*
* @param array $notice Notice arguments.
* @param int $key Notice array index.
* @return string HTML if for the notice.
*/
private static function get_notice_id( $notice, $key ) {
if ( isset( $notice['id'] ) && ! empty( $notice['id'] ) ) {
return $notice['id'];
}
return 'astra-notices-id-' . $key;
}
/**
* Check if the notice is expires.
*
* @since 1.0.0
*
* @param array $notice Notice arguments.
* @return boolean
*/
private static function is_expired( $notice ) {
$transient_status = get_transient( $notice['id'] );
if ( false === $transient_status ) {
if ( isset( $notice['display-notice-after'] ) && false !== $notice['display-notice-after'] ) {
if ( 'delayed-notice' !== get_user_meta( get_current_user_id(), $notice['id'], true ) &&
'notice-dismissed' !== get_user_meta( get_current_user_id(), $notice['id'], true ) ) {
set_transient( $notice['id'], 'delayed-notice', $notice['display-notice-after'] );
update_user_meta( get_current_user_id(), $notice['id'], 'delayed-notice' );
return false;
}
}
// Check the user meta status if current notice is dismissed or delay completed.
$meta_status = get_user_meta( get_current_user_id(), $notice['id'], true );
if ( empty( $meta_status ) || 'delayed-notice' === $meta_status ) {
return true;
}
}
return false;
}
/**
* Get base URL for the astra-notices.
*
* @return mixed URL.
*/
public static function get_url() {
$path = wp_normalize_path( dirname( __FILE__ ) ); // phpcs:ignore Modernize.FunctionCalls.Dirname.FileConstant
$theme_dir = wp_normalize_path( get_template_directory() );
if ( strpos( $path, $theme_dir ) !== false ) {
return trailingslashit( get_template_directory_uri() . str_replace( $theme_dir, '', $path ) );
} else {
return plugin_dir_url( __FILE__ );
}
}
}
/**
* Kicking this off by calling 'get_instance()' method
*/
Astra_Notices::get_instance();
endif;

View File

@@ -0,0 +1,39 @@
.astra-review-notice-container {
display: flex;
align-items: center;
padding-top: 10px;
}
.astra-review-notice-container .dashicons {
font-size: 1.4em;
padding-left: 10px;
}
.astra-review-notice-container a {
padding-left: 5px;
text-decoration: none;
}
.astra-review-notice-container .dashicons:first-child {
padding-left: 0;
}
.astra-notice-container .notice-image img {
max-width: 90px;
}
.astra-notice-container .notice-content .notice-heading {
padding-bottom: 5px;
}
.astra-notice-container .notice-content {
margin-left: 15px;
}
.astra-notice-container {
padding-top: 10px;
padding-bottom: 10px;
display: flex;
justify-content: left;
align-items: center;
}

View File

@@ -0,0 +1,95 @@
/**
* Customizer controls toggles
*
* @package Astra
*/
( function( $ ) {
/**
* Helper class for the main Customizer interface.
*
* @since 1.0.0
* @class ASTCustomizer
*/
AstraNotices = {
/**
* Initializes our custom logic for the Customizer.
*
* @since 1.0.0
* @method init
*/
init: function()
{
this._bind();
},
/**
* Binds events for the Astra Portfolio.
*
* @since 1.0.0
* @access private
* @method _bind
*/
_bind: function()
{
$( document ).on('click', '.astra-notice-close', AstraNotices._dismissNoticeNew );
$( document ).on('click', '.astra-notice .notice-dismiss', AstraNotices._dismissNotice );
},
_dismissNotice: function( event ) {
event.preventDefault();
var repeat_notice_after = $( this ).parents('.astra-notice').data( 'repeat-notice-after' ) || '';
var notice_id = $( this ).parents('.astra-notice').attr( 'id' ) || '';
AstraNotices._ajax( notice_id, repeat_notice_after );
},
_dismissNoticeNew: function( event ) {
event.preventDefault();
var repeat_notice_after = $( this ).attr( 'data-repeat-notice-after' ) || '';
var notice_id = $( this ).parents('.astra-notice').attr( 'id' ) || '';
var $el = $( this ).parents('.astra-notice');
$el.fadeTo( 100, 0, function() {
$el.slideUp( 100, function() {
$el.remove();
});
});
AstraNotices._ajax( notice_id, repeat_notice_after );
var link = $( this ).attr( 'href' ) || '';
var target = $( this ).attr( 'target' ) || '';
if( '' !== link && '_blank' === target ) {
window.open(link , '_blank');
}
},
_ajax: function( notice_id, repeat_notice_after ) {
if( '' === notice_id ) {
return;
}
$.ajax({
url: ajaxurl,
type: 'POST',
data: {
action : 'astra-notice-dismiss',
nonce : astraNotices._notice_nonce,
notice_id : notice_id,
repeat_notice_after : parseInt( repeat_notice_after ),
},
});
}
};
$( function() {
AstraNotices.init();
} );
} )( jQuery );

View File

@@ -0,0 +1,202 @@
<?php
/**
* WP Async Request
*
* @package WP-Background-Processing
*/
/**
* Abstract WP_Async_Request class.
*
* @abstract
*/
abstract class WP_Async_Request {
/**
* Prefix
*
* (default value: 'wp')
*
* @var string
* @access protected
*/
protected $prefix = 'wp';
/**
* Action
*
* (default value: 'async_request')
*
* @var string
* @access protected
*/
protected $action = 'async_request';
/**
* Identifier
*
* @var mixed
* @access protected
*/
protected $identifier;
/**
* Data
*
* (default value: array())
*
* @var array
* @access protected
*/
protected $data = array();
/**
* Initiate new async request.
*/
public function __construct() {
$this->identifier = $this->prefix . '_' . $this->action;
add_action( 'wp_ajax_' . $this->identifier, array( $this, 'maybe_handle' ) );
add_action( 'wp_ajax_nopriv_' . $this->identifier, array( $this, 'maybe_handle' ) );
}
/**
* Set data used during the request.
*
* @param array $data Data.
*
* @return $this
*/
public function data( $data ) {
$this->data = $data;
return $this;
}
/**
* Dispatch the async request.
*
* @return array|WP_Error|false HTTP Response array, WP_Error on failure, or false if not attempted.
*/
public function dispatch() {
$url = add_query_arg( $this->get_query_args(), $this->get_query_url() );
$args = $this->get_post_args();
return wp_remote_post( esc_url_raw( $url ), $args );
}
/**
* Get query args.
*
* @return array
*/
protected function get_query_args() {
if ( property_exists( $this, 'query_args' ) ) {
return $this->query_args;
}
$args = array(
'action' => $this->identifier,
'nonce' => wp_create_nonce( $this->identifier ),
);
/**
* Filters the post arguments used during an async request.
*
* @param array $url
*/
return apply_filters( $this->identifier . '_query_args', $args );
}
/**
* Get query URL.
*
* @return string
*/
protected function get_query_url() {
if ( property_exists( $this, 'query_url' ) ) {
return $this->query_url;
}
$url = admin_url( 'admin-ajax.php' );
/**
* Filters the post arguments used during an async request.
*
* @param string $url
*/
return apply_filters( $this->identifier . '_query_url', $url );
}
/**
* Get post args.
*
* @return array
*/
protected function get_post_args() {
if ( property_exists( $this, 'post_args' ) ) {
return $this->post_args;
}
$args = array(
'timeout' => 5, // @phpcs:ignore
'blocking' => false,
'body' => $this->data,
'cookies' => $_COOKIE, // @phpcs:ignore
'sslverify' => apply_filters( 'https_local_ssl_verify', false ), // Local requests, fine to pass false.
);
/**
* Filters the post arguments used during an async request.
*
* @param array $args
*/
return apply_filters( $this->identifier . '_post_args', $args );
}
/**
* Maybe handle a dispatched request.
*
* Check for correct nonce and pass to handler.
*
* @return void|mixed
*/
public function maybe_handle() {
// Don't lock up other requests while processing.
session_write_close(); // @phpcs:ignore
check_ajax_referer( $this->identifier, 'nonce' );
$this->handle();
return $this->maybe_wp_die();
}
/**
* Should the process exit with wp_die?
*
* @param mixed $return What to return if filter says don't die, default is null.
*
* @return void|mixed
*/
protected function maybe_wp_die( $return = null ) {
/**
* Should wp_die be used?
*
* @return bool
*/
if ( apply_filters( $this->identifier . '_wp_die', true ) ) {
wp_die();
}
return $return;
}
/**
* Handle a dispatched request.
*
* Override this method to perform any actions required
* during the async request.
*/
abstract protected function handle();
}

View File

@@ -0,0 +1,506 @@
<?php
/**
* WP Background Process
*
* @package WP-Background-Processing
*/
if ( ! class_exists( 'WP_Background_Process' ) ) {
/**
* Abstract WP_Background_Process class.
*
* @abstract
* @extends WP_Async_Request
*/
abstract class WP_Background_Process extends WP_Async_Request {
/**
* Action
*
* (default value: 'background_process')
*
* @var string
* @access protected
*/
protected $action = 'background_process';
/**
* Start time of current process.
*
* (default value: 0)
*
* @var int
* @access protected
*/
protected $start_time = 0;
/**
* Cron_hook_identifier
*
* @var mixed
* @access protected
*/
protected $cron_hook_identifier;
/**
* Cron_interval_identifier
*
* @var mixed
* @access protected
*/
protected $cron_interval_identifier;
/**
* Initiate new background process
*/
public function __construct() {
parent::__construct();
$this->cron_hook_identifier = $this->identifier . '_cron';
$this->cron_interval_identifier = $this->identifier . '_cron_interval';
add_action( $this->cron_hook_identifier, array( $this, 'handle_cron_healthcheck' ) );
add_filter( 'cron_schedules', array( $this, 'schedule_cron_healthcheck' ) );
}
/**
* Dispatch
*
* @access public
* @return void
*/
public function dispatch() {
// Schedule the cron healthcheck.
$this->schedule_event();
// Perform remote post.
return parent::dispatch();
}
/**
* Push to queue
*
* @param mixed $data Data.
*
* @return $this
*/
public function push_to_queue( $data ) {
$this->data[] = $data;
return $this;
}
/**
* Save queue
*
* @return $this
*/
public function save() {
$key = $this->generate_key();
if ( ! empty( $this->data ) ) {
update_site_option( $key, $this->data );
}
return $this;
}
/**
* Update queue
*
* @param string $key Key.
* @param array $data Data.
*
* @return $this
*/
public function update( $key, $data ) {
if ( ! empty( $data ) ) {
update_site_option( $key, $data );
}
return $this;
}
/**
* Delete queue
*
* @param string $key Key.
*
* @return $this
*/
public function delete( $key ) {
delete_site_option( $key );
return $this;
}
/**
* Generate key
*
* Generates a unique key based on microtime. Queue items are
* given a unique key so that they can be merged upon save.
*
* @param int $length Length.
*
* @return string
*/
protected function generate_key( $length = 64 ) {
$unique = md5( microtime() . rand() );
$prepend = $this->identifier . '_batch_';
return substr( $prepend . $unique, 0, $length );
}
/**
* Maybe process queue
*
* Checks whether data exists within the queue and that
* the process is not already running.
*/
public function maybe_handle() {
// Don't lock up other requests while processing
session_write_close();
if ( $this->is_process_running() ) {
// Background process already running.
wp_die();
}
if ( $this->is_queue_empty() ) {
// No data to process.
wp_die();
}
check_ajax_referer( $this->identifier, 'nonce' );
$this->handle();
wp_die();
}
/**
* Is queue empty
*
* @return bool
*/
protected function is_queue_empty() {
global $wpdb;
$table = $wpdb->options;
$column = 'option_name';
if ( is_multisite() ) {
$table = $wpdb->sitemeta;
$column = 'meta_key';
}
$key = $wpdb->esc_like( $this->identifier . '_batch_' ) . '%';
$count = $wpdb->get_var( $wpdb->prepare( "
SELECT COUNT(*)
FROM {$table}
WHERE {$column} LIKE %s
", $key ) );
return ( $count > 0 ) ? false : true;
}
/**
* Is process running
*
* Check whether the current process is already running
* in a background process.
*/
protected function is_process_running() {
if ( get_site_transient( $this->identifier . '_process_lock' ) ) {
// Process already running.
return true;
}
return false;
}
/**
* Lock process
*
* Lock the process so that multiple instances can't run simultaneously.
* Override if applicable, but the duration should be greater than that
* defined in the time_exceeded() method.
*/
protected function lock_process() {
$this->start_time = time(); // Set start time of current process.
$lock_duration = ( property_exists( $this, 'queue_lock_time' ) ) ? $this->queue_lock_time : 60; // 1 minute
$lock_duration = apply_filters( $this->identifier . '_queue_lock_time', $lock_duration );
set_site_transient( $this->identifier . '_process_lock', microtime(), $lock_duration );
}
/**
* Unlock process
*
* Unlock the process so that other instances can spawn.
*
* @return $this
*/
protected function unlock_process() {
delete_site_transient( $this->identifier . '_process_lock' );
return $this;
}
/**
* Get batch
*
* @return stdClass Return the first batch from the queue
*/
protected function get_batch() {
global $wpdb;
$table = $wpdb->options;
$column = 'option_name';
$key_column = 'option_id';
$value_column = 'option_value';
if ( is_multisite() ) {
$table = $wpdb->sitemeta;
$column = 'meta_key';
$key_column = 'meta_id';
$value_column = 'meta_value';
}
$key = $wpdb->esc_like( $this->identifier . '_batch_' ) . '%';
$query = $wpdb->get_row( $wpdb->prepare( "
SELECT *
FROM {$table}
WHERE {$column} LIKE %s
ORDER BY {$key_column} ASC
LIMIT 1
", $key ) );
$batch = new stdClass();
$batch->key = $query->$column;
$batch->data = maybe_unserialize( $query->$value_column );
return $batch;
}
/**
* Handle
*
* Pass each queue item to the task handler, while remaining
* within server memory and time limit constraints.
*/
protected function handle() {
$this->lock_process();
do {
$batch = $this->get_batch();
foreach ( $batch->data as $key => $value ) {
$task = $this->task( $value );
if ( false !== $task ) {
$batch->data[ $key ] = $task;
} else {
unset( $batch->data[ $key ] );
}
if ( $this->time_exceeded() || $this->memory_exceeded() ) {
// Batch limits reached.
break;
}
}
// Update or delete current batch.
if ( ! empty( $batch->data ) ) {
$this->update( $batch->key, $batch->data );
} else {
$this->delete( $batch->key );
}
} while ( ! $this->time_exceeded() && ! $this->memory_exceeded() && ! $this->is_queue_empty() );
$this->unlock_process();
// Start next batch or complete process.
if ( ! $this->is_queue_empty() ) {
$this->dispatch();
} else {
$this->complete();
}
wp_die();
}
/**
* Memory exceeded
*
* Ensures the batch process never exceeds 90%
* of the maximum WordPress memory.
*
* @return bool
*/
protected function memory_exceeded() {
$memory_limit = $this->get_memory_limit() * 0.9; // 90% of max memory
$current_memory = memory_get_usage( true );
$return = false;
if ( $current_memory >= $memory_limit ) {
$return = true;
}
return apply_filters( $this->identifier . '_memory_exceeded', $return );
}
/**
* Get memory limit
*
* @return int
*/
protected function get_memory_limit() {
if ( function_exists( 'ini_get' ) ) {
$memory_limit = ini_get( 'memory_limit' );
} else {
// Sensible default.
$memory_limit = '128M';
}
if ( ! $memory_limit || -1 === intval( $memory_limit ) ) {
// Unlimited, set to 32GB.
$memory_limit = '32000M';
}
return intval( $memory_limit ) * 1024 * 1024;
}
/**
* Time exceeded.
*
* Ensures the batch never exceeds a sensible time limit.
* A timeout limit of 30s is common on shared hosting.
*
* @return bool
*/
protected function time_exceeded() {
$finish = $this->start_time + apply_filters( $this->identifier . '_default_time_limit', 20 ); // 20 seconds
$return = false;
if ( time() >= $finish ) {
$return = true;
}
return apply_filters( $this->identifier . '_time_exceeded', $return );
}
/**
* Complete.
*
* Override if applicable, but ensure that the below actions are
* performed, or, call parent::complete().
*/
protected function complete() {
// Unschedule the cron healthcheck.
$this->clear_scheduled_event();
}
/**
* Schedule cron healthcheck
*
* @access public
* @param mixed $schedules Schedules.
* @return mixed
*/
public function schedule_cron_healthcheck( $schedules ) {
$interval = apply_filters( $this->identifier . '_cron_interval', 5 );
if ( property_exists( $this, 'cron_interval' ) ) {
$interval = apply_filters( $this->identifier . '_cron_interval', $this->cron_interval );
}
// Adds every 5 minutes to the existing schedules.
$schedules[ $this->identifier . '_cron_interval' ] = array(
'interval' => MINUTE_IN_SECONDS * $interval,
'display' => sprintf( /* translators: %d: Minutes interval */ __( 'Every %d Minutes', 'ultimate-addons-for-gutenberg' ), $interval ),
);
return $schedules;
}
/**
* Handle cron healthcheck
*
* Restart the background process if not already running
* and data exists in the queue.
*/
public function handle_cron_healthcheck() {
if ( $this->is_process_running() ) {
// Background process already running.
exit;
}
if ( $this->is_queue_empty() ) {
// No data to process.
$this->clear_scheduled_event();
exit;
}
$this->handle();
exit;
}
/**
* Schedule event
*/
protected function schedule_event() {
if ( ! wp_next_scheduled( $this->cron_hook_identifier ) ) {
wp_schedule_event( time(), $this->cron_interval_identifier, $this->cron_hook_identifier );
}
}
/**
* Clear scheduled event
*/
protected function clear_scheduled_event() {
$timestamp = wp_next_scheduled( $this->cron_hook_identifier );
if ( $timestamp ) {
wp_unschedule_event( $timestamp, $this->cron_hook_identifier );
}
}
/**
* Cancel Process
*
* Stop processing queue items, clear cronjob and delete batch.
*
*/
public function cancel_process() {
if ( ! $this->is_queue_empty() ) {
$batch = $this->get_batch();
$this->delete( $batch->key );
wp_clear_scheduled_hook( $this->cron_hook_identifier );
}
}
/**
* Task
*
* Override this method to perform any actions required on each
* queue item. Return the modified item for further processing
* in the next pass through. Or, return false to remove the
* item from the queue.
*
* @param mixed $item Queue item to iterate over.
*
* @return mixed
*/
abstract protected function task( $item );
}
}

View File

@@ -0,0 +1 @@
[ID*="-optin-notice"]{padding:1px 12px;border-right-color:#007cba}[ID*="-optin-notice"] .notice-container{padding-top:10px;padding-bottom:12px}[ID*="-optin-notice"] .notice-content{margin:0}[ID*="-optin-notice"] .notice-heading{padding:0 0 12px 20px}[ID*="-optin-notice"] .button-primary{margin-left:5px}

View File

@@ -0,0 +1 @@
[ID*="-optin-notice"]{padding:1px 12px;border-left-color:#007cba}[ID*="-optin-notice"] .notice-container{padding-top:10px;padding-bottom:12px}[ID*="-optin-notice"] .notice-content{margin:0}[ID*="-optin-notice"] .notice-heading{padding:0 20px 12px 0}[ID*="-optin-notice"] .button-primary{margin-right:5px}

View File

@@ -0,0 +1,21 @@
[ID*="-optin-notice"] {
padding: 1px 12px;
border-right-color: #007cba;
}
[ID*="-optin-notice"] .notice-container {
padding-top: 10px;
padding-bottom: 12px;
}
[ID*="-optin-notice"] .notice-content {
margin: 0;
}
[ID*="-optin-notice"] .notice-heading {
padding: 0 0 12px 20px;
}
[ID*="-optin-notice"] .button-primary {
margin-left: 5px;
}

View File

@@ -0,0 +1,21 @@
[ID*="-optin-notice"] {
padding: 1px 12px;
border-left-color: #007cba;
}
[ID*="-optin-notice"] .notice-container {
padding-top: 10px;
padding-bottom: 12px;
}
[ID*="-optin-notice"] .notice-content {
margin: 0;
}
[ID*="-optin-notice"] .notice-heading {
padding: 0 20px 12px 0;
}
[ID*="-optin-notice"] .button-primary {
margin-right: 5px;
}

View File

@@ -0,0 +1,20 @@
v1.1.17 - 29-January-2025
- Improvement: Renamed options from `*_analytics_*` to `*_usage_*`.
v1.1.16 - 15-July-2025
- Improvement: Added `SureRank` slug to UTM analytics.
v1.1.15 - 1-July-2025
- Improvement: Added `Ultimate_VC_Addons` slug to UTM analytics.
v1.1.14 - 6-May-2025
- New: Introduced a key 'hide_optin_checkbox' to hide checkbox from Settings > General.
- Improvement: Single optin notice for all bsf products.
- Improvement: Introduced delay of 7 days for next optin message if user has reqested request from product.
v1.1.13 - 17-April-2025
- Improvement: Ensured unique id for label's `for` attribute in deactivation survey fields by prefixing them with product slugs.
- Improvement: Prevented deactivation survey from triggering when switching from a child theme to its parent.
v1.1.12 - 24-March-2025
- Improvement: Added `suremails` and `latepoint` slugs to UTM analytics.

View File

@@ -0,0 +1,118 @@
<?php
/**
* BSF analytics loader file.
*
* @version 1.0.0
*
* @package bsf-analytics
*/
if ( ! defined( 'ABSPATH' ) ) {
exit();
}
/**
* Class BSF_Analytics_Loader.
*/
class BSF_Analytics_Loader {
/**
* Analytics Entities.
*
* @access private
* @var array Entities array.
*/
private $entities = array();
/**
* Analytics Version.
*
* @access private
* @var float analytics version.
*/
private $analytics_version = '';
/**
* Analytics path.
*
* @access private
* @var string path array.
*/
private $analytics_path = '';
/**
* Instance
*
* @access private
* @var object Class object.
*/
private static $instance = null;
/**
* Get instace of class.
*
* @return object
*/
public static function get_instance() {
if ( null === self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Constructor
*/
public function __construct() {
add_action( 'init', array( $this, 'load_analytics' ) );
}
/**
* Set entity for analytics.
*
* @param string $data Entity attributes data.
* @return void
*/
public function set_entity( $data ) {
array_push( $this->entities, $data );
}
/**
* Load Analytics library.
*
* @return void
*/
public function load_analytics() {
$unique_entities = array();
if ( ! empty( $this->entities ) ) {
foreach ( $this->entities as $entity ) {
foreach ( $entity as $key => $data ) {
if ( isset( $data['path'] ) ) {
if ( file_exists( $data['path'] . '/version.json' ) ) {
$file_contents = file_get_contents( $data['path'] . '/version.json' ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
$analytics_version = json_decode( $file_contents, 1 );
$analytics_version = $analytics_version['bsf-analytics-ver'];
if ( version_compare( $analytics_version, $this->analytics_version, '>' ) ) {
$this->analytics_version = $analytics_version;
$this->analytics_path = $data['path'];
}
}
}
if ( ! isset( $unique_entities[ $key ] ) ) {
$unique_entities[ $key ] = $data;
}
}
}
if ( file_exists( $this->analytics_path ) && ! class_exists( 'BSF_Analytics' ) ) {
require_once $this->analytics_path . '/class-bsf-analytics.php';
new BSF_Analytics( $unique_entities, $this->analytics_path, $this->analytics_version );
}
}
}
}

View File

@@ -0,0 +1,258 @@
<?php
/**
* BSF analytics stat class file.
*
* @package bsf-analytics
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'BSF_Analytics_Stats' ) ) {
/**
* BSF analytics stat class.
*/
class BSF_Analytics_Stats {
/**
* Active plugins.
*
* Holds the sites active plugins list.
*
* @var array
*/
private $plugins;
/**
* Instance of BSF_Analytics_Stats.
*
* Holds only the first object of class.
*
* @var object
*/
private static $instance = null;
/**
* Create only once instance of a class.
*
* @return object
* @since 1.0.0
*/
public static function instance() {
if ( null === self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Get stats.
*
* @return array stats data.
* @since 1.0.0
*/
public function get_stats() {
return apply_filters( 'bsf_core_stats', $this->get_default_stats() );
}
/**
* Retrieve stats for site.
*
* @return array stats data.
* @since 1.0.0
*/
private function get_default_stats() {
return array(
'graupi_version' => defined( 'BSF_UPDATER_VERSION' ) ? BSF_UPDATER_VERSION : false,
'domain_name' => get_site_url(),
'php_os' => PHP_OS,
'server_software' => isset( $_SERVER['SERVER_SOFTWARE'] ) ? wp_kses( wp_unslash( $_SERVER['SERVER_SOFTWARE'] ), [] ) : '',
'mysql_version' => $this->get_mysql_version(),
'php_version' => $this->get_php_version(),
'php_max_input_vars' => ini_get( 'max_input_vars' ), // phpcs:ignore:PHPCompatibility.IniDirectives.NewIniDirectives.max_input_varsFound
'php_post_max_size' => ini_get( 'post_max_size' ),
'php_max_execution_time' => ini_get( 'max_execution_time' ),
'php_memory_limit' => ini_get( 'memory_limit' ),
'zip_installed' => extension_loaded( 'zip' ),
'imagick_availabile' => extension_loaded( 'imagick' ),
'xmlreader_exists' => class_exists( 'XMLReader' ),
'gd_available' => extension_loaded( 'gd' ),
'curl_version' => $this->get_curl_version(),
'curl_ssl_version' => $this->get_curl_ssl_version(),
'is_writable' => $this->is_content_writable(),
'wp_version' => get_bloginfo( 'version' ),
'user_count' => $this->get_user_count(),
'posts_count' => wp_count_posts()->publish,
'page_count' => wp_count_posts( 'page' )->publish,
'site_language' => get_locale(),
'timezone' => wp_timezone_string(),
'is_ssl' => is_ssl(),
'is_multisite' => is_multisite(),
'network_url' => network_site_url(),
'external_object_cache' => (bool) wp_using_ext_object_cache(),
'wp_debug' => WP_DEBUG,
'wp_debug_display' => WP_DEBUG_DISPLAY,
'script_debug' => SCRIPT_DEBUG,
'active_plugins' => $this->get_active_plugins(),
'active_theme' => get_template(),
'active_stylesheet' => get_stylesheet(),
);
}
/**
* Get installed PHP version.
*
* @return float PHP version.
* @since 1.0.0
*/
private function get_php_version() {
if ( defined( 'PHP_MAJOR_VERSION' ) && defined( 'PHP_MINOR_VERSION' ) && defined( 'PHP_RELEASE_VERSION' ) ) { // phpcs:ignore
return PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION . '.' . PHP_RELEASE_VERSION;
}
return phpversion();
}
/**
* User count on site.
*
* @return int User count.
* @since 1.0.0
*/
private function get_user_count() {
if ( is_multisite() ) {
$user_count = get_user_count();
} else {
$count = count_users();
$user_count = $count['total_users'];
}
return $user_count;
}
/**
* Get active plugin's data.
*
* @return array active plugin's list.
* @since 1.0.0
*/
private function get_active_plugins() {
if ( ! $this->plugins ) {
// Ensure get_plugin_data function is loaded.
if ( ! function_exists( 'get_plugin_data' ) ) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
$plugins = wp_get_active_and_valid_plugins();
$plugins = array_map( 'get_plugin_data', $plugins );
$this->plugins = array_map( array( $this, 'format_plugin' ), $plugins );
}
return $this->plugins;
}
/**
* Format plugin data.
*
* @param string $plugin plugin.
* @return array formatted plugin data.
* @since 1.0.0
*/
public function format_plugin( $plugin ) {
return array(
'name' => html_entity_decode( $plugin['Name'], ENT_COMPAT, 'UTF-8' ),
'url' => $plugin['PluginURI'],
'version' => $plugin['Version'],
'slug' => $plugin['TextDomain'],
'author_name' => html_entity_decode( wp_strip_all_tags( $plugin['Author'] ), ENT_COMPAT, 'UTF-8' ),
'author_url' => $plugin['AuthorURI'],
);
}
/**
* Curl SSL version.
*
* @return float SSL version.
* @since 1.0.0
*/
private function get_curl_ssl_version() {
$curl = array();
if ( function_exists( 'curl_version' ) ) {
$curl = curl_version(); // phpcs:ignore WordPress.WP.AlternativeFunctions.curl_curl_version
}
return isset( $curl['ssl_version'] ) ? $curl['ssl_version'] : false;
}
/**
* Get cURL version.
*
* @return float cURL version.
* @since 1.0.0
*/
private function get_curl_version() {
if ( function_exists( 'curl_version' ) ) {
$curl = curl_version(); // phpcs:ignore WordPress.WP.AlternativeFunctions.curl_curl_version
}
return isset( $curl['version'] ) ? $curl['version'] : false;
}
/**
* Get MySQL version.
*
* @return float MySQL version.
* @since 1.0.0
*/
private function get_mysql_version() {
global $wpdb;
return $wpdb->db_version();
}
/**
* Check if content directory is writable.
*
* @return bool
* @since 1.0.0
*/
private function is_content_writable() {
$upload_dir = wp_upload_dir();
return wp_is_writable( $upload_dir['basedir'] );
}
}
}
/**
* Polyfill for sites using WP version less than 5.3
*/
if ( ! function_exists( 'wp_timezone_string' ) ) {
/**
* Get timezone string.
*
* @return string timezone string.
* @since 1.0.0
*/
function wp_timezone_string() {
$timezone_string = get_option( 'timezone_string' );
if ( $timezone_string ) {
return $timezone_string;
}
$offset = (float) get_option( 'gmt_offset' );
$hours = (int) $offset;
$minutes = ( $offset - $hours );
$sign = ( $offset < 0 ) ? '-' : '+';
$abs_hour = abs( $hours );
$abs_mins = abs( $minutes * 60 );
$tz_offset = sprintf( '%s%02d:%02d', $sign, $abs_hour, $abs_mins );
return $tz_offset;
}
}

View File

@@ -0,0 +1,650 @@
<?php
/**
* BSF analytics class file.
*
* @version 1.0.0
*
* @package bsf-analytics
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'BSF_Analytics' ) ) {
/**
* BSF analytics
*/
class BSF_Analytics {
/**
* Member Variable
*
* @var array Entities data.
*/
private $entities;
/**
* Member Variable
*
* @var string Usage tracking document URL
*/
public $usage_doc_link = 'https://store.brainstormforce.com/usage-tracking/?utm_source=wp_dashboard&utm_medium=general_settings&utm_campaign=usage_tracking';
/**
* Setup actions, load files.
*
* @param array $args entity data for analytics.
* @param string $analytics_path directory path to analytics library.
* @param float $analytics_version analytics library version.
* @since 1.0.0
*/
public function __construct( $args, $analytics_path, $analytics_version ) {
// Bail when no analytics entities are registered.
if ( empty( $args ) ) {
return;
}
$this->entities = $args;
// Run migration from old "analytics" option names to new "usage" names.
$this->maybe_migrate_options();
define( 'BSF_ANALYTICS_VERSION', $analytics_version );
define( 'BSF_ANALYTICS_URI', $this->get_analytics_url( $analytics_path ) );
add_action( 'admin_init', array( $this, 'handle_optin_optout' ) );
add_action( 'admin_init', array( $this, 'option_notice' ) );
add_action( 'init', array( $this, 'maybe_track_analytics' ), 99 );
$this->set_actions();
add_action( 'admin_init', array( $this, 'register_usage_tracking_setting' ) );
$this->includes();
$this->load_deactivation_survey_actions();
}
/**
* Function to load the deactivation survey form actions.
*
* @since 1.1.6
* @return void
*/
public function load_deactivation_survey_actions() {
// If not in a admin area then return it.
if ( ! is_admin() ) {
return;
}
add_filter( 'uds_survey_vars', array( $this, 'add_slugs_to_uds_vars' ) );
add_action( 'admin_footer', array( $this, 'load_deactivation_survey_form' ) );
}
/**
* Setup actions for admin notice style and analytics cron event.
*
* @since 1.0.4
*/
public function set_actions() {
foreach ( $this->entities as $key => $data ) {
add_action( 'astra_notice_before_markup_' . $key . '-optin-notice', array( $this, 'enqueue_assets' ) );
add_action( 'update_option_' . $key . '_usage_optin', array( $this, 'update_analytics_option_callback' ), 10, 3 );
add_action( 'add_option_' . $key . '_usage_optin', array( $this, 'add_analytics_option_callback' ), 10, 2 );
}
}
/**
* BSF Analytics URL
*
* @param string $analytics_path directory path to analytics library.
* @return String URL of bsf-analytics directory.
* @since 1.0.0
*/
public function get_analytics_url( $analytics_path ) {
$content_dir_path = wp_normalize_path( WP_CONTENT_DIR );
$analytics_path = wp_normalize_path( $analytics_path );
return str_replace( $content_dir_path, content_url(), $analytics_path );
}
/**
* Enqueue Scripts.
*
* @since 1.0.0
* @return void
*/
public function enqueue_assets() {
/**
* Load unminified if SCRIPT_DEBUG is true.
*
* Directory and Extensions.
*/
$dir_name = ( SCRIPT_DEBUG ) ? 'unminified' : 'minified';
$file_rtl = ( is_rtl() ) ? '-rtl' : '';
$css_ext = ( SCRIPT_DEBUG ) ? '.css' : '.min.css';
$css_uri = BSF_ANALYTICS_URI . '/assets/css/' . $dir_name . '/style' . $file_rtl . $css_ext;
wp_enqueue_style( 'bsf-analytics-admin-style', $css_uri, false, BSF_ANALYTICS_VERSION, 'all' );
}
/**
* Send analytics API call.
*
* @since 1.0.0
*/
public function send() {
$api_url = BSF_Analytics_Helper::get_api_url();
wp_remote_post(
$api_url . 'api/analytics/',
array(
'body' => BSF_Analytics_Stats::instance()->get_stats(),
'timeout' => 5,
'blocking' => false,
)
);
}
/**
* Check if usage tracking is enabled.
*
* @return bool
* @since 1.0.0
*/
public function is_tracking_enabled() {
foreach ( $this->entities as $key => $data ) {
$is_enabled = get_site_option( $key . '_usage_optin', false ) === 'yes' ? true : false;
$is_enabled = $this->is_white_label_enabled( $key ) ? false : $is_enabled;
if ( apply_filters( $key . '_tracking_enabled', $is_enabled ) ) {
return true;
}
}
return false;
}
/**
* Check if WHITE label is enabled for BSF products.
*
* @param string $source source of analytics.
* @return bool
* @since 1.0.0
*/
public function is_white_label_enabled( $source ) {
$options = apply_filters( $source . '_white_label_options', array() );
$is_enabled = false;
if ( is_array( $options ) ) {
foreach ( $options as $option ) {
if ( true === $option ) {
$is_enabled = true;
break;
}
}
}
return $is_enabled;
}
/**
* Display admin notice for usage tracking.
*
* @since 1.0.0
*/
public function option_notice() {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
if( $this->is_tracking_enabled() ) {
return; // Don't need to display notice if any of our plugin already have the permission.
}
// If the user has opted out of tracking, don't show the notice till 7 days.
$last_displayed_time = get_site_option( 'bsf_usage_last_displayed_time', false );
if ( $last_displayed_time && $last_displayed_time > time() - ( 7 * DAY_IN_SECONDS ) ) {
return; // Don't display the notice if it was displayed recently.
}
foreach ( $this->entities as $key => $data ) {
$time_to_display = isset( $data['time_to_display'] ) ? $data['time_to_display'] : '+24 hours';
$usage_doc_link = isset( $data['usage_doc_link'] ) ? $data['usage_doc_link'] : $this->usage_doc_link;
// Don't display the notice if tracking is disabled or White Label is enabled for any of our plugins.
if ( false !== get_site_option( $key . '_usage_optin', false ) || $this->is_white_label_enabled( $key ) ) {
continue;
}
// Show tracker consent notice after 24 hours from installed time.
if ( strtotime( $time_to_display, $this->get_analytics_install_time( $key ) ) > time() ) {
continue;
}
/* translators: %s product name */
$notice_string = sprintf(
__(
'Help us improve %1$s and our other products!<br><br>With your permission, we\'d like to collect <strong>non-sensitive information</strong> from your website — like your PHP version and which features you use — so we can fix bugs faster, make smarter decisions, and build features that actually matter to you. <em>No personal info. Ever.</em>', 'ultimate-addons-for-gutenberg' ),
'<strong>' . esc_html( $data['product_name'] ) . '</strong>'
);
if ( is_multisite() ) {
$notice_string .= __( 'This will be applicable for all sites from the network.', 'ultimate-addons-for-gutenberg' );
}
$language_dir = is_rtl() ? 'rtl' : 'ltr';
Astra_Notices::add_notice(
array(
'id' => $key . '-optin-notice',
'type' => '',
'message' => sprintf(
'<div class="notice-content">
<div class="notice-heading">
%1$s
</div>
<div class="astra-notices-container">
<a href="%2$s" class="astra-notices button-primary">
%3$s
</a>
<a href="%4$s" data-repeat-notice-after="%5$s" class="astra-notices button-secondary">
%6$s
</a>
</div>
</div>',
/* translators: %s usage doc link */
sprintf( $notice_string . '<span dir="%1s"><a href="%2s" target="_blank" rel="noreferrer noopener">%3s</a><span><br><br>', $language_dir, esc_url( $usage_doc_link ), __( ' Know More.', 'ultimate-addons-for-gutenberg' ) ),
esc_url(
add_query_arg(
array(
$key . '_analytics_optin' => 'yes',
$key . '_analytics_nonce' => wp_create_nonce( $key . '_analytics_optin' ),
'bsf_analytics_source' => $key,
)
)
),
__( 'Yes! Allow it', 'ultimate-addons-for-gutenberg' ),
esc_url(
add_query_arg(
array(
$key . '_analytics_optin' => 'no',
$key . '_analytics_nonce' => wp_create_nonce( $key . '_analytics_optin' ),
'bsf_analytics_source' => $key,
)
)
),
MONTH_IN_SECONDS,
__( 'No Thanks', 'ultimate-addons-for-gutenberg' )
),
'show_if' => true,
'repeat-notice-after' => false,
'priority' => 18,
'display-with-other-notices' => true,
)
);
return;
}
}
/**
* Process usage tracking opt out.
*
* @since 1.0.0
*/
public function handle_optin_optout() {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
$source = isset( $_GET['bsf_analytics_source'] ) ? sanitize_text_field( wp_unslash( $_GET['bsf_analytics_source'] ) ) : '';
if ( ! isset( $_GET[ $source . '_analytics_nonce' ] ) ) {
return;
}
if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET[ $source . '_analytics_nonce' ] ) ), $source . '_analytics_optin' ) ) {
return;
}
$optin_status = isset( $_GET[ $source . '_analytics_optin' ] ) ? sanitize_text_field( wp_unslash( $_GET[ $source . '_analytics_optin' ] ) ) : '';
if ( 'yes' === $optin_status ) {
$this->optin( $source );
} elseif ( 'no' === $optin_status ) {
$this->optout( $source );
}
wp_safe_redirect(
esc_url_raw(
remove_query_arg(
array(
$source . '_analytics_optin',
$source . '_analytics_nonce',
'bsf_analytics_source',
)
)
)
);
}
/**
* Opt in to usage tracking.
*
* @param string $source source of analytics.
* @since 1.0.0
*/
private function optin( $source ) {
update_site_option( $source . '_usage_optin', 'yes' );
}
/**
* Opt out of usage tracking.
*
* @param string $source source of analytics.
* @since 1.0.0
*/
private function optout( $source ) {
update_site_option( $source . '_usage_optin', 'no' );
update_site_option( 'bsf_usage_last_displayed_time', time() );
}
/**
* Load analytics stat class.
*
* @since 1.0.0
*/
private function includes() {
require_once __DIR__ . '/classes/class-bsf-analytics-helper.php';
require_once __DIR__ . '/class-bsf-analytics-stats.php';
// Loads all the modules.
require_once __DIR__ . '/modules/deactivation-survey/classes/class-deactivation-survey-feedback.php';
require_once __DIR__ . '/modules/utm-analytics.php';
}
/**
* Migrate old "analytics" options to new "usage" naming.
* Copies values to new options and deletes old options.
*
* @since 1.1.17
*/
private function maybe_migrate_options() {
if ( get_site_option( 'bsf_usage_migrated' ) ) {
return;
}
// Migrate global options.
$old_last_displayed = get_site_option( 'bsf_analytics_last_displayed_time' );
if ( false !== $old_last_displayed ) {
update_site_option( 'bsf_usage_last_displayed_time', $old_last_displayed );
delete_site_option( 'bsf_analytics_last_displayed_time' );
}
// Migrate per-product options.
foreach ( $this->entities as $key => $data ) {
$old_optin = get_site_option( $key . '_analytics_optin' );
if ( false !== $old_optin ) {
update_site_option( $key . '_usage_optin', $old_optin );
delete_site_option( $key . '_analytics_optin' );
}
$old_install_time = get_site_option( $key . '_analytics_installed_time' );
if ( false !== $old_install_time ) {
update_site_option( $key . '_usage_installed_time', $old_install_time );
delete_site_option( $key . '_analytics_installed_time' );
}
}
// Migrate transient.
$old_track = get_site_transient( 'bsf_analytics_track' );
if ( false !== $old_track ) {
set_site_transient( 'bsf_usage_track', $old_track, 2 * DAY_IN_SECONDS );
delete_site_transient( 'bsf_analytics_track' );
}
update_site_option( 'bsf_usage_migrated', true );
}
/**
* Register usage tracking option in General settings page.
*
* @since 1.0.0
*/
public function register_usage_tracking_setting() {
foreach ( $this->entities as $key => $data ) {
if ( ! apply_filters( $key . '_tracking_enabled', true ) || $this->is_white_label_enabled( $key ) ) {
return;
}
/**
* Introducing a new key 'hide_optin_checkbox, which allows individual plugin to hide optin checkbox
* If they are providing providing in-plugin option to manage this option.
* from General > Settings page.
*
* @since 1.1.14
*/
if( ! empty( $data['hide_optin_checkbox'] ) && true === $data['hide_optin_checkbox'] ) {
continue;
}
$usage_doc_link = isset( $data['usage_doc_link'] ) ? $data['usage_doc_link'] : $this->usage_doc_link;
$author = isset( $data['author'] ) ? $data['author'] : 'Brainstorm Force';
register_setting(
'general', // Options group.
$key . '_usage_optin', // Option name/database.
array( 'sanitize_callback' => array( $this, 'sanitize_option' ) ) // sanitize callback function.
);
add_settings_field(
$key . '-usage-optin', // Field ID.
__( 'Usage Tracking', 'ultimate-addons-for-gutenberg' ), // Field title.
array( $this, 'render_settings_field_html' ), // Field callback function.
'general',
'default', // Settings page slug.
array(
'type' => 'checkbox',
'title' => $author,
'name' => $key . '_usage_optin',
'label_for' => $key . '-usage-optin',
'id' => $key . '-usage-optin',
'usage_doc_link' => $usage_doc_link,
)
);
}
}
/**
* Sanitize Callback Function
*
* @param bool $input Option value.
* @since 1.0.0
*/
public function sanitize_option( $input ) {
if ( ! $input || 'no' === $input ) {
return 'no';
}
return 'yes';
}
/**
* Print settings field HTML.
*
* @param array $args arguments to field.
* @since 1.0.0
*/
public function render_settings_field_html( $args ) {
$is_checked = ( 'yes' === get_site_option( $args['name'], false ) );
?>
<fieldset>
<label for="<?php echo esc_attr( $args['label_for'] ); ?>">
<input id="<?php echo esc_attr( $args['id'] ); ?>" type="checkbox" value="1" name="<?php echo esc_attr( $args['name'] ); ?>" <?php checked( $is_checked ); ?>>
<?php
/* translators: %s Product title */
echo esc_html( sprintf( __( 'Allow %s products to track non-sensitive usage tracking data.', 'ultimate-addons-for-gutenberg' ), $args['title'] ) );// phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralText
if ( is_multisite() ) {
esc_html_e( ' This will be applicable for all sites from the network.', 'ultimate-addons-for-gutenberg' );
}
?>
</label>
<?php
echo wp_kses_post( sprintf( '<a href="%1s" target="_blank" rel="noreferrer noopener">%2s</a>', esc_url( $args['usage_doc_link'] ), __( 'Learn More.', 'ultimate-addons-for-gutenberg' ) ) );
?>
</fieldset>
<?php
}
/**
* Get analytics installed time from option.
*
* @param string $source source of analytics.
* @return string $time analytics installed time.
* @since 1.0.0
*/
private function get_analytics_install_time( $source ) {
$time = get_site_option( $source . '_usage_installed_time' );
if ( ! $time ) {
$time = time();
update_site_option( $source . '_usage_installed_time', $time );
}
return $time;
}
/**
* Schedule/unschedule cron event on updation of option.
*
* @param string $old_value old value of option.
* @param string $value value of option.
* @param string $option Option name.
* @since 1.0.0
*/
public function update_analytics_option_callback( $old_value, $value, $option ) {
if ( is_multisite() ) {
$this->add_option_to_network( $option, $value );
}
}
/**
* Analytics option add callback.
*
* @param string $option Option name.
* @param string $value value of option.
* @since 1.0.0
*/
public function add_analytics_option_callback( $option, $value ) {
if ( is_multisite() ) {
$this->add_option_to_network( $option, $value );
}
}
/**
* Send analytics track event if tracking is enabled.
*
* @since 1.0.0
*/
public function maybe_track_analytics() {
if ( ! $this->is_tracking_enabled() ) {
return;
}
$analytics_track = get_site_transient( 'bsf_usage_track' );
// If the last data sent is 2 days old i.e. transient is expired.
if ( ! $analytics_track ) {
$this->send();
set_site_transient( 'bsf_usage_track', true, 2 * DAY_IN_SECONDS );
}
}
/**
* Save analytics option to network.
*
* @param string $option name of option.
* @param string $value value of option.
* @since 1.0.0
*/
public function add_option_to_network( $option, $value ) {
// If action coming from general settings page.
if ( isset( $_POST['option_page'] ) && 'general' === $_POST['option_page'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
if ( get_site_option( $option ) ) {
update_site_option( $option, $value );
} else {
add_site_option( $option, $value );
}
}
}
/**
* Function to load the deactivation survey form on the admin footer.
*
* This function checks if the Deactivation_Survey_Feedback class exists and if so, it loads the deactivation survey form.
* The form is configured with specific settings for plugin. Example: For CartFlows, including the source, logo, plugin slug, title, support URL, description, and the screen on which to show the form.
*
* @since 1.1.6
* @return void
*/
public function load_deactivation_survey_form() {
if ( class_exists( 'Deactivation_Survey_Feedback' ) ) {
foreach ( $this->entities as $key => $data ) {
// If the deactivation_survey info in available then only add the form.
if ( ! empty( $data['deactivation_survey'] ) && is_array( $data['deactivation_survey'] ) ) {
foreach ( $data['deactivation_survey'] as $key => $survey_args ) {
Deactivation_Survey_Feedback::show_feedback_form(
$survey_args
);
}
}
}
}
}
/**
* Function to add plugin slugs to Deactivation Survey vars for JS operations.
*
* @param array $vars UDS vars array.
* @return array Modified UDS vars array with plugin slugs.
* @since 1.1.6
*/
public function add_slugs_to_uds_vars( $vars ) {
foreach ( $this->entities as $key => $data ) {
if ( ! empty( $data['deactivation_survey'] ) && is_array( $data['deactivation_survey'] ) ) {
foreach ( $data['deactivation_survey'] as $key => $survey_args ) {
$vars['_plugin_slug'] = isset( $vars['_plugin_slug'] ) ? array_merge( $vars['_plugin_slug'], array( $survey_args['plugin_slug'] ) ) : array( $survey_args['plugin_slug'] );
}
}
}
return $vars;
}
}
}

View File

@@ -0,0 +1,98 @@
<?php
/**
* BSF analytics Helper Class File.
*
* @package bsf-analytics
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'BSF_Analytics_Helper' ) ) {
/**
* BSF analytics stat class.
*/
class BSF_Analytics_Helper {
/**
* Check is error in the received response.
*
* @param object $response Received API Response.
* @return array $result Error result.
*/
public static function is_api_error( $response ) {
$result = array(
'error' => false,
'error_message' => __( 'Oops! Something went wrong. Please refresh the page and try again.', 'ultimate-addons-for-gutenberg' ),
'error_code' => 0,
);
if ( is_wp_error( $response ) ) {
$result['error'] = true;
$result['error_message'] = $response->get_error_message();
$result['error_code'] = $response->get_error_code();
} elseif ( ! empty( wp_remote_retrieve_response_code( $response ) ) && ! in_array( wp_remote_retrieve_response_code( $response ), array( 200, 201, 204 ), true ) ) {
$result['error'] = true;
$result['error_message'] = wp_remote_retrieve_response_message( $response );
$result['error_code'] = wp_remote_retrieve_response_code( $response );
}
return $result;
}
/**
* Get API headers
*
* @since 1.1.6
* @return array<string, string>
*/
public static function get_api_headers() {
return array(
'Content-Type' => 'application/json',
'Accept' => 'application/json',
);
}
/**
* Get API URL for sending analytics.
*
* @return string API URL.
* @since 1.0.0
*/
public static function get_api_url() {
return defined( 'BSF_ANALYTICS_API_BASE_URL' ) ? BSF_ANALYTICS_API_BASE_URL : 'https://analytics.brainstormforce.com/';
}
/**
* Check if the current screen is allowed for the survey.
*
* This function checks if the current screen is one of the allowed screens for displaying the survey.
* It uses the `get_current_screen` function to get the current screen information and compares it with the list of allowed screens.
*
* @since 1.1.6
* @return bool True if the current screen is allowed, false otherwise.
*/
public static function is_allowed_screen() {
// This filter allows to dynamically modify the list of allowed screens for the survey.
$allowed_screens = apply_filters( 'uds_survey_allowed_screens', array( 'plugins' ) );
$current_screen = get_current_screen();
// Check if $current_screen is a valid object before accessing its properties.
if ( ! is_object( $current_screen ) ) {
return false; // Return false if current screen is not valid.
}
$screen_id = $current_screen->id;
if ( ! empty( $screen_id ) && in_array( $screen_id, $allowed_screens, true ) ) {
return true;
}
return false;
}
}
}

View File

@@ -0,0 +1,236 @@
/* Base CSS to normalize the default. */
.uds-feedback-form--wrapper h2,
.uds-feedback-form--wrapper p,
.uds-feedback-form--wrapper input[type="radio"] {
margin: 0;
padding: 0;
}
.uds-feedback-form--wrapper .show {
display: block;
}
.uds-feedback-form--wrapper .hide {
display: none;
}
.uds-feedback-form--wrapper {
align-items: center;
background-color: rgba( 0, 0, 0, 0.75 );
bottom: 0;
display: none;
justify-content: center;
left: 0;
position: fixed;
right: 0;
top: 0;
user-select: none;
z-index: -9999;
}
.uds-feedback-form--wrapper.show_popup {
display: flex !important;
z-index: 99999;
}
.uds-feedback-form--wrapper .uds-feedback-form--container {
background-color: #fff;
border-radius: 8px;
box-shadow: 4px 4px 24px rgba( 0, 0, 0, 0.25 );
max-width: 90%;
width: 540px;
}
.uds-feedback-form--container .uds-form-header--wrapper {
align-items: center;
display: flex;
justify-content: space-between;
padding: 16px 20px 0;
}
.uds-feedback-form--container .uds-form-title--icon-wrapper {
display: flex;
align-items: center;
gap: 12px;
}
.uds-feedback-form--container .uds-form-title--icon-wrapper .uds-icon,
.uds-feedback-form--container .uds-form-header--wrapper .uds-close {
width: 20px;
height: 20px;
}
.uds-feedback-form--container .uds-form-title--icon-wrapper .uds-title {
color: #1f2937;
font-size: 16px;
font-weight: 600;
line-height: 24px;
text-align: left;
}
.uds-feedback-form--container .uds-form-header--wrapper .uds-close {
color: #9ca3af;
cursor: pointer;
}
.uds-feedback-form--container .uds-form-header--wrapper .uds-close:hover {
color: #4b5563;
}
.uds-feedback-form--container .uds-form-body--content {
padding: 20px 20px 0 20px;
display: flex;
flex-direction: column;
gap: 20px;
}
.uds-feedback-form--container .uds-form-body--content .uds-form-description {
color: #1f2937;
font-size: 16px;
font-weight: 500;
line-height: 24px;
text-align: left;
}
.uds-feedback-form--container .uds-form-body--content #uds-feedback-form .reason {
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 12px;
}
.uds-feedback-form--container .uds-form-body--content #uds-feedback-form .uds-options-feedback {
color: #6b7280;
font-size: 14px;
font-weight: 400;
line-height: 20px;
text-align: left;
width: 100%;
padding: 9px 13px;
border-radius: 6px;
border-width: 1px;
border-style: solid;
border-color: #e5e7eb;
box-shadow: 0 1px 2px 0 #0000000d;
background: #fff;
}
.uds-feedback-form--container .uds-form-body--content #uds-feedback-form .uds-options-feedback:hover,
.uds-feedback-form--container .uds-form-body--content #uds-feedback-form .uds-options-feedback:focus,
.uds-feedback-form--container .uds-form-body--content #uds-feedback-form .uds-options-feedback:active {
border-color: #d1d5db;
}
.uds-feedback-form--container .uds-form-body--content #uds-feedback-form .uds-option-feedback-cta {
color: #4b5563;
margin-top: 10px;
font-size: 13px;
font-weight: 400;
line-height: 20px;
text-align: left;
}
.uds-feedback-form--container .uds-form-body--content #uds-feedback-form .uds-option-feedback-cta a {
text-decoration: none;
color: #006ba1;
}
.uds-feedback-form--container .uds-form-body--content #uds-feedback-form .uds-options-feedback::placeholder {
font-size: 14px;
font-weight: 400;
line-height: 20px;
text-align: left;
color: #6b7280;
opacity: 1;
}
.uds-feedback-form--container .uds-form-body--content .uds-feedback-form-sumbit--actions {
display: flex;
align-items: center;
justify-content: space-between;
padding: 16px 20px;
background-color: #f6f7f7;
border-top: 1px solid #e1e1e1;
margin: 40px -20px 0;
border-bottom-left-radius: 8px;
border-bottom-right-radius: 8px;
}
.uds-feedback-form--container .uds-form-body--content .uds-feedback-form-sumbit--actions .button {
padding: 7px 13px;
border-radius: 3px;
border-width: 1px;
font-size: 14px;
font-weight: 400;
line-height: 20px;
text-align: left;
border-style: solid;
display: flex;
gap: 8px;
align-items: center;
}
.uds-feedback-form--container .uds-form-body--content .uds-feedback-form-sumbit--actions .button:focus {
outline: none;
box-shadow: none;
}
.uds-feedback-form--container .uds-form-body--content .uds-feedback-form-sumbit--actions .button.processing {
pointer-events: none;
opacity: 0.8;
}
.uds-feedback-form--container .uds-form-body--content .uds-feedback-form-sumbit--actions .button.processing::before {
content: "\f463";
animation: spin 2s linear infinite;
font-family: dashicons, sans-serif;
font-weight: 400;
font-size: 18px;
cursor: pointer;
}
.uds-feedback-form--container .uds-form-body--content #uds-feedback-form .uds-reason-label {
font-size: 14px;
font-weight: 400;
line-height: 20px;
text-align: left;
}
.uds-feedback-form--container .uds-form-body--content #uds-feedback-form input[type="radio"] {
display: flex;
justify-content: center;
height: 18px;
width: 18px;
cursor: pointer;
margin: 0;
border: 1px solid #d1d5db;
border-radius: 50%;
line-height: 0;
box-shadow: inset 0 1px 2px rgb( 0 0 0 / 10% );
transition: 0.05s border-color ease-in-out;
-webkit-appearance: none;
padding: 0;
}
.uds-feedback-form--container .uds-form-body--content #uds-feedback-form input[type="radio"]:checked {
vertical-align: middle;
background-color: #006ba1;
}
.uds-feedback-form--container .uds-form-body--content #uds-feedback-form input[type="radio"]:checked::before {
background-color: #fff !important;
border-radius: 50px;
content: "\2022";
font-size: 24px;
height: 6px;
line-height: 13px;
margin: 5px;
text-indent: -9999px;
width: 6px;
}
@keyframes spin {
0% {
transform: rotate( 0deg );
}
100% {
transform: rotate( 360deg );
}
}

View File

@@ -0,0 +1,239 @@
( function ( $ ) {
const UserDeactivationPopup = {
slug: '',
skipButton: '',
formWrapper: '',
radioButton: '',
closeButton: '',
buttonAction: '',
feedbackForm: '',
feedbackInput: '',
deactivateUrl: '',
buttonTrigger: '',
deactivateButton: '',
submitDeactivate: '',
/**
* Caches elements for later use.
*/
_cacheElements() {
this.slug = udsVars?._plugin_slug || '';
this.skipButton = $( '.uds-feedback-skip' );
this.submitDeactivate = $( '.uds-feedback-submit' );
this.deactivateButton = $( '#the-list' ).find(
`.row-actions span.deactivate a`
);
this.feedbackForm = $( '.uds-feedback-form' ); // Feedback Form.
this.feedbackInput = $( '.uds-options-feedback' ); // Feedback Textarea.
this.formWrapper = $( '.uds-feedback-form--wrapper' );
this.closeButton = $( '.uds-feedback-form--wrapper .uds-close' );
this.radioButton = $( '.uds-reason-input' );
},
/**
* Shows the feedback popup by adding the 'show' class to the form wrapper.
*
* @param {string} slug - The slug of the plugin.
*/
_showPopup( slug ) {
$( `#deactivation-survey-${ slug }` ).addClass( 'show_popup' );
},
/**
* Hides the feedback popup by removing the 'show' class from the form wrapper.
*/
_hidePopup() {
this.formWrapper.removeClass( 'show_popup' );
},
/**
* Redirects to the deactivate URL if it exists, otherwise reloads the current page.
*/
_redirectOrReload() {
if ( this.deactivateUrl ) {
window.location.href = this.deactivateUrl;
} else {
location.reload();
}
},
/**
* Toggles the visibility of the feedback form and CTA based on the event target's attributes.
*
* @param {Event} event - The event that triggered this function.
*/
_hideShowFeedbackAndCTA( event ) {
const acceptFeedback =
$( event.target ).attr( 'data-accept_feedback' ) === 'true';
const showCta =
$( event.target ).attr( 'data-show_cta' ) === 'true';
$( event.target )
.closest( this.formWrapper )
.find( '.uds-options-feedback' )
.removeClass( 'hide' )
.addClass( acceptFeedback ? 'show' : 'hide' );
$( event.target )
.closest( this.formWrapper )
.find( '.uds-option-feedback-cta' )
.removeClass( 'hide' )
.addClass( showCta ? 'show' : 'hide' );
},
/**
* Changes the placeholder text of the feedback input based on the event target's attribute.
*
* @param {Event} event - The event that triggered this function.
*/
_changePlaceholderText( event ) {
const radioButtonPlaceholder =
event.target.getAttribute( 'data-placeholder' );
$( event.target )
.closest( this.formWrapper )
.find( this.feedbackInput )
.attr( 'placeholder', radioButtonPlaceholder || '' );
this._hideShowFeedbackAndCTA( event );
},
/**
* Submits the feedback form and handles the response.
*
* @param {Event} event - The event that triggered this function.
* @param {Object} self - A reference to the current object.
*/
_submitFeedback( event, self ) {
event.preventDefault();
const currentForm = $( event.target );
const closestForm = currentForm.closest( this.feedbackForm ); // Cache the closest form
// Gather form data.
const formData = {
action: 'uds_plugin_deactivate_feedback',
security: udsVars?._ajax_nonce || '',
reason:
closestForm
.find( this.radioButton.filter( ':checked' ) )
.val() || '', // Get the selected radio button value from the current form.
source: closestForm.find( 'input[name="source"]' ).val() || '',
referer:
closestForm.find( 'input[name="referer"]' ).val() || '',
version:
closestForm.find( 'input[name="version"]' ).val() || '',
feedback: closestForm.find( this.feedbackInput ).val() || '', // Get the feedback input value from the current form.
};
currentForm
.find( '.uds-feedback-' + this.buttonAction )
.text( 'Deactivating.' )
.addClass( 'processing' );
// Prepare AJAX call.
$.ajax( {
url: udsVars?.ajaxurl, // URL to send the request to.
type: 'POST', // HTTP method.
data: formData, // Data to be sent.
success( response ) {
if ( response.success ) {
self._redirectOrReload();
}
self._hidePopup();
},
/* eslint-disable */
error( xhr, status, error ) {
/* eslint-disable */
self._redirectOrReload();
},
} );
},
_handleClick( e ) {
// Close feedback form or show/hide popup if clicked outside and add a click on a Activate button of Theme.
if (
e.target.classList.contains( 'show_popup' ) &&
e.target.closest( '.uds-feedback-form--wrapper' )
) {
this._hidePopup();
} else if ( e.target.classList.contains( 'activate' ) ) {
this.deactivateUrl = e.target.href;
// Don't show for Child Themes if parent theme is active & Parent Theme if child theme is active.
if (
-1 !==
this.deactivateUrl.indexOf(
`stylesheet=${ udsVars?._current_theme }-child`
) ||
-1 !==
this.deactivateUrl.indexOf(`stylesheet=${udsVars?._current_theme}&`)
) {
return;
}
e.preventDefault();
this._showPopup( udsVars?._current_theme );
}
},
/**
* Initializes the feedback popup by caching elements and binding events.
*/
_init() {
this._cacheElements();
this._bind();
},
/**
* Binds event listeners to various elements to handle user interactions.
*/
_bind() {
const self = this; // Store reference to the current object.
// Open the popup when clicked on the deactivate button.
this.deactivateButton.on( 'click', function ( event ) {
let closestTr = $( event.target ).closest( 'tr' );
let slug = closestTr.data( 'slug' );
if ( self.slug.includes( slug ) ) {
event.preventDefault();
// Set the deactivation URL.
self.deactivateUrl = $( event.target ).attr( 'href' );
self._showPopup( slug );
}
} );
// Close the popup on a click of Close button.
this.closeButton.on( 'click', function ( event ) {
event.preventDefault();
self._hidePopup(); // Use self to refer to the UserDeactivationPopup instance.
} );
// Click event on radio button to change the placeholder of textarea.
this.radioButton.on( 'click', function ( event ) {
self._changePlaceholderText( event );
} );
// Combined submit and skip button actions.
this.submitDeactivate
.add( this.skipButton )
.on( 'click', function ( event ) {
event.preventDefault(); // Prevent default button action.
self.buttonAction = $( event.target ).attr( 'data-action' );
$( event.target ).closest( self.feedbackForm ).submit();
} );
this.feedbackForm.on( 'submit', function ( event ) {
self._submitFeedback( event, self );
} );
document.addEventListener( 'click', function ( e ) {
self._handleClick( e );
} );
},
};
$( function () {
UserDeactivationPopup._init();
} );
} )( jQuery );

View File

@@ -0,0 +1 @@
(i=>{let t={slug:"",skipButton:"",formWrapper:"",radioButton:"",closeButton:"",buttonAction:"",feedbackForm:"",feedbackInput:"",deactivateUrl:"",buttonTrigger:"",deactivateButton:"",submitDeactivate:"",_cacheElements(){this.slug=udsVars?._plugin_slug||"",this.skipButton=i(".uds-feedback-skip"),this.submitDeactivate=i(".uds-feedback-submit"),this.deactivateButton=i("#the-list").find(".row-actions span.deactivate a"),this.feedbackForm=i(".uds-feedback-form"),this.feedbackInput=i(".uds-options-feedback"),this.formWrapper=i(".uds-feedback-form--wrapper"),this.closeButton=i(".uds-feedback-form--wrapper .uds-close"),this.radioButton=i(".uds-reason-input")},_showPopup(t){i("#deactivation-survey-"+t).addClass("show_popup")},_hidePopup(){this.formWrapper.removeClass("show_popup")},_redirectOrReload(){this.deactivateUrl?window.location.href=this.deactivateUrl:location.reload()},_hideShowFeedbackAndCTA(t){var e="true"===i(t.target).attr("data-accept_feedback"),a="true"===i(t.target).attr("data-show_cta");i(t.target).closest(this.formWrapper).find(".uds-options-feedback").removeClass("hide").addClass(e?"show":"hide"),i(t.target).closest(this.formWrapper).find(".uds-option-feedback-cta").removeClass("hide").addClass(a?"show":"hide")},_changePlaceholderText(t){var e=t.target.getAttribute("data-placeholder");i(t.target).closest(this.formWrapper).find(this.feedbackInput).attr("placeholder",e||""),this._hideShowFeedbackAndCTA(t)},_submitFeedback(t,s){t.preventDefault();var t=i(t.target),e=t.closest(this.feedbackForm),e={action:"uds_plugin_deactivate_feedback",security:udsVars?._ajax_nonce||"",reason:e.find(this.radioButton.filter(":checked")).val()||"",source:e.find('input[name="source"]').val()||"",referer:e.find('input[name="referer"]').val()||"",version:e.find('input[name="version"]').val()||"",feedback:e.find(this.feedbackInput).val()||""};t.find(".uds-feedback-"+this.buttonAction).text("Deactivating.").addClass("processing"),i.ajax({url:udsVars?.ajaxurl,type:"POST",data:e,success(t){t.success&&s._redirectOrReload(),s._hidePopup()},error(t,e,a){s._redirectOrReload()}})},_handleClick(t){t.target.classList.contains("show_popup")&&t.target.closest(".uds-feedback-form--wrapper")?this._hidePopup():t.target.classList.contains("activate")&&(this.deactivateUrl=t.target.href,-1===this.deactivateUrl.indexOf(`stylesheet=${udsVars?._current_theme}-child`))&&-1===this.deactivateUrl.indexOf(`stylesheet=${udsVars?._current_theme}&`)&&(t.preventDefault(),this._showPopup(udsVars?._current_theme))},_init(){this._cacheElements(),this._bind()},_bind(){let a=this;this.deactivateButton.on("click",function(t){var e=i(t.target).closest("tr").data("slug");a.slug.includes(e)&&(t.preventDefault(),a.deactivateUrl=i(t.target).attr("href"),a._showPopup(e))}),this.closeButton.on("click",function(t){t.preventDefault(),a._hidePopup()}),this.radioButton.on("click",function(t){a._changePlaceholderText(t)}),this.submitDeactivate.add(this.skipButton).on("click",function(t){t.preventDefault(),a.buttonAction=i(t.target).attr("data-action"),i(t.target).closest(a.feedbackForm).submit()}),this.feedbackForm.on("submit",function(t){a._submitFeedback(t,a)}),document.addEventListener("click",function(t){a._handleClick(t)})}};i(function(){t._init()})})(jQuery);

View File

@@ -0,0 +1,324 @@
<?php
/**
* Deactivation Survey Feedback.
*
* @package bsf-analytics
*/
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'Deactivation_Survey_Feedback' ) ) {
/**
* Class Deactivation_Survey_Feedback.
*/
class Deactivation_Survey_Feedback {
/**
* Feedback URL.
*
* @var string
*/
private static $feedback_api_endpoint = 'api/plugin-deactivate';
/**
* Instance
*
* @access private
* @var object Class object.
* @since 1.1.6
*/
private static $instance;
/**
* Initiator
*
* @since 1.1.6
* @return object initialized object of class.
*/
public static function get_instance() {
if ( ! isset( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Constructor
*/
public function __construct() {
add_action( 'admin_enqueue_scripts', array( $this, 'load_form_styles' ) );
add_action( 'wp_ajax_uds_plugin_deactivate_feedback', array( $this, 'send_plugin_deactivate_feedback' ) );
}
/**
* Render feedback HTML on plugins.php admin page only.
*
* This function renders the feedback form HTML on the plugins.php admin page.
* It takes an optional string parameter $id for the form wrapper ID and an optional array parameter $args for customizing the form.
*
* @since 1.1.6
* @param array $args Optional. Custom arguments for the form. Defaults to an empty array.
* @return void
*/
public static function show_feedback_form( array $args = array() ) {
// Return if not in admin.
if ( ! is_admin() ) {
return;
}
// Set default arguments for the feedback form.
$defaults = array(
'source' => 'User Deactivation Survey',
'popup_logo' => '',
'plugin_slug' => 'user-deactivation-survey',
'plugin_version' => '',
'popup_title' => __( 'Quick Feedback', 'ultimate-addons-for-gutenberg' ),
'support_url' => 'https://brainstormforce.com/contact/',
'popup_reasons' => self::get_default_reasons(),
'popup_description' => __( 'If you have a moment, please share why you are deactivating the plugin.', 'ultimate-addons-for-gutenberg' ),
'show_on_screens' => array( 'plugins' ),
);
// Parse the arguments with defaults.
$args = wp_parse_args( $args, $defaults );
$id = '';
// Set a default ID if none is provided.
if ( empty( $args['id'] ) ) {
$id = 'uds-feedback-form--wrapper';
}
$id = sanitize_text_field( $args['id'] );
// Return if not on the allowed screen.
if ( ! BSF_Analytics_Helper::is_allowed_screen() ) {
return;
}
// Product slug used for input fields and labels in each plugin's deactivation survey.
$product_slug = isset( $args['plugin_slug'] ) ? sanitize_text_field( $args['plugin_slug'] ) : 'bsf';
?>
<div id="<?php echo esc_attr( $id ); ?>" class="uds-feedback-form--wrapper" style="display: none">
<div class="uds-feedback-form--container">
<div class="uds-form-header--wrapper">
<div class="uds-form-title--icon-wrapper">
<?php if ( ! empty( $args['popup_logo'] ) ) { ?>
<img class="uds-icon" src="<?php echo esc_url( $args['popup_logo'] ); ?>" title="<?php echo esc_attr( $args['plugin_slug'] ); ?> <?php echo esc_attr( __( 'Icon', 'ultimate-addons-for-gutenberg' ) ); ?>" />
<?php } ?>
<h2 class="uds-title"><?php echo esc_html( $args['popup_title'] ); ?></h2>
</div>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="uds-close">
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12" />
</svg>
</div>
<div class="uds-form-body--content">
<?php if ( ! empty( $args['popup_description'] ) ) { ?>
<p class="uds-form-description"><?php echo esc_html( $args['popup_description'] ); ?></p>
<?php } ?>
<form class="uds-feedback-form" id="uds-feedback-form" method="post">
<?php foreach ( $args['popup_reasons'] as $key => $value ) {
$input_id = $product_slug . '_uds_reason_input_' . $key;
?>
<fieldset>
<div class="reason">
<input type="radio" class="uds-reason-input" name="uds_reason_input" id="<?php echo esc_attr( $input_id ); ?>" value="<?php echo esc_attr( $key ); ?>" data-placeholder="<?php echo esc_attr( $value['placeholder'] ); ?>" data-show_cta="<?php echo esc_attr( $value['show_cta'] ); ?>" data-accept_feedback="<?php echo esc_attr( $value['accept_feedback'] ); ?>">
<label class="uds-reason-label" for="<?php echo esc_attr( $input_id ); ?>"><?php echo esc_html( $value['label'] ); ?></label>
</div>
</fieldset>
<?php } ?>
<fieldset>
<textarea class="uds-options-feedback hide" id="uds-options-feedback" rows="3" name="uds_options_feedback" placeholder="<?php echo esc_attr( __( 'Please tell us more details.', 'ultimate-addons-for-gutenberg' ) ); ?>"></textarea>
<?php
if ( ! empty( $args['support_url'] ) ) {
?>
<p class="uds-option-feedback-cta hide">
<?php
echo wp_kses_post(
sprintf(
/* translators: %1$s: link html start, %2$s: link html end*/
__( 'Need help from our experts? %1$sClick here to contact us.%2$s', 'ultimate-addons-for-gutenberg' ),
'<a href="' . esc_url( $args['support_url'] ) . '" target="_blank">',
'</a>'
)
);
?>
</p>
<?php } ?>
</fieldset>
<div class="uds-feedback-form-sumbit--actions">
<button class="button button-primary uds-feedback-submit" data-action="submit"><?php esc_html_e( 'Submit & Deactivate', 'ultimate-addons-for-gutenberg' ); ?></button>
<button class="button button-secondary uds-feedback-skip" data-action="skip"><?php esc_html_e( 'Skip & Deactivate', 'ultimate-addons-for-gutenberg' ); ?></button>
<input type="hidden" name="referer" value="<?php echo esc_url( get_site_url() ); ?>">
<input type="hidden" name="version" value="<?php echo esc_attr( $args['plugin_version'] ); ?>">
<input type="hidden" name="source" value="<?php echo esc_attr( $args['plugin_slug'] ); ?>">
</div>
</form>
</div>
</div>
</div>
<?php
}
/**
* Load form styles.
*
* This function loads the necessary styles for the feedback form.
*
* @since 1.1.6
* @return void
*/
public static function load_form_styles() {
if ( ! BSF_Analytics_Helper::is_allowed_screen() ) {
return;
}
$dir_path = BSF_ANALYTICS_URI . '/modules/deactivation-survey/';
$file_ext = ! SCRIPT_DEBUG ? '.min' : '';
wp_enqueue_script(
'uds-feedback-script',
$dir_path . 'assets/js/feedback' . $file_ext . '.js',
array( 'jquery' ),
BSF_ANALYTICS_VERSION,
true
);
$data = apply_filters(
'uds_survey_vars',
array(
'ajaxurl' => esc_url( admin_url( 'admin-ajax.php' ) ),
'_ajax_nonce' => wp_create_nonce( 'uds_plugin_deactivate_feedback' ),
'_current_theme' => function_exists( 'wp_get_theme' ) ? wp_get_theme()->get_template() : '',
'_plugin_slug' => array(),
)
);
// Add localize JS.
wp_localize_script(
'uds-feedback-script',
'udsVars',
$data
);
wp_enqueue_style( 'uds-feedback-style', $dir_path . 'assets/css/feedback' . $file_ext . '.css', array(), BSF_ANALYTICS_VERSION );
wp_style_add_data( 'uds-feedback-style', 'rtl', 'replace' );
}
/**
* Sends plugin deactivation feedback to the server.
*
* This function checks the user's permission and verifies the nonce for the request.
* If the checks pass, it sends the feedback data to the server for processing.
*
* @return void
*/
public function send_plugin_deactivate_feedback() {
$response_data = array( 'message' => __( 'Sorry, you are not allowed to do this operation.', 'ultimate-addons-for-gutenberg' ) );
/**
* Check permission
*/
if ( ! current_user_can( 'manage_options' ) ) {
wp_send_json_error( $response_data );
}
/**
* Nonce verification
*/
if ( ! check_ajax_referer( 'uds_plugin_deactivate_feedback', 'security', false ) ) {
$response_data = array( 'message' => __( 'Nonce validation failed', 'ultimate-addons-for-gutenberg' ) );
wp_send_json_error( $response_data );
}
$feedback_data = array(
'reason' => isset( $_POST['reason'] ) ? sanitize_text_field( wp_unslash( $_POST['reason'] ) ) : '',
'feedback' => isset( $_POST['feedback'] ) ? sanitize_text_field( wp_unslash( $_POST['feedback'] ) ) : '',
'domain_name' => isset( $_POST['referer'] ) ? sanitize_text_field( wp_unslash( $_POST['referer'] ) ) : '',
'version' => isset( $_POST['version'] ) ? sanitize_text_field( wp_unslash( $_POST['version'] ) ) : '',
'plugin' => isset( $_POST['source'] ) ? sanitize_text_field( wp_unslash( $_POST['source'] ) ) : '',
);
$api_args = array(
'body' => wp_json_encode( $feedback_data ),
'headers' => BSF_Analytics_Helper::get_api_headers(),
'timeout' => 90, //phpcs:ignore WordPressVIPMinimum.Performance.RemoteRequestTimeout.timeout_timeout
);
$target_url = BSF_Analytics_Helper::get_api_url() . self::$feedback_api_endpoint;
$response = wp_safe_remote_post( $target_url, $api_args );
$has_errors = BSF_Analytics_Helper::is_api_error( $response );
if ( $has_errors['error'] ) {
wp_send_json_error(
array(
'success' => false,
'message' => $has_errors['error_message'],
)
);
}
wp_send_json_success();
}
/**
* Get the array of default reasons.
*
* @return array Default reasons.
*/
public static function get_default_reasons() {
return apply_filters(
'uds_default_deactivation_reasons',
array(
'temporary_deactivation' => array(
'label' => esc_html__( 'This is a temporary deactivation for testing.', 'ultimate-addons-for-gutenberg' ),
'placeholder' => esc_html__( 'How can we assist you?', 'ultimate-addons-for-gutenberg' ),
'show_cta' => 'false',
'accept_feedback' => 'false',
),
'plugin_not_working' => array(
'label' => esc_html__( 'The plugin isn\'t working properly.', 'ultimate-addons-for-gutenberg' ),
'placeholder' => esc_html__( 'Please tell us more about what went wrong?', 'ultimate-addons-for-gutenberg' ),
'show_cta' => 'true',
'accept_feedback' => 'true',
),
'found_better_plugin' => array(
'label' => esc_html__( 'I found a better alternative plugin.', 'ultimate-addons-for-gutenberg' ),
'placeholder' => esc_html__( 'Could you please specify which plugin?', 'ultimate-addons-for-gutenberg' ),
'show_cta' => 'false',
'accept_feedback' => 'true',
),
'missing_a_feature' => array(
'label' => esc_html__( 'It\'s missing a specific feature.', 'ultimate-addons-for-gutenberg' ),
'placeholder' => esc_html__( 'Please tell us more about the feature.', 'ultimate-addons-for-gutenberg' ),
'show_cta' => 'false',
'accept_feedback' => 'true',
),
'other' => array(
'label' => esc_html__( 'Other', 'ultimate-addons-for-gutenberg' ),
'placeholder' => esc_html__( 'Please tell us more details.', 'ultimate-addons-for-gutenberg' ),
'show_cta' => 'false',
'accept_feedback' => 'true',
),
)
);
}
}
Deactivation_Survey_Feedback::get_instance();
}

View File

@@ -0,0 +1,166 @@
<?php
/**
* UTM Analytics class
*
* @package bsf-analytics
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'BSF_UTM_Analytics' ) ) {
if ( ! defined( 'BSF_UTM_ANALYTICS_REFERER' ) ) {
define( 'BSF_UTM_ANALYTICS_REFERER', 'bsf_product_referers' );
}
/**
* UTM Analytics class
*
* @since 1.1.10
*/
class BSF_UTM_Analytics {
/**
* List of slugs of all the bsf products that will be referer, referring another product.
*
* @var array<string>
* @since 1.1.10
*/
private static $bsf_product_slugs = [
'all-in-one-schemaorg-rich-snippets',
'astra',
'astra-portfolio',
'astra-sites',
'bb-ultimate-addon',
'cartflows',
'checkout-paypal-woo',
'checkout-plugins-stripe-woo',
'convertpro',
'header-footer-elementor',
'latepoint',
'presto-player',
'surecart',
'sureforms',
'suremails',
'surerank',
'suretriggers',
'ultimate-addons-for-beaver-builder-lite',
'ultimate-addons-for-gutenberg',
'ultimate-elementor',
'Ultimate_VC_Addons',
'variation-swatches-woo',
'woo-cart-abandonment-recovery',
'wp-schema-pro',
'zipwp'
];
/**
* This function will help to determine if provided slug is a valid bsf product or not,
* This way we will maintain consistency through out all our products.
*
* @param string $slug unique slug of the product which can be used for referer, product.
* @since 1.1.10
* @return boolean
*/
public static function is_valid_bsf_product_slug( $slug ) {
if ( empty( $slug ) || ! is_string( $slug ) ) {
return false;
}
return in_array( $slug, self::$bsf_product_slugs, true );
}
/**
* This function updates value of referer and product in option
* bsf_product_referer in form of key value pair as 'product' => 'referer'
*
* @param string $referer slug of the product which is refering another product.
* @param string $product slug of the product which is refered.
* @since 1.1.10
* @return void
*/
public static function update_referer( $referer, $product ) {
$slugs = [
'referer' => $referer,
'product' => $product,
];
$error_count = 0;
foreach ( $slugs as $type => $slug ) {
if ( ! self::is_valid_bsf_product_slug( $slug ) ) {
error_log( sprintf( 'Invalid %1$s slug provided "%2$s", does not match bsf_product_slugs', $type, $slug ) ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- adding logs in case of failure will help in debugging.
$error_count++;
}
}
if ( $error_count > 0 ) {
return;
}
$slugs = array_map( 'sanitize_text_field', $slugs );
$bsf_product_referers = get_option( BSF_UTM_ANALYTICS_REFERER, [] );
if ( ! is_array( $bsf_product_referers ) ) {
$bsf_product_referers = [];
}
$bsf_product_referers[ $slugs['product'] ] = $slugs['referer'];
update_option( BSF_UTM_ANALYTICS_REFERER, $bsf_product_referers );
}
/**
* This function will add utm_args to pro link or purchase link
* added utm_source by default additional utm_args such as utm_medium etc can be provided to generate location specific links
*
* @param string $link Ideally this should be product site link where utm_params can be tracked.
* @param string $product Product slug whose utm_link need to be created.
* @param mixed $utm_args additional args to be passed ex: [ 'utm_medium' => 'dashboard'].
* @since 1.1.10
* @return string
*/
public static function get_utm_ready_link( $link, $product, $utm_args = [] ) {
if ( false === wp_http_validate_url( $link ) ) {
error_log( 'Invalid url passed to get_utm_ready_link function' ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- adding logs in case of failure will help in debugging.
return $link;
}
if ( empty( $product ) || ! is_string( $product ) || ! self::is_valid_bsf_product_slug( $product ) ) {
error_log( sprintf( 'Invalid product slug provided "%1$s", does not match bsf_product_slugs', $product ) ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- adding logs in case of failure will help in debugging.
return $link;
}
$bsf_product_referers = get_option( BSF_UTM_ANALYTICS_REFERER, [] );
if ( ! is_array( $bsf_product_referers ) || empty( $bsf_product_referers[ $product ] ) ) {
return $link;
}
if ( ! self::is_valid_bsf_product_slug( $bsf_product_referers[ $product ] ) ) {
return $link;
}
if ( ! is_array( $utm_args ) ) {
$utm_args = [];
}
$utm_args['utm_source'] = $bsf_product_referers[ $product ];
$link = add_query_arg(
$utm_args,
$link
);
return $link;
}
}
}

View File

@@ -0,0 +1,4 @@
{
"bsf-analytics-ver": "1.1.17"
}

View File

@@ -0,0 +1,122 @@
<?php
/**
* Init
*
* @since 1.0.0
* @package Ast Block Templates
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'UAGB_Ast_Block_Templates' ) ) :
/**
* Admin
*/
class UAGB_Ast_Block_Templates {
/**
* Instance
*
* @since 1.0.0
* @var (Object) UAGB_Ast_Block_Templates
*/
private static $instance = null;
/**
* Get Instance
*
* @since 1.0.0
*
* @return object Class object.
*/
public static function get_instance() {
if ( ! isset( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Constructor.
*
* @since 1.0.0
*/
private function __construct() {
$this->version_check();
add_action( 'init', array( $this, 'load' ), 999 );
add_filter( 'ast_block_templates_localize_vars', array( $this, 'update_vars' ) );
}
/**
* Add support to change template button text.
*
* @since 1.21.0
* @param array $vars localize array of button.
*/
public function update_vars( $vars = array() ) {
if ( defined( 'ASTRA_SITES_VER' ) ) {
return $vars;
}
$vars['button_text'] = __( 'Design Library', 'ultimate-addons-for-gutenberg' );
$vars['display_button_logo'] = true;
$vars['popup_logo_uri'] = UAGB_URL . 'admin-core/assets/images/uag-logo.svg';
$vars['button_logo'] = UAGB_URL . 'admin-core/assets/images/btn-spectra.svg';
$vars['button_class'] = 'uagb-template-button-logo';
return $vars;
}
/**
* Version Check
*
* @return void
*/
public function version_check() {
$file = realpath( dirname( __FILE__ ) . '/gutenberg-templates/version.json' );
// Is file exist?
if ( is_file( $file ) ) {
// @codingStandardsIgnoreStart
$file_data = json_decode( file_get_contents( $file ), true );
// @codingStandardsIgnoreEnd
global $ast_block_templates_version, $ast_block_templates_init;
$path = realpath( dirname( __FILE__ ) . '/gutenberg-templates/ast-block-templates.php' );
$version = isset( $file_data['ast-block-templates'] ) ? $file_data['ast-block-templates'] : 0;
if ( null === $ast_block_templates_version ) {
$ast_block_templates_version = '1.0.0';
}
// Compare versions.
if ( version_compare( $version, $ast_block_templates_version, '>' ) ) {
$ast_block_templates_version = $version;
$ast_block_templates_init = $path;
}
}
}
/**
* Load latest plugin
*
* @return void
*/
public function load() {
global $ast_block_templates_version, $ast_block_templates_init;
if ( is_file( realpath( $ast_block_templates_init ) ) ) {
include_once realpath( $ast_block_templates_init );
}
}
}
/**
* Kicking this off by calling 'get_instance()' method
*/
UAGB_Ast_Block_Templates::get_instance();
endif;

View File

@@ -0,0 +1,96 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'UAGB_Nps_Survey' ) ) :
/**
* Admin
*/
class UAGB_Nps_Survey {
/**
* Instance
*
* @since 2.18.0
* @var (Object) UAGB_Nps_Survey
*/
private static $instance = null;
/**
* Get Instance
*
* @since 2.18.0
*
* @return object Class object.
*/
public static function get_instance() {
if ( ! isset( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Constructor.
*
* @since 2.18.0
*/
private function __construct() {
$this->version_check();
add_action( 'init', array( $this, 'load' ), 999 );
}
/**
* Version Check
*
* @return void
*/
public function version_check() {
$file = realpath( dirname( __DIR__ ) . '/lib/nps-survey/version.json' );
// Is file exist?
if ( is_file( $file ) ) {
$file_data = json_decode( file_get_contents( $file ), true );
global $nps_survey_version, $nps_survey_init;
$path = realpath( dirname( __DIR__ ) . '/lib/nps-survey/nps-survey.php' );
$version = isset( $file_data['nps-survey'] ) ? $file_data['nps-survey'] : 0;
if ( null === $nps_survey_version ) {
$nps_survey_version = '1.0.0';
}
// Compare versions.
if ( version_compare( $version, $nps_survey_version, '>=' ) ) {
$nps_survey_version = $version;
$nps_survey_init = $path;
}
}
}
/**
* Load latest plugin
*
* @return void
*/
public function load() {
global $nps_survey_version, $nps_survey_init;
if ( is_file( realpath( $nps_survey_init ) ) ) {
include_once realpath( $nps_survey_init );
}
}
}
/**
* Kicking this off by calling 'get_instance()' method
*/
UAGB_Nps_Survey::get_instance();
endif;

View File

@@ -0,0 +1,102 @@
<?php
/**
* Init
*
* Loads latest UTM Analytics library in environment.
*
* @since 2.19.2
* @package UTM Analytics
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'UAGB_Utm_Analytics' ) ) :
/**
* Admin
*/
class UAGB_Utm_Analytics {
/**
* Instance
*
* @since 2.19.2
* @var (Object) UAGB_Utm_Analytics
*/
private static $instance = null;
/**
* Get Instance
*
* @since 2.19.2
*
* @return object Class object.
*/
public static function get_instance() {
if ( ! isset( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Constructor.
*
* @since 2.19.2
*/
private function __construct() {
$this->version_check();
add_action( 'init', [ $this, 'load' ], 999 );
}
/**
* Version Check
*
* @return void
*/
public function version_check() {
$file = realpath( dirname( __FILE__ ) . '/utm-analytics/version.json' );
// Is file exist?
if ( is_file( $file ) ) {
// @codingStandardsIgnoreStart
$file_data = json_decode( file_get_contents( $file ), true );
// @codingStandardsIgnoreEnd
global $utm_analytics_version, $utm_analytics_init;
$path = realpath( dirname( __FILE__ ) . '/utm-analytics/bsf-utm-analytics.php' );
$version = isset( $file_data['bsf-utm-analytics'] ) ? $file_data['bsf-utm-analytics'] : 0;
if ( null === $utm_analytics_version ) {
$utm_analytics_version = '0.0.1';
}
// Compare versions.
if ( version_compare( $version, $utm_analytics_version, '>=' ) ) {
$utm_analytics_version = $version;
$utm_analytics_init = $path;
}
}
}
/**
* Load latest plugin
*
* @return void
*/
public function load() {
global $utm_analytics_version, $utm_analytics_init;
if ( is_file( realpath( $utm_analytics_init ) ) ) {
include_once realpath( $utm_analytics_init );
}
}
}
UAGB_Utm_Analytics::get_instance();
endif;

View File

@@ -0,0 +1,110 @@
<?php
/**
* Zip AI initialization
*
* @since 2.10.2
* @package zip-ai
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'UAGB_Zip_AI' ) ) :
/**
* This class connect zip ai library with spectra
*
* @since 2.10.2
*/
class UAGB_Zip_AI {
/**
* Instance
*
* @since 2.10.2
* @var (Object) UAGB_Zip_AI
*/
private static $instance = null;
/**
* Get Instance
*
* @since 2.10.2
*
* @return object Class object.
*/
public static function get_instance() {
if ( ! isset( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Constructor.
*
* @since 2.10.2
*
* @return void
*/
private function __construct() {
$this->version_check();
add_action( 'plugins_loaded', array( $this, 'load' ), 15 );
}
/**
* Checks for latest version of zip-ai library available in environment.
*
* @since 2.10.2
*
* @return void
*/
public function version_check() {
$file = realpath( dirname( __FILE__ ) . '/zip-ai/version.json' );
// Is file exist?
if ( is_file( $file ) ) {
// @codingStandardsIgnoreStart
$file_data = json_decode( file_get_contents( $file ), true );
// @codingStandardsIgnoreEnd
global $zip_ai_version, $zip_ai_path;
$path = realpath( dirname( __FILE__ ) . '/zip-ai/zip-ai.php' );
$version = isset( $file_data['zip-ai'] ) ? $file_data['zip-ai'] : 0;
if ( null === $zip_ai_version ) {
$zip_ai_version = '1.0.0';
}
// Compare versions.
if ( version_compare( $version, $zip_ai_version, '>' ) ) {
$zip_ai_version = $version;
$zip_ai_path = $path;
}
}
}
/**
* Load latest zip-ai library
*
* @since 2.10.2
*
* @return void
*/
public function load() {
global $zip_ai_path;
if ( ! is_null( $zip_ai_path ) && is_file( realpath( $zip_ai_path ) ) ) {
include_once realpath( $zip_ai_path );
}
}
}
/**
* Kicking this off by calling 'get_instance()' method
*/
UAGB_Zip_AI::get_instance();
endif;

View File

@@ -0,0 +1,108 @@
<?php
/**
* Init
*
* @since 2.17.0
* @package ZipWP Images
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'UAGB_Zipwp_Images' ) ) :
/**
* Admin
*
* @since 2.17.0
*/
class UAGB_Zipwp_Images {
/**
* Instance
*
* @since 2.17.0
* @var (Object) Spectra_Zipwp_Images
*/
private static $instance = null;
/**
* Get Instance
*
* @since 2.17.0
*
* @return object
*/
public static function get_instance() {
if ( ! isset( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Constructor.
*
* @since 2.17.0
*/
private function __construct() {
$this->version_check();
add_action( 'init', array( $this, 'load' ) );
}
/**
* Version Check
*
* @since 2.17.0
*
* @return void
*/
public function version_check() {
$file = realpath( dirname( __DIR__ ) . '/lib/zipwp-images/version.json' );
// Is file exist?
if ( is_file( $file ) ) {
// @codingStandardsIgnoreStart
$file_data = json_decode( file_get_contents( $file ), true );
// @codingStandardsIgnoreEnd
global $zipwp_images_version, $zipwp_images_init;
$path = realpath( dirname( __DIR__ ) . '/lib/zipwp-images/zipwp-images.php' );
$version = isset( $file_data['zipwp-images'] ) ? $file_data['zipwp-images'] : 0;
if ( false == $zipwp_images_version ) {
$zipwp_images_version = '1.0.0';
}
// Compare versions.
if ( version_compare( $version, $zipwp_images_version, '>=' ) ) {
$zipwp_images_version = $version;
$zipwp_images_init = $path;
}
}
}
/**
* Load latest plugin
*
* @since 2.17.0
*
* @return void
*/
public function load() {
global $zipwp_images_version, $zipwp_images_init;
if ( is_file( realpath( $zipwp_images_init ) ) ) {
include_once realpath( $zipwp_images_init );
}
}
}
/**
* Kicking this off by calling 'get_instance()' method
*/
UAGB_Zipwp_Images::get_instance();
endif;

Binary file not shown.

After

Width:  |  Height:  |  Size: 513 KiB

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<svg xmlns="http://www.w3.org/2000/svg">
<metadata>Generated by IcoMoon</metadata>
<defs>
<font id="ast-block-templates" horiz-adv-x="1024">
<font-face units-per-em="1024" ascent="960" descent="-64" />
<missing-glyph horiz-adv-x="1024" />
<glyph unicode="&#x20;" horiz-adv-x="512" d="" />
<glyph unicode="&#xe900;" glyph-name="maximize" d="M341.333 853.334h-128c-35.328 0-67.413-14.379-90.496-37.504s-37.504-55.168-37.504-90.496v-128c0-23.552 19.115-42.667 42.667-42.667s42.667 19.115 42.667 42.667v128c0 11.776 4.736 22.4 12.501 30.165s18.389 12.501 30.165 12.501h128c23.552 0 42.667 19.115 42.667 42.667s-19.115 42.667-42.667 42.667zM938.667 597.334v128c0 35.328-14.379 67.413-37.504 90.496s-55.168 37.504-90.496 37.504h-128c-23.552 0-42.667-19.115-42.667-42.667s19.115-42.667 42.667-42.667h128c11.776 0 22.4-4.736 30.165-12.501s12.501-18.389 12.501-30.165v-128c0-23.552 19.115-42.667 42.667-42.667s42.667 19.115 42.667 42.667zM682.667-0h128c35.328 0 67.413 14.379 90.496 37.504s37.504 55.168 37.504 90.496v128c0 23.552-19.115 42.667-42.667 42.667s-42.667-19.115-42.667-42.667v-128c0-11.776-4.736-22.4-12.501-30.165s-18.389-12.501-30.165-12.501h-128c-23.552 0-42.667-19.115-42.667-42.667s19.115-42.667 42.667-42.667zM85.333 256v-128c0-35.328 14.379-67.413 37.504-90.496s55.168-37.504 90.496-37.504h128c23.552 0 42.667 19.115 42.667 42.667s-19.115 42.667-42.667 42.667h-128c-11.776 0-22.4 4.736-30.165 12.501s-12.501 18.389-12.501 30.165v128c0 23.552-19.115 42.667-42.667 42.667s-42.667-19.115-42.667-42.667z" />
<glyph unicode="&#xe901;" glyph-name="rotate-cw" d="M834.005 312.875c-31.403-88.875-95.787-156.587-174.677-194.261s-171.989-45.269-260.864-13.867-156.587 95.787-194.261 174.677-45.269 171.989-13.867 260.864 95.787 156.587 174.677 194.261 171.989 45.269 260.864 13.867c50.688-17.92 94.251-46.421 127.445-80.299l120.491-113.451h-148.48c-23.552 0-42.667-19.115-42.667-42.667s19.115-42.667 42.667-42.667h255.872c0.171 0 0.384 0 0.555 0 5.845 0.043 11.392 1.28 16.469 3.499 5.077 2.176 9.771 5.376 13.824 9.6 0.512 0.512 0.981 1.067 1.451 1.621 3.243 3.712 5.717 7.851 7.467 12.245 1.749 4.352 2.773 9.088 2.944 13.995 0.085 0.555 0.085 1.109 0.085 1.707v256c0 23.552-19.115 42.667-42.667 42.667s-42.667-19.115-42.667-42.667v-157.227l-124.416 117.12c-42.368 43.179-97.024 78.763-159.915 100.949-111.104 39.296-227.669 29.781-326.144-17.28s-179.072-131.755-218.325-242.859-29.696-227.627 17.323-326.101 131.755-179.072 242.859-218.325 227.627-29.739 326.101 17.323 179.072 131.755 218.325 242.859c7.851 22.229-3.797 46.592-26.027 54.443s-46.592-3.797-54.443-26.027z" />
<glyph unicode="&#xe902;" glyph-name="file" d="M554.667 896h-298.667c-35.328 0-67.413-14.379-90.496-37.504s-37.504-55.168-37.504-90.496v-682.667c0-35.328 14.379-67.413 37.504-90.496s55.168-37.504 90.496-37.504h512c35.328 0 67.413 14.379 90.496 37.504s37.504 55.168 37.504 90.496v469.333c0 11.776-4.779 22.443-12.501 30.165l-298.667 298.667c-4.096 4.096-8.789 7.168-13.824 9.259-5.205 2.176-10.795 3.243-16.341 3.243zM750.336 597.334h-153.003v153.003zM512 810.667v-256c0-23.552 19.115-42.667 42.667-42.667h256v-426.667c0-11.776-4.736-22.4-12.501-30.165s-18.389-12.501-30.165-12.501h-512c-11.776 0-22.4 4.736-30.165 12.501s-12.501 18.389-12.501 30.165v682.667c0 11.776 4.736 22.4 12.501 30.165s18.389 12.501 30.165 12.501z" />
<glyph unicode="&#xe903;" glyph-name="layers" d="M512 805.632l331.264-165.632-331.264-165.632-331.264 165.632zM492.928 891.478l-426.667-213.333c-21.077-10.539-29.611-36.139-19.072-57.216 4.309-8.661 11.136-15.189 19.072-19.072l426.667-213.333c12.459-6.229 26.453-5.803 38.144 0l426.667 213.333c21.077 10.539 29.611 36.181 19.072 57.259-4.309 8.619-11.179 15.147-19.072 19.072l-426.667 213.333c-12.459 6.229-26.453 5.803-38.144 0zM66.261 175.19l426.667-213.333c12.459-6.229 26.453-5.803 38.144 0l426.667 213.333c21.077 10.539 29.611 36.181 19.072 57.259s-36.181 29.611-57.259 19.072l-407.552-203.819-407.595 203.776c-21.077 10.539-46.72 2.005-57.259-19.072s-2.005-46.72 19.072-57.259zM66.261 388.523l426.667-213.333c12.459-6.229 26.453-5.803 38.144 0l426.667 213.333c21.077 10.539 29.611 36.181 19.072 57.259s-36.181 29.611-57.259 19.072l-407.552-203.819-407.595 203.776c-21.077 10.539-46.72 2.005-57.259-19.072s-2.005-46.72 19.072-57.259z" />
<glyph unicode="&#xe904;" glyph-name="chevron-left" d="M670.165 200.832l-225.835 225.835 225.835 225.835c16.683 16.683 16.683 43.691 0 60.331s-43.691 16.683-60.331 0l-256-256c-16.683-16.683-16.683-43.691 0-60.331l256-256c16.683-16.683 43.691-16.683 60.331 0s16.683 43.691 0 60.331z" />
</font></defs></svg>

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

@@ -0,0 +1,5 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Plus sm">
<path id="Icon" fill-rule="evenodd" clip-rule="evenodd" d="M10 5C10.5523 5 11 5.44772 11 6V9L14 9C14.5523 9 15 9.44772 15 10C15 10.5523 14.5523 11 14 11H11V14C11 14.5523 10.5523 15 10 15C9.44771 15 9 14.5523 9 14V11H6C5.44772 11 5 10.5523 5 10C5 9.44771 5.44772 9 6 9L9 9V6C9 5.44772 9.44771 5 10 5Z" fill="white"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 441 B

View File

@@ -0,0 +1,209 @@
/**
* AJAX Request Queue
*
* - add()
* - remove()
* - run()
* - stop()
*
* @since 2.0.0
*/
const AstBlockTemplatesAjaxQueue = ( function () {
let requests = [];
return {
/**
* Add AJAX request
*
* @param {string} opt selected opt.
* @since 2.0.0
*/
add( opt ) {
requests.push( opt );
},
/**
* Remove AJAX request
*
* @param {string} opt selected opt.
* @since 2.0.0
*/
remove( opt ) {
if ( jQuery.inArray( opt, requests ) > -1 ) {
requests.splice( jQuery.inArray( opt, requests ), 1 );
}
},
/**
* Run / Process AJAX request
*
* @since 2.0.0
*/
run() {
const self = this;
let oriSuc;
if ( requests.length ) {
oriSuc = requests[ 0 ].complete;
requests[ 0 ].complete = function () {
if ( typeof oriSuc === 'function' ) {
oriSuc();
}
requests.shift();
self.run.apply( self, [] );
};
jQuery.ajax( requests[ 0 ] );
} else {
self.tid = setTimeout( function () {
self.run.apply( self, [] );
}, 1000 );
}
},
/**
* Stop AJAX request
*
* @since 2.0.0
*/
stop() {
requests = [];
clearTimeout( this.tid );
},
};
}() );
( function ( $ ) {
const AstBlockTemplates = {
remaining_install_plugins: 0,
remaining_active_plugins: 0,
init() {
this._bind();
},
/**
* Bind
*/
_bind() {
//Page builder installation & save option
$( document )
// .on(
// 'click',
// '.install-required-plugins',
// AstBlockTemplates._install_required_plugins
// )
.on( 'wp-plugin-installing', AstBlockTemplates._pluginInstalling )
.on( 'wp-plugin-install-error', AstBlockTemplates._installError )
.on(
'wp-plugin-install-success',
AstBlockTemplates._installSuccess
);
},
_installPlugin( plugin_slug ) {
if (
wp.updates.shouldRequestFilesystemCredentials &&
! wp.updates.ajaxLocked
) {
wp.updates.requestFilesystemCredentials( event );
$document.on( 'credential-modal-cancel', function () {
const $message = $( '.install-now.updating-message' );
$message
.removeClass( 'updating-message' )
.text( wp.updates.l10n.installNow );
wp.a11y.speak( wp.updates.l10n.updateCancel, 'polite' );
} );
}
wp.updates.queue.push( {
action: 'install-plugin', // Required action.
data: {
slug: plugin_slug,
},
} );
// Required to set queue.
wp.updates.queueChecker();
},
_activatePlugin( plugin_init, plugin_slug ) {
$.ajax( {
url: ajaxurl,
method: 'POST',
data: {
action: '',
plugin_slug,
plugin_init,
security: '',
},
} )
.done( function ( response ) {
if ( response.success ) {
console.log( plugin_slug + ' activated' );
// trigger_event();
} else {
console.log(
'Error: ' + response.data && response.data.message
? response.data.message
: 'Plugin not activated'
);
}
} )
.fail( function () {
console.log( 'activation error' );
} );
},
/**
* Installing Plugin
*
* @param {Object} event event data.
*/
_pluginInstalling( event ) {
event.preventDefault();
console.log( 'Installing..' );
},
/**
* Install Error
*
* @param {Object} event event data.
*/
_installError( event ) {
event.preventDefault();
console.log( 'Install Error!' );
},
/**
* Install Success
*
* @param {Object} event event data.
* @param {Array} args args data.
*/
_installSuccess( event, args ) {
event.preventDefault();
const plugin_init = args.slug + '/' + args.slug + '.php';
const plugin_slug = args.slug;
// WordPress adds "Activate" button after waiting for 1000ms. So we will run our activation after that.
setTimeout( function () {
AstBlockTemplates._activatePlugin( plugin_init, plugin_slug );
}, 1500 );
},
};
function trigger_event() {
const custom_event = new Event( 'ast-plugins-install-success' );
document.dispatchEvent( custom_event );
}
$( function () {
AstBlockTemplates.init();
} );
}( jQuery ) );

View File

@@ -0,0 +1,5 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<title>aspect_ratio</title>
<path d="M21 19.031v-14.063h-18v14.063h18zM21 3q0.797 0 1.406 0.609t0.609 1.406v13.969q0 0.797-0.609 1.406t-1.406 0.609h-18q-0.797 0-1.406-0.609t-0.609-1.406v-13.969q0-0.797 0.609-1.406t1.406-0.609h18zM6.984 9v3h-1.969v-5.016h4.969v2.016h-3zM18.984 12v5.016h-4.969v-2.016h3v-3h1.969z"></path>
</svg>

After

Width:  |  Height:  |  Size: 459 B

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<svg xmlns="http://www.w3.org/2000/svg">
<metadata>Generated by IcoMoon</metadata>
<defs>
<font id="ast-block-templates" horiz-adv-x="1024">
<font-face units-per-em="1024" ascent="960" descent="-64" />
<missing-glyph horiz-adv-x="1024" />
<glyph unicode="&#x20;" horiz-adv-x="512" d="" />
<glyph unicode="&#xe900;" glyph-name="maximize" d="M341.333 853.334h-128c-35.328 0-67.413-14.379-90.496-37.504s-37.504-55.168-37.504-90.496v-128c0-23.552 19.115-42.667 42.667-42.667s42.667 19.115 42.667 42.667v128c0 11.776 4.736 22.4 12.501 30.165s18.389 12.501 30.165 12.501h128c23.552 0 42.667 19.115 42.667 42.667s-19.115 42.667-42.667 42.667zM938.667 597.334v128c0 35.328-14.379 67.413-37.504 90.496s-55.168 37.504-90.496 37.504h-128c-23.552 0-42.667-19.115-42.667-42.667s19.115-42.667 42.667-42.667h128c11.776 0 22.4-4.736 30.165-12.501s12.501-18.389 12.501-30.165v-128c0-23.552 19.115-42.667 42.667-42.667s42.667 19.115 42.667 42.667zM682.667-0h128c35.328 0 67.413 14.379 90.496 37.504s37.504 55.168 37.504 90.496v128c0 23.552-19.115 42.667-42.667 42.667s-42.667-19.115-42.667-42.667v-128c0-11.776-4.736-22.4-12.501-30.165s-18.389-12.501-30.165-12.501h-128c-23.552 0-42.667-19.115-42.667-42.667s19.115-42.667 42.667-42.667zM85.333 256v-128c0-35.328 14.379-67.413 37.504-90.496s55.168-37.504 90.496-37.504h128c23.552 0 42.667 19.115 42.667 42.667s-19.115 42.667-42.667 42.667h-128c-11.776 0-22.4 4.736-30.165 12.501s-12.501 18.389-12.501 30.165v128c0 23.552-19.115 42.667-42.667 42.667s-42.667-19.115-42.667-42.667z" />
<glyph unicode="&#xe901;" glyph-name="rotate-cw" d="M834.005 312.875c-31.403-88.875-95.787-156.587-174.677-194.261s-171.989-45.269-260.864-13.867-156.587 95.787-194.261 174.677-45.269 171.989-13.867 260.864 95.787 156.587 174.677 194.261 171.989 45.269 260.864 13.867c50.688-17.92 94.251-46.421 127.445-80.299l120.491-113.451h-148.48c-23.552 0-42.667-19.115-42.667-42.667s19.115-42.667 42.667-42.667h255.872c0.171 0 0.384 0 0.555 0 5.845 0.043 11.392 1.28 16.469 3.499 5.077 2.176 9.771 5.376 13.824 9.6 0.512 0.512 0.981 1.067 1.451 1.621 3.243 3.712 5.717 7.851 7.467 12.245 1.749 4.352 2.773 9.088 2.944 13.995 0.085 0.555 0.085 1.109 0.085 1.707v256c0 23.552-19.115 42.667-42.667 42.667s-42.667-19.115-42.667-42.667v-157.227l-124.416 117.12c-42.368 43.179-97.024 78.763-159.915 100.949-111.104 39.296-227.669 29.781-326.144-17.28s-179.072-131.755-218.325-242.859-29.696-227.627 17.323-326.101 131.755-179.072 242.859-218.325 227.627-29.739 326.101 17.323 179.072 131.755 218.325 242.859c7.851 22.229-3.797 46.592-26.027 54.443s-46.592-3.797-54.443-26.027z" />
<glyph unicode="&#xe902;" glyph-name="file" d="M554.667 896h-298.667c-35.328 0-67.413-14.379-90.496-37.504s-37.504-55.168-37.504-90.496v-682.667c0-35.328 14.379-67.413 37.504-90.496s55.168-37.504 90.496-37.504h512c35.328 0 67.413 14.379 90.496 37.504s37.504 55.168 37.504 90.496v469.333c0 11.776-4.779 22.443-12.501 30.165l-298.667 298.667c-4.096 4.096-8.789 7.168-13.824 9.259-5.205 2.176-10.795 3.243-16.341 3.243zM750.336 597.334h-153.003v153.003zM512 810.667v-256c0-23.552 19.115-42.667 42.667-42.667h256v-426.667c0-11.776-4.736-22.4-12.501-30.165s-18.389-12.501-30.165-12.501h-512c-11.776 0-22.4 4.736-30.165 12.501s-12.501 18.389-12.501 30.165v682.667c0 11.776 4.736 22.4 12.501 30.165s18.389 12.501 30.165 12.501z" />
<glyph unicode="&#xe903;" glyph-name="layers" d="M512 805.632l331.264-165.632-331.264-165.632-331.264 165.632zM492.928 891.478l-426.667-213.333c-21.077-10.539-29.611-36.139-19.072-57.216 4.309-8.661 11.136-15.189 19.072-19.072l426.667-213.333c12.459-6.229 26.453-5.803 38.144 0l426.667 213.333c21.077 10.539 29.611 36.181 19.072 57.259-4.309 8.619-11.179 15.147-19.072 19.072l-426.667 213.333c-12.459 6.229-26.453 5.803-38.144 0zM66.261 175.19l426.667-213.333c12.459-6.229 26.453-5.803 38.144 0l426.667 213.333c21.077 10.539 29.611 36.181 19.072 57.259s-36.181 29.611-57.259 19.072l-407.552-203.819-407.595 203.776c-21.077 10.539-46.72 2.005-57.259-19.072s-2.005-46.72 19.072-57.259zM66.261 388.523l426.667-213.333c12.459-6.229 26.453-5.803 38.144 0l426.667 213.333c21.077 10.539 29.611 36.181 19.072 57.259s-36.181 29.611-57.259 19.072l-407.552-203.819-407.595 203.776c-21.077 10.539-46.72 2.005-57.259-19.072s-2.005-46.72 19.072-57.259z" />
<glyph unicode="&#xe904;" glyph-name="chevron-left" d="M670.165 200.832l-225.835 225.835 225.835 225.835c16.683 16.683 16.683 43.691 0 60.331s-43.691 16.683-60.331 0l-256-256c-16.683-16.683-16.683-43.691 0-60.331l256-256c16.683-16.683 43.691-16.683 60.331 0s16.683 43.691 0 60.331z" />
</font></defs></svg>

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.2.1, SVG Export Plug-In SVG - Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 100 100" style="enable-background:new 0 0 100 100;" xml:space="preserve">
<style type="text/css">
.st0{opacity:0.83;enable-background:new ;}
.st1{fill:#95F9EF;}
.st2{opacity:0.53;enable-background:new ;}
.st3{fill:url(#SVGID_1_);}
.st4{opacity:0.7;enable-background:new ;}
.st5{fill:url(#SVGID_2_);}
.st6{fill:#FFFFFF;}
</style>
<g>
<g class="st0">
<path class="st1" d="M26.8,88L9,33.5C8,30.7,9.6,27.8,12.2,27L66.8,9.2c2.7-0.9,5.7,0.6,6.4,3.2l17.9,54.6
c0.9,2.7-0.6,5.7-3.2,6.4l-54.6,18C30.5,92.2,27.6,90.8,26.8,88z"/>
</g>
<g class="st2">
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="4.238" y1="739.9995" x2="95.762" y2="739.9995" gradientTransform="matrix(1 0 0 1 0 -690)">
<stop offset="0" style="stop-color:#00E97B"/>
<stop offset="1" style="stop-color:#00F9D7"/>
</linearGradient>
<path class="st3" d="M44.7,94.3L5.6,52c-1.9-2.1-1.8-5.3,0.3-7.3L48.1,5.4c2.1-1.9,5.3-1.8,7.2,0.3L94.4,48
c1.9,2.1,1.8,5.3-0.3,7.3L51.9,94.6C50,96.6,46.6,96.4,44.7,94.3z"/>
</g>
<g class="st4">
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="296.5753" y1="-720.5554" x2="368.5928" y2="-720.5554" gradientTransform="matrix(0.9591 0.2829 0.2829 -0.9591 -65.1611 -734.9626)">
<stop offset="0" style="stop-color:#00DBDE"/>
<stop offset="1" style="stop-color:#FC00FF"/>
</linearGradient>
<path class="st5" d="M69.2,93.3L10.6,76.1c-2.9-0.8-4.5-3.9-3.7-6.8l17.2-58.6c0.8-2.9,3.9-4.5,6.8-3.7l58.6,17.2
c2.9,0.8,4.5,3.9,3.7,6.8L75.9,89.6C75.1,92.5,72,94.1,69.2,93.3z"/>
</g>
<g>
<path class="st6" d="M51.9,39.1L51.9,39.1h14.4V28.4H45.9c-1.9,0-3.7,0.3-5.3,1.1c-1.6,0.6-3.1,1.8-4.4,2.9
c-1.3,1.3-2.2,2.7-2.9,4.4c-0.4,0.7-0.6,1.6-0.8,2.4L51.9,39.1L51.9,39.1z"/>
<path class="st6" d="M66.9,53.3c-0.6-1.6-1.8-3.2-2.9-4.4c-1.3-1.3-2.7-2.2-4.4-2.9c-1.6-0.6-3.5-1.1-5.3-1.1h-2.4h-6H32.5
c0.2,0.9,0.5,1.7,0.8,2.6c0.6,1.6,1.8,3.2,2.9,4.4c1.3,1.3,2.7,2.2,4.4,2.9c1.6,0.8,3.5,1.1,5.3,1.1h8.4c0.5,0,0.8,0,1.1,0.2
c0.3,0.2,0.6,0.3,0.9,0.6c0.3,0.3,0.5,0.6,0.6,0.9c0.2,0.3,0.2,0.8,0.2,1.1c0,0.5,0,0.8-0.2,1.1c-0.2,0.3-0.3,0.6-0.6,0.9
c-0.3,0.3-0.6,0.5-0.9,0.6c-0.3,0.2-0.8,0.2-1.1,0.2h-20v10.8h19.8c1.9,0,3.7-0.3,5.5-1.1c1.6-0.6,3.2-1.8,4.4-2.9
c1.3-1.3,2.2-2.7,2.9-4.4c0.6-1.6,1.1-3.5,1.1-5.3C68,56.6,67.7,54.9,66.9,53.3z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@@ -0,0 +1,9 @@
<svg width="60" height="60" viewBox="0 0 84 85" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M41.7849 0C33.5206 0 25.4419 2.49258 18.5705 7.16254C11.699 11.8325 6.34331 18.4701 3.18071 26.236C0.0181112 34.0018 -0.809377 42.5471 0.802901 50.7913C2.41518 59.0355 6.3948 66.6083 12.2385 72.552C18.0822 78.4958 25.5276 82.5435 33.633 84.1834C41.7385 85.8232 50.1401 84.9816 57.7753 81.7649C65.4105 78.5482 71.9363 73.1008 76.5277 66.1117C81.1191 59.1226 83.5697 50.9057 83.5697 42.5C83.565 31.2298 79.1612 20.4225 71.326 12.4533C63.4908 4.48402 52.8655 0.0048112 41.7849 0ZM57.5278 49.0175C57.5278 49.1264 57.5278 49.2354 57.5278 49.3443V49.6529V49.8526C57.3161 51.0856 56.8673 52.2639 56.207 53.3201L55.8143 53.8829L55.2431 54.5546C55.0482 54.8082 54.8268 55.0396 54.5827 55.2445V55.3353L54.4578 55.4261L54.2079 55.6258C54.1249 55.7007 54.0353 55.7675 53.9402 55.8255L53.6724 56.0071L34.3061 69.0602C34.1479 69.1683 33.9612 69.2253 33.7706 69.2236H33.5743C33.447 69.1967 33.3262 69.1443 33.2189 69.0695C33.1117 68.9947 33.0201 68.899 32.9495 68.7879C32.9495 68.7879 32.5033 67.9891 32.4676 67.9347V67.7531V67.6623V67.5534V67.4263V67.2811C31.7014 65.262 31.6378 63.0371 32.2872 60.9761C32.9366 58.9152 34.2601 57.1424 36.0375 55.9526L45.0691 49.8708C45.2101 49.7754 45.3201 49.6398 45.3853 49.4809C45.4505 49.322 45.4679 49.147 45.4355 48.9781C45.403 48.8091 45.3221 48.6537 45.2029 48.5315C45.0837 48.4093 44.9316 48.3257 44.7657 48.2913L34.1633 46.1128H33.8599H33.7706H33.485H33.1816H33.0567H32.896H32.8068L32.5212 46.0038H32.4319H32.2534L31.9679 45.8586L31.6823 45.7134L31.4145 45.55L31.1468 45.3866C30.3041 44.8521 29.5509 44.1841 28.9156 43.4077L28.6836 43.0809L28.4159 42.6634C27.73 41.6278 27.255 40.4629 27.0189 39.2375C26.7828 38.012 26.7905 36.751 27.0415 35.5286C27.228 34.6884 27.5221 33.8766 27.9161 33.1141C28.0232 32.9144 28.1124 32.7328 28.2195 32.5694L28.3802 32.3153C28.4948 32.1207 28.6199 31.9329 28.755 31.7525L28.9156 31.5528L29.112 31.3167L29.3083 31.0989L29.4333 30.9718L29.6475 30.754L29.8259 30.5906L30.0223 30.4272L30.2365 30.2456H30.3257L30.4685 30.1185H30.5578L30.7898 29.9551L50.049 16.9746C50.1725 16.8912 50.3113 16.8338 50.457 16.806C50.6027 16.7782 50.7524 16.7804 50.8973 16.8126C51.0421 16.8448 51.1791 16.9062 51.3002 16.9933C51.4212 17.0804 51.5238 17.1913 51.6019 17.3195L51.7626 17.5918L51.8875 17.846C51.8875 17.9368 51.9768 18.0094 52.0125 18.082C52.0125 18.082 52.0125 18.082 52.0125 18.191C52.0239 18.2325 52.0239 18.2765 52.0125 18.318L52.1195 18.5904C52.1292 18.6383 52.1292 18.6877 52.1195 18.7356C52.1195 18.7356 52.1195 18.7356 52.1195 18.8445C52.8288 20.8305 52.8625 23.0011 52.2153 25.0089C51.5681 27.0166 50.2774 28.7455 48.5497 29.9188L39.6251 35.9462C39.4842 36.0415 39.3742 36.1772 39.309 36.3361C39.2438 36.495 39.2263 36.6699 39.2588 36.8389C39.2912 37.0078 39.3722 37.1632 39.4914 37.2854C39.6106 37.4077 39.7627 37.4912 39.9286 37.5256L50.4417 39.686C52.5458 40.1281 54.4361 41.2935 55.7948 42.9862C57.1536 44.679 57.8979 46.796 57.9027 48.9812C57.5635 48.4003 57.5278 48.9812 57.5278 48.9812V49.0175Z" fill="url(#paint0_linear_619_170)"/>
<defs>
<linearGradient id="paint0_linear_619_170" x1="1.17098e-05" y1="1.49716e-06" x2="84.02" y2="71.3596" gradientUnits="userSpaceOnUse">
<stop stop-color="#4E01D1"/>
<stop offset="1" stop-color="#6104FF"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@@ -0,0 +1,3 @@
<svg width="71" height="71" viewBox="0 0 71 71" fill="#000000" xmlns="http://www.w3.org/2000/svg">
<path d="M35.292 0C28.3119 0 21.4885 2.08204 15.6848 5.98283C9.88107 9.88362 5.35762 15.428 2.68645 21.9147C0.0152817 28.4015 -0.683625 35.5394 0.678124 42.4257C2.03987 49.312 5.40111 55.6375 10.3368 60.6023C15.2725 65.5671 21.5609 68.9481 28.4068 70.3179C35.2528 71.6876 42.3489 70.9846 48.7976 68.2977C55.2464 65.6108 60.7583 61.0607 64.6362 55.2227C68.5141 49.3848 70.584 42.5212 70.584 35.5C70.58 26.0861 66.8604 17.0588 60.2428 10.4021C53.6251 3.74548 44.6508 0.00401876 35.292 0V0ZM48.5887 40.944C48.5887 41.035 48.5887 41.126 48.5887 41.217V41.4748V41.6416C48.4098 42.6715 48.0307 43.6558 47.4731 44.538L47.1414 45.0081L46.659 45.5692C46.4943 45.781 46.3073 45.9742 46.1012 46.1454V46.2213L45.9957 46.2971L45.7846 46.4639C45.7145 46.5265 45.6388 46.5823 45.5585 46.6307L45.3323 46.7824L28.9753 57.6856C28.8417 57.7759 28.684 57.8235 28.523 57.8221H28.3572C28.2497 57.7996 28.1477 57.7558 28.0571 57.6933C27.9665 57.6309 27.8892 57.5509 27.8296 57.4582C27.8296 57.4582 27.4527 56.7909 27.4225 56.7454V56.5938V56.5179V56.4269V56.3208V56.1995C26.7754 54.513 26.7216 52.6545 27.2701 50.933C27.8187 49.2115 28.9365 47.7307 30.4376 46.7369L38.0659 41.6568C38.1849 41.5771 38.2779 41.4638 38.3329 41.3311C38.388 41.1984 38.4027 41.0522 38.3753 40.9111C38.3479 40.77 38.2796 40.6402 38.1789 40.5381C38.0782 40.436 37.9497 40.3662 37.8096 40.3375L28.8547 38.5177H28.5984H28.523H28.2818H28.0255H27.92H27.7843H27.709L27.4678 38.4267H27.3924H27.2416L27.0004 38.3054L26.7592 38.1841L26.533 38.0476L26.3069 37.9111C25.5952 37.4647 24.959 36.9067 24.4225 36.2582L24.2265 35.9853L24.0004 35.6365C23.421 34.7714 23.0198 33.7984 22.8205 32.7748C22.6211 31.7512 22.6276 30.6979 22.8395 29.6769C22.9971 28.975 23.2455 28.2969 23.5782 27.66C23.6687 27.4932 23.7441 27.3415 23.8345 27.205L23.9702 26.9927C24.067 26.8303 24.1727 26.6733 24.2868 26.5226L24.4225 26.3558L24.5883 26.1587L24.7541 25.9767L24.8597 25.8706L25.0406 25.6886L25.1913 25.5521L25.3572 25.4156L25.5381 25.264H25.6134L25.734 25.1578H25.8094L26.0054 25.0214L42.272 14.1788C42.3763 14.1091 42.4935 14.0612 42.6166 14.038C42.7396 14.0147 42.8661 14.0166 42.9884 14.0435C43.1108 14.0704 43.2265 14.1217 43.3287 14.1944C43.431 14.2672 43.5176 14.3598 43.5836 14.4669L43.7192 14.6944L43.8248 14.9067C43.8248 14.9825 43.9002 15.0432 43.9303 15.1038C43.9303 15.1038 43.9303 15.1038 43.9303 15.1948C43.94 15.2295 43.94 15.2662 43.9303 15.3009V15.3009L44.0208 15.5284C44.0289 15.5684 44.0289 15.6097 44.0208 15.6497C44.0208 15.6497 44.0208 15.6497 44.0208 15.7407C44.6198 17.3996 44.6483 19.2127 44.1017 20.8897C43.555 22.5668 42.4648 24.011 41.0056 24.991L33.4678 30.0256C33.3488 30.1053 33.2559 30.2186 33.2008 30.3513C33.1457 30.484 33.131 30.6302 33.1584 30.7713C33.1858 30.9124 33.2542 31.0422 33.3549 31.1443C33.4555 31.2464 33.584 31.3162 33.7241 31.3449L42.6036 33.1495C44.3808 33.5188 45.9773 34.4922 47.1249 35.9061C48.2726 37.3201 48.9012 39.0884 48.9053 40.9137C48.6188 40.4285 48.5887 40.9137 48.5887 40.9137V40.944Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@@ -0,0 +1,4 @@
<svg width="90" height="90" viewBox="0 0 90 90" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M71.2429 7.34463H18.3616C12.2771 7.34463 7.34463 12.2771 7.34463 18.3616V71.2429C7.34463 77.3274 12.2771 82.2598 18.3616 82.2598H71.2429C77.3274 82.2598 82.2598 77.3274 82.2598 71.2429V18.3616C82.2598 12.2771 77.3274 7.34463 71.2429 7.34463ZM18.3616 0C8.22076 0 0 8.22075 0 18.3616V71.2429C0 81.3837 8.22075 89.6045 18.3616 89.6045H71.2429C81.3837 89.6045 89.6045 81.3837 89.6045 71.2429V18.3616C89.6045 8.22076 81.3837 0 71.2429 0H18.3616Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M54.1449 28.1896C53.9728 28.0356 53.7911 27.8882 53.5998 27.7474C51.9414 26.5264 49.6907 25.9159 46.8478 25.9159C44.916 25.9159 43.285 26.1892 41.9546 26.7359C40.6243 27.2644 39.6037 28.0025 38.893 28.9502C38.1294 29.995 36.829 30.8418 35.7046 30.2012C34.8223 29.6985 34.0076 29.0784 33.2839 28.3548C31.9339 27.0047 30.944 25.3377 30.405 23.5061C30.1674 22.6988 30.3776 21.8165 31.0133 21.265C32.434 20.0323 34.0947 18.9948 35.9954 18.1524C39.2028 16.7309 42.8476 16.0202 46.9298 16.0202C51.0849 16.0202 54.7115 16.7309 57.8095 18.1524C60.9259 19.5739 63.3496 21.5512 65.0809 24.0843C65.7142 25.011 66.2354 25.9913 66.6443 27.0252C67.8571 30.0913 65.0579 32.8866 61.7607 32.8866C59.1869 32.8866 57.1265 30.9615 55.18 29.1429L55.1799 29.1428C54.8321 28.8178 54.4878 28.4962 54.1449 28.1896ZM37.1987 34.2544C37.6871 34.0635 38.21 34.3524 38.4829 34.8001C38.9568 35.5473 39.6037 36.1942 40.4238 36.7409C41.2439 37.2694 42.1915 37.7342 43.2667 38.1351C44.342 38.5178 45.4901 38.8458 46.7111 39.1192L51.7409 40.322C54.183 40.8687 56.4245 41.5977 58.4656 42.5089C60.5067 43.4201 62.2744 44.5408 63.7688 45.8712C65.2632 47.2015 66.4204 48.7688 67.2405 50.573C68.0788 52.3772 68.5071 54.4456 68.5253 56.7783C68.5071 60.2044 67.6323 63.1749 65.901 65.6898C64.188 68.1865 61.7095 70.1274 58.4656 71.5124C55.2399 72.8792 51.3491 73.5626 46.7931 73.5626C42.2735 73.5626 38.3371 72.8701 34.9839 71.4851C31.6489 70.1001 29.0429 68.0499 27.1658 65.3345C26.2995 64.0605 25.6252 62.646 25.1428 61.091C24.1699 57.9547 26.943 55.1928 30.2268 55.1928H30.6526C33.4909 55.1928 35.5992 57.6279 37.3075 59.8946C38.2734 61.1338 39.5582 62.0724 41.1619 62.7102C42.7838 63.3298 44.6153 63.6396 46.6564 63.6396C48.6611 63.6396 50.4015 63.3481 51.8776 62.7649C53.372 62.1817 54.5292 61.3707 55.3493 60.332C56.1694 59.2932 56.5794 58.0995 56.5794 56.7509C56.5794 55.4935 56.2058 54.4365 55.4586 53.58C54.7297 52.7234 53.6545 51.9945 52.233 51.3931C50.8297 50.7917 49.1076 50.245 47.0665 49.7529L40.9705 48.2221C36.9718 47.2494 33.6859 45.8124 31.1129 43.9111C30.4174 43.3972 30.1608 42.4925 30.405 41.6629C30.9439 39.8315 31.9336 38.1645 33.2834 36.8145C34.4003 35.6975 35.7342 34.827 37.1987 34.2544ZM29.9545 26.532L29.4188 24.7118C29.3957 24.6328 29.3476 24.5633 29.2818 24.5139C29.2159 24.4645 29.1358 24.4378 29.0535 24.4378C28.9712 24.4378 28.8911 24.4645 28.8252 24.5139C28.7593 24.5633 28.7113 24.6328 28.6882 24.7118L28.1532 26.532C27.7938 27.7529 27.1338 28.8641 26.2338 29.764C25.3338 30.6639 24.2224 31.3236 23.0014 31.6829L21.1811 32.2186C20.8166 32.3267 20.8166 32.8426 21.1811 32.9491L23.0014 33.4849C24.2222 33.8442 25.3335 34.5041 26.2334 35.4039C27.1333 36.3038 27.7931 37.415 28.1525 38.6358L28.6882 40.4568C28.7955 40.8205 29.3115 40.8205 29.4188 40.4568L29.9545 38.6365C30.3138 37.4156 30.9736 36.3043 31.8735 35.4042C32.7734 34.5042 33.8847 33.8443 35.1056 33.4849L36.9266 32.9491C37.2904 32.8419 37.2904 32.3259 36.9266 32.2194L35.1064 31.6837C33.8853 31.3243 32.7738 30.6645 31.8738 29.7644C30.9738 28.8644 30.3138 27.753 29.9545 26.532ZM23.461 37.2817L23.6218 37.8277C23.7296 38.194 23.9275 38.5275 24.1975 38.7975C24.4676 39.0675 24.801 39.2654 25.1673 39.3732L25.7134 39.5339C25.8225 39.5659 25.8225 39.7207 25.7134 39.7529L25.1671 39.9136C24.8008 40.0214 24.4674 40.2194 24.1975 40.4894C23.9275 40.7594 23.7295 41.0928 23.6218 41.4591L23.461 42.0051C23.4288 42.1143 23.2741 42.1143 23.2419 42.0051L23.0812 41.4589C22.9733 41.0926 22.7754 40.7593 22.5054 40.4893C22.2354 40.2193 21.9021 40.0214 21.5358 39.9136L20.9897 39.7529C20.8804 39.7209 20.8804 39.5661 20.9897 39.5337L21.5358 39.373C21.9021 39.2652 22.2355 39.0673 22.5055 38.7973C22.7756 38.5274 22.9735 38.194 23.0814 37.8277L23.2419 37.2817C23.2488 37.2579 23.2632 37.2371 23.283 37.2223C23.3027 37.2075 23.3268 37.1995 23.3515 37.1995C23.3762 37.1995 23.4002 37.2075 23.4199 37.2223C23.4397 37.2371 23.4541 37.2579 23.461 37.2817ZM22.4142 22.428L22.1642 21.5786C22.1535 21.5417 22.131 21.5093 22.1003 21.4863C22.0696 21.4632 22.0322 21.4508 21.9938 21.4508C21.9554 21.4508 21.918 21.4632 21.8872 21.4863C21.8565 21.5093 21.8341 21.5417 21.8233 21.5786L21.5737 22.428C21.4059 22.9978 21.0979 23.5164 20.6779 23.9363C20.2579 24.3562 19.7392 24.6641 19.1695 24.8318L18.32 25.0818C18.1499 25.1322 18.1499 25.373 18.32 25.4227L19.1695 25.6727C19.7392 25.8404 20.2578 26.1483 20.6777 26.5683C21.0977 26.9882 21.4056 27.5068 21.5733 28.0765L21.8233 28.9263C21.8734 29.096 22.1142 29.096 22.1642 28.9263L22.4142 28.0768C22.5819 27.507 22.8898 26.9884 23.3098 26.5684C23.7297 26.1484 24.2483 25.8404 24.8181 25.6727L25.6679 25.4227C25.8377 25.3726 25.8377 25.1319 25.6679 25.0821L24.8184 24.8321C24.2486 24.6645 23.7299 24.3565 23.3099 23.9365C22.8899 23.5165 22.5819 22.9978 22.4142 22.428Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 100 100" style="enable-background:new 0 0 100 100;" xml:space="preserve">
<style type="text/css">
.st0{opacity:0.5;}
.st1{fill:#FFFFFF;}
.st2{opacity:0.8;}
</style>
<g>
<g class="st0">
<path class="st1" d="M68.02,6.1l-6.81,2.16l6.14,6.64l10.29,2.99l-2.82-8.47C73.99,6.76,71.01,5.1,68.02,6.1z"/>
<path class="st1" d="M5.94,32.16l2.32,6.81l6.64-6.14l2.99-10.46l-8.47,2.82C6.6,26.18,4.94,29.34,5.94,32.16z"/>
<path class="st1" d="M22.37,82.45l2.82,8.47c0.83,2.99,3.98,4.48,6.97,3.65l7.14-2.32l-5.98-6.47L22.37,82.45z"/>
<path class="st1" d="M94.08,68.18l-2.32-7.14l-6.31,5.98l-3.32,10.95l8.47-2.82C93.41,74.32,95.24,71.16,94.08,68.18z"/>
</g>
<g class="st2">
<path class="st1" d="M55.73,2.45c-2.16-2.32-5.48-2.49-7.8-0.33l-5.98,5.48l11.29,3.32l13.94,4.15l-6.14-6.64L55.73,2.45z"/>
<path class="st1" d="M2.62,44.27c-2.32,2.16-2.49,5.48-0.33,7.8l5.15,5.64l3.15-10.95l4.15-13.94L8.1,38.96L2.62,44.27z"/>
<path class="st1" d="M97.73,47.93l-5.15-5.48l-3.32,11.12l-3.98,13.28l6.31-5.98l5.64-5.31C99.72,53.73,99.89,50.25,97.73,47.93z"
/>
<path class="st1" d="M33.16,85.6l5.98,6.47l5.15,5.48c2.16,2.32,5.64,2.49,7.8,0.33l5.64-5.15l-10.79-3.15L33.16,85.6z"/>
</g>
<path class="st1" d="M92.42,22.36l-14.77-4.32l-10.29-2.99l-13.94-4.15L42.12,7.59L29.51,3.94c-3.15-0.83-6.47,0.83-7.3,3.98
L17.89,22.7L14.9,33.15L10.75,47.1L7.6,58.05L3.78,71.16c-0.83,3.15,0.83,6.47,3.98,7.3l14.77,4.32l10.79,3.15l13.61,3.98
l10.79,3.15l12.95,3.82c3.15,0.83,6.47-0.83,7.3-3.98l4.32-14.61l3.32-10.95l3.98-13.28l3.32-11.12l3.82-12.78
C97.23,26.51,95.57,23.19,92.42,22.36z M67.69,26.68V38.3H52.25l0,0H31.5c0.17-0.83,0.5-1.83,0.83-2.66
c0.66-1.66,1.66-3.32,3.15-4.65c1.33-1.16,2.99-2.49,4.65-3.15c1.66-0.83,3.65-1.16,5.64-1.16H67.69z M33.33,74.15V62.53h21.41
c0.33,0,0.83,0,1.16-0.17c0.33-0.17,0.66-0.33,1-0.66c0.33-0.33,0.5-0.66,0.66-1c0.17-0.33,0.17-0.66,0.17-1.16
c0-0.33,0-0.83-0.17-1.16c-0.17-0.33-0.33-0.66-0.66-1c-0.33-0.33-0.66-0.5-1-0.66c-0.33-0.17-0.66-0.17-1.16-0.17h-8.96
c-1.83,0-3.98-0.33-5.64-1.16c-1.66-0.66-3.32-1.66-4.65-3.15c-1.16-1.16-2.49-2.99-3.15-4.65c-0.5-1-0.66-1.83-0.83-2.82h14.44
h6.47h2.49c1.83,0,3.98,0.5,5.64,1.16c1.66,0.66,3.32,1.66,4.65,3.15c1.16,1.16,2.49,2.99,3.15,4.65c0.83,1.66,1.16,3.65,1.16,5.81
c0,1.83-0.5,3.98-1.16,5.64c-0.66,1.66-1.66,3.32-3.15,4.65c-1.16,1.16-2.99,2.49-4.65,3.15c-1.83,0.83-3.82,1.16-5.81,1.16
L33.33,74.15L33.33,74.15z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@@ -0,0 +1,49 @@
@font-face {
font-family: ast-block-templates;
src: url( "fonts/ast-block-templates.eot?p3u0q1" );
src:
url( "fonts/ast-block-templates.eot?p3u0q1#iefix" ) format( "embedded-opentype" ),
url( "fonts/ast-block-templates.ttf?p3u0q1" ) format( "truetype" ),
url( "fonts/ast-block-templates.woff?p3u0q1" ) format( "woff" ),
url( "fonts/ast-block-templates.svg?p3u0q1#ast-block-templates" ) format( "svg" );
font-weight: 400;
font-style: normal;
font-display: block;
}
[class^="ast-block-templates-icon-"],
[class*=" ast-block-templates-icon-"] {
/* use !important to prevent issues with browser extensions that change fonts */
font-family: ast-block-templates, sans-serif !important;
speak: never;
font-style: normal;
font-weight: 400;
font-variant: normal;
text-transform: none;
line-height: 1;
/* Better Font Rendering =========== */
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.ast-block-templates-icon-chevron-left::before {
content: "\e904";
}
.ast-block-templates-icon-pages::before {
content: "\e902";
}
.ast-block-templates-icon-patterns::before {
content: "\e903";
}
.ast-block-templates-icon-wireframe::before {
content: "\e900";
}
.ast-block-templates-icon-refresh::before {
content: "\e901";
}

View File

@@ -0,0 +1,185 @@
<?php
/**
* Plugin Loader.
*
* @package {{package}}
* @since 2.0.0
*/
namespace Gutenberg_Templates;
use Gutenberg_Templates\Inc\Api\Api_Init;
use Gutenberg_Templates\Inc\Importer\Sync_Library;
use Gutenberg_Templates\Inc\Importer\Sync_Library_WP_CLI;
use Gutenberg_Templates\Inc\Importer\Plugin;
use Gutenberg_Templates\Inc\Importer\Image_Importer;
use Gutenberg_Templates\Inc\Importer\Updater;
use Gutenberg_Templates\Inc\Content\Ai_Content;
use Gutenberg_Templates\Inc\Traits\Upgrade;
use Gutenberg_Templates\Inc\Importer\Template_Kit_Importer;
use Gutenberg_Templates\Inc\Block\Spectra_AI_Block;
use Gutenberg_Templates\Inc\Classes\Ast_Block_Templates_Zipwp_Api;
use Gutenberg_Templates\Inc\Classes\Ast_Block_Templates_Notices;
/**
* Ast_Block_Plugin_Loader
*
* @since 2.0.0
*/
class Ast_Block_Plugin_Loader {
/**
* Instance
*
* @access private
* @var object Class Instance.
* @since 2.0.0
*/
private static $instance = null;
/**
* Initiator
*
* @since 2.0.0
* @return object initialized object of class.
*/
public static function get_instance() {
if ( null === self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Autoload classes.
*
* @param string $class class name.
*
* @return void
*/
public function autoload( $class ) {
if ( 0 !== strpos( $class, __NAMESPACE__ ) ) {
return;
}
$class_to_load = $class;
$filename = strtolower(
(string) preg_replace(
array( '/^' . __NAMESPACE__ . '\\\/', '/([a-z])([A-Z])/', '/_/', '/\\\/' ),
array( '', '$1-$2', '-', DIRECTORY_SEPARATOR ),
$class_to_load
)
);
$file = AST_BLOCK_TEMPLATES_DIR . $filename . '.php';
// if the file redable, include it.
if ( is_readable( $file ) ) {
require_once $file;
}
}
/**
* Constructor
*
* @since 2.0.0
*/
public function __construct() {
spl_autoload_register( array( $this, 'autoload' ) );
add_action( 'wp_loaded', array( $this, 'load_textdomain' ) );
add_action( 'wp_loaded', array( $this, 'load_classes' ), 999 );
}
/**
* Loads plugin classes as per requirement.
*
* @return void
* @since 2.0.0
*/
public function load_classes() {
require_once AST_BLOCK_TEMPLATES_DIR . 'inc/classes/ast-block-templates-notices.php';
if ( ! Ast_Block_Templates_Notices::instance()->has_file_read_write() ) {
return;
}
Ast_Block_Templates_Zipwp_Api::instance();
Api_Init::instance();
Template_Kit_Importer::instance();
Plugin::instance();
Image_Importer::instance();
Sync_Library::instance();
Sync_Library_WP_CLI::instance();
Ai_Content::instance();
Upgrade::instance();
Updater::instance();
//phpcs:disable Squiz
// Spectra_AI_Block::get_instance();
//phpcs:enable Squiz
}
/**
* Load Plugin Text Domain.
* This will load the translation textdomain depending on the file priorities.
* 1. Global Languages /wp-content/languages/gutenberg-templates/ folder
* 2. Local dorectory /wp-content/plugins/gutenberg-templates/languages/ folder
*
* @since 2.0.0
* @return void
*/
public function load_textdomain() {
// Default languages directory.
$lang_dir = AST_BLOCK_TEMPLATES_DIR . 'languages/';
/**
* Filters the languages directory path to use for plugin.
*
* @param string $lang_dir The languages directory path.
*/
$lang_dir = apply_filters( 'wpb_languages_directory', $lang_dir );
// Traditional WordPress plugin locale filter.
global $wp_version;
$get_locale = get_locale();
if ( $wp_version >= 4.7 ) {
$get_locale = get_user_locale();
}
/**
* Language Locale for plugin
*
* @var string $get_locale The locale to use.
* Uses get_user_locale()` in WordPress 4.7 or greater,
* otherwise uses `get_locale()`.
*/
$locale = apply_filters( 'plugin_locale', $get_locale, 'ast-block-templates' );
$mofile = sprintf( '%1$s-%2$s.mo', 'ast-block-templates', $locale );
// Setup paths to current locale file.
$mofile_global = WP_LANG_DIR . '/plugins/' . $mofile;
$mofile_local = $lang_dir . $mofile;
if ( file_exists( $mofile_global ) ) {
// Look in global /wp-content/languages/gutenberg-templates/ folder.
load_textdomain( 'ast-block-templates', $mofile_global );
} elseif ( file_exists( $mofile_local ) ) {
// Look in local /wp-content/plugins/gutenberg-templates/languages/ folder.
load_textdomain( 'ast-block-templates', $mofile_local );
} else {
// Load the default language files.
load_plugin_textdomain( 'ast-block-templates', false, $lang_dir );
}
}
}
/**
* Kicking this off by calling 'get_instance()' method
*/
Ast_Block_Plugin_Loader::get_instance();

View File

@@ -0,0 +1,41 @@
<?php
/**
* Plugin Name: Gutenberg Starter Templates
* Plugin URI: https://wpastra.com/
* Description: Gutenberg single page templates, and blocks library to imported your website easily.
* Version: 2.4.8
* Author: Brainstorm Force
* Author URI: https://www.brainstormforce.com
* Text Domain: ast-block-templates
*
* @package Ast Block Templates
*/
/**
* Set constants.
*/
if ( defined( 'Ast_Block_Templates' ) ) {
return;
}
if ( apply_filters( 'ast_block_templates_disable', false ) ) {
return;
}
// Set constants.
if ( ! defined( 'AST_BLOCK_TEMPLATES_LIBRARY_URL' ) ) {
define( 'AST_BLOCK_TEMPLATES_LIBRARY_URL', trailingslashit( apply_filters( 'ast_block_templates_library_url', 'https://websitedemos.net/' ) ) );
}
define( 'AST_BLOCK_TEMPLATES_VER', '2.4.8' );
define( 'AST_BLOCK_TEMPLATES_FILE', __FILE__ );
define( 'AST_BLOCK_TEMPLATES_BASE', plugin_basename( AST_BLOCK_TEMPLATES_FILE ) );
define( 'AST_BLOCK_TEMPLATES_DIR', plugin_dir_path( AST_BLOCK_TEMPLATES_FILE ) );
define( 'AST_BLOCK_TEMPLATES_URI', plugins_url( '/', AST_BLOCK_TEMPLATES_FILE ) );
if ( ! defined( 'AST_BLOCK_TEMPLATES_JSON_DIR' ) ) {
$upload_dir = wp_get_upload_dir();
define( 'AST_BLOCK_TEMPLATES_JSON_DIR', trailingslashit( $upload_dir['basedir'] ) . 'ast-block-templates-json/' );
}
require_once 'class-ast-block-templates.php';

View File

@@ -0,0 +1,353 @@
v.2.4.8 - 29-November-2024
Improvement: Improved business description screen for better user experience.
Improvement: UI enhancements for better usability.
Improvement: Improved code quality for enhanced performance and maintainability.
v.2.4.7 - 31-October-2024
Improvement: Generating business description based on the selected language.
Improvement: Optimized styles for better readability and usability on smaller screens.
v.2.4.6 - 14-October-2024
- New: Added source parameters to URLs redirecting to ZipWP for better tracking.
v.2.4.5 - 08-October-2024
Improvement: Removed outdated options data that were previously left undeleted.
Improvement: Optimized server API call execution for better performance.
v.2.4.4 - 30-September-2024
Improvement: Added loading skeleton when uploading the images on AI onboarding.
Improvement: Added images validation on AI onboarding.
Fix: Fixed PHP warning when generating content.
v.2.4.3 - 26-September-2024
Fix: Content was not getting generated in the selected language.
v.2.4.2 - 11-September-2024
New: Introduced filter `ast_block_templates_exclude_post_types` to exclude asset loading for specified post types.
Fix: Resolved CSS conflicts with the WordPress core list block.
v.2.4.1 - 29-August-2024
Improvement: Enhanced API performance by optimizing execution times and reducing delays.
Fix: Corrected styling issues for patterns/pages preview to ensure consistent display.
Fix: Addressed CSS conflicts with SureCart blocks to prevent styling discrepancies.
v.2.4.0 - 08-August-2024
New: Enhanced AI onboarding UI.
v.2.3.6 - 06-August-2024
Fix: Pattern CSS file was not loading correctly.
v.2.3.5 - 06-August-2024
Improvement: Hidden Update Image option until the user personalizes the library.
Improvement: Blocked block pages preview if import is in process.
v.2.3.4 - 02-August-2024
Improvement: Converted spectra common stylesheet to json file instead of option variable.
v.2.3.3 - 30-July-2024
Fix: Resolved issue where the Favorites functionality was not working in certain cases.
Fix: Addressed problem where related block pages were not displaying in some scenarios.
Fix: Content regeneration for a category was not working.
v.2.3.2 - 26-July-2024
Fix: Resolved visibility issue with the "Design Library" button in WordPress 6.6 with full site editor.
v.2.3.1 - 3-July-2024
Fix: Resolved an issue where adding social media URLs caused an error when proceeding to the next step.
v.2.3.0 - 2-July-2024
New: Added a page preview feature along with other page options.
Improvement: Introduced a new "Favorites" tab, separated from Patterns, Pages, and Kits.
Improvement: Added clickable navigation in the sidebar, allowing users to jump to previous steps.
Improvement: Disbaled live preview while inserting the kit into a page.
Improvement: Improved UI/UX for a better user experience.
Fix: Resolved an issue where the Design Library button was not displayed in the Spectra One theme editor when the Gutenberg Plugin was activated.
Fix: Fixed a console error that occurred on the screen of the image when AI data was prefilled.
Fix: Addressed a blank screen issue when accessing the "Design Library" on Bedrock-powered sites.
Fix: Fixed option 'ast-block-templates_data-' was not getting deleted after importing the site template.
v2.2.5 - 27-June-2024
- Fix: Fixed console error causing blank screen in GT AI onboarding if already prefilled.
v2.2.4 - 17-June-2024
- New: Added error boundaries for better error management.
- Improvement: Improved UI for better consistency.
- Improvement: Enhanced error handling during the import process.
- Improvement: Blocked all other actions while inserting the kit into a page.
- Improvement: Added an admin notice for missing file permissions.
- Improvement: Removed validation for the mobile field in AI onboarding.
- Improvement: Added loader while inserting the block.
- Fix: Prevented adding block to new page after Spectra installation.
- Fix: Shuffling of images if changes the orientation multiple times.
- Fix: AI generated business description response count was not working as expected.
- Fix: Fixed issue with authentication redirection.
v2.2.3 - 06-June-2024
- Fix: Resolved Console error for undefined images.
v2.2.2 - 20-May-2024
- Fix: Fixed design library was displaying empty on subfolder sites.
v2.2.1 - 02-May-2024
- Improvement: Better error message handling.
- Improvement: Blocked everything after clicking on the continue button.
- Fix: Removed the hotlinking of websitedemos link after import.
v2.2.0 - 26-April-2024
- Improvement: Revamped AI onboarding with language compatibility.
- Improvement: User Interface Enhancements & tweaks.
- Fix: JSON file names renamed correctly.
v2.1.28 - 12-April-2024
- Fix: Resolved line-height issue for blocks.
v2.1.27 - 9-April-2024
- Fix: Design library button not showing sometime.
v2.1.26 - 9-April-2024
- Fix: Fixed Media library not working.
v2.1.25 - 8-April-2024
- Fix: Custom permission fix for search category API.
- Fix: Fixed an issue where the Personalisation of the library was failing.
v2.1.24 - 5-April-2024
- Fix: Improved parsing mechanism for social media icons to ensure error-free processing.
v2.1.23 - 5-April-2024
- Fix: Pre-selected images were not displaying.
v2.1.22 - 4-April-2024
- Improvement: Updated image replacement mechanisms to enhance compatibility with the ZipWP.
v2.1.21 - 3 April-2024
- New: Added business type selection option in onboarding.
- Improvement: Using a ZipWP constant instead of a URL to facilitate easy overriding from the WordPress configuration.
- Improvement: Automatically prefill business details for sites created through ZipWP.
- Improvement: Moved JSON folder from plugin directory to WP upload folder to address memory issues.
v2.1.20 - 1-April-2024
- Improvement: Added Compatibility for Rank Match SEO plugin.
v2.1.19 - 29-March-2024
- Improvement: Updated the way to call REST API.
v2.1.18 - 14-March-2024
- Improvement: Added a filter to bypass the auth for non authenticated users to be able to import Templates
v2.1.17 - 11-March-2024
- Fix: Fixed broken patterns and pages caused by missing Spectra Plugin.
v2.1.16 - 07-March-2024
- Fix: Resolved an issue where the AI description won't get generated on WordPress.com sites.
v2.1.15 - 01-March-2024
- Improvement: Rename Template kits to Design Library and updated UI.
v2.1.14 - 20-February-2024
- Fix: Changed the button position and fixed console errors.
v2.1.13 - 12-February-2024
- Fix: Resolved an issue where the Template Kit button was not visible due to console error.
v2.1.12 - 07-February-2024
- Fix: Resolved an issue where the Template Kit button was not visible.
v2.1.11 - 30-January-2024
- Improvement: Moved the Template Kits button to the left of the post header center element.
v2.1.10 - 29-January-2024
- Fix: Resolved premium pages import issue in the kits section.
v2.1.9 - 08-January-2024
- Fix: Reverted capabilities check from manage_options to edit_post.
v2.1.8 - 08-January-2024
- Improvement: Show three dots loading indicator when regenerating content for a specific category.
- Improvement: Prevent unnecessary re-render to improve performance and UX.
- Improvement: Improved access control by transitioning from 'edit_post' to 'manage_options' for enhanced user capabilities.
- Fix: Google map location/address not getting updated.
- Fix: Not showing loading skeleton while regenerating content.
- Fix: 503 Error by removing kits data from the localize variable.
v2.1.7 - 04-January-2024
- Fix: Extra check added for checking wpforms-lite plugin.
v2.1.6 - 03-January-2024
- Fix: Spelling "organization" changed to "organisation".
v2.1.5 - 03-January-2024
- Fix: Tightened the plugin security while importing.
v2.1.4 - 02-January-2024
- Fix: Suggested items were not showing on the empty search results screen.
v2.1.3 - 02-January-2024
- Fix: Showing invalid message on the toaster while generating content.
v2.1.2 - 02-January-2024
- Improvement: Enhanced user experience and streamlined workflow.
v2.1.1 - 30-December-2023
- Fix: Resolved conflict with Gravity Forms plugin by transitioning from localization to using API for patterns and pages data.
v2.1.0 - 27-December-2023
- New: Added site templates kits.
- Fix: Customizer color palette was getting applied in non-adaptive mode.
- Fix: Templates looks broken if Spectra activated while importing template.
v2.0.19 - 22-December-2023
- New: Added "Revoke Access" button for seamless ZipAI authentication revocation.
- Fix: Resolved issue of patterns/pages importing at last index instead of selected insertion point.
- Fix: Resolved the need for two refreshes to reflect changes in Manage AI feature options.
v2.0.18 - 20-December-2023
- Fix: ZipAI authentication screen is visible even ZipAI Copilot module is disabled.
v2.0.17 - 19-December-2023
- Improvement: Downloading the selected images in onboarding to media.
- Improvement: Added compatibility for the ZipAI Manage AI feature option.
- Improvement: User Interface Enhancements & tweaks.
- Improvement: Updating Disable AI option value based on Non-Adaptive mode option.
- Fix: Updating Non-Adaptive mode option was not getting enabled after reloading the page.
v2.0.16 - 15-December-2023
- Improvement: Added RTL compatibility to the new Template Kits library.
- Fix: Generate Content with AI button was not showing if already authorised.
v2.0.15 - 13-December-2023
- Improvement: Added conditional logo for onboarding screen.
v2.0.14 - 13-December-2023
- New: Introduced Non-Adaptive mode option.
- Improvement: Improved pattern and page preview UI.
v2.0.13 - 07-December-2023
- Improvement: Showing Server Traffic Surge toaster.
- Improvement: Updated the flat rates for Pages and Patterns library from 3000 to 5000.
v2.0.12 - 05-December-2023
- Improvement: Added no credit notice in AI onoarding.
- Improvement: Removed Generate Content button if showing welcome scrren.
- Fix: Removed unwanted parameters from URL while passing the success_url for checkout process fir credits purchase.
v2.0.11 - 04-December-2023
- New: Introduced 'ast_block_templates_authorization_url_param' filter for authorization url parameters.
v2.0.10 - 04-December-2023
- Fix: Removed URL parameter after redirection.
v2.0.9 - 04-December-2023
- Synchronised the pattern/page library.
v2.0.8 - 04-December-2023
Improvement: Compatibility with ZipAI authorization.
- Fix: Removed Header and Footer from the preview.
- Fix: Redirction URL not working after authorization.
v2.0.4 - 27-November-2023
- Fix: Success url parameter was missing for some credit purchase url.
v2.0.3 - 27-November-2023
- Fix: Fixed conditional logo for the library.
- Fix: Displaying the default content and toaster error after updating content.
v2.0.2 - 24-November-2023
- Fix: Fixed an issue where the library won't load when integrated with Premium Starter Templates.
v2.0.0 - 24-November-2023
- New: AI based templates
v1.3.3 - 07-Sept-2023
- Fix: Temporary remove Template Kit support to Full Site Editor.
v1.3.2 - 11-July-2023
- Improvement: Added Template Kit support to Full Site Editor.
v1.3.1 - 14-June-2023
- Fix: WP Forms won't get imported due to regression in v1.3.0
v1.3.0 - 13-June-2023
- Improvement: Now we refresh the page and save the content if the required plugins for the template kit are missing.
- Improvement: Tightened the security of the plugin.
v1.2.1 - 19-May-2023
- Fix: Discarded the incorrect null.js generated for the library, instead added main.js.
v1.2.0 - 18-May-2023
- Improvement: Added Premium Block Editor Templates.
v1.1.11 - 20-February-2023
- Improvement: Sync library.
v1.1.10 - 30-January-2023
- Improvement: Capability updated for active plugin.
v1.1.9 - 25-January-2023
- Improvement: Hardened the security.
v1.1.8 - 19-January-2023
- Improvement: Added extra checks while block templates import.
v1.1.7 - 01-September-2022
- Fix: Install and Activate Spectra for light category patterns only.
v1.1.6 - 22-Auguest-2022
- Improvement: Install Spectra while importing Block Patterns and Wireframe Pattern.
v1.1.3 - 19-May-2022
- Improvement: Renamed button text and logo to template kits and spectra logo.
v1.1.2 - 08-March-2022
- Improvement: CSS tweaks for spectra button.
v1.1.1 - 14-February-2022
- Fix: Undefined error for WP_CLI
v1.1.0 - 4-October-2021
- New: Wireframe blocks for Gutenberg - [Doc](https://wpastra.com/docs/starter-templates-wireframe-blocks/)
v1.0.11 - 17-September-2021
- Improvement: Added site URL while importing the demo for analytics.
v1.0.10 - 12-August-2021
- Improvement: Rectified the condition to load the scripts in other screens.
- Fix: Starter template button not visible when gutenberg plugin is activated.
v1.0.9 - 2-August-2021
- Improvement: Rectified the condition to load the scripts in customizer screen.
v1.0.8 - 22-June-2021
- Improvement: Avoided to load the scripts in customizer screen.
v1.0.7 - 13-June-2021
- Improvement: Compatibility to WordPress 5.8.
- Improvement: Added support for dark and light support for block patterns with improved sidebar UI.
- Improvement: Added a filter `ast_block_templates_disable_auto_sync` to disable auto sync feature.
- Fix: Handle the white label support.
v1.0.6 - 24-May-2021
- Improvement: Added auto sync feature.
- Fix: Starter Templates popup opens by default on every page load on Gutenberg pages.
v1.0.5 - 21-May-2021
- Improvement: Added the dark and light filter support for blocks.
v1.0.4 - 14-May-2021
- Fix: Added the dynamic category support for multisites.
v1.0.3 - 10-May-2021
- Improvement: Added the dynamic category support.
v1.0.2 - 09-March-2021
- Improvement: Added a helper function to set the default assets
v1.0.1 - 09-March-2021
- Improvement: Used `version.json` instead of `package.json` to manage the dependency.
- Improvement: Added the suggestion link.
- Improvement: Added filter to disable the Gutenberg Templates.
- Fix: Block pattern category filter keep showing all category.
- Fix: Avoided dynamic json file names for importing.
v1.0.0 - 17-February-2021
- Initial Commit

View File

@@ -0,0 +1,59 @@
<?php
/**
* Init
*
* @since 2.0.0
* @package Ast Block Templates
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'Ast_Block_Templates' ) ) :
/**
* Admin
*/
class Ast_Block_Templates {
/**
* Instance
*
* @since 2.0.0
* @var (Object) Ast_Block_Templates
*/
private static $instance = null;
/**
* Get Instance
*
* @since 2.0.0
*
* @return object Class object.
*/
public static function get_instance() {
if ( ! isset( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Constructor.
*
* @since 2.0.0
*/
private function __construct() {
require_once AST_BLOCK_TEMPLATES_DIR . 'ast-block-plugin-loader.php';
}
}
/**
* Kicking this off by calling 'get_instance()' method
*/
Ast_Block_Templates::get_instance();
endif;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,5 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<title>aspect_ratio</title>
<path d="M21 19.031v-14.063h-18v14.063h18zM21 3q0.797 0 1.406 0.609t0.609 1.406v13.969q0 0.797-0.609 1.406t-1.406 0.609h-18q-0.797 0-1.406-0.609t-0.609-1.406v-13.969q0-0.797 0.609-1.406t1.406-0.609h18zM6.984 9v3h-1.969v-5.016h4.969v2.016h-3zM18.984 12v5.016h-4.969v-2.016h3v-3h1.969z"></path>
</svg>

After

Width:  |  Height:  |  Size: 459 B

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<svg xmlns="http://www.w3.org/2000/svg">
<metadata>Generated by IcoMoon</metadata>
<defs>
<font id="ast-block-templates" horiz-adv-x="1024">
<font-face units-per-em="1024" ascent="960" descent="-64" />
<missing-glyph horiz-adv-x="1024" />
<glyph unicode="&#x20;" horiz-adv-x="512" d="" />
<glyph unicode="&#xe900;" glyph-name="maximize" d="M341.333 853.334h-128c-35.328 0-67.413-14.379-90.496-37.504s-37.504-55.168-37.504-90.496v-128c0-23.552 19.115-42.667 42.667-42.667s42.667 19.115 42.667 42.667v128c0 11.776 4.736 22.4 12.501 30.165s18.389 12.501 30.165 12.501h128c23.552 0 42.667 19.115 42.667 42.667s-19.115 42.667-42.667 42.667zM938.667 597.334v128c0 35.328-14.379 67.413-37.504 90.496s-55.168 37.504-90.496 37.504h-128c-23.552 0-42.667-19.115-42.667-42.667s19.115-42.667 42.667-42.667h128c11.776 0 22.4-4.736 30.165-12.501s12.501-18.389 12.501-30.165v-128c0-23.552 19.115-42.667 42.667-42.667s42.667 19.115 42.667 42.667zM682.667-0h128c35.328 0 67.413 14.379 90.496 37.504s37.504 55.168 37.504 90.496v128c0 23.552-19.115 42.667-42.667 42.667s-42.667-19.115-42.667-42.667v-128c0-11.776-4.736-22.4-12.501-30.165s-18.389-12.501-30.165-12.501h-128c-23.552 0-42.667-19.115-42.667-42.667s19.115-42.667 42.667-42.667zM85.333 256v-128c0-35.328 14.379-67.413 37.504-90.496s55.168-37.504 90.496-37.504h128c23.552 0 42.667 19.115 42.667 42.667s-19.115 42.667-42.667 42.667h-128c-11.776 0-22.4 4.736-30.165 12.501s-12.501 18.389-12.501 30.165v128c0 23.552-19.115 42.667-42.667 42.667s-42.667-19.115-42.667-42.667z" />
<glyph unicode="&#xe901;" glyph-name="rotate-cw" d="M834.005 312.875c-31.403-88.875-95.787-156.587-174.677-194.261s-171.989-45.269-260.864-13.867-156.587 95.787-194.261 174.677-45.269 171.989-13.867 260.864 95.787 156.587 174.677 194.261 171.989 45.269 260.864 13.867c50.688-17.92 94.251-46.421 127.445-80.299l120.491-113.451h-148.48c-23.552 0-42.667-19.115-42.667-42.667s19.115-42.667 42.667-42.667h255.872c0.171 0 0.384 0 0.555 0 5.845 0.043 11.392 1.28 16.469 3.499 5.077 2.176 9.771 5.376 13.824 9.6 0.512 0.512 0.981 1.067 1.451 1.621 3.243 3.712 5.717 7.851 7.467 12.245 1.749 4.352 2.773 9.088 2.944 13.995 0.085 0.555 0.085 1.109 0.085 1.707v256c0 23.552-19.115 42.667-42.667 42.667s-42.667-19.115-42.667-42.667v-157.227l-124.416 117.12c-42.368 43.179-97.024 78.763-159.915 100.949-111.104 39.296-227.669 29.781-326.144-17.28s-179.072-131.755-218.325-242.859-29.696-227.627 17.323-326.101 131.755-179.072 242.859-218.325 227.627-29.739 326.101 17.323 179.072 131.755 218.325 242.859c7.851 22.229-3.797 46.592-26.027 54.443s-46.592-3.797-54.443-26.027z" />
<glyph unicode="&#xe902;" glyph-name="file" d="M554.667 896h-298.667c-35.328 0-67.413-14.379-90.496-37.504s-37.504-55.168-37.504-90.496v-682.667c0-35.328 14.379-67.413 37.504-90.496s55.168-37.504 90.496-37.504h512c35.328 0 67.413 14.379 90.496 37.504s37.504 55.168 37.504 90.496v469.333c0 11.776-4.779 22.443-12.501 30.165l-298.667 298.667c-4.096 4.096-8.789 7.168-13.824 9.259-5.205 2.176-10.795 3.243-16.341 3.243zM750.336 597.334h-153.003v153.003zM512 810.667v-256c0-23.552 19.115-42.667 42.667-42.667h256v-426.667c0-11.776-4.736-22.4-12.501-30.165s-18.389-12.501-30.165-12.501h-512c-11.776 0-22.4 4.736-30.165 12.501s-12.501 18.389-12.501 30.165v682.667c0 11.776 4.736 22.4 12.501 30.165s18.389 12.501 30.165 12.501z" />
<glyph unicode="&#xe903;" glyph-name="layers" d="M512 805.632l331.264-165.632-331.264-165.632-331.264 165.632zM492.928 891.478l-426.667-213.333c-21.077-10.539-29.611-36.139-19.072-57.216 4.309-8.661 11.136-15.189 19.072-19.072l426.667-213.333c12.459-6.229 26.453-5.803 38.144 0l426.667 213.333c21.077 10.539 29.611 36.181 19.072 57.259-4.309 8.619-11.179 15.147-19.072 19.072l-426.667 213.333c-12.459 6.229-26.453 5.803-38.144 0zM66.261 175.19l426.667-213.333c12.459-6.229 26.453-5.803 38.144 0l426.667 213.333c21.077 10.539 29.611 36.181 19.072 57.259s-36.181 29.611-57.259 19.072l-407.552-203.819-407.595 203.776c-21.077 10.539-46.72 2.005-57.259-19.072s-2.005-46.72 19.072-57.259zM66.261 388.523l426.667-213.333c12.459-6.229 26.453-5.803 38.144 0l426.667 213.333c21.077 10.539 29.611 36.181 19.072 57.259s-36.181 29.611-57.259 19.072l-407.552-203.819-407.595 203.776c-21.077 10.539-46.72 2.005-57.259-19.072s-2.005-46.72 19.072-57.259z" />
<glyph unicode="&#xe904;" glyph-name="chevron-left" d="M670.165 200.832l-225.835 225.835 225.835 225.835c16.683 16.683 16.683 43.691 0 60.331s-43.691 16.683-60.331 0l-256-256c-16.683-16.683-16.683-43.691 0-60.331l256-256c16.683-16.683 43.691-16.683 60.331 0s16.683 43.691 0 60.331z" />
</font></defs></svg>

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.2.1, SVG Export Plug-In SVG - Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 100 100" style="enable-background:new 0 0 100 100;" xml:space="preserve">
<style type="text/css">
.st0{opacity:0.83;enable-background:new ;}
.st1{fill:#95F9EF;}
.st2{opacity:0.53;enable-background:new ;}
.st3{fill:url(#SVGID_1_);}
.st4{opacity:0.7;enable-background:new ;}
.st5{fill:url(#SVGID_2_);}
.st6{fill:#FFFFFF;}
</style>
<g>
<g class="st0">
<path class="st1" d="M26.8,88L9,33.5C8,30.7,9.6,27.8,12.2,27L66.8,9.2c2.7-0.9,5.7,0.6,6.4,3.2l17.9,54.6
c0.9,2.7-0.6,5.7-3.2,6.4l-54.6,18C30.5,92.2,27.6,90.8,26.8,88z"/>
</g>
<g class="st2">
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="4.238" y1="739.9995" x2="95.762" y2="739.9995" gradientTransform="matrix(1 0 0 1 0 -690)">
<stop offset="0" style="stop-color:#00E97B"/>
<stop offset="1" style="stop-color:#00F9D7"/>
</linearGradient>
<path class="st3" d="M44.7,94.3L5.6,52c-1.9-2.1-1.8-5.3,0.3-7.3L48.1,5.4c2.1-1.9,5.3-1.8,7.2,0.3L94.4,48
c1.9,2.1,1.8,5.3-0.3,7.3L51.9,94.6C50,96.6,46.6,96.4,44.7,94.3z"/>
</g>
<g class="st4">
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="296.5753" y1="-720.5554" x2="368.5928" y2="-720.5554" gradientTransform="matrix(0.9591 0.2829 0.2829 -0.9591 -65.1611 -734.9626)">
<stop offset="0" style="stop-color:#00DBDE"/>
<stop offset="1" style="stop-color:#FC00FF"/>
</linearGradient>
<path class="st5" d="M69.2,93.3L10.6,76.1c-2.9-0.8-4.5-3.9-3.7-6.8l17.2-58.6c0.8-2.9,3.9-4.5,6.8-3.7l58.6,17.2
c2.9,0.8,4.5,3.9,3.7,6.8L75.9,89.6C75.1,92.5,72,94.1,69.2,93.3z"/>
</g>
<g>
<path class="st6" d="M51.9,39.1L51.9,39.1h14.4V28.4H45.9c-1.9,0-3.7,0.3-5.3,1.1c-1.6,0.6-3.1,1.8-4.4,2.9
c-1.3,1.3-2.2,2.7-2.9,4.4c-0.4,0.7-0.6,1.6-0.8,2.4L51.9,39.1L51.9,39.1z"/>
<path class="st6" d="M66.9,53.3c-0.6-1.6-1.8-3.2-2.9-4.4c-1.3-1.3-2.7-2.2-4.4-2.9c-1.6-0.6-3.5-1.1-5.3-1.1h-2.4h-6H32.5
c0.2,0.9,0.5,1.7,0.8,2.6c0.6,1.6,1.8,3.2,2.9,4.4c1.3,1.3,2.7,2.2,4.4,2.9c1.6,0.8,3.5,1.1,5.3,1.1h8.4c0.5,0,0.8,0,1.1,0.2
c0.3,0.2,0.6,0.3,0.9,0.6c0.3,0.3,0.5,0.6,0.6,0.9c0.2,0.3,0.2,0.8,0.2,1.1c0,0.5,0,0.8-0.2,1.1c-0.2,0.3-0.3,0.6-0.6,0.9
c-0.3,0.3-0.6,0.5-0.9,0.6c-0.3,0.2-0.8,0.2-1.1,0.2h-20v10.8h19.8c1.9,0,3.7-0.3,5.5-1.1c1.6-0.6,3.2-1.8,4.4-2.9
c1.3-1.3,2.2-2.7,2.9-4.4c0.6-1.6,1.1-3.5,1.1-5.3C68,56.6,67.7,54.9,66.9,53.3z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,25 @@
/*!
* is-plain-object <https://github.com/jonschlinkert/is-plain-object>
*
* Copyright (c) 2014-2017, Jon Schlinkert.
* Released under the MIT License.
*/
/**
* @license
* Lodash <https://lodash.com/>
* Copyright OpenJS Foundation and other contributors <https://openjsf.org/>
* Released under MIT license <https://lodash.com/license>
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
* Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
*/
/**
* @license React
* react-jsx-runtime.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@@ -0,0 +1,9 @@
<svg width="60" height="60" viewBox="0 0 84 85" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M41.7849 0C33.5206 0 25.4419 2.49258 18.5705 7.16254C11.699 11.8325 6.34331 18.4701 3.18071 26.236C0.0181112 34.0018 -0.809377 42.5471 0.802901 50.7913C2.41518 59.0355 6.3948 66.6083 12.2385 72.552C18.0822 78.4958 25.5276 82.5435 33.633 84.1834C41.7385 85.8232 50.1401 84.9816 57.7753 81.7649C65.4105 78.5482 71.9363 73.1008 76.5277 66.1117C81.1191 59.1226 83.5697 50.9057 83.5697 42.5C83.565 31.2298 79.1612 20.4225 71.326 12.4533C63.4908 4.48402 52.8655 0.0048112 41.7849 0ZM57.5278 49.0175C57.5278 49.1264 57.5278 49.2354 57.5278 49.3443V49.6529V49.8526C57.3161 51.0856 56.8673 52.2639 56.207 53.3201L55.8143 53.8829L55.2431 54.5546C55.0482 54.8082 54.8268 55.0396 54.5827 55.2445V55.3353L54.4578 55.4261L54.2079 55.6258C54.1249 55.7007 54.0353 55.7675 53.9402 55.8255L53.6724 56.0071L34.3061 69.0602C34.1479 69.1683 33.9612 69.2253 33.7706 69.2236H33.5743C33.447 69.1967 33.3262 69.1443 33.2189 69.0695C33.1117 68.9947 33.0201 68.899 32.9495 68.7879C32.9495 68.7879 32.5033 67.9891 32.4676 67.9347V67.7531V67.6623V67.5534V67.4263V67.2811C31.7014 65.262 31.6378 63.0371 32.2872 60.9761C32.9366 58.9152 34.2601 57.1424 36.0375 55.9526L45.0691 49.8708C45.2101 49.7754 45.3201 49.6398 45.3853 49.4809C45.4505 49.322 45.4679 49.147 45.4355 48.9781C45.403 48.8091 45.3221 48.6537 45.2029 48.5315C45.0837 48.4093 44.9316 48.3257 44.7657 48.2913L34.1633 46.1128H33.8599H33.7706H33.485H33.1816H33.0567H32.896H32.8068L32.5212 46.0038H32.4319H32.2534L31.9679 45.8586L31.6823 45.7134L31.4145 45.55L31.1468 45.3866C30.3041 44.8521 29.5509 44.1841 28.9156 43.4077L28.6836 43.0809L28.4159 42.6634C27.73 41.6278 27.255 40.4629 27.0189 39.2375C26.7828 38.012 26.7905 36.751 27.0415 35.5286C27.228 34.6884 27.5221 33.8766 27.9161 33.1141C28.0232 32.9144 28.1124 32.7328 28.2195 32.5694L28.3802 32.3153C28.4948 32.1207 28.6199 31.9329 28.755 31.7525L28.9156 31.5528L29.112 31.3167L29.3083 31.0989L29.4333 30.9718L29.6475 30.754L29.8259 30.5906L30.0223 30.4272L30.2365 30.2456H30.3257L30.4685 30.1185H30.5578L30.7898 29.9551L50.049 16.9746C50.1725 16.8912 50.3113 16.8338 50.457 16.806C50.6027 16.7782 50.7524 16.7804 50.8973 16.8126C51.0421 16.8448 51.1791 16.9062 51.3002 16.9933C51.4212 17.0804 51.5238 17.1913 51.6019 17.3195L51.7626 17.5918L51.8875 17.846C51.8875 17.9368 51.9768 18.0094 52.0125 18.082C52.0125 18.082 52.0125 18.082 52.0125 18.191C52.0239 18.2325 52.0239 18.2765 52.0125 18.318L52.1195 18.5904C52.1292 18.6383 52.1292 18.6877 52.1195 18.7356C52.1195 18.7356 52.1195 18.7356 52.1195 18.8445C52.8288 20.8305 52.8625 23.0011 52.2153 25.0089C51.5681 27.0166 50.2774 28.7455 48.5497 29.9188L39.6251 35.9462C39.4842 36.0415 39.3742 36.1772 39.309 36.3361C39.2438 36.495 39.2263 36.6699 39.2588 36.8389C39.2912 37.0078 39.3722 37.1632 39.4914 37.2854C39.6106 37.4077 39.7627 37.4912 39.9286 37.5256L50.4417 39.686C52.5458 40.1281 54.4361 41.2935 55.7948 42.9862C57.1536 44.679 57.8979 46.796 57.9027 48.9812C57.5635 48.4003 57.5278 48.9812 57.5278 48.9812V49.0175Z" fill="url(#paint0_linear_619_170)"/>
<defs>
<linearGradient id="paint0_linear_619_170" x1="1.17098e-05" y1="1.49716e-06" x2="84.02" y2="71.3596" gradientUnits="userSpaceOnUse">
<stop stop-color="#4E01D1"/>
<stop offset="1" stop-color="#6104FF"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@@ -0,0 +1,3 @@
<svg width="71" height="71" viewBox="0 0 71 71" fill="#000000" xmlns="http://www.w3.org/2000/svg">
<path d="M35.292 0C28.3119 0 21.4885 2.08204 15.6848 5.98283C9.88107 9.88362 5.35762 15.428 2.68645 21.9147C0.0152817 28.4015 -0.683625 35.5394 0.678124 42.4257C2.03987 49.312 5.40111 55.6375 10.3368 60.6023C15.2725 65.5671 21.5609 68.9481 28.4068 70.3179C35.2528 71.6876 42.3489 70.9846 48.7976 68.2977C55.2464 65.6108 60.7583 61.0607 64.6362 55.2227C68.5141 49.3848 70.584 42.5212 70.584 35.5C70.58 26.0861 66.8604 17.0588 60.2428 10.4021C53.6251 3.74548 44.6508 0.00401876 35.292 0V0ZM48.5887 40.944C48.5887 41.035 48.5887 41.126 48.5887 41.217V41.4748V41.6416C48.4098 42.6715 48.0307 43.6558 47.4731 44.538L47.1414 45.0081L46.659 45.5692C46.4943 45.781 46.3073 45.9742 46.1012 46.1454V46.2213L45.9957 46.2971L45.7846 46.4639C45.7145 46.5265 45.6388 46.5823 45.5585 46.6307L45.3323 46.7824L28.9753 57.6856C28.8417 57.7759 28.684 57.8235 28.523 57.8221H28.3572C28.2497 57.7996 28.1477 57.7558 28.0571 57.6933C27.9665 57.6309 27.8892 57.5509 27.8296 57.4582C27.8296 57.4582 27.4527 56.7909 27.4225 56.7454V56.5938V56.5179V56.4269V56.3208V56.1995C26.7754 54.513 26.7216 52.6545 27.2701 50.933C27.8187 49.2115 28.9365 47.7307 30.4376 46.7369L38.0659 41.6568C38.1849 41.5771 38.2779 41.4638 38.3329 41.3311C38.388 41.1984 38.4027 41.0522 38.3753 40.9111C38.3479 40.77 38.2796 40.6402 38.1789 40.5381C38.0782 40.436 37.9497 40.3662 37.8096 40.3375L28.8547 38.5177H28.5984H28.523H28.2818H28.0255H27.92H27.7843H27.709L27.4678 38.4267H27.3924H27.2416L27.0004 38.3054L26.7592 38.1841L26.533 38.0476L26.3069 37.9111C25.5952 37.4647 24.959 36.9067 24.4225 36.2582L24.2265 35.9853L24.0004 35.6365C23.421 34.7714 23.0198 33.7984 22.8205 32.7748C22.6211 31.7512 22.6276 30.6979 22.8395 29.6769C22.9971 28.975 23.2455 28.2969 23.5782 27.66C23.6687 27.4932 23.7441 27.3415 23.8345 27.205L23.9702 26.9927C24.067 26.8303 24.1727 26.6733 24.2868 26.5226L24.4225 26.3558L24.5883 26.1587L24.7541 25.9767L24.8597 25.8706L25.0406 25.6886L25.1913 25.5521L25.3572 25.4156L25.5381 25.264H25.6134L25.734 25.1578H25.8094L26.0054 25.0214L42.272 14.1788C42.3763 14.1091 42.4935 14.0612 42.6166 14.038C42.7396 14.0147 42.8661 14.0166 42.9884 14.0435C43.1108 14.0704 43.2265 14.1217 43.3287 14.1944C43.431 14.2672 43.5176 14.3598 43.5836 14.4669L43.7192 14.6944L43.8248 14.9067C43.8248 14.9825 43.9002 15.0432 43.9303 15.1038C43.9303 15.1038 43.9303 15.1038 43.9303 15.1948C43.94 15.2295 43.94 15.2662 43.9303 15.3009V15.3009L44.0208 15.5284C44.0289 15.5684 44.0289 15.6097 44.0208 15.6497C44.0208 15.6497 44.0208 15.6497 44.0208 15.7407C44.6198 17.3996 44.6483 19.2127 44.1017 20.8897C43.555 22.5668 42.4648 24.011 41.0056 24.991L33.4678 30.0256C33.3488 30.1053 33.2559 30.2186 33.2008 30.3513C33.1457 30.484 33.131 30.6302 33.1584 30.7713C33.1858 30.9124 33.2542 31.0422 33.3549 31.1443C33.4555 31.2464 33.584 31.3162 33.7241 31.3449L42.6036 33.1495C44.3808 33.5188 45.9773 34.4922 47.1249 35.9061C48.2726 37.3201 48.9012 39.0884 48.9053 40.9137C48.6188 40.4285 48.5887 40.9137 48.5887 40.9137V40.944Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@@ -0,0 +1,4 @@
<svg width="90" height="90" viewBox="0 0 90 90" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M71.2429 7.34463H18.3616C12.2771 7.34463 7.34463 12.2771 7.34463 18.3616V71.2429C7.34463 77.3274 12.2771 82.2598 18.3616 82.2598H71.2429C77.3274 82.2598 82.2598 77.3274 82.2598 71.2429V18.3616C82.2598 12.2771 77.3274 7.34463 71.2429 7.34463ZM18.3616 0C8.22076 0 0 8.22075 0 18.3616V71.2429C0 81.3837 8.22075 89.6045 18.3616 89.6045H71.2429C81.3837 89.6045 89.6045 81.3837 89.6045 71.2429V18.3616C89.6045 8.22076 81.3837 0 71.2429 0H18.3616Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M54.1449 28.1896C53.9728 28.0356 53.7911 27.8882 53.5998 27.7474C51.9414 26.5264 49.6907 25.9159 46.8478 25.9159C44.916 25.9159 43.285 26.1892 41.9546 26.7359C40.6243 27.2644 39.6037 28.0025 38.893 28.9502C38.1294 29.995 36.829 30.8418 35.7046 30.2012C34.8223 29.6985 34.0076 29.0784 33.2839 28.3548C31.9339 27.0047 30.944 25.3377 30.405 23.5061C30.1674 22.6988 30.3776 21.8165 31.0133 21.265C32.434 20.0323 34.0947 18.9948 35.9954 18.1524C39.2028 16.7309 42.8476 16.0202 46.9298 16.0202C51.0849 16.0202 54.7115 16.7309 57.8095 18.1524C60.9259 19.5739 63.3496 21.5512 65.0809 24.0843C65.7142 25.011 66.2354 25.9913 66.6443 27.0252C67.8571 30.0913 65.0579 32.8866 61.7607 32.8866C59.1869 32.8866 57.1265 30.9615 55.18 29.1429L55.1799 29.1428C54.8321 28.8178 54.4878 28.4962 54.1449 28.1896ZM37.1987 34.2544C37.6871 34.0635 38.21 34.3524 38.4829 34.8001C38.9568 35.5473 39.6037 36.1942 40.4238 36.7409C41.2439 37.2694 42.1915 37.7342 43.2667 38.1351C44.342 38.5178 45.4901 38.8458 46.7111 39.1192L51.7409 40.322C54.183 40.8687 56.4245 41.5977 58.4656 42.5089C60.5067 43.4201 62.2744 44.5408 63.7688 45.8712C65.2632 47.2015 66.4204 48.7688 67.2405 50.573C68.0788 52.3772 68.5071 54.4456 68.5253 56.7783C68.5071 60.2044 67.6323 63.1749 65.901 65.6898C64.188 68.1865 61.7095 70.1274 58.4656 71.5124C55.2399 72.8792 51.3491 73.5626 46.7931 73.5626C42.2735 73.5626 38.3371 72.8701 34.9839 71.4851C31.6489 70.1001 29.0429 68.0499 27.1658 65.3345C26.2995 64.0605 25.6252 62.646 25.1428 61.091C24.1699 57.9547 26.943 55.1928 30.2268 55.1928H30.6526C33.4909 55.1928 35.5992 57.6279 37.3075 59.8946C38.2734 61.1338 39.5582 62.0724 41.1619 62.7102C42.7838 63.3298 44.6153 63.6396 46.6564 63.6396C48.6611 63.6396 50.4015 63.3481 51.8776 62.7649C53.372 62.1817 54.5292 61.3707 55.3493 60.332C56.1694 59.2932 56.5794 58.0995 56.5794 56.7509C56.5794 55.4935 56.2058 54.4365 55.4586 53.58C54.7297 52.7234 53.6545 51.9945 52.233 51.3931C50.8297 50.7917 49.1076 50.245 47.0665 49.7529L40.9705 48.2221C36.9718 47.2494 33.6859 45.8124 31.1129 43.9111C30.4174 43.3972 30.1608 42.4925 30.405 41.6629C30.9439 39.8315 31.9336 38.1645 33.2834 36.8145C34.4003 35.6975 35.7342 34.827 37.1987 34.2544ZM29.9545 26.532L29.4188 24.7118C29.3957 24.6328 29.3476 24.5633 29.2818 24.5139C29.2159 24.4645 29.1358 24.4378 29.0535 24.4378C28.9712 24.4378 28.8911 24.4645 28.8252 24.5139C28.7593 24.5633 28.7113 24.6328 28.6882 24.7118L28.1532 26.532C27.7938 27.7529 27.1338 28.8641 26.2338 29.764C25.3338 30.6639 24.2224 31.3236 23.0014 31.6829L21.1811 32.2186C20.8166 32.3267 20.8166 32.8426 21.1811 32.9491L23.0014 33.4849C24.2222 33.8442 25.3335 34.5041 26.2334 35.4039C27.1333 36.3038 27.7931 37.415 28.1525 38.6358L28.6882 40.4568C28.7955 40.8205 29.3115 40.8205 29.4188 40.4568L29.9545 38.6365C30.3138 37.4156 30.9736 36.3043 31.8735 35.4042C32.7734 34.5042 33.8847 33.8443 35.1056 33.4849L36.9266 32.9491C37.2904 32.8419 37.2904 32.3259 36.9266 32.2194L35.1064 31.6837C33.8853 31.3243 32.7738 30.6645 31.8738 29.7644C30.9738 28.8644 30.3138 27.753 29.9545 26.532ZM23.461 37.2817L23.6218 37.8277C23.7296 38.194 23.9275 38.5275 24.1975 38.7975C24.4676 39.0675 24.801 39.2654 25.1673 39.3732L25.7134 39.5339C25.8225 39.5659 25.8225 39.7207 25.7134 39.7529L25.1671 39.9136C24.8008 40.0214 24.4674 40.2194 24.1975 40.4894C23.9275 40.7594 23.7295 41.0928 23.6218 41.4591L23.461 42.0051C23.4288 42.1143 23.2741 42.1143 23.2419 42.0051L23.0812 41.4589C22.9733 41.0926 22.7754 40.7593 22.5054 40.4893C22.2354 40.2193 21.9021 40.0214 21.5358 39.9136L20.9897 39.7529C20.8804 39.7209 20.8804 39.5661 20.9897 39.5337L21.5358 39.373C21.9021 39.2652 22.2355 39.0673 22.5055 38.7973C22.7756 38.5274 22.9735 38.194 23.0814 37.8277L23.2419 37.2817C23.2488 37.2579 23.2632 37.2371 23.283 37.2223C23.3027 37.2075 23.3268 37.1995 23.3515 37.1995C23.3762 37.1995 23.4002 37.2075 23.4199 37.2223C23.4397 37.2371 23.4541 37.2579 23.461 37.2817ZM22.4142 22.428L22.1642 21.5786C22.1535 21.5417 22.131 21.5093 22.1003 21.4863C22.0696 21.4632 22.0322 21.4508 21.9938 21.4508C21.9554 21.4508 21.918 21.4632 21.8872 21.4863C21.8565 21.5093 21.8341 21.5417 21.8233 21.5786L21.5737 22.428C21.4059 22.9978 21.0979 23.5164 20.6779 23.9363C20.2579 24.3562 19.7392 24.6641 19.1695 24.8318L18.32 25.0818C18.1499 25.1322 18.1499 25.373 18.32 25.4227L19.1695 25.6727C19.7392 25.8404 20.2578 26.1483 20.6777 26.5683C21.0977 26.9882 21.4056 27.5068 21.5733 28.0765L21.8233 28.9263C21.8734 29.096 22.1142 29.096 22.1642 28.9263L22.4142 28.0768C22.5819 27.507 22.8898 26.9884 23.3098 26.5684C23.7297 26.1484 24.2483 25.8404 24.8181 25.6727L25.6679 25.4227C25.8377 25.3726 25.8377 25.1319 25.6679 25.0821L24.8184 24.8321C24.2486 24.6645 23.7299 24.3565 23.3099 23.9365C22.8899 23.5165 22.5819 22.9978 22.4142 22.428Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 100 100" style="enable-background:new 0 0 100 100;" xml:space="preserve">
<style type="text/css">
.st0{opacity:0.5;}
.st1{fill:#FFFFFF;}
.st2{opacity:0.8;}
</style>
<g>
<g class="st0">
<path class="st1" d="M68.02,6.1l-6.81,2.16l6.14,6.64l10.29,2.99l-2.82-8.47C73.99,6.76,71.01,5.1,68.02,6.1z"/>
<path class="st1" d="M5.94,32.16l2.32,6.81l6.64-6.14l2.99-10.46l-8.47,2.82C6.6,26.18,4.94,29.34,5.94,32.16z"/>
<path class="st1" d="M22.37,82.45l2.82,8.47c0.83,2.99,3.98,4.48,6.97,3.65l7.14-2.32l-5.98-6.47L22.37,82.45z"/>
<path class="st1" d="M94.08,68.18l-2.32-7.14l-6.31,5.98l-3.32,10.95l8.47-2.82C93.41,74.32,95.24,71.16,94.08,68.18z"/>
</g>
<g class="st2">
<path class="st1" d="M55.73,2.45c-2.16-2.32-5.48-2.49-7.8-0.33l-5.98,5.48l11.29,3.32l13.94,4.15l-6.14-6.64L55.73,2.45z"/>
<path class="st1" d="M2.62,44.27c-2.32,2.16-2.49,5.48-0.33,7.8l5.15,5.64l3.15-10.95l4.15-13.94L8.1,38.96L2.62,44.27z"/>
<path class="st1" d="M97.73,47.93l-5.15-5.48l-3.32,11.12l-3.98,13.28l6.31-5.98l5.64-5.31C99.72,53.73,99.89,50.25,97.73,47.93z"
/>
<path class="st1" d="M33.16,85.6l5.98,6.47l5.15,5.48c2.16,2.32,5.64,2.49,7.8,0.33l5.64-5.15l-10.79-3.15L33.16,85.6z"/>
</g>
<path class="st1" d="M92.42,22.36l-14.77-4.32l-10.29-2.99l-13.94-4.15L42.12,7.59L29.51,3.94c-3.15-0.83-6.47,0.83-7.3,3.98
L17.89,22.7L14.9,33.15L10.75,47.1L7.6,58.05L3.78,71.16c-0.83,3.15,0.83,6.47,3.98,7.3l14.77,4.32l10.79,3.15l13.61,3.98
l10.79,3.15l12.95,3.82c3.15,0.83,6.47-0.83,7.3-3.98l4.32-14.61l3.32-10.95l3.98-13.28l3.32-11.12l3.82-12.78
C97.23,26.51,95.57,23.19,92.42,22.36z M67.69,26.68V38.3H52.25l0,0H31.5c0.17-0.83,0.5-1.83,0.83-2.66
c0.66-1.66,1.66-3.32,3.15-4.65c1.33-1.16,2.99-2.49,4.65-3.15c1.66-0.83,3.65-1.16,5.64-1.16H67.69z M33.33,74.15V62.53h21.41
c0.33,0,0.83,0,1.16-0.17c0.33-0.17,0.66-0.33,1-0.66c0.33-0.33,0.5-0.66,0.66-1c0.17-0.33,0.17-0.66,0.17-1.16
c0-0.33,0-0.83-0.17-1.16c-0.17-0.33-0.33-0.66-0.66-1c-0.33-0.33-0.66-0.5-1-0.66c-0.33-0.17-0.66-0.17-1.16-0.17h-8.96
c-1.83,0-3.98-0.33-5.64-1.16c-1.66-0.66-3.32-1.66-4.65-3.15c-1.16-1.16-2.49-2.99-3.15-4.65c-0.5-1-0.66-1.83-0.83-2.82h14.44
h6.47h2.49c1.83,0,3.98,0.5,5.64,1.16c1.66,0.66,3.32,1.66,4.65,3.15c1.16,1.16,2.49,2.99,3.15,4.65c0.83,1.66,1.16,3.65,1.16,5.81
c0,1.83-0.5,3.98-1.16,5.64c-0.66,1.66-1.66,3.32-3.15,4.65c-1.16,1.16-2.99,2.49-4.65,3.15c-1.83,0.83-3.82,1.16-5.81,1.16
L33.33,74.15L33.33,74.15z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@@ -0,0 +1,49 @@
@font-face {
font-family: ast-block-templates;
src: url( "fonts/ast-block-templates.eot?p3u0q1" );
src:
url( "fonts/ast-block-templates.eot?p3u0q1#iefix" ) format( "embedded-opentype" ),
url( "fonts/ast-block-templates.ttf?p3u0q1" ) format( "truetype" ),
url( "fonts/ast-block-templates.woff?p3u0q1" ) format( "woff" ),
url( "fonts/ast-block-templates.svg?p3u0q1#ast-block-templates" ) format( "svg" );
font-weight: 400;
font-style: normal;
font-display: block;
}
[class^="ast-block-templates-icon-"],
[class*=" ast-block-templates-icon-"] {
/* use !important to prevent issues with browser extensions that change fonts */
font-family: ast-block-templates, sans-serif !important;
speak: never;
font-style: normal;
font-weight: 400;
font-variant: normal;
text-transform: none;
line-height: 1;
/* Better Font Rendering =========== */
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.ast-block-templates-icon-chevron-left::before {
content: "\e904";
}
.ast-block-templates-icon-pages::before {
content: "\e902";
}
.ast-block-templates-icon-patterns::before {
content: "\e903";
}
.ast-block-templates-icon-wireframe::before {
content: "\e900";
}
.ast-block-templates-icon-refresh::before {
content: "\e901";
}

View File

@@ -0,0 +1,43 @@
<?php
/**
* API base.
*
* @package {{package}}
* @since 0.0.1
*/
namespace Gutenberg_Templates\Inc\Api;
/**
* Api_Base
*
* @since 0.0.1
*/
abstract class Api_Base extends \WP_REST_Controller {
/**
* Endpoint namespace.
*
* @var string
*/
protected $namespace = 'gutenberg-templates/v1';
/**
* Constructor
*
* @since 0.0.1
*/
public function __construct() {
}
/**
* Get API namespace.
*
* @since 0.0.1
* @return string
*/
public function get_api_namespace() {
return $this->namespace;
}
}

View File

@@ -0,0 +1,71 @@
<?php
/**
* INitialize API.
*
* @package {{package}}
* @since 0.0.1
*/
namespace Gutenberg_Templates\Inc\Api;
use Gutenberg_Templates\Inc\Traits\Instance;
/**
* Api_Base
*
* @since 0.0.1
*/
class Api_Init {
use Instance;
/**
* Controller object.
*
* @var object class.
*/
public $controller = null;
/**
* Constructor
*
* @since 0.0.1
*/
public function __construct() {
// REST API extensions init.
add_action( 'rest_api_init', array( $this, 'register_routes' ) );
}
/**
* Register API routes.
*
* @since 0.0.1
* @return void
*/
public function register_routes() {
$controllers = array(
'\Gutenberg_Templates\Inc\Api\Category',
'\Gutenberg_Templates\Inc\Api\Description',
'\Gutenberg_Templates\Inc\Api\PageDescription',
'\Gutenberg_Templates\Inc\Api\Keywords',
'\Gutenberg_Templates\Inc\Api\Images',
'\Gutenberg_Templates\Inc\Api\Settings',
'\Gutenberg_Templates\Inc\Api\Favorite',
'Gutenberg_Templates\Inc\Api\Do_It_Later',
'\Gutenberg_Templates\Inc\Api\Pages',
'\Gutenberg_Templates\Inc\Api\RevokeAccess',
'\Gutenberg_Templates\Inc\Api\Blocks',
'\Gutenberg_Templates\Inc\Api\Initialize_Setup',
'\Gutenberg_Templates\Inc\Api\Sites',
);
foreach ( $controllers as $controller ) {
$this->controller = $controller::instance();
$this->controller->register_routes();
}
}
}

View File

@@ -0,0 +1,115 @@
<?php
/**
* Progress API.
*
* @package {{package}}
* @since 0.0.1
*/
namespace Gutenberg_Templates\Inc\Api;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
use Gutenberg_Templates\Inc\Traits\Instance;
use Gutenberg_Templates\Inc\Api\Api_Base;
use Gutenberg_Templates\Inc\Importer\Plugin;
/**
* Progress
*
* @since 0.0.1
*/
class Blocks extends Api_Base {
use Instance;
/**
* Route base.
*
* @var string
*/
protected $rest_base = '/blocks/';
/**
* Init Hooks.
*
* @since 0.0.1
* @return void
*/
public function register_routes() {
$namespace = $this->get_api_namespace();
register_rest_route(
$namespace,
$this->rest_base,
array(
array(
'methods' => \WP_REST_Server::READABLE,
'callback' => array( $this, 'get_blocks' ),
'permission_callback' => array( $this, 'get_item_permissions_check' ),
),
)
);
}
/**
* Check whether a given request has permission to read notes.
*
* @param object $request WP_REST_Request Full details about the request.
* @return object|boolean
*/
public function get_item_permissions_check( $request ) {
// To do: Check api token or JWT token for permission.
if ( ! current_user_can( 'manage_ast_block_templates' ) ) {
return new \WP_Error(
'gt_rest_cannot_access',
__( 'Sorry, you are not allowed to do that.', 'ultimate-addons-for-gutenberg' ),
array( 'status' => rest_authorization_required_code() )
);
}
return true;
}
/**
* Save Prompts.
*
* @param \WP_REST_Request $request Full details about the request.
* @return \WP_REST_Response
*/
public function get_blocks( $request ) {
$nonce = (string) $request->get_header( 'X-WP-Nonce' );
// Verify the nonce.
if ( ! wp_verify_nonce( sanitize_text_field( $nonce ), 'wp_rest' ) ) {
return new \WP_REST_Response(
array(
'success' => false,
'data' => __( 'Nonce verification failed.', 'ultimate-addons-for-gutenberg' ),
),
403
);
}
$start = isset( $request['start'] ) ? intval( $request['start'] ) : 1;
$end = isset( $request['end'] ) ? intval( $request['end'] ) : 1;
$blocks = Plugin::instance()->get_all_blocks( $start, $end );
$response = new \WP_REST_Response(
array(
'success' => true,
'allBlocks' => $blocks['blocks'],
'allBlocksPages' => $blocks['blocks_pages'],
)
);
$response->set_status( 200 );
return $response;
}
}

View File

@@ -0,0 +1,112 @@
<?php
/**
* Progress API.
*
* @package {{package}}
* @since 0.0.1
*/
namespace Gutenberg_Templates\Inc\Api;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
use Gutenberg_Templates\Inc\Traits\Instance;
use Gutenberg_Templates\Inc\Traits\Helper;
use Gutenberg_Templates\Inc\Api\Api_Base;
/**
* Progress
*
* @since 0.0.1
*/
class Category extends Api_Base {
use Instance;
/**
* Route base.
*
* @var string
*/
protected $rest_base = '/categories/';
/**
* Init Hooks.
*
* @since 0.0.1
* @return void
*/
public function register_routes() {
$namespace = $this->get_api_namespace();
register_rest_route(
$namespace,
$this->rest_base,
array(
array(
'methods' => \WP_REST_Server::READABLE,
'callback' => array( $this, 'get' ),
'permission_callback' => array( $this, 'get_item_permissions_check' ),
),
)
);
}
/**
* Check whether a given request has permission to read notes.
*
* @param object $request WP_REST_Request Full details about the request.
* @return object|boolean
*/
public function get_item_permissions_check( $request ) {
if ( ! current_user_can( 'manage_ast_block_templates' ) ) {
return new \WP_Error(
'gt_rest_cannot_access',
__( 'Sorry, you are not allowed to do that.', 'ultimate-addons-for-gutenberg' ),
array( 'status' => rest_authorization_required_code() )
);
}
return true;
}
/**
* Save Prompts.
*
* @param \WP_REST_Request $request Full details about the request.
* @return \WP_REST_Response
*/
public function get( $request ) {
$nonce = (string) $request->get_header( 'X-WP-Nonce' );
// Verify the nonce.
if ( ! wp_verify_nonce( sanitize_text_field( $nonce ), 'wp_rest' ) ) {
return new \WP_REST_Response(
array(
'success' => false,
'data' => __( 'Nonce verification failed.', 'ultimate-addons-for-gutenberg' ),
),
403
);
}
$categories = Helper::instance()->get_block_template_category();
$total_requests = (int) Helper::instance()->get_block_templates_requests();
$response = new \WP_REST_Response(
array(
'success' => true,
'categories' => $categories,
'total_requests' => $total_requests,
)
);
$response->set_status( 200 );
return $response;
}
}

View File

@@ -0,0 +1,191 @@
<?php
/**
* Description API.
*
* @package {{package}}
* @since 2.0.0
*/
namespace Gutenberg_Templates\Inc\Api;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
use Gutenberg_Templates\Inc\Traits\Instance;
use Gutenberg_Templates\Inc\Api\Api_Base;
use Gutenberg_Templates\Inc\Importer\Importer_Helper;
/**
* Progress
*
* @since 2.0.0
*/
class Description extends Api_Base {
use Instance;
/**
* Route base.
*
* @var string
*/
protected $rest_base = '/description/';
/**
* Init Hooks.
*
* @since 2.0.0
* @return void
*/
public function register_routes() {
$namespace = $this->get_api_namespace();
register_rest_route(
$namespace,
$this->rest_base,
array(
array(
'methods' => \WP_REST_Server::CREATABLE,
'callback' => array( $this, 'get' ),
'permission_callback' => array( $this, 'get_item_permissions_check' ),
'args' => array(
'business_name' => array(
'type' => 'string',
'required' => true,
'sanitize_callback' => 'sanitize_text_field',
),
'business_description' => array(
'type' => 'string',
'required' => false,
'sanitize_callback' => 'sanitize_text_field',
),
'category' => array(
'type' => 'string',
'required' => false,
'sanitize_callback' => 'sanitize_text_field',
),
'language_name' => array(
'type' => 'string',
'required' => false,
'sanitize_callback' => 'sanitize_text_field',
),
),
),
)
);
}
/**
* Check whether a given request has permission to read notes.
*
* @param object $request WP_REST_Request Full details about the request.
* @return object|boolean
*/
public function get_item_permissions_check( $request ) {
if ( ! current_user_can( 'manage_ast_block_templates' ) ) {
return new \WP_Error(
'gt_rest_cannot_access',
__( 'Sorry, you are not allowed to do that.', 'ultimate-addons-for-gutenberg' ),
array( 'status' => rest_authorization_required_code() )
);
}
return true;
}
/**
* Save Prompts.
*
* @param \WP_REST_Request $request Full details about the request.
* @return mixed
*/
public function get( $request ) {
$nonce = (string) $request->get_header( 'X-WP-Nonce' );
// Verify the nonce.
if ( ! wp_verify_nonce( sanitize_text_field( $nonce ), 'wp_rest' ) ) {
wp_send_json_error(
array(
'data' => __( 'Nonce verification failed.', 'ultimate-addons-for-gutenberg' ),
'status' => false,
)
);
}
$api_endpoint = AST_BLOCK_TEMPLATES_LIBRARY_URL . 'wp-json/ai/v1/description';
$token = Importer_Helper::get_business_details( 'token' );
$post_data = array(
'business_name' =>
isset( $request['business_name'] ) ?
sanitize_text_field( $request['business_name'] ) :
'',
'business_description' =>
isset( $request['business_description'] ) ? sanitize_text_field( $request['business_description'] ) : '',
'category' =>
isset( $request['category'] ) ? sanitize_text_field( $request['category'] ) : '',
'language_name' =>
isset( $request['language_name'] ) ? sanitize_text_field( $request['language_name'] ) : '',
'token' =>
$token,
);
$body = wp_json_encode( $post_data );
$request_args = array(
'body' => is_string( $body ) ? $body : '',
'headers' => array(
'Content-Type' => 'application/json',
),
'timeout' => 100,
);
$response = wp_safe_remote_post( $api_endpoint, $request_args );
if ( is_wp_error( $response ) ) {
// There was an error in the request.
wp_send_json_error(
array(
'data' => 'Failed ' . $response->get_error_message(),
'status' => false,
)
);
} else {
$response_code = wp_remote_retrieve_response_code( $response );
$response_body = wp_remote_retrieve_body( $response );
if ( 200 === $response_code ) {
$response_data = json_decode( $response_body, true );
if ( $response_data['status'] ) {
wp_send_json_success(
array(
'data' => $response_data['data'],
'status' => true,
)
);
} else {
wp_send_json_error(
array(
'data' => 'Failed ' . $response_data['data'],
'status' => false,
)
);
}
} else {
wp_send_json_error(
array(
'data' => 'Failed',
'status' => false,
)
);
}
}
}
}

View File

@@ -0,0 +1,91 @@
<?php
/**
* Do It Later API.
*
* @package {{package}}
* @since 2.0.0
*/
namespace Gutenberg_Templates\Inc\Api;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
use Gutenberg_Templates\Inc\Traits\Instance;
use Gutenberg_Templates\Inc\Api\Api_Base;
/**
* Do It Later
*
* @since 2.0.0
*/
class Do_It_Later extends Api_Base {
use Instance;
/**
* Route base.
*
* @var string
*/
protected $rest_base = '/do-it-later/';
/**
* Init Hooks.
*
* @since 2.0.0
* @return void
*/
public function register_routes() {
$namespace = $this->get_api_namespace();
register_rest_route(
$namespace,
$this->rest_base,
array(
array(
'methods' => \WP_REST_Server::READABLE,
'callback' => array( $this, 'get' ),
'permission_callback' => array( $this, 'get_item_permissions_check' ),
),
)
);
}
/**
* Check whether a given request has permission to read notes.
*
* @param object $request WP_REST_Request Full details about the request.
* @return object|boolean
*/
public function get_item_permissions_check( $request ) {
if ( ! current_user_can( 'manage_ast_block_templates' ) ) {
return new \WP_Error(
'gt_rest_cannot_access',
__( 'Sorry, you are not allowed to do that.', 'ultimate-addons-for-gutenberg' ),
array( 'status' => rest_authorization_required_code() )
);
}
return true;
}
/**
* Save Prompts.
*
* @return \WP_REST_Response
*/
public function get() {
update_option( 'ast-block-templates-show-onboarding', 'no' );
$response = new \WP_REST_Response(
array(
'success' => true,
)
);
$response->set_status( 200 );
return $response;
}
}

View File

@@ -0,0 +1,187 @@
<?php
/**
* Favorite API.
*
* @package {{package}}
* @since 2.0.0
*/
namespace Gutenberg_Templates\Inc\Api;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
use Gutenberg_Templates\Inc\Traits\Instance;
use Gutenberg_Templates\Inc\Api\Api_Base;
/**
* Favorite
*
* @since 2.0.0
*/
class Favorite extends Api_Base {
use Instance;
/**
* Route base.
*
* @var string
*/
protected $rest_base = '/favorite/';
/**
* Init Hooks.
*
* @since 2.0.0
* @return void
*/
public function register_routes() {
$namespace = $this->get_api_namespace();
register_rest_route(
$namespace,
$this->rest_base,
array(
array(
'methods' => \WP_REST_Server::READABLE,
'callback' => array( $this, 'get' ),
'permission_callback' => array( $this, 'get_item_permissions_check' ),
),
)
);
register_rest_route(
$namespace,
$this->rest_base,
array(
array(
'methods' => \WP_REST_Server::EDITABLE,
'callback' => array( $this, 'save' ),
'permission_callback' => array( $this, 'get_item_permissions_check' ),
'args' => array(
'type' => array(
'type' => 'string',
'required' => true,
'sanitize_callback' => 'sanitize_text_field',
),
'block_id' => array(
'type' => 'integer',
'required' => true,
),
'status' => array(
'type' => 'boolean',
'required' => true,
),
),
),
)
);
}
/**
* Check whether a given request has permission to read notes.
*
* @param object $request WP_REST_Request Full details about the request.
* @return object|boolean
*/
public function get_item_permissions_check( $request ) {
if ( ! current_user_can( 'manage_ast_block_templates' ) ) {
return new \WP_Error(
'gt_rest_cannot_access',
__( 'Sorry, you are not allowed to do that.', 'ultimate-addons-for-gutenberg' ),
array( 'status' => rest_authorization_required_code() )
);
}
return true;
}
/**
* Get Favorite.
*
* @param \WP_REST_Request $request Full details about the request.
* @return mixed
*/
public function get( $request ) {
$favorites = get_option( 'ast_block_templates_favorites', array() );
$response = new \WP_REST_Response(
array(
'success' => true,
'data' => $favorites,
)
);
$response->set_status( 200 );
return $response;
}
/**
* Save Favorite.
*
* @param \WP_REST_Request $request Full details about the request.
* @return mixed
*/
public function save( $request ) {
$nonce = (string) $request->get_header( 'X-WP-Nonce' );
// Verify the nonce.
if ( ! wp_verify_nonce( sanitize_text_field( $nonce ), 'wp_rest' ) ) {
wp_send_json_error(
array(
'data' => __( 'Nonce verification failed.', 'ultimate-addons-for-gutenberg' ),
'status' => false,
)
);
}
$favorites = get_option( 'ast_block_templates_favorites', array() );
$block_type = $request->get_param( 'type' );
$id = $request->get_param( 'block_id' );
$status = $request->get_param( 'status' );
// Empty favorite then add favorite in respective array tye and early return.
if ( ! isset( $favorites[ $block_type ] ) || ! is_array( $favorites[ $block_type ] ) ) {
$favorites[ $block_type ] = array();
}
if ( empty( $favorites ) && $status ) {
$favorites[ $block_type ][] = $id;
}
// Empty patterns OR blocks array then add favorite and return early.
if ( empty( $favorites[ $block_type ] ) && $status ) {
$favorites[ $block_type ][] = $id;
}
if ( $status ) {
// Insert the block-id/page-id if it doesn't already exist.
if ( ! in_array( $id, $favorites[ $block_type ] ) ) {
$favorites[ $block_type ][] = $id;
}
} else {
// Remove the block-id/page-id if it exists.
if ( isset( $favorites[ $block_type ] ) && is_array( $favorites[ $block_type ] ) ) {
$key = array_search( $id, $favorites[ $block_type ] );
if ( false !== $key ) {
unset( $favorites[ $block_type ][ $key ] );
$favorites[ $block_type ] = array_values( $favorites[ $block_type ] );
}
}
}
$update_status = update_option( 'ast_block_templates_favorites', $favorites );
$data = array(
'success' => $update_status,
'message' => $update_status ? __( 'Action Completed', 'ultimate-addons-for-gutenberg' ) : __( 'Action failed', 'ultimate-addons-for-gutenberg' ),
'data' => $favorites,
);
return rest_ensure_response( $data );
}
}

View File

@@ -0,0 +1,174 @@
<?php
/**
* Images API.
*
* @package {{package}}
* @since 2.0.0
*/
namespace Gutenberg_Templates\Inc\Api;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
use Gutenberg_Templates\Inc\Traits\Instance;
use Gutenberg_Templates\Inc\Api\Api_Base;
/**
* Progress
*
* @since 2.0.0
*/
class Images extends Api_Base {
use Instance;
/**
* Route base.
*
* @var string
*/
protected $rest_base = '/images/';
/**
* Init Hooks.
*
* @since 2.0.0
* @return void
*/
public function register_routes() {
$namespace = $this->get_api_namespace();
register_rest_route(
$namespace,
$this->rest_base,
array(
array(
'methods' => \WP_REST_Server::CREATABLE,
'callback' => array( $this, 'get' ),
'permission_callback' => array( $this, 'get_item_permissions_check' ),
'args' => array(
'keywords' => array(
'type' => 'string',
'required' => true,
),
'per_page' => array(
'type' => 'integer',
'required' => false,
),
'page' => array(
'type' => 'integer',
'required' => false,
),
'orientation' => array(
'type' => 'string',
'sanitize_callback' => 'sanitize_text_field',
'required' => false,
),
'engine' => array(
'type' => 'string',
'required' => false,
'sanitize_callback' => 'sanitize_text_field',
),
),
),
)
);
}
/**
* Check whether a given request has permission to read notes.
*
* @param object $request WP_REST_Request Full details about the request.
* @return object|boolean
*/
public function get_item_permissions_check( $request ) {
if ( ! current_user_can( 'manage_ast_block_templates' ) ) {
return new \WP_Error(
'gt_rest_cannot_access',
__( 'Sorry, you are not allowed to do that.', 'ultimate-addons-for-gutenberg' ),
array( 'status' => rest_authorization_required_code() )
);
}
return true;
}
/**
* Save Prompts.
*
* @param \WP_REST_Request $request Full details about the request.
* @return mixed
*/
public function get( $request ) {
$nonce = (string) $request->get_header( 'X-WP-Nonce' );
// Verify the nonce.
if ( ! wp_verify_nonce( sanitize_text_field( $nonce ), 'wp_rest' ) ) {
wp_send_json_error(
array(
'data' => __( 'Nonce verification failed.', 'ultimate-addons-for-gutenberg' ),
'status' => false,
)
);
}
$api_endpoint = AST_BLOCK_TEMPLATES_LIBRARY_URL . 'wp-json/image/v1/images';
$post_data = array(
'keywords' => isset( $request['keywords'] ) ? $request['keywords'] : '',
'per_page' => isset( $request['per_page'] ) ? $request['per_page'] : 20,
'page' => isset( $request['page'] ) ? $request['page'] : 1,
'orientation' => isset( $request['orientation'] ) ? sanitize_text_field( $request['orientation'] ) : '',
'engine' => isset( $request['engine'] ) ? sanitize_text_field( $request['engine'] ) : '',
);
$body = wp_json_encode( $post_data );
$request_args = array(
'body' => is_string( $body ) ? $body : '',
'headers' => array(
'Content-Type' => 'application/json',
),
'timeout' => 100,
);
$response = wp_safe_remote_post( $api_endpoint, $request_args );
if ( is_wp_error( $response ) ) {
// There was an error in the request.
wp_send_json_error(
array(
'data' => 'Failed ' . $response->get_error_message(),
'status' => false,
)
);
} else {
$response_code = wp_remote_retrieve_response_code( $response );
$response_body = wp_remote_retrieve_body( $response );
if ( 200 === $response_code ) {
$response_data = json_decode( $response_body, true );
wp_send_json_success(
array(
'data' => $response_data,
'status' => true,
)
);
} else {
wp_send_json_error(
array(
'data' => 'Failed',
'status' => false,
)
);
}
}
}
}

View File

@@ -0,0 +1,104 @@
<?php
/**
* Initialize Setup.
*
* @package {{package}}
* @since 0.0.1
*/
namespace Gutenberg_Templates\Inc\Api;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
use Gutenberg_Templates\Inc\Traits\Instance;
use Gutenberg_Templates\Inc\Api\Api_Base;
use Gutenberg_Templates\Inc\Importer\Plugin;
use Gutenberg_Templates\Inc\Importer\Sync_Library;
/**
* Progress
*
* @since 0.0.1
*/
class Initialize_Setup extends Api_Base {
use Instance;
/**
* Route base.
*
* @var string
*/
protected $rest_base = '/setup/';
/**
* Init Hooks.
*
* @since 0.0.1
* @return void
*/
public function register_routes() {
$namespace = $this->get_api_namespace();
register_rest_route(
$namespace,
$this->rest_base,
array(
array(
'methods' => \WP_REST_Server::READABLE,
'callback' => array( $this, 'setup_templates' ),
'permission_callback' => array( $this, 'get_item_permissions_check' ),
),
)
);
}
/**
* Check whether a given request has permission to read notes.
*
* @param object $request WP_REST_Request Full details about the request.
* @return object|boolean
*/
public function get_item_permissions_check( $request ) {
if ( ! current_user_can( 'manage_ast_block_templates' ) ) {
return new \WP_Error(
'gt_rest_cannot_access',
__( 'Sorry, you are not allowed to do that.', 'ultimate-addons-for-gutenberg' ),
array( 'status' => rest_authorization_required_code() )
);
}
return true;
}
/**
* Save Prompts.
*
* @param \WP_REST_Request $request Full details about the request.
* @return \WP_REST_Response
*/
public function setup_templates( $request ) {
$is_fresh_site = get_option( 'ast_block_templates_fresh_site', 'yes' );
if ( 'yes' === $is_fresh_site ) {
Sync_Library::instance()->set_default_assets();
update_option( 'ast_block_templates_fresh_site', 'no' );
}
Sync_Library::instance()->process_sync();
$response = new \WP_REST_Response(
array(
'success' => true,
'syncing' => $is_fresh_site,
)
);
$response->set_status( 200 );
return $response;
}
}

View File

@@ -0,0 +1,176 @@
<?php
/**
* Keywords API.
*
* @package {{package}}
* @since 2.0.0
*/
namespace Gutenberg_Templates\Inc\Api;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
use Gutenberg_Templates\Inc\Traits\Instance;
use Gutenberg_Templates\Inc\Api\Api_Base;
use Gutenberg_Templates\Inc\Importer\Importer_Helper;
/**
* Progress
*
* @since 2.0.0
*/
class Keywords extends Api_Base {
use Instance;
/**
* Route base.
*
* @var string
*/
protected $rest_base = '/keywords/';
/**
* Init Hooks.
*
* @since 2.0.0
* @return void
*/
public function register_routes() {
$namespace = $this->get_api_namespace();
register_rest_route(
$namespace,
$this->rest_base,
array(
array(
'methods' => \WP_REST_Server::CREATABLE,
'callback' => array( $this, 'get' ),
'permission_callback' => array( $this, 'get_item_permissions_check' ),
'args' => array(
'business_name' => array(
'type' => 'string',
'required' => true,
'sanitize_callback' => 'sanitize_text_field',
),
'business_description' => array(
'type' => 'string',
'required' => false,
'sanitize_callback' => 'sanitize_text_field',
),
'category' => array(
'type' => 'string',
'sanitize_callback' => 'sanitize_text_field',
'required' => false,
),
),
),
)
);
}
/**
* Check whether a given request has permission to read notes.
*
* @param object $request WP_REST_Request Full details about the request.
* @return object|boolean
*/
public function get_item_permissions_check( $request ) {
if ( ! current_user_can( 'manage_ast_block_templates' ) ) {
return new \WP_Error(
'gt_rest_cannot_access',
__( 'Sorry, you are not allowed to do that.', 'ultimate-addons-for-gutenberg' ),
array( 'status' => rest_authorization_required_code() )
);
}
return true;
}
/**
* Save Prompts.
*
* @param \WP_REST_Request $request Full details about the request.
* @return mixed
*/
public function get( $request ) {
$nonce = (string) $request->get_header( 'X-WP-Nonce' );
// Verify the nonce.
if ( ! wp_verify_nonce( sanitize_text_field( $nonce ), 'wp_rest' ) ) {
wp_send_json_error(
array(
'data' => __( 'Nonce verification failed.', 'ultimate-addons-for-gutenberg' ),
'status' => false,
)
);
}
$api_endpoint = AST_BLOCK_TEMPLATES_LIBRARY_URL . 'wp-json/ai/v1/keywords';
$token = Importer_Helper::get_business_details( 'token' );
$post_data = array(
'business_name' => isset( $request['business_name'] ) ? sanitize_text_field( $request['business_name'] ) : '',
'business_description' => isset( $request['business_description'] ) ? sanitize_text_field( $request['business_description'] ) : '',
'category' => isset( $request['category'] ) ? sanitize_text_field( $request['category'] ) : '',
'token' => $token,
);
$body = wp_json_encode( $post_data );
$request_args = array(
'body' => is_string( $body ) ? $body : '',
'headers' => array(
'Content-Type' => 'application/json',
),
'timeout' => 100,
);
$response = wp_safe_remote_post( $api_endpoint, $request_args );
if ( is_wp_error( $response ) ) {
// There was an error in the request.
wp_send_json_error(
array(
'data' => 'Failed ' . $response->get_error_message(),
'status' => false,
)
);
} else {
$response_code = wp_remote_retrieve_response_code( $response );
$response_body = wp_remote_retrieve_body( $response );
if ( 200 === $response_code ) {
$response_data = json_decode( $response_body, true );
if ( $response_data['status'] ) {
wp_send_json_success(
array(
'data' => $response_data['data'],
'status' => true,
)
);
} else {
wp_send_json_error(
array(
'data' => 'Failed ' . $response_data['data'],
'status' => false,
)
);
}
} else {
wp_send_json_error(
array(
'data' => 'Failed',
'status' => false,
)
);
}
}
}
}

View File

@@ -0,0 +1,190 @@
<?php
/**
* PageDescription API.
*
* @package {{package}}
* @since 2.0.16
*/
namespace Gutenberg_Templates\Inc\Api;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
use Gutenberg_Templates\Inc\Traits\Instance;
use Gutenberg_Templates\Inc\Api\Api_Base;
use Gutenberg_Templates\Inc\Importer\Importer_Helper;
/**
* Progress
*
* @since 2.0.16
*/
class PageDescription extends Api_Base {
use Instance;
/**
* Route base.
*
* @var string
*/
protected $rest_base = '/page-description/';
/**
* Init Hooks.
*
* @since 2.0.16
* @return void
*/
public function register_routes() {
$namespace = $this->get_api_namespace();
register_rest_route(
$namespace,
$this->rest_base,
array(
array(
'methods' => \WP_REST_Server::CREATABLE,
'callback' => array( $this, 'get' ),
'permission_callback' => array( $this, 'get_item_permissions_check' ),
'args' => array(
'business_name' => array(
'type' => 'string',
'required' => true,
'sanitize_callback' => 'sanitize_text_field',
),
'business_description' => array(
'type' => 'string',
'required' => false,
'sanitize_callback' => 'sanitize_text_field',
),
'page_name' => array(
'type' => 'string',
'required' => true,
'sanitize_callback' => 'sanitize_text_field',
),
'page_description' => array(
'type' => 'string',
'required' => false,
'sanitize_callback' => 'sanitize_text_field',
),
'category' => array(
'type' => 'string',
'sanitize_callback' => 'sanitize_text_field',
'required' => false,
),
),
),
)
);
}
/**
* Check whether a given request has permission to read notes.
*
* @param object $request WP_REST_Request Full details about the request.
* @return object|boolean
*/
public function get_item_permissions_check( $request ) {
if ( ! current_user_can( 'manage_ast_block_templates' ) ) {
return new \WP_Error(
'gt_rest_cannot_access',
__( 'Sorry, you are not allowed to do that.', 'ultimate-addons-for-gutenberg' ),
array( 'status' => rest_authorization_required_code() )
);
}
return true;
}
/**
* Save Prompts.
*
* @param \WP_REST_Request $request Full details about the request.
* @return mixed
*/
public function get( $request ) {
$nonce = (string) $request->get_header( 'X-WP-Nonce' );
// Verify the nonce.
if ( ! wp_verify_nonce( sanitize_text_field( $nonce ), 'wp_rest' ) ) {
wp_send_json_error(
array(
'data' => __( 'Nonce verification failed.', 'ultimate-addons-for-gutenberg' ),
'status' => false,
)
);
}
$api_endpoint = AST_BLOCK_TEMPLATES_LIBRARY_URL . 'wp-json/ai/v1/page-description';
$token = Importer_Helper::get_business_details( 'token' );
$post_data = array(
'business_name' => isset( $request['business_name'] ) ? sanitize_text_field( $request['business_name'] ) : '',
'business_description' => isset( $request['business_description'] ) ? sanitize_text_field( $request['business_description'] ) : '',
'page_name' => isset( $request['page_name'] ) ? sanitize_text_field( $request['page_name'] ) : '',
'page_description' => isset( $request['page_description'] ) ? sanitize_text_field( $request['page_description'] ) : '',
'category' => isset( $request['category'] ) ? sanitize_text_field( $request['category'] ) : '',
'token' => $token,
);
$body = wp_json_encode( $post_data );
$request_args = array(
'body' => is_string( $body ) ? $body : '',
'headers' => array(
'Content-Type' => 'application/json',
),
'timeout' => 100,
);
$response = wp_safe_remote_post( $api_endpoint, $request_args );
if ( is_wp_error( $response ) ) {
// There was an error in the request.
wp_send_json_error(
array(
'data' => 'Failed ' . $response->get_error_message(),
'status' => false,
)
);
} else {
$response_code = wp_remote_retrieve_response_code( $response );
$response_body = wp_remote_retrieve_body( $response );
if ( 200 === $response_code ) {
$response_data = json_decode( $response_body, true );
if ( $response_data['status'] ) {
wp_send_json_success(
array(
'data' => $response_data['data'],
'status' => true,
)
);
} else {
wp_send_json_error(
array(
'data' => 'Failed ' . $response_data['data'],
'status' => false,
)
);
}
} else {
wp_send_json_error(
array(
'data' => 'Failed',
'status' => false,
)
);
}
}
}
}

View File

@@ -0,0 +1,97 @@
<?php
/**
* Pages generate content confirmation API.
*
* @package {{package}}
* @since 0.0.1
*/
namespace Gutenberg_Templates\Inc\Api;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
use Gutenberg_Templates\Inc\Traits\Instance;
use Gutenberg_Templates\Inc\Api\Api_Base;
use WP_Error;
use WP_REST_Request;
use WP_REST_Response;
use WP_REST_Server;
/**
* Pages generate content confirmation.
*
* @since 0.0.1
*/
class Pages extends Api_Base {
use Instance;
/**
* Route base.
*
* @var string
*/
protected $rest_base = '/pages-onboarding/';
/**
* Init Hooks.
*
* @since 0.0.1
* @return void
*/
public function register_routes() {
$namespace = $this->get_api_namespace();
register_rest_route(
$namespace,
$this->rest_base,
array(
array(
'methods' => WP_REST_Server::CREATABLE,
'callback' => array( $this, 'set' ),
'permission_callback' => array( $this, 'get_item_permissions_check' ),
),
)
);
}
/**
* Check whether a given request has permission to read notes.
*
* @param object $request WP_REST_Request Full details about the request.
* @return object|boolean
*/
public function get_item_permissions_check( $request ) {
if ( ! current_user_can( 'manage_ast_block_templates' ) ) {
return new WP_Error(
'gt_rest_cannot_access',
__( 'Sorry, you are not allowed to do that.', 'ultimate-addons-for-gutenberg' ),
array( 'status' => rest_authorization_required_code() )
);
}
return true;
}
/**
* Save the pages onboarding flag status.
*
* @return WP_REST_Response
*/
public function set(): WP_REST_Response {
$saved = update_option( 'ast-show-pages-onboarding', 'no' );
$response = new WP_REST_Response(
array(
'success' => $saved,
)
);
$response->set_status( 200 );
return $response;
}
}

View File

@@ -0,0 +1,113 @@
<?php
/**
* Revoke Access API.
*
* @package {{package}}
* @since 0.0.1
*/
namespace Gutenberg_Templates\Inc\Api;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
use Gutenberg_Templates\Inc\Traits\Instance;
use Gutenberg_Templates\Inc\Api\Api_Base;
use Gutenberg_Templates\Inc\Traits\Helper;
use WP_Error;
use WP_REST_Response;
use WP_REST_Server;
/**
* Pages generate content confirmation.
*
* @since 0.0.1
*/
class RevokeAccess extends Api_Base {
use Instance;
/**
* Route base.
*
* @var string
*/
protected $rest_base = '/revoke-access/';
/**
* Init Hooks.
*
* @since 0.0.1
* @return void
*/
public function register_routes() {
$namespace = $this->get_api_namespace();
register_rest_route(
$namespace,
$this->rest_base,
array(
array(
'methods' => WP_REST_Server::CREATABLE,
'callback' => array( $this, 'set' ),
'permission_callback' => array( $this, 'get_item_permissions_check' ),
),
)
);
}
/**
* Check whether a given request has permission to read notes.
*
* @param object $request WP_REST_Request Full details about the request.
* @return object|boolean
*/
public function get_item_permissions_check( $request ) {
if ( ! current_user_can( 'manage_ast_block_templates' ) ) {
return new WP_Error(
'gt_rest_cannot_access',
__( 'Sorry, you are not allowed to do that.', 'ultimate-addons-for-gutenberg' ),
array( 'status' => rest_authorization_required_code() )
);
}
return true;
}
/**
* Revoke access.
*
* @param \WP_REST_Request $request Full details about the request.
* @return WP_REST_Response
*/
public function set( $request ): WP_REST_Response {
$nonce = $request->get_header( 'X-WP-Nonce' );
$nonce = isset( $nonce ) ? sanitize_text_field( $nonce ) : '';
// Verify the nonce.
if ( ! wp_verify_nonce( $nonce, 'wp_rest' ) ) {
wp_send_json_error(
array(
'data' => __( 'Nonce verification failed.', 'ultimate-addons-for-gutenberg' ),
'status' => false,
)
);
}
delete_option( 'ast-block-templates-show-onboarding' );
Helper::delete_admin_settings_option( 'zip_ai_settings' );
$response = new WP_REST_Response(
array(
'success' => true,
)
);
$response->set_status( 200 );
return $response;
}
}

View File

@@ -0,0 +1,186 @@
<?php
/**
* Settings API.
*
* @package {{package}}
* @since 2.0.0
*/
namespace Gutenberg_Templates\Inc\Api;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
use Gutenberg_Templates\Inc\Traits\Instance;
use Gutenberg_Templates\Inc\Api\Api_Base;
use Gutenberg_Templates\Inc\Importer\Plugin;
/**
* Settings
*
* @since 2.0.0
*/
class Settings extends Api_Base {
use Instance;
/**
* Route base.
*
* @var string
*/
protected $rest_base = '/settings/';
/**
* Init Hooks.
*
* @since 2.0.0
* @return void
*/
public function register_routes() {
$namespace = $this->get_api_namespace();
register_rest_route(
$namespace,
$this->rest_base,
array(
array(
'methods' => \WP_REST_Server::READABLE,
'callback' => array( $this, 'get' ),
'permission_callback' => array( $this, 'get_item_permissions_check' ),
),
)
);
register_rest_route(
$namespace,
$this->rest_base,
array(
array(
'methods' => \WP_REST_Server::EDITABLE,
'callback' => array( $this, 'save' ),
'permission_callback' => array( $this, 'get_item_permissions_check' ),
'args' => array(
'key' => array(
'type' => 'string',
'required' => true,
),
'value' => array(
'type' => 'boolean',
'required' => true,
),
),
),
)
);
}
/**
* Check whether a given request has permission to read notes.
*
* @param object $request WP_REST_Request Full details about the request.
* @return object|boolean
*/
public function get_item_permissions_check( $request ) {
if ( ! current_user_can( 'manage_ast_block_templates' ) ) {
return new \WP_Error(
'gt_rest_cannot_access',
__( 'Sorry, you are not allowed to do that.', 'ultimate-addons-for-gutenberg' ),
array( 'status' => rest_authorization_required_code() )
);
}
return true;
}
/**
* Get Settings.
*
* @param \WP_REST_Request $request Full details about the request.
* @return mixed
*/
public function get( $request ) {
$ai_settings = get_option( 'ast_block_templates_ai_settings', array() );
$response = new \WP_REST_Response(
array(
'success' => true,
'data' => $ai_settings,
)
);
$response->set_status( 200 );
return $response;
}
/**
* Save Settings.
*
* @param \WP_REST_Request $request Full details about the request.
* @return mixed
*/
public function save( $request ) {
$nonce = (string) $request->get_header( 'X-WP-Nonce' );
// Verify the nonce.
if ( ! wp_verify_nonce( sanitize_text_field( $nonce ), 'wp_rest' ) ) {
wp_send_json_error(
array(
'data' => __( 'Nonce verification failed.', 'ultimate-addons-for-gutenberg' ),
'status' => false,
)
);
}
$setting_key = $request->get_param( 'key' );
$setting_value = $request->get_param( 'value' );
if ( ! empty( $setting_key ) ) {
$settings = get_option( 'ast_block_templates_ai_settings', array() );
$settings[ $setting_key ] = $setting_value;
if ( 'disable_ai' === $setting_key ) {
$ai_settings = get_option( 'zip_ai_modules', array() );
$ai_copilot_value = $setting_value ? 'disabled' : 'enabled';
$ai_settings['ai_design_copilot']['status'] = $ai_copilot_value;
update_option( 'zip_ai_modules', $ai_settings );
$settings['disable_ai'] = $setting_value;
}
if ( 'adaptive_mode' === $setting_key ) {
$ai_settings = get_option( 'zip_ai_modules', array() );
$ai_copilot_value = $setting_value ? 'enabled' : 'disabled';
$ai_settings['ai_design_copilot']['status'] = $ai_copilot_value;
update_option( 'zip_ai_modules', $ai_settings );
$settings['disable_ai'] = ! $setting_value;
}
$status = update_option( 'ast_block_templates_ai_settings', $settings );
$blocks = Plugin::instance()->get_all_blocks();
$response = new \WP_REST_Response(
array(
'success' => $status,
'blocks' => $blocks,
)
);
$response->set_status( 200 );
return $response;
}
return new \WP_Error(
'failed',
__( 'Sorry, settings are not saved.', 'ultimate-addons-for-gutenberg' ),
array( 'status' => 'fail' )
);
}
}

View File

@@ -0,0 +1,109 @@
<?php
/**
* Progress API.
*
* @package {{package}}
* @since 0.0.1
*/
namespace Gutenberg_Templates\Inc\Api;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
use Gutenberg_Templates\Inc\Traits\Instance;
use Gutenberg_Templates\Inc\Importer\Plugin;
use Gutenberg_Templates\Inc\Api\Api_Base;
/**
* Progress
*
* @since 0.0.1
*/
class Sites extends Api_Base {
use Instance;
/**
* Route base.
*
* @var string
*/
protected $rest_base = '/sites/';
/**
* Init Hooks.
*
* @since 0.0.1
* @return void
*/
public function register_routes() {
$namespace = $this->get_api_namespace();
register_rest_route(
$namespace,
$this->rest_base,
array(
array(
'methods' => \WP_REST_Server::READABLE,
'callback' => array( $this, 'get_sites' ),
'permission_callback' => array( $this, 'get_item_permissions_check' ),
),
)
);
}
/**
* Check whether a given request has permission to read notes.
*
* @param object $request WP_REST_Request Full details about the request.
* @return object|boolean
*/
public function get_item_permissions_check( $request ) {
if ( ! current_user_can( 'manage_ast_block_templates' ) ) {
return new \WP_Error(
'gt_rest_cannot_access',
__( 'Sorry, you are not allowed to do that.', 'ultimate-addons-for-gutenberg' ),
array( 'status' => rest_authorization_required_code() )
);
}
return true;
}
/**
* Save Prompts.
*
* @param \WP_REST_Request $request Full details about the request.
* @return \WP_REST_Response
*/
public function get_sites( $request ) {
$nonce = (string) $request->get_header( 'X-WP-Nonce' );
// Verify the nonce.
if ( ! wp_verify_nonce( sanitize_text_field( $nonce ), 'wp_rest' ) ) {
return new \WP_REST_Response(
array(
'success' => false,
'data' => __( 'Nonce verification failed.', 'ultimate-addons-for-gutenberg' ),
),
403
);
}
$all_sites = Plugin::instance()->get_all_sites();
$response = new \WP_REST_Response(
array(
'success' => true,
'sites' => $all_sites,
)
);
$response->set_status( 200 );
return $response;
}
}

View File

@@ -0,0 +1,8 @@
{
"apiVersion": 3,
"title": "Spectra AI",
"name": "gutenberg-templates/spectra-ai",
"category": "layout",
"editorScript": "file:./index.js",
"editorStyle": "file:./index.css"
}

View File

@@ -0,0 +1 @@
<?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-blocks', 'wp-i18n'), 'version' => 'f9a7230af2d27cbc398e');

View File

@@ -0,0 +1 @@
:root{--ast-spectra-ai-primary: #0073aa;--ast-spectra-ai-primary-hover: #007cba;--ast-spectra-ai-primary-text: #fff;--ast-spectra-ai-heading-text: #030712;--ast-spectra-ai-text: #374151;--ast-spectra-ai-icon-active: #111827;--ast-spectra-ai-icon-inactive: #374151}.spectra-ai-block-layout{font-family:Inter,sans-serif}.spectra-ai-block-layout.block-wrapper{width:100%;max-width:544px !important;padding:32px;border-radius:5px;display:flex;flex-direction:column;gap:32px}.spectra-ai-block-layout.block-wrapper:hover{box-shadow:none}.spectra-ai-block-layout .block-heading-wrapper{display:flex;flex-direction:column;align-items:center;justify-content:flex-start;gap:12px}.spectra-ai-block-layout .block-title{font-size:24px;font-weight:600;line-height:33.6px;text-align:center;margin:0 !important;padding:0 !important;color:var(--ast-spectra-ai-heading-text)}.spectra-ai-block-layout .block-description{font-size:16px;font-weight:400;line-height:24px;text-align:center;margin:0 !important;padding:0 !important;color:var(--ast-spectra-ai-text)}.spectra-ai-block-layout .block-button{font-size:16px;font-weight:500;line-height:24px;padding:8px 20px;border-radius:4px;display:flex;align-items:center;justify-content:center;gap:8px;transition:color .15s ease-in-out}.spectra-ai-block-layout .block-button.prefix-icon{padding-left:12px}.spectra-ai-block-layout .button-icon{width:24px;height:24px}.spectra-ai-block-layout .button-primary{background-color:var(--ast-spectra-ai-primary);border-color:var(--ast-spectra-ai-primary);color:var(--ast-spectra-ai-primary-text)}.spectra-ai-block-layout .button-primary:hover{background-color:var(--ast-spectra-ai-primary-hover);border:1px solid var(--ast-spectra-ai-primary-hover);color:var(--ast-spectra-ai-primary-text)}.spectra-ai-block-layout .button-secondary{background-color:#fff;color:var(--ast-spectra-ai-primary);border:1px solid var(--ast-spectra-ai-primary)}.spectra-ai-block-layout .button-secondary:hover{background-color:#fff;color:var(--ast-spectra-ai-primary-hover);border:1px solid var(--ast-spectra-ai-primary-hover)}.spectra-ai-block-layout .block-buttons{display:flex;align-items:center;justify-content:center;gap:16px}.spectra-ai-block-layout .close-button{position:absolute;top:16px;right:16px;width:24px;height:24px;cursor:pointer;border:none;outline:none;background:none;color:var(--ast-spectra-ai-icon-inactive);transition:color .15s ease-in-out}.spectra-ai-block-layout .close-button:hover{color:var(--ast-spectra-ai-icon-active)}.spectra-ai-block-layout .close-button .close-button-icon{width:24px;height:24px}.spectra-ai-block-layout+.block-list-appender .block-editor-default-block-appender{display:none !important}

View File

@@ -0,0 +1 @@
(()=>{"use strict";const e=window.wp.blocks,t=window.wp.blockEditor,a=window.wp.i18n,l=window.React;function n({title:e,titleId:t,...a},n){return l.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:1.5,stroke:"currentColor","aria-hidden":"true","data-slot":"icon",ref:n,"aria-labelledby":t},a),e?l.createElement("title",{id:t},e):null,l.createElement("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M9.813 15.904 9 18.75l-.813-2.846a4.5 4.5 0 0 0-3.09-3.09L2.25 12l2.846-.813a4.5 4.5 0 0 0 3.09-3.09L9 5.25l.813 2.846a4.5 4.5 0 0 0 3.09 3.09L15.75 12l-2.846.813a4.5 4.5 0 0 0-3.09 3.09ZM18.259 8.715 18 9.75l-.259-1.035a3.375 3.375 0 0 0-2.455-2.456L14.25 6l1.036-.259a3.375 3.375 0 0 0 2.455-2.456L18 2.25l.259 1.035a3.375 3.375 0 0 0 2.456 2.456L21.75 6l-1.035.259a3.375 3.375 0 0 0-2.456 2.456ZM16.894 20.567 16.5 21.75l-.394-1.183a2.25 2.25 0 0 0-1.423-1.423L13.5 18.75l1.183-.394a2.25 2.25 0 0 0 1.423-1.423l.394-1.183.394 1.183a2.25 2.25 0 0 0 1.423 1.423l1.183.394-1.183.394a2.25 2.25 0 0 0-1.423 1.423Z"}))}const o=l.forwardRef(n);function c({title:e,titleId:t,...a},n){return l.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:1.5,stroke:"currentColor","aria-hidden":"true","data-slot":"icon",ref:n,"aria-labelledby":t},a),e?l.createElement("title",{id:t},e):null,l.createElement("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M6 18 18 6M6 6l12 12"}))}const r=l.forwardRef(c),s=(()=>{const e={};return Object.seal({on:(t,a)=>{e[t]||(e[t]=[]),e[t].push(a)},emit:(t,...a)=>{const l=e[t];l&&l.forEach((e=>e(...a)))},removeListener:(t,a)=>{const l=e[t];if(l){const e=l.findIndex((e=>e===a));-1!==e&&l.splice(e,1)}},removeAllListeners:t=>{e[t]&&delete e[t]}})})();function i(){return i=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var a=arguments[t];for(var l in a)({}).hasOwnProperty.call(a,l)&&(e[l]=a[l])}return e},i.apply(null,arguments)}const u=JSON.parse('{"UU":"gutenberg-templates/spectra-ai"}');(0,e.registerBlockType)(u.UU,{icon:React.createElement("svg",{width:"32",height:"32",viewBox:"0 0 32 32",fill:"none",xmlns:"http://www.w3.org/2000/svg"},React.createElement("path",{fillRule:"evenodd",clipRule:"evenodd",d:"M16 32C24.8366 32 32 24.8366 32 16C32 7.16343 24.8366 0 16 0C7.16343 0 0 7.16343 0 16C0 24.8366 7.16343 32 16 32ZM20.9202 20.688C21.8453 20.1032 22.4 19.1247 22.4 18.0775C22.4 16.6224 21.3376 15.357 19.8308 15.0174L15.3161 13.8968C14.8905 13.8009 14.7885 13.2761 15.1506 13.0452L18.6679 10.8017C20.3051 9.75739 20.7308 7.66455 19.6187 6.12718C19.4797 5.93499 19.2011 5.88503 18.9964 6.01559L11.0507 11.3753C10.1433 11.9541 9.6 12.9173 9.6 13.9473C9.6 15.3851 10.6496 16.6352 12.1385 16.9708L16.7267 18.108C17.1533 18.2042 17.2544 18.7307 16.8905 18.9607L13.3473 21.2006C11.7055 22.2385 11.2706 24.3297 12.3759 25.8714C12.5141 26.0641 12.7925 26.1152 12.9977 25.9854L20.9202 20.688Z",fill:"var(--colors-accent-spectra)"})),attributes:{isOpen:{type:"boolean",default:!0}},useOnce:!0,supports:{customClassName:!1,className:!1,html:!1},edit:({onReplace:e})=>{const{blockProps:l}=(0,t.useBlockProps)();return React.createElement("div",i({className:"spectra-ai-block-layout block-wrapper border border-solid border-border-primary relative"},l),React.createElement("div",{className:"block-heading-wrapper"},React.createElement("h5",{className:"block-title"},(0,a.__)("Spectra AI Block","ast-block-templates")),React.createElement("p",{className:"block-description"},(0,a.__)("Eu lectus mauris vulputate et sem consequat ornare. Et consectetur sagittis faucibus eget.","ast-block-templates"))),React.createElement("div",{className:"block-buttons"},React.createElement("button",{className:"block-button button-primary prefix-icon",onClick:()=>{s.emit("toggle-onboarding-page-ai"),e([])}},React.createElement(o,{className:"button-icon"}),React.createElement("span",null,(0,a.__)("Build using AI","ast-block-templates"))),React.createElement("button",{className:"block-button button-secondary",onClick:()=>{const t=document.querySelector("#ast-block-templates-button");e([]),t&&t.click()}},React.createElement("span",null,(0,a.__)("Template Kits","ast-block-templates")))),React.createElement("button",{className:"close-button",onClick:()=>{e([])}},React.createElement(r,{className:"close-button-icon"})))},save:()=>!1})})();

View File

@@ -0,0 +1,157 @@
<?php
/**
* Spectra AI Block.
*
* @package Gutenberg_Templates
*/
namespace Gutenberg_Templates\Inc\Block;
/**
* Spectra_AI_Block
*
* @since 2.0.16
*/
class Spectra_AI_Block {
/**
* Instance
*
* @access private
* @var object Class Instance.
* @since 2.0.16
*/
private static $instance = null;
/**
* Constructor
*
* @since 2.0.16
*/
public function __construct() {
global $wp_version;
$hook = version_compare( $wp_version, '5.8-alpha', '<' ) ? 'block_editor_preload_paths' : 'block_editor_rest_api_preload_paths';
add_action( 'init', array( $this, 'register_block_type' ) );
add_filter( $hook, array( $this, 'update_new_post' ), 10, 2 );
}
/**
* Get Instance
*
* @since 2.0.16
*
* @return object Class object.
*/
public static function get_instance() {
if ( null === self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Register Block Type
*
* @since 2.0.16
*
* @return void
*/
public function register_block_type() {
register_block_type( AST_BLOCK_TEMPLATES_DIR . '/block/dist' );
}
/**
* Add the block on new page creation.
*
* @since 2.0.16
*
* @param array<string, string> $paths Array of preload paths.
* @param mixed $context Context of the request.
*
* @return array<string, string>
*/
public static function update_new_post( $paths, $context ) {
if ( ! is_object( $context ) || ! property_exists( $context, 'post' ) ) {
return $paths;
}
$post = $context->post;
if ( ! is_object( $post ) || ! property_exists( $post, 'ID' ) || ! property_exists( $post, 'post_content' ) ) {
return $paths;
}
if ( ! is_string( $post->post_content ) ) {
return $paths;
}
$blocks = preg_match( '/<!-- wp:(.*) \/?-->/', $post->post_content );
if ( ! $blocks ) {
$block = '<!-- wp:gutenberg-templates/spectra-ai -->';
$block .= self::remove_broken_p_tags( $post->post_content );
$block .= '<!-- /wp:gutenberg-templates/spectra-ai -->';
$post->post_content = $block;
wp_update_post(
array(
'ID' => $post->ID,
'post_content' => $block,
)
);
}
return $paths;
}
/**
* Remove broken p tags.
*
* @since 2.0.16
*
* @param string $content Post content.
*
* @return string
*/
public static function remove_broken_p_tags( $content ) {
if ( ! is_string( $content ) ) {
return '';
}
// Convert microsoft special characters.
$replace = array(
'' => "'",
'' => "'",
'”' => '"',
'“' => '"',
'' => '-',
'—' => '-',
'…' => '&#8230;',
);
// Remove empty tags.
$content = preg_replace( '@<([^>]+)\s*>\s*<\/\1\s*>@m', '', $content );
// Remove all <p> tags.
$content = preg_replace( '/<\/?p[^>]*\>/i', '', $content ?? '' );
// Replace special characters.
foreach ( $replace as $k => $v ) {
$content = str_replace( $k, $v, $content ?? '' );
}
// Balance tags.
$content = force_balance_tags( $content );
return $content;
}
}
/**
* Kicking this off by calling 'get_instance()' method.
*/
Spectra_AI_Block::get_instance();

View File

@@ -0,0 +1,118 @@
<?php
/**
* Ast BlockTemplates
*
* @since 2.2.4
* @package Astra Sites
*/
namespace Gutenberg_Templates\Inc\Classes;
use Gutenberg_Templates\Inc\Traits\Instance;
if ( ! class_exists( 'Ast_Block_Templates_Notices' ) ) :
/**
* Ast BlockTemplates
*/
class Ast_Block_Templates_Notices {
use Instance;
/**
* Check file read/write permissions and process.
*
* @since 2.2.4
* @return bool
*/
public function has_file_read_write() {
if ( defined( 'WP_CLI' ) && WP_CLI ) {
return true;
}
$upload_dir = self::log_dir();
$file_created = self::get_filesystem()->put_contents( $upload_dir['path'] . 'index.html', '' );
if ( ! $file_created ) {
add_action( 'admin_notices', array( $this, 'file_permission_notice' ) );
return false;
}
return true;
}
/**
* File Permission Notice
*
* @since 2.0.0
* @return void
*/
public function file_permission_notice() {
$notice = __( 'File Permissions Needed - Importing patterns, pages, and templates from Design Library requires proper file permissions. For guidance on resolving this issue and ensuring smooth importing processes, please refer to the accompanying documentation.', 'ultimate-addons-for-gutenberg' );
?>
<div class="notice notice-error ast-block-templates-must-notices ast-block-templates-file-permission-issue">
<p><?php echo esc_html( $notice ); ?></p>
<p><?php echo esc_html( __( 'Doc: ', 'ultimate-addons-for-gutenberg' ) ); ?><a href="https://wpastra.com/docs/could-not-store-files-in-wp-content-folder/" target="__blank"><?php echo esc_html( __( 'Resolve file permission issue', 'ultimate-addons-for-gutenberg' ) ); ?></a></p>
</div>
<?php
}
/**
* Get an instance of WP_Filesystem_Direct.
*
* @since 2.0.0
* @return mixed A WP_Filesystem_Direct instance.
*/
public static function get_filesystem() {
global $wp_filesystem;
require_once ABSPATH . '/wp-admin/includes/file.php';
WP_Filesystem();
return $wp_filesystem;
}
/**
* Log file directory
*
* @since 2.2.4
* @param string $dir_name Directory Name.
* @return array<string, string> Uploads directory array.
*/
public static function log_dir( $dir_name = 'ast-block-templates-json' ) {
$upload_dir = wp_upload_dir();
// Build the paths.
$dir_info = array(
'path' => $upload_dir['basedir'] . '/' . $dir_name . '/',
'url' => $upload_dir['baseurl'] . '/' . $dir_name . '/',
);
// Create the upload dir if it doesn't exist.
if ( ! file_exists( $dir_info['path'] ) ) {
// Create the directory.
wp_mkdir_p( $dir_info['path'] );
// Add an index file for security.
self::get_filesystem()->put_contents( $dir_info['path'] . 'index.html', '' );
// Add an .htaccess for security.
self::get_filesystem()->put_contents( $dir_info['path'] . '.htaccess', 'deny from all' );
}
return $dir_info;
}
}
/**
* Kicking this off by calling 'get_instance()' method
*/
Ast_Block_Templates_Notices::instance();
endif;

View File

@@ -0,0 +1,249 @@
<?php
/**
* Handle ZipWP API calls.
*
* @package {{package}}
* @since {{since}}
*/
namespace Gutenberg_Templates\Inc\Classes;
use Gutenberg_Templates\Inc\Traits\Helper;
use Gutenberg_Templates\Inc\Traits\Instance;
/**
* AST Block Templates ZipWP API
*
* @since {{since}}
*/
class Ast_Block_Templates_Zipwp_Api {
use Instance;
/**
* Constructor
*
* @since 2.1.13
*/
public function __construct() {
add_action( 'rest_api_init', array( $this, 'register_route' ) );
}
/**
* Get api domain
*
* @since 2.1.13
* @return string
*/
public function get_api_domain() {
return ( defined( 'ZIPWP_API' ) ? ZIPWP_API : 'https://api.zipwp.com/api/' );
}
/**
* Get API headers
*
* @since 2.1.13
* @return array<string, string>
*/
public function get_api_headers() {
return array(
'Content-Type' => 'application/json',
'Accept' => 'application/json',
'Authorization' => 'Bearer ' . Helper::decrypt( Helper::get_setting( 'zip_token' ) ),
);
}
/**
* Get api namespace
*
* @since 2.1.13
* @return string
*/
public function get_api_namespace() {
return 'zipwp/v1';
}
/**
* Check whether a given request has permission to read notes.
*
* @param object $request WP_REST_Request Full details about the request.
* @return object|boolean
*/
public function get_item_permissions_check( $request ) {
if ( ! current_user_can( 'manage_ast_block_templates' ) ) {
return new \WP_Error(
'gt_rest_cannot_access',
__( 'Sorry, you are not allowed to do that.', 'ultimate-addons-for-gutenberg' ),
array( 'status' => rest_authorization_required_code() )
);
}
return true;
}
/**
* Register route
*
* @since 2.1.13
* @return void
*/
public function register_route() {
$namespace = $this->get_api_namespace();
register_rest_route(
$namespace,
'/search-category/',
array(
array(
'methods' => \WP_REST_Server::CREATABLE,
'callback' => array( $this, 'search_business_category' ),
'permission_callback' => array( $this, 'get_item_permissions_check' ),
'args' => array(
'keyword' => array(
'type' => 'string',
'sanitize_callback' => 'sanitize_text_field',
'required' => true,
),
),
),
)
);
register_rest_route(
$namespace,
'/site-languages/',
array(
array(
'methods' => \WP_REST_Server::READABLE,
'callback' => array( $this, 'get_site_languages' ),
'permission_callback' => array( $this, 'get_item_permissions_check' ),
),
)
);
}
/**
* Search business category.
*
* @param \WP_REST_Request $request Full details about the request.
* @return mixed
*/
public function search_business_category( $request ) {
$nonce = (string) $request->get_header( 'X-WP-Nonce' );
// Verify the nonce.
if ( ! wp_verify_nonce( sanitize_text_field( $nonce ), 'wp_rest' ) ) {
wp_send_json_error(
array(
'data' => __( 'Nonce verification failed.', 'ultimate-addons-for-gutenberg' ),
'status' => false,
)
);
}
$keyword = $request['keyword'];
$api_endpoint = $this->get_api_domain() . 'sites/business/search?q=' . $keyword;
$request_args = array(
'headers' => $this->get_api_headers(),
'timeout' => 100,
);
$response = wp_safe_remote_get( $api_endpoint, $request_args );
if ( is_wp_error( $response ) ) {
// There was an error in the request.
wp_send_json_error(
array(
'data' => 'Failed ' . $response->get_error_message(),
'status' => false,
)
);
}
$response_code = wp_remote_retrieve_response_code( $response );
$response_body = wp_remote_retrieve_body( $response );
if ( 200 === $response_code ) {
$response_data = json_decode( $response_body, true );
wp_send_json_success(
array(
'data' => $response_data['results'],
'status' => true,
)
);
} else {
wp_send_json_error(
array(
'data' => 'Failed - ' . $response_body,
'status' => false,
)
);
}
}
/**
* Get ZipWP Languages list.
*
* @param \WP_REST_Request $request Full details about the request.
* @return mixed
*/
public function get_site_languages( $request ) {
$nonce = (string) $request->get_header( 'X-WP-Nonce' );
// Verify the nonce.
if ( ! wp_verify_nonce( sanitize_text_field( $nonce ), 'wp_rest' ) ) {
wp_send_json_error(
array(
'data' => __( 'Nonce verification failed.', 'ultimate-addons-for-gutenberg' ),
'status' => false,
)
);
}
$api_endpoint = $this->get_api_domain() . 'sites/languages/';
$request_args = array(
'headers' => $this->get_api_headers(),
'timeout' => 100,
);
$response = wp_safe_remote_get( $api_endpoint, $request_args );
if ( is_wp_error( $response ) ) {
// There was an error in the request.
wp_send_json_error(
array(
'data' => 'Failed ' . $response->get_error_message(),
'status' => false,
)
);
}
$response_code = wp_remote_retrieve_response_code( $response );
$response_body = wp_remote_retrieve_body( $response );
if ( 200 === $response_code ) {
$response_data = json_decode( $response_body, true );
if ( $response_data ) {
wp_send_json_success(
array(
'data' => $response_data['data'],
'status' => true,
)
);
}
wp_send_json_error(
array(
'data' => $response_data,
'status' => false,
)
);
}
wp_send_json_error(
array(
'data' => 'Failed ' . $response_body,
'status' => false,
)
);
}
}

View File

@@ -0,0 +1,408 @@
<?php
/**
* Sync Library
*
* @package Ast Block Templates
* @since 1.0.0
*/
namespace Gutenberg_Templates\Inc\Content;
use Gutenberg_Templates\Inc\Traits\Instance;
use Gutenberg_Templates\Inc\Importer\Importer_Helper;
use Gutenberg_Templates\Inc\Importer\Plugin;
use Gutenberg_Templates\Inc\Traits\Helper;
use Gutenberg_Templates\Inc\Importer\Images;
/**
* Sync Library
*
* @since 1.0.0
*/
class Ai_Content {
use Instance;
/**
* Constructor
*
* @since 1.0.0
*/
public function __construct() {
$this->define_required_constants();
add_action( 'wp_ajax_ast-block-templates-ai-content', array( $this, 'save_user_details' ) );
add_action( 'wp_ajax_ast-block-templates-regenerate', array( $this, 'generate_ai_content' ) );
add_action( 'wp_ajax_ast-block-templates-reset-business-details', array( $this, 'reset_business_details' ) );
add_action( 'wp_footer', array( $this, 'footer' ) );
add_action( 'ast_templates_download_selected_images', array( $this, 'download_selected_images' ) );
}
/**
* Debug mode for testing.
*
* @return void
*/
public function footer() {
if ( isset( $_GET['debug'] ) && Helper::instance()->is_debug_mode() ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
echo '<xmp>';
print_r( get_option( 'ast_block_ai_content_log', array() ) ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
print_r( get_option( 'zipwp_user_business_details' ) ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
echo '</xmp>';
}
}
/**
* Define Required Constants
*
* @since 2.0.0
* @return void
*/
public function define_required_constants() {
define( 'AST_BLOCK_TEMPLATES_IMAGE_COUNT', 20 );
}
/**
* Reset Business details
*
* @since 2.0.0
* @return void
*/
public function reset_business_details() {
// Verify Nonce.
check_ajax_referer( 'ast-block-templates-reset-business-details', 'security' );
delete_option( 'ast-block-templates-show-onboarding' );
delete_option( 'zipwp_user_business_details' );
delete_option( 'ast_block_ai_content_log' );
delete_option( 'ast-templates-ai-content' );
wp_send_json_success(
array(
'status' => true,
)
);
}
/**
* Generate AI based blocks.
*
* @since 2.0.0
* @return void
*/
public function generate_ai_content() {
// Verify Nonce.
check_ajax_referer( 'ast-block-templates-ai-content', 'security' );
$details = Importer_Helper::get_business_details();
$language = 'en';
if ( isset( $details['language'] ) ) {
$language = is_array( $details['language'] ) ? $details['language']['code'] : $details['language'];
}
$post_data = array(
'business_name' => isset( $details['business_name'] ) ? sanitize_text_field( $details['business_name'] ) : '',
'business_description' => isset( $details['business_description'] ) ? sanitize_text_field( $details['business_description'] ) : '',
'business_category' => isset( $details['business_category'] ) ? sanitize_text_field( $details['business_category'] ) : '',
'category' => isset( $_POST['category'] ) ? intval( $_POST['category'] ) : '',
'token' => isset( $details['token'] ) ? $details['token'] : '',
'regenerate' => isset( $_POST['regenerate'] ) ? filter_var( $_POST['regenerate'], FILTER_VALIDATE_BOOLEAN ) : false,
'block_type' => isset( $_POST['block_type'] ) ? sanitize_text_field( $_POST['block_type'] ) : 'block',
'is_last_category' => isset( $_POST['is_last_category'] ) ? filter_var( $_POST['is_last_category'], FILTER_VALIDATE_BOOLEAN ) : false,
'language_slug' => $language,
'language_name' => isset( $details['language']['name'] ) ? sanitize_text_field( $details['language']['name'] ) : '',
);
$category_content = get_option( 'ast-templates-ai-content', array() );
if ( ! $post_data['regenerate'] ) {
if ( isset( $category_content[ $post_data['category'] ] ) ) {
wp_send_json_success(
array(
'data' => $category_content,
'status' => true,
'extra' => 'from club saved already',
'single' => $category_content[ $post_data['category'] ],
'spec_credit_details' => Plugin::instance()->get_spec_credit_details(),
)
);
}
}
$this->get_ai_content( $post_data, $category_content );
}
/**
* Get Club of Category
*
* @since 2.0.0
* @param array<int, array<string, mixed>> $categories Categories.
* @param array<string, mixed> $post_data Post Data.
*
* @return string
*/
public function get_club_of_category( $categories, $post_data ) {
$club_categories = null;
foreach ( $categories as $single_category ) {
if ( $single_category['id'] === $post_data['category'] ) {
$club_categories = $single_category['club'] ?? null;
break;
}
}
return $club_categories;
}
/**
* Get Matching Categories
*
* @since 2.0.0
* @param array<int, array<string, mixed>> $categories Categories.
* @param string $club_categories Club Categories.
*
* @return array<int, array<string, mixed>>
*/
public function get_matching_categories( $categories, $club_categories ) {
$matching_categories = array();
if ( null !== $club_categories ) {
// Find all other categories with the same club.
foreach ( $categories as $single_category ) {
if ( isset( $single_category['club'] ) && $single_category['club'] === $club_categories ) {
$matching_categories[] = $single_category;
}
}
}
return $matching_categories;
}
/**
* Get AI Content
*
* @since 2.0.0
* @param array<string, mixed> $post_data Post Data.
* @param string $category_content Categories content.
*
* @return void
*/
public function get_ai_content( $post_data, $category_content ) {
$api_endpoint = Helper::instance()->is_debug_mode() ? AST_BLOCK_TEMPLATES_LIBRARY_URL . 'wp-json/ai/v1/content?debug=yes' : AST_BLOCK_TEMPLATES_LIBRARY_URL . 'wp-json/ai/v1/content';
$body = wp_json_encode( $post_data );
$request_args = array(
'body' => is_string( $body ) ? $body : '',
'headers' => array(
'Content-Type' => 'application/json',
),
'timeout' => 50,
);
$response = wp_safe_remote_post( $api_endpoint, $request_args );
$log = get_option( 'ast_block_ai_content_log', array() );
$log[ $post_data['category'] ] = array();
if ( is_wp_error( $response ) ) {
$log[ $post_data['category'] ] = 'Error: ' . $response->get_error_message();
update_option( 'ast_block_ai_content_log', $log );
wp_send_json_error(
array(
'data' => 'Error: ' . $response->get_error_message(),
'status' => false,
)
);
} else {
$response_code = wp_remote_retrieve_response_code( $response );
$response_body = wp_remote_retrieve_body( $response );
$response_data = json_decode( $response_body, true );
if ( 200 === $response_code ) {
if ( $response_data['status'] ) {
if ( ! $post_data['regenerate'] ) {
$categories = Helper::instance()->get_block_template_category();
// Find the club of the current category.
$club = $this->get_club_of_category( $categories, $post_data );
// Find all other categories with the same club.
$matching_categories = $this->get_matching_categories( $categories, $club );
// Save same content for all categories with same club.
foreach ( $matching_categories as $m_category ) {
$category_content[ $m_category['id'] ] = $response_data['content'];
}
$category_content[ $post_data['category'] ] = $response_data['content'];
update_option( 'ast-templates-ai-content', $category_content );
} else {
$category_content[ $post_data['category'] ] = $response_data['content'];
update_option( 'ast-templates-ai-content', $category_content );
}
$log[ $post_data['category'] ] = $response_data['debug'];
update_option( 'ast_block_ai_content_log', $log );
// Set the new user flag to 'no'.
if ( get_option( 'ast-block-templates-new-user', 'yes' ) === 'yes' ) {
update_option( 'ast-block-templates-new-user', 'no' );
}
if ( Helper::instance()->is_debug_mode() ) {
wp_send_json_success(
array(
'data' => $category_content,
'status' => true,
'extra' => $response_data['debug'],
'single' => $category_content[ $post_data['category'] ],
'spec_credit_details' => Plugin::instance()->get_spec_credit_details(),
)
);
} else {
wp_send_json_success(
array(
'data' => $category_content,
'status' => true,
'spec_credit_details' => Plugin::instance()->get_spec_credit_details(),
)
);
}
} else {
$log[ $post_data['category'] ] = $response_data['data'];
update_option( 'ast_block_ai_content_log', $log );
wp_send_json_error(
array(
'data' => 'Failed ' . $response_data['data'],
'status' => false,
)
);
}
} else {
$log[ $post_data['category'] ] = $response_code . ' - Failed';
update_option( 'ast_block_ai_content_log', $log );
wp_send_json_error(
array(
'data' => 'Failed',
'status' => false,
'code' => $response_data['code'],
'error' => $response_data['message'],
)
);
}
}
}
/**
* Save user details
*
* @since 2.0.0
* @return void
*/
public function save_user_details() {
// Verify Nonce.
check_ajax_referer( 'ast-block-templates-ai-content', 'security' );
$keywords = isset( $_POST['image_keyword'] ) ? json_decode( wp_unslash( $_POST['image_keyword'] ), true ) : array(); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
$images = isset( $_POST['images'] ) ? json_decode( wp_unslash( $_POST['images'] ), true ) : array(); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
$social_profiles = isset( $_POST['social_profiles'] ) ? json_decode( wp_unslash( $_POST['social_profiles'] ), true ) : array(); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
$save_only = isset( $_POST['save_only'] ) ? filter_var( $_POST['save_only'], FILTER_VALIDATE_BOOLEAN ) : false;
foreach ( $keywords as $key => $keyword ) {
$keywords[ $key ] = sanitize_text_field( wp_unslash( $keyword ) );
}
if ( ! empty( $images ) ) {
foreach ( $images as $key => $image ) {
foreach ( $image as $j => $image_attr ) {
switch ( $image_attr ) {
case 'author_name':
case 'orientation':
case 'author_url':
case 'description':
case 'engine':
case 'id':
$images[ $key ][ $image_attr ] = sanitize_text_field( wp_unslash( $image_attr ) );
break;
case 'engine_url':
case 'author_url':
case 'optimized_url':
case 'url':
$images[ $key ][ $image_attr ] = esc_url_raw( wp_unslash( $image_attr ) );
break;
}
}
}
}
$language = isset( $_POST['language'] ) ? json_decode( wp_unslash( $_POST['language'] ), true ) : array(); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
$business_details = get_option( 'zipwp_user_business_details', array() );
$business_details['business_name'] = isset( $_POST['business_name'] ) ? sanitize_text_field( wp_unslash( $_POST['business_name'] ) ) : '';
$business_details['business_description'] = isset( $_POST['business_desc'] ) ? sanitize_text_field( wp_unslash( $_POST['business_desc'] ) ) : '';
$business_details['business_category'] = isset( $_POST['business_category'] ) ? sanitize_text_field( wp_unslash( $_POST['business_category'] ) ) : '';
$business_details['images'] = $images;
$business_details['image_keyword'] = $keywords;
$business_details['business_address'] = ( isset( $_POST['business_address'] ) ) ? sanitize_text_field( wp_unslash( $_POST['business_address'] ) ) : '';
$business_details['business_phone'] = ( isset( $_POST['business_phone'] ) ) ? sanitize_text_field( wp_unslash( $_POST['business_phone'] ) ) : '';
$business_details['business_email'] = ( isset( $_POST['business_email'] ) ) ? sanitize_email( wp_unslash( $_POST['business_email'] ) ) : '';
$business_details['social_profiles'] = $social_profiles;
$business_details['language'] = $language;
update_option( 'ast-block-templates-show-onboarding', 'no' );
update_option( 'zipwp_user_business_details', $business_details );
if ( ! $save_only ) {
delete_option( 'ast-templates-ai-content' );
}
// Schedule event to download images in background.
wp_schedule_single_event( time() + 1, 'ast_templates_download_selected_images' );
wp_send_json_success(
array(
'status' => true,
'images' => $images,
)
);
}
/**
* Download Selected Images
*
* @since 2.0.17
*
* @return void
*/
public function download_selected_images() {
$image = get_option( 'zipwp_user_business_details', array() );
$all_images = isset( $image['images'] ) ? $image['images'] : array();
if ( empty( $all_images ) ) {
return;
}
$images = $all_images;
$downloaded_ids = array();
foreach ( $images as $image ) {
$image = array(
'url' => $image['url'],
'id' => $image['id'],
'description' => $image['description'],
'engine' => $image['engine'],
);
$image_id = Images::instance()->download_image( $image );
$downloaded_ids[ $image['id'] ] = $image_id;
}
update_option( 'ast_block_downloaded_images', $downloaded_ids );
}
}

View File

@@ -0,0 +1,466 @@
<?php
/**
* AI content generator and replacer file.
*
* @package {{package}}
* @since {{since}}
*/
namespace Gutenberg_Templates\Inc\Importer;
use Gutenberg_Templates\Inc\Traits\Instance;
use Gutenberg_Templates\Inc\Traits\Helper;
use Gutenberg_Templates\Inc\Importer\Importer_Helper;
use Gutenberg_Templates\Inc\Importer\Images;
/**
* Block Editor Blocks Replacer
*
* @since {{since}}
*/
class BlockEditor {
use Instance;
/**
* Constructor
*
* @since {{since}}
*/
public function __construct() {}
/**
* Old Images
*
* @var array<int> $old_images Old images.
*/
public static $old_images = array();
/**
* Parses images and other content in the Spectra Container block.
*
* @since {{since}}
* @param array<mixed> $block Block.
* @return array<mixed> $block Block.
*/
public function parse_spectra_container( $block ) {
if (
! isset( $block['attrs']['backgroundImageDesktop'] ) ||
empty( $block['attrs']['backgroundImageDesktop'] ) ||
Importer_Helper::is_skipable( $block['attrs']['backgroundImageDesktop']['url'] )
) {
return $block;
}
$image = Images::instance()->get_image( Images::$image_index );
if ( empty( $image ) || ! is_array( $image ) ) {
return $block;
}
$image = Images::instance()->download_image( $image );
if ( is_wp_error( $image ) ) {
Helper::instance()->ast_block_templates_log( 'Replacing Image problem : ' . $block['attrs']['backgroundImageDesktop']['url'] . ' Warning: ' . wp_json_encode( $image ) );
return $block;
}
$attachment = wp_prepare_attachment_for_js( absint( $image ) );
if ( ! is_array( $attachment ) ) {
return $block;
}
self::$old_images[] = $block['attrs']['backgroundImageDesktop']['id'];
Helper::instance()->ast_block_templates_log( 'Replacing Image from ' . $block['attrs']['backgroundImageDesktop']['url'] . 'to "' . $attachment['url'] . '" for ' . $block['blockName'] . '" with index "' . Images::$image_index . '"' );
$block['attrs']['backgroundImageDesktop'] = $attachment;
Images::$image_index++;
return $block;
}
/**
* Parses images and other content in the Spectra Info Box block.
*
* @since {{since}}
* @param array<mixed> $block Block.
* @return array<mixed> $block Block.
*/
public function parse_spectra_infobox( $block ) {
if (
! isset( $block['attrs']['iconImage'] ) ||
empty( $block['attrs']['iconImage'] ) ||
Importer_Helper::is_skipable( $block['attrs']['iconImage']['url'] )
) {
return $block;
}
$image = Images::instance()->get_image( Images::$image_index );
if ( empty( $image ) || ! is_array( $image ) ) {
return $block;
}
$image = Images::instance()->download_image( $image );
if ( is_wp_error( $image ) ) {
Helper::instance()->ast_block_templates_log( 'Replacing Image problem : ' . $block['attrs']['iconImage']['url'] . ' Warning: ' . wp_json_encode( $image ) );
return $block;
}
$attachment = wp_prepare_attachment_for_js( absint( $image ) );
if ( ! is_array( $attachment ) ) {
return $block;
}
self::$old_images[] = $block['attrs']['iconImage']['id'];
if ( ! empty( $block['attrs']['iconImage']['url'] ) ) {
Helper::instance()->ast_block_templates_log( 'Replacing Image from ' . $block['attrs']['iconImage']['url'] . ' to "' . $attachment['url'] . '" for ' . $block['blockName'] . '" with index "' . Images::$image_index . '"' );
$block['innerHTML'] = str_replace( $block['attrs']['iconImage']['url'], $attachment['url'], $block['innerHTML'] );
}
foreach ( $block['innerContent'] as $key => &$inner_content ) {
if ( is_string( $block['innerContent'][ $key ] ) && '' === trim( $block['innerContent'][ $key ] ) ) {
continue;
}
$block['innerContent'][ $key ] = str_replace( $block['attrs']['iconImage']['url'], $attachment['url'], $block['innerContent'][ $key ] );
}
$block['attrs']['iconImage'] = $attachment;
Images::$image_index++;
return $block;
}
/**
* Parses images and other content in the Spectra Image block.
*
* @since {{since}}
* @param array<mixed> $block Block.
* @return array<mixed> $block Block.
*/
public function parse_spectra_image( $block ) {
if (
! isset( $block['attrs']['url'] ) ||
Importer_Helper::is_skipable( $block['attrs']['url'] )
) {
return $block;
}
$image = Images::instance()->get_image( Images::$image_index );
if ( empty( $image ) || ! is_array( $image ) ) {
return $block;
}
$image = Images::instance()->download_image( $image );
if ( is_wp_error( $image ) ) {
Helper::instance()->ast_block_templates_log( 'Replacing Image problem : ' . $block['attrs']['url'] . ' Warning: ' . wp_json_encode( $image ) );
return $block;
}
$attachment = wp_prepare_attachment_for_js( absint( $image ) );
if ( ! is_array( $attachment ) ) {
return $block;
}
self::$old_images[] = $block['attrs']['id'];
Helper::instance()->ast_block_templates_log( 'Replacing Image from ' . $block['attrs']['url'] . ' to "' . $attachment['url'] . '" for ' . $block['blockName'] . '" with index "' . Images::$image_index . '"' );
$block['innerHTML'] = str_replace( $block['attrs']['url'], $attachment['url'], $block['innerHTML'] );
$block['innerHTML'] = str_replace( $block['attrs']['id'], (string) $attachment['id'], $block['innerHTML'] );
$tablet_size_slug = ! empty( $block['attrs']['sizeSlugTablet'] ) ? $block['attrs']['sizeSlugTablet'] : '';
$mobile_size_slug = ! empty( $block['attrs']['sizeSlugMobile'] ) ? $block['attrs']['sizeSlugMobile'] : '';
$is_attachemnts = is_array( $attachment['sizes'] ) && ! empty( $attachment['sizes'] );
if ( ! empty( $block['attrs']['urlTablet'] ) && ! empty( $tablet_size_slug ) && ! empty( $attachment['sizes'][ $tablet_size_slug ]['url'] ) ) {
$block['innerHTML'] = str_replace( $block['attrs']['urlTablet'], $attachment['sizes'][ $tablet_size_slug ]['url'], $block['innerHTML'] );
}
if ( ! empty( $block['attrs']['urlMobile'] && ! empty( $mobile_size_slug ) ) && ! empty( $attachment['sizes'][ $mobile_size_slug ]['url'] ) ) {
$block['innerHTML'] = str_replace( $block['attrs']['urlMobile'], $attachment['sizes'][ $mobile_size_slug ]['url'], $block['innerHTML'] );
}
foreach ( $block['innerContent'] as $key => &$inner_content ) {
if ( is_string( $block['innerContent'][ $key ] ) && '' === trim( $block['innerContent'][ $key ] ) ) {
continue;
}
$block['innerContent'][ $key ] = str_replace( $block['attrs']['url'], $attachment['url'], $block['innerContent'][ $key ] );
$block['innerContent'][ $key ] = str_replace( $block['attrs']['id'], (string) $attachment['id'], $block['innerContent'][ $key ] );
if ( $is_attachemnts ) {
if ( ! empty( $block['attrs']['urlTablet'] ) ) {
$block['innerContent'][ $key ] = str_replace( $block['attrs']['urlTablet'], $attachment['url'], $block['innerContent'][ $key ] );
}
if ( ! empty( $block['attrs']['urlMobile'] ) ) {
$block['innerContent'][ $key ] = str_replace( $block['attrs']['urlMobile'], $attachment['url'], $block['innerContent'][ $key ] );
}
}
}
if ( $is_attachemnts ) {
if ( ! empty( $block['attrs']['urlTablet'] ) ) {
$block['attrs']['urlTablet'] = $attachment['url'];
}
if ( ! empty( $block['attrs']['urlMobile'] ) ) {
$block['attrs']['urlMobile'] = $attachment['url'];
}
}
$block['attrs']['url'] = $attachment['url'];
$block['attrs']['id'] = $attachment['id'];
Images::$image_index++;
return $block;
}
/**
* Parses images and other content in the Spectra Info Box block.
*
* @since {{since}}
* @param array<mixed> $block Block.
* @return array<mixed> $block Block.
*/
public function parse_spectra_gallery( $block ) {
$images = $block['attrs']['mediaGallery'];
$gallery_ids = array();
foreach ( $images as $key => &$image ) {
if (
! isset( $image ) ||
empty( $image ) ||
Importer_Helper::is_skipable( $image['url'] )
) {
continue;
}
$new_image = Images::instance()->get_image( Images::$image_index );
if ( empty( $new_image ) || ! is_array( $new_image ) ) {
continue;
}
$new_image = Images::instance()->download_image( $new_image );
if ( is_wp_error( $new_image ) ) {
Helper::instance()->ast_block_templates_log( 'Replacing Image problem : ' . $image['url'] . ' Warning: ' . wp_json_encode( $new_image ) );
continue;
}
$attachment = wp_prepare_attachment_for_js( absint( $new_image ) );
if ( ! is_array( $attachment ) ) {
continue;
}
$gallery_ids[] = $attachment['id'];
self::$old_images[] = $image['id'];
Helper::instance()->ast_block_templates_log( 'Replacing Image from ' . $image['url'] . ' to "' . $attachment['url'] . '" for ' . $block['blockName'] . '" with index "' . Images::$image_index . '"' );
$image['url'] = ! empty( $attachment['url'] ) ? $attachment['url'] : $image['url'];
$image['sizes'] = ! empty( $attachment['sizes'] ) ? $attachment['sizes'] : $image['sizes'];
$image['mime'] = ! empty( $attachment['mime'] ) ? $attachment['mime'] : $image['mime'];
$image['type'] = ! empty( $attachment['type'] ) ? $attachment['type'] : $image['type'];
$image['subtype'] = ! empty( $attachment['subtype'] ) ? $attachment['subtype'] : $image['subtype'];
$image['id'] = ! empty( $attachment['id'] ) ? $attachment['id'] : $image['id'];
$image['alt'] = ! empty( $attachment['alt'] ) ? $attachment['alt'] : $image['alt'];
$image['link'] = ! empty( $attachment['link'] ) ? $attachment['link'] : $image['link'];
Images::$image_index++;
}
$block['attrs']['mediaGallery'] = $images;
$block['attrs']['mediaIDs'] = $gallery_ids;
return $block;
}
/**
* Parses Google Map for the Spectra Google Map block.
*
* @since {{since}}
* @param array<mixed> $block Block.
* @return array<mixed> $block Block.
*/
public function parse_spectra_google_map( $block ) {
$address = Importer_Helper::get_business_details( 'business_address' );
if ( empty( $address ) ) {
return $block;
}
Helper::instance()->ast_block_templates_log( 'Replacing Google Map from ' . $block['attrs']['address'] . ' to "' . wp_json_encode( $address ) );
$block['attrs']['address'] = $address;
return $block;
}
/**
* Parses images and other content in the Spectra Info Box block.
*
* @since {{since}}
* @param \WP_Post $post Post.
* @return void
*/
public function parse_featured_image( $post ) {
$thumb_id = get_post_thumbnail_id( $post );
if ( false === $thumb_id ) {
return;
}
$thumb = wp_prepare_attachment_for_js( $thumb_id );
if (
! isset( $thumb['url'] ) ||
Importer_Helper::is_skipable( $thumb['url'] )
) {
return;
}
$image = Images::instance()->get_image( Images::$image_index );
if ( empty( $image ) || ! is_array( $image ) ) {
return;
}
$image = Images::instance()->download_image( $image );
if ( is_wp_error( $image ) ) {
Helper::instance()->ast_block_templates_log( 'Replacing Image problem : ' . $thumb['url'] . ' Warning: ' . wp_json_encode( $image ) );
return;
}
$attachment = wp_prepare_attachment_for_js( absint( $image ) );
if ( ! is_array( $attachment ) ) {
return;
}
self::$old_images[] = $thumb['id'];
Helper::instance()->ast_block_templates_log( 'Replacing Image from ' . $thumb['url'] . ' to "' . $attachment['url'] . '" with index "' . Images::$image_index . '"' );
set_post_thumbnail( $post, $attachment['id'] );
Images::$image_index++;
}
/**
* Parses address and contct in the block.
*
* @since {{since}}
* @param string $key key to replace.
* @param string $ai_content ai content string.
*
* @return string
*/
public function replace_contact_details( $key, $ai_content ) {
$business_details = Importer_Helper::get_business_details();
$social_profiles = $business_details['social_profiles'];
if ( ! is_array( $social_profiles ) ) {
return $ai_content;
}
$social_icons = array_combine( array_column( $social_profiles, 'type' ), array_column( $social_profiles, 'url' ) );
switch ( $key ) {
case '2360 Hood Avenue, San Diego, CA, 92123':
$ai_content = $business_details['business_address'];
break;
case '202-555-0188':
$ai_content = $business_details['business_phone'];
break;
case 'contact@example.com':
$ai_content = $business_details['business_email'];
break;
case '#facebook':
case '#twitter':
case '#linkenin':
case '#instagram':
case '#youtube':
$ai_content = $social_icons[ str_replace( '#', '', $key ) ];
break;
}
return $ai_content;
}
/**
* Parses Spectra form block.
*
* @since {{since}}
* @param array<mixed> $block Block.
* @return array<mixed> $block Block.
*/
public function parse_spectra_form( $block ) {
$business_email = Importer_Helper::get_business_details( 'business_email' );
if ( ! empty( $business_email ) ) {
$block['attrs']['afterSubmitToEmail'] = $business_email;
}
return $block;
}
/**
* Parse social icon list.
*
* @since {{since}}
* @param array<mixed> $block Block.
* @return array<mixed> $block Block.
*/
public function parse_spectra_social_icons( $block ) {
$social_profile = Importer_Helper::get_business_details( 'social_profiles' );
if ( empty( $social_profile ) ) {
return $block;
}
$social_icons = array_combine( array_column( $social_profile, 'id' ), array_column( $social_profile, 'url' ) );
$inner_blocks = $block['innerBlocks'];
if ( is_array( $inner_blocks ) ) {
$social_icons_list = array_map(
function( $item ) {
return $item['attrs']['icon'];
},
$inner_blocks
);
// Check if icon-list contains social icons by checking facebook icon in list.
if ( ! in_array( 'facebook', $social_icons_list, true ) ) {
return $block;
}
foreach ( $inner_blocks as $index => &$inner_block ) {
if ( 'uagb/icon-list-child' !== $inner_block['blockName'] ) {
continue;
}
$icon = $inner_block['attrs']['icon'];
if ( empty( $icon ) ) {
continue;
}
if ( in_array( $icon, array_keys( $social_icons ), true ) ) {
$block['innerBlocks'][ $index ]['attrs']['link'] = $social_icons[ $icon ];
}
if ( ! in_array( $icon, array_keys( $social_icons ), true ) ) {
unset( $block['innerBlocks'][ $index ] );
}
}
$block['innerBlocks'] = array_values( $block['innerBlocks'] );
}
return $block;
}
}

View File

@@ -0,0 +1,253 @@
<?php
/**
* Image Importer
*
* => How to use?
*
* $image = array(
* 'url' => '<image-url>',
* 'id' => '<image-id>',
* );
*
* $downloaded_image = Image_Importer::get_instance()->import( $image );
*
* @package Ast Block Templates
* @since 1.0.0
*/
namespace Gutenberg_Templates\Inc\Importer;
use Gutenberg_Templates\Inc\Traits\Instance;
use Gutenberg_Templates\Inc\Traits\Helper;
/**
* Ast_Block Templates Image Importer
*
* @since 1.0.0
*/
class Image_Importer {
use Instance;
/**
* Images IDs
*
* @var array<int, int> The Array of already image IDs.
* @since 1.0.0
*/
private $already_imported_ids = array();
/**
* Constructor
*
* @since 1.0.0
*/
public function __construct() {
if ( ! function_exists( 'WP_Filesystem' ) ) {
require_once ABSPATH . 'wp-admin/includes/file.php';
}
WP_Filesystem();
}
/**
* Process Image Download
*
* @since 1.0.0
* @param array<int, mixed> $attachments Attachment array.
* @return array<int, mixed> Attachment array.
*/
public function process( $attachments ) {
$downloaded_images = array();
foreach ( $attachments as $key => $attachment ) {
$downloaded_images[] = $this->import( $attachment );
}
return $downloaded_images;
}
/**
* Get Hash Image.
*
* @since 1.0.0
* @param string $attachment_url Attachment URL.
* @return string Hash string.
*/
public function get_hash_image( $attachment_url ) {
return sha1( $attachment_url );
}
/**
* Get Already Imported IDs
*
* @return array<int>
* This function to is to suppress phpstan warnings
* since this parameter is not being used
*/
public function get_already_imported_ids() {
return $this->already_imported_ids;
}
/**
* Get Saved Image.
*
* @since 1.0.0
* @param array<string, mixed> $attachment Attachment Data.
* @return array<string, mixed> Hash string.
*/
private function get_saved_image( $attachment ) {
if ( apply_filters( 'ast_block_templates_image_importer_skip_image', false, $attachment ) ) {
Helper::instance()->ast_block_templates_log( 'BATCH - SKIP Image - {from filter} - ' . $attachment['url'] . ' - Filter name `ast_block_templates_image_importer_skip_image`.' );
return array(
'status' => true,
'attachment' => $attachment,
);
}
global $wpdb;
// 1. Is already imported in Batch Import Process?
$post_id = $wpdb->get_var( $wpdb->prepare( 'SELECT `post_id` FROM `' . $wpdb->postmeta . '` WHERE `meta_key` = \'_ast_block_templates_image_hash\' AND `meta_value` = %s;', $this->get_hash_image( $attachment['url'] ) ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
// 2. Is image already imported though XML?
if ( empty( $post_id ) ) {
// Get file name without extension.
// To check it exist in attachment.
$filename = basename( $attachment['url'] );
$post_id = $wpdb->get_var( $wpdb->prepare( "SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = '_wp_attached_file' AND meta_value LIKE %s", '%/' . $filename . '%' ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
Helper::instance()->ast_block_templates_log( 'BATCH - SKIP Image {already imported from xml} - ' . $attachment['url'] );
}
if ( $post_id ) {
$new_attachment = array(
'id' => $post_id,
'url' => wp_get_attachment_url( $post_id ),
);
$this->already_imported_ids[] = $post_id;
return array(
'status' => true,
'attachment' => $new_attachment,
);
}
return array(
'status' => false,
'attachment' => $attachment,
);
}
/**
* Import Image
*
* @since 1.0.0
* @param array<string, mixed> $attachment Attachment array.
* @return array<string, mixed> Attachment array.,
*/
public function import( $attachment ) {
Helper::instance()->ast_block_templates_log( 'Source - ' . $attachment['url'] );
$saved_image = $this->get_saved_image( $attachment );
Helper::instance()->ast_block_templates_log( 'Log - ' . wp_json_encode( $saved_image['attachment'] ) );
if ( $saved_image['status'] ) {
return $saved_image['attachment'];
}
// Extract the file name and extension from the URL.
$filename = basename( $attachment['url'] );
if ( isset( $attachment['engine'] ) && 'unsplash' === $attachment['engine'] ) {
$filename = 'unsplash-photo-' . $attachment['id'] . '.jpg';
}
$file_content = wp_remote_retrieve_body(
wp_safe_remote_get(
$attachment['url'],
array(
'timeout' => 60,
)
)
);
// Empty file content?
if ( empty( $file_content ) ) {
Helper::instance()->ast_block_templates_log( 'BATCH - FAIL Image {Error: Failed wp_remote_retrieve_body} - ' . $attachment['url'] );
return $attachment;
}
$upload = wp_upload_bits( $filename, null, $file_content );
$upload_json = wp_json_encode( $upload );
if ( is_string( $upload_json ) ) {
Helper::instance()->ast_block_templates_log( $upload_json );
} else {
Helper::instance()->ast_block_templates_log( "Failed to log: {$filename}" );
}
$post = array(
'post_title' => $filename,
'guid' => $upload['url'],
);
$post_json = wp_json_encode( $post );
if ( is_string( $post_json ) ) {
Helper::instance()->ast_block_templates_log( $post_json );
} else {
Helper::instance()->ast_block_templates_log( "Failed to log post data: {$filename}" );
}
$info = wp_check_filetype( $upload['file'] );
if ( is_array( $info ) ) {
$post['post_mime_type'] = $info['type'];
}
if ( ! function_exists( 'wp_generate_attachment_metadata' ) ) {
include ABSPATH . 'wp-admin/includes/image.php';
}
$post_id = wp_insert_attachment( $post, $upload['file'] );
wp_update_attachment_metadata(
$post_id,
wp_generate_attachment_metadata( $post_id, $upload['file'] )
);
update_post_meta( $post_id, '_ast_block_templates_image_hash', $this->get_hash_image( $attachment['url'] ) );
$new_attachment = array(
'id' => $post_id,
'url' => $upload['url'],
);
Helper::instance()->ast_block_templates_log( 'BATCH - SUCCESS Image {Imported} - ' . $new_attachment['url'] );
$this->already_imported_ids[] = $post_id;
return $new_attachment;
}
/**
* Is Image URL
*
* @since 1.0.0
*
* @param string $url URL.
* @return boolean
*/
public function is_image_url( $url = '' ) {
if ( empty( $url ) ) {
return false;
}
if ( Helper::instance()->ast_block_templates_is_valid_image( $url ) ) {
return true;
}
return false;
}
}

View File

@@ -0,0 +1,144 @@
<?php
/**
* AI content generator and Images file.
*
* @package {{package}}
* @since {{since}}
*/
namespace Gutenberg_Templates\Inc\Importer;
use Gutenberg_Templates\Inc\Traits\Instance;
use Gutenberg_Templates\Inc\Traits\Helper;
use Gutenberg_Templates\Inc\Importer\Importer_Helper;
/**
* Images
*
* @since {{since}}
*/
class Images {
use Instance;
/**
* Images
*
* @since {{since}}
* @var array<string, array<mixed>> $images
*/
public static $images = array(
'landscape' => array(),
'portrait' => array(),
'square' => array(),
);
/**
* Image index
*
* @since {{since}}
* @var (int) image_index
*/
public static $image_index = 0;
/**
* Get Images
*
* @return array<string|int, mixed> Array of images.
* @since {{since}}
*/
public function get_images() {
return Importer_Helper::get_business_details( 'images' );
}
/**
* Get Image for the specified index and orientation
*
* @param int $index Index of the image.
* @return array<int, mixed>|boolean Array of images or false.
* @since {{since}}
*/
public function get_image( $index = 0 ) {
$images = $this->get_images();
Helper::instance()->ast_block_templates_log( 'Fetching image with index ' . $index );
return ( isset( $images[ $index ] ) ) ? $images[ $index ] : false;
}
/**
* Download image from URL.
*
* @param array<int|string, mixed> $image Image data.
* @return int|\WP_Error Image ID or WP_Error.
* @since {{since}}
*/
public function download_image( $image ) {
$id = isset( $image['id'] ) ? $image['id'] : 0;
$downloaded_ids = get_option( 'ast_block_downloaded_images', array() );
$downloaded_ids = ( is_array( $downloaded_ids ) ) ? $downloaded_ids : array();
if ( array_key_exists( $id, $downloaded_ids ) ) {
// Return already downloaded image.
return $downloaded_ids[ $id ];
}
/* This is a Pixabay code $name = $image['tags']; Pixabay. */
$name = 'zipwp-image-' . sanitize_title( $id );
/* This is a Pixabay code $url = $image['largeImageURL']; Pixabay. */
$url = $image['url']; // Unsplash.
$description = isset( $image['description'] ) ? $image['description'] : '';
$name = preg_replace( '/\.[^.]+$/', '', $name ) . '.jpg';
Helper::instance()->ast_block_templates_log( 'Downloading Image as "' . $name . '" : ' . $url );
$wp_id = $this->create_image_from_url( $url, $name, $id, $description );
$downloaded_ids[ $id ] = $wp_id;
update_option( 'ast_block_downloaded_images', $downloaded_ids );
return $wp_id;
}
/**
* Create the image and return the new media upload id.
*
* @param String $url URL to the image.
* @param String $name Name to the image.
* @param String $photo_id Photo ID to the image.
* @param String $description Description to the image.
* @return mixed
* @see http://codex.wordpress.org/Function_Reference/wp_insert_attachment#Example
*/
public function create_image_from_url( $url, $name, $photo_id, $description ) {
require_once ABSPATH . 'wp-admin/includes/media.php';
require_once ABSPATH . 'wp-admin/includes/file.php';
require_once ABSPATH . 'wp-admin/includes/image.php';
$file_array = array();
$file_array['name'] = wp_basename( $name );
// Download file to temp location.
$file_array['tmp_name'] = download_url( $url );
// If error storing temporarily, return the error.
if ( is_wp_error( $file_array['tmp_name'] ) ) {
return $file_array;
}
// Do the validation and storage stuff.
$id = media_handle_sideload( $file_array, 0, null );
// If error storing permanently, unlink.
if ( is_wp_error( $id ) ) {
@unlink( $file_array['tmp_name'] ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged, WordPressVIPMinimum.Functions.RestrictedFunctions.file_ops_unlink -- Deleting the file from temp location.
return $id;
}
$alt = ( '' === $description ) ? $name : $description;
// Store the original attachment source in meta.
add_post_meta( $id, '_source_url', $url );
update_post_meta( $id, '_wp_attachment_image_alt', $alt );
return $id;
}
}

View File

@@ -0,0 +1,151 @@
<?php
/**
* Import Helper.
*
* @package {{package}}
* @since {{since}}
*/
namespace Gutenberg_Templates\Inc\Importer;
use Gutenberg_Templates\Inc\Traits\Helper;
use WP_Query;
/**
* Importer Helper
*
* @since {{since}}
*/
class Importer_Helper {
/**
* Get pages.
*
* @return array<int|\WP_Post> Array for pages.
* @param string $type Post type.
* @since {{since}}
*/
public static function get_pages( $type = 'page' ) {
$query_args = array(
'post_type' => array( $type ),
// Query performance optimization.
'fields' => array( 'ids', 'post_content', 'post_title' ),
'posts_per_page' => '10',
'post_status' => 'publish',
'ignore_sticky_posts' => true,
'no_found_rows' => true,
);
$query = new WP_Query( $query_args );
$desired_first_page_id = intval( get_option( 'page_on_front', 0 ) );
$pages = $query->posts ? $query->posts : array();
$desired_page_index = false;
if ( is_array( $pages ) && ! empty( $pages ) && ! empty( $desired_first_page_id ) ) {
foreach ( $pages as $key => $page ) {
if ( isset( $page->ID ) && $page->ID === $desired_first_page_id ) {
$desired_page_index = $key;
break;
}
}
if ( false !== $desired_page_index ) {
$desired_page = $pages[ $desired_page_index ];
unset( $pages[ $desired_page_index ] );
array_unshift( $pages, $desired_page );
}
}
return $pages;
}
/**
* Get Business details.
*
* @since {{since}}
* @param string $key options name.
* @return array<string, mixed> Array for business details or single detail in a string.
*/
public static function get_business_details( $key = '' ) {
$details = get_option(
'zipwp_user_business_details',
array(
'business_name' => '',
'business_address' => '',
'business_phone' => '',
'business_category' => '',
'business_email' => '',
'social_profiles' => array(),
'business_description' => '',
'token' => '',
'images' => array(),
'image_keyword' => array(),
'templates' => array(),
'language' => 'en',
)
);
$details = array(
'business_name' => ( ! empty( $details['business_name'] ) ) ? $details['business_name'] : '',
'business_address' => ( ! empty( $details['business_address'] ) ) ? $details['business_address'] : '2360 Hood Avenue, San Diego, CA, 92123',
'business_phone' => ( ! empty( $details['business_phone'] ) ) ? $details['business_phone'] : '202-555-0188',
'business_category' => ( ! empty( $details['business_category'] ) ) ? $details['business_category'] : '',
'business_email' => ( ! empty( $details['business_email'] ) ) ? $details['business_email'] : 'contact@example.com',
'social_profiles' => ( ! empty( $details['social_profiles'] ) ) ? $details['social_profiles'] : array(),
'business_description' => ( ! empty( $details['business_description'] ) ) ? $details['business_description'] : '',
'token' => Helper::get_decrypted_auth_token(),
'images' => ( ! empty( $details['images'] ) ) ? $details['images'] : array(),
'image_keyword' => ( ! empty( $details['image_keyword'] ) ) ? $details['image_keyword'] : array(),
'templates' => ( ! empty( $details['templates'] ) ) ? $details['templates'] : array(),
'language' => ( ! empty( $details['language'] ) ) ? $details['language'] : '',
);
if ( ! empty( $key ) ) {
return isset( $details[ $key ] ) ? $details[ $key ] : array();
}
return $details;
}
/**
* Check if we need to skip the URL.
*
* @param string $url URL to check.
* @return boolean
* @since {{since}}
*/
public static function is_skipable( $url ) {
if ( strpos( $url, 'skip' ) !== false ) {
return true;
}
return false;
}
/**
* Get image orientation of the specified image.
*
* @param string $url Image URL.
* @return string Image orientation.
* @since {{since}}
*/
public static function get_image_orientation( $url ): string {
// Use `@` to suppress warnings from `getimagesize` if the file is not valid or accessible.
$size = getimagesize( $url );
if ( $size && is_array( $size ) ) {
list( $width, $height ) = $size;
// Determine orientation based on width and height.
if ( $width > $height ) {
return 'landscape';
} else {
return 'portrait';
}
} else {
return 'landscape';
}
}
}

View File

@@ -0,0 +1,68 @@
<?php
/**
* WP CLI
*
* 1. Run `wp ast-block-templates sync` Info.
*
* @since 1.0.0
*
* @package ast-block-templates
*/
namespace Gutenberg_Templates\Inc\Importer;
use Gutenberg_Templates\Inc\Importer\Sync_Library;
use Gutenberg_Templates\Inc\Traits\Helper;
use Gutenberg_Templates\Inc\Traits\Instance;
use WP_CLI;
use WP_CLI_Command;
/**
* Ast_Block Templates WP CLI
*/
class Sync_Library_WP_CLI {
use Instance;
/**
* Sync
*
* Example: wp ast-block-templates sync
*
* @since 1.0.0
* @param array<string, string|int> $args Arguments with specific value types.
* @param array<string, mixed> $assoc_args Associated Arguments.
* @return void
*/
public function sync( $args = array(), $assoc_args = array() ) {
// Start Sync.
if ( Helper::instance()->ast_block_templates_doing_wp_cli() ) {
WP_CLI::line( 'Sync Started' );
}
$force = isset( $assoc_args['force'] ) ? true : false;
$result_data = Sync_Library::instance()->check_checksum_and_get_blocks_data();
if ( empty( $result_data ) && Helper::instance()->ast_block_templates_doing_wp_cli() && ! $force ) {
WP_CLI::line( 'Blocks are up to date.' );
return;
}
Sync_Library::instance()->process_data_sync( $result_data );
Sync_Library::instance()->update_latest_checksums( $result_data['checksum'] );
Sync_Library::instance()->get_server_astra_customizer_css();
// Start Sync.
if ( Helper::instance()->ast_block_templates_doing_wp_cli() ) {
WP_CLI::line( 'Sync Completed' );
}
}
}
/**
* Add Command
*/
if ( Helper::instance()->ast_block_templates_doing_wp_cli() ) {
WP_CLI::add_command( 'ast-block-templates', 'Gutenberg_Templates\Inc\Importer\Sync_Library_WP_CLI' );
}

Some files were not shown because too many files have changed in this diff Show More