initial
This commit is contained in:
+115
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
/**
|
||||
* Service provider for async (background) processors.
|
||||
*
|
||||
* @package Gravity_Forms\Gravity_Forms
|
||||
*/
|
||||
|
||||
namespace Gravity_Forms\Gravity_Forms\Async;
|
||||
|
||||
use Gravity_Forms\Gravity_Forms\GF_Service_Container;
|
||||
use Gravity_Forms\Gravity_Forms\GF_Service_Provider;
|
||||
use Gravity_Forms\Gravity_Forms\Telemetry\GF_Telemetry_Processor;
|
||||
use Gravity_Forms\Gravity_Forms\Bulk_Actions\GF_Entry_Bulk_Action_Processor;
|
||||
use Gravity_Forms\Gravity_Forms\Bulk_Actions\Endpoints\GF_Bulk_Action_Endpoint_Start;
|
||||
use Gravity_Forms\Gravity_Forms\Bulk_Actions\Endpoints\GF_Bulk_Action_Endpoint_Status;
|
||||
use Gravity_Forms\Gravity_Forms\Bulk_Actions\Endpoints\GF_Bulk_Action_Endpoint_Cancel;
|
||||
use GFForms;
|
||||
use GF_Background_Upgrader;
|
||||
use GF_Feed_Processor;
|
||||
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
/**
|
||||
* Class GF_Background_Processing_Service_Provider
|
||||
*
|
||||
* @since 2.6.9
|
||||
*/
|
||||
class GF_Background_Process_Service_Provider extends GF_Service_Provider {
|
||||
|
||||
const UPGRADER = 'upgrade_processor';
|
||||
const FEEDS = 'feeds_processor';
|
||||
const NOTIFICATIONS = 'notifications_processor';
|
||||
const TELEMETRY = 'telemetry_processor';
|
||||
const BULK_ACTION = 'bulk_action_processor';
|
||||
const BULK_ACTION_ENDPOINT_START = 'bulk_action_endpoint_start';
|
||||
const BULK_ACTION_ENDPOINT_STATUS = 'bulk_action_endpoint_status';
|
||||
const BULK_ACTION_ENDPOINT_CANCEL = 'bulk_action_endpoint_cancel';
|
||||
|
||||
/**
|
||||
* The names and classes of the async (background) processors.
|
||||
*
|
||||
* @since 2.6.9
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $processors = array(
|
||||
self::UPGRADER => GF_Background_Upgrader::class,
|
||||
self::FEEDS => GF_Feed_Processor::class,
|
||||
self::NOTIFICATIONS => GF_Notifications_Processor::class,
|
||||
self::TELEMETRY => GF_Telemetry_Processor::class,
|
||||
self::BULK_ACTION => GF_Entry_Bulk_Action_Processor::class,
|
||||
);
|
||||
|
||||
/**
|
||||
* Initializing the processors and adding them to the container as services.
|
||||
*
|
||||
* @since 2.6.9
|
||||
*
|
||||
* @param GF_Service_Container $container
|
||||
*/
|
||||
public function register( GF_Service_Container $container ) {
|
||||
GFForms::init_background_upgrader();
|
||||
require_once GF_PLUGIN_DIR_PATH . 'includes/addon/class-gf-feed-processor.php';
|
||||
require_once GF_PLUGIN_DIR_PATH . 'includes/async/class-gf-notifications-processor.php';
|
||||
require_once GF_PLUGIN_DIR_PATH . 'includes/telemetry/class-gf-telemetry-processor.php';
|
||||
require_once GF_PLUGIN_DIR_PATH . 'includes/bulk-actions/class-gf-entry-bulk-action-processor.php';
|
||||
require_once GF_PLUGIN_DIR_PATH . 'includes/bulk-actions/endpoints/class-gf-bulk-action-endpoint-start.php';
|
||||
require_once GF_PLUGIN_DIR_PATH . 'includes/bulk-actions/endpoints/class-gf-bulk-action-endpoint-status.php';
|
||||
require_once GF_PLUGIN_DIR_PATH . 'includes/bulk-actions/endpoints/class-gf-bulk-action-endpoint-cancel.php';
|
||||
|
||||
foreach ( $this->processors as $name => $class ) {
|
||||
$container->add( $name, function () use ( $name, $class ) {
|
||||
if ( $name === self::UPGRADER ) {
|
||||
return GFForms::$background_upgrader;
|
||||
}
|
||||
|
||||
$callback = array( $class, 'get_instance' );
|
||||
if ( is_callable( $callback ) ) {
|
||||
return call_user_func( $callback );
|
||||
}
|
||||
|
||||
return new $class();
|
||||
} );
|
||||
}
|
||||
|
||||
$container->add( self::BULK_ACTION_ENDPOINT_START, function() {
|
||||
return new GF_Bulk_Action_Endpoint_Start();
|
||||
} );
|
||||
|
||||
$container->add( self::BULK_ACTION_ENDPOINT_STATUS, function() {
|
||||
return new GF_Bulk_Action_Endpoint_Status();
|
||||
} );
|
||||
|
||||
$container->add( self::BULK_ACTION_ENDPOINT_CANCEL, function() {
|
||||
return new GF_Bulk_Action_Endpoint_Cancel();
|
||||
} );
|
||||
}
|
||||
|
||||
public function init( GF_Service_Container $container ) {
|
||||
add_action( 'wp_ajax_' . GF_Bulk_Action_Endpoint_Start::ACTION_NAME, function() use ( $container ) {
|
||||
$container->get( self::BULK_ACTION_ENDPOINT_START )->handle();
|
||||
} );
|
||||
|
||||
add_action( 'wp_ajax_' . GF_Bulk_Action_Endpoint_Status::ACTION_NAME, function() use ( $container ) {
|
||||
$container->get( self::BULK_ACTION_ENDPOINT_STATUS )->handle();
|
||||
} );
|
||||
|
||||
add_action( 'wp_ajax_' . GF_Bulk_Action_Endpoint_Cancel::ACTION_NAME, function() use ( $container ) {
|
||||
$container->get( self::BULK_ACTION_ENDPOINT_CANCEL )->handle();
|
||||
} );
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,160 @@
|
||||
<?php
|
||||
|
||||
namespace Gravity_Forms\Gravity_Forms\Async;
|
||||
|
||||
use GFCommon;
|
||||
use GFAPI;
|
||||
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'Gravity_Forms\Gravity_Forms\Async\GF_Background_Process' ) ) {
|
||||
require_once GF_PLUGIN_DIR_PATH . 'includes/async/class-gf-background-process.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* GF_Notifications_Processor Class.
|
||||
*
|
||||
* @since 2.6.9
|
||||
*/
|
||||
class GF_Notifications_Processor extends GF_Background_Process {
|
||||
|
||||
/**
|
||||
* The action name.
|
||||
*
|
||||
* @since 2.6.9
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $action = 'gf_notifications_processor';
|
||||
|
||||
/**
|
||||
* Indicates if the task uses an array that supports the attempts key.
|
||||
*
|
||||
* @since 2.9.9
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $supports_attempts = true;
|
||||
|
||||
/**
|
||||
* Processes the task.
|
||||
*
|
||||
* @since 2.6.9
|
||||
*
|
||||
* @param array $item The task arguments.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function task( $item ) {
|
||||
$key = isset( $item['notification'] ) ? 'notification' : 'notifications';
|
||||
$notification_or_ids = rgar( $item, $key );
|
||||
if ( empty( $notification_or_ids ) || ! is_array( $notification_or_ids ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! empty( $item['entry'] ) ) {
|
||||
$entry = $item['entry'];
|
||||
} else {
|
||||
$entry = GFAPI::get_entry( rgar( $item, 'entry_id' ) );
|
||||
if ( is_wp_error( $entry ) ) {
|
||||
GFCommon::log_debug( __METHOD__ . sprintf( '(): Aborting; Entry #%d not found.', rgar( $item, 'entry_id' ) ) );
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$form = GFAPI::get_form( rgar( $item, 'form_id' ) );
|
||||
if ( empty( $form ) ) {
|
||||
GFCommon::log_debug( __METHOD__ . sprintf( '(): Aborting; Form #%d not found.', rgar( $item, 'form_id' ) ) );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$form = $this->filter_form( $form, $entry );
|
||||
$event = rgar( $item, 'event', 'form_submission' );
|
||||
$data = rgar( $item, 'data' );
|
||||
if ( ! is_array( $data ) ) {
|
||||
$data = array();
|
||||
}
|
||||
|
||||
if ( $key === 'notification' ) {
|
||||
$notifications = array( rgar( $notification_or_ids, 'id', 'custom' ) );
|
||||
} else {
|
||||
$notifications = $notification_or_ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows custom actions to be performed before notifications are sent asynchronously.
|
||||
*
|
||||
* @since 2.7.1
|
||||
*
|
||||
* @param string $event The event being processed.
|
||||
* @param array $notifications An array containing the IDs of the notifications being processed.
|
||||
* @param array $form The form being processed.
|
||||
* @param array $entry The entry being processed.
|
||||
* @param array $data An array of data which can be used in the notifications via the generic {object:property} merge tag. Defaults to empty array.
|
||||
*/
|
||||
do_action( 'gform_pre_process_async_notifications', $event, $notifications, $form, $entry, $data );
|
||||
|
||||
if ( $key === 'notification' ) {
|
||||
GFCommon::send_notification( $notification_or_ids, $form, $entry, $data );
|
||||
} else {
|
||||
GFCommon::send_notifications( $notifications, $form, $entry, true, $event, $data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows custom actions to be performed after notifications are sent asynchronously.
|
||||
*
|
||||
* @since 2.7.1
|
||||
*
|
||||
* @param string $event The event being processed.
|
||||
* @param array $notifications An array containing the IDs of the notifications being processed.
|
||||
* @param array $form The form being processed.
|
||||
* @param array $entry The entry being processed.
|
||||
* @param array $data An array of data which can be used in the notifications via the generic {object:property} merge tag. Defaults to empty array.
|
||||
*/
|
||||
do_action( 'gform_post_process_async_notifications', $event, $notifications, $form, $entry, $data );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if async (background) processing of notifications is enabled.
|
||||
*
|
||||
* @since 2.7.1
|
||||
* @since 2.10.0 Background notifications enabled by default for new installs.
|
||||
*
|
||||
* @param array $notifications An array containing the IDs of the notifications to be sent.
|
||||
* @param array $form The form being processed.
|
||||
* @param array $entry The entry being processed.
|
||||
* @param string $event The event being processed.
|
||||
* @param array $data An array of data which can be used in the notifications via the generic {object:property} merge tag. Defaults to empty array.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_enabled( $notifications, $form, $entry, $event = 'form_submission', $data = array() ) {
|
||||
$form_id = absint( rgar( $form, 'id' ) );
|
||||
$is_enabled = (bool) get_option( 'gform_enable_async_notifications' );
|
||||
|
||||
/**
|
||||
* Allows async (background) processing of notifications to be enabled or disabled.
|
||||
*
|
||||
* @since 2.6.9
|
||||
* @since 2.10.0 Updated to use the gform_enable_async_notifications option value as the default.
|
||||
*
|
||||
* @param bool $is_enabled Is async (background) processing of notifications enabled? Defaults to the value of the gform_enable_async_notifications option.
|
||||
* @param string $event The event the notifications are to be sent for.
|
||||
* @param array $notifications An array containing the IDs of the notifications to be sent.
|
||||
* @param array $form The form currently being processed.
|
||||
* @param array $entry The entry currently being processed.
|
||||
* @param array $data An array of data which can be used in the notifications via the generic {object:property} merge tag. Defaults to empty array.
|
||||
*/
|
||||
return gf_apply_filters( array(
|
||||
'gform_is_asynchronous_notifications_enabled',
|
||||
$form_id,
|
||||
), $is_enabled, $event, $notifications, $form, $entry, $data );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
<?php
|
||||
/**
|
||||
* WP Async Request
|
||||
*
|
||||
* @package WP-Background-Processing
|
||||
*/
|
||||
|
||||
namespace Gravity_Forms\Gravity_Forms\Async;
|
||||
|
||||
/**
|
||||
* Abstract WP_Async_Request class.
|
||||
*
|
||||
* @since 2.2
|
||||
* @since 2.9.8 Namespaced.
|
||||
*
|
||||
* @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' ) ); // @phpstan-ignore-line
|
||||
add_action( 'wp_ajax_nopriv_' . $this->identifier, array( $this, 'maybe_handle' ) ); // @phpstan-ignore-line
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
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 query arguments used during an async request.
|
||||
*
|
||||
* @since 2.9.7
|
||||
*
|
||||
* @param array $args
|
||||
*/
|
||||
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 query URL used during an async request.
|
||||
*
|
||||
* @since 2.9.7
|
||||
*
|
||||
* @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,
|
||||
'blocking' => false,
|
||||
'body' => $this->data,
|
||||
'cookies' => $_COOKIE, // Passing cookies ensures request is performed as initiating user.
|
||||
'sslverify' => apply_filters( 'https_local_ssl_verify', false ), // Local requests, fine to pass false.
|
||||
);
|
||||
|
||||
/**
|
||||
* Filters the post arguments used during an async request.
|
||||
*
|
||||
* @since 2.9.7
|
||||
*
|
||||
* @param array $args
|
||||
*/
|
||||
return apply_filters( $this->identifier . '_post_args', $args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Maybe handle
|
||||
*
|
||||
* 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();
|
||||
|
||||
check_ajax_referer( $this->identifier, 'nonce' );
|
||||
|
||||
$this->handle();
|
||||
|
||||
return $this->maybe_wp_die();
|
||||
}
|
||||
|
||||
/**
|
||||
* Should the process exit with wp_die?
|
||||
*
|
||||
* @since 2.9.7
|
||||
*
|
||||
* @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
|
||||
*
|
||||
* Override this method to perform any actions required
|
||||
* during the async request.
|
||||
*/
|
||||
abstract protected function handle();
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user