Skip to content

Commit

Permalink
Fix delaying all actions (fixes #4).
Browse files Browse the repository at this point in the history
  • Loading branch information
rvdsteege committed Jan 25, 2022
1 parent 0ced221 commit 4e92df7
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 58 deletions.
89 changes: 56 additions & 33 deletions src/Extension.php
Expand Up @@ -67,7 +67,8 @@ public function setup() {
\add_filter( 'ninja_forms_field_settings_groups', array( $this, 'register_settings_groups' ) );

// Delayed actions.
\add_filter( 'ninja_forms_submission_actions', array( $this, 'submission_actions' ) );
\add_filter( 'ninja_forms_submission_actions', array( $this, 'submission_actions' ), 10, 3 );
\add_action( 'ninja_forms_before_response', array( $this, 'maybe_update_session_before_response' ), 10, 1 );
}

/**
Expand Down Expand Up @@ -247,12 +248,14 @@ function( $handler ) {
/**
* Maybe delay actions.
*
* @param array $actions Actions.
* @return array
* @param array $actions Actions.
* @param array $form_cache Form cache.
* @param array $form_data Form data.
* @retrun array
*/
public function submission_actions( $actions ) {
public function submission_actions( $actions, $form_cache, $form_data ) {
// Find active 'Collect payment' actions with our gateway.
$collect_payments = array();
$collect_settings = null;

foreach ( $actions as $action ) {
$action_settings = $action['settings'];
Expand All @@ -272,54 +275,74 @@ public function submission_actions( $actions ) {
continue;
}

$collect_payments[] = $action;
$delayed_action_ids = NinjaFormsHelper::get_delayed_action_ids_from_settings( $action['settings'] );

if ( empty( $delayed_action_ids ) ) {
continue;
}

// Set collect payment settings.
// @todo consider conditional logic when getting the 'Collect payment' action.
$collect_settings = $action['settings'];

break;
}

// Check 'Collect Payment' actions.
if ( empty( $collect_payments ) ) {
// Check 'Collect Payment' action with delayed actions.
if ( null === $collect_settings ) {
return $actions;
}

// Get 'Collect payment' to get settings from.
// @todo consider conditional logic when getting the 'Collect payment' action.
$collect_payment = \array_shift( $collect_payments );

$collect_settings = $collect_payment['settings'];
$is_resuming = \defined( 'PRONAMIC_PAY_NINJA_FORMS_RESUME' ) && PRONAMIC_PAY_NINJA_FORMS_RESUME;

foreach ( $actions as &$action ) {
// On resume, activate delayed actions.
if ( \defined( 'PRONAMIC_PAY_NINJA_FORMS_RESUME' ) && PRONAMIC_PAY_NINJA_FORMS_RESUME ) {
if ( \array_key_exists( 'pronamic_pay_delayed', $action ) ) {
$action['settings']['active'] = true;
}
// Update session with data for later processing of delayed actions.
if ( ! $is_resuming ) {
\Ninja_Forms()->session()->set( 'nf_processing_form_cache', $form_cache );
\Ninja_Forms()->session()->set( 'nf_processing_form_data', $form_data );
}

continue;
}
// Update action activation status for delayed actions.
$delayed_action_ids = NinjaFormsHelper::get_delayed_action_ids_from_settings( $collect_settings );

// Check if action is active.
if ( ! $action['settings']['active'] ) {
foreach ( $actions as &$action ) {
// Ignore inactive actions.
if ( 0 === (int) $action['settings']['active'] ) {
continue;
}

$action_id = $action['id'];

// Check if action should be delayed.
if ( ! \array_key_exists( 'pronamic_pay_delayed_action_' . $action_id, $collect_settings ) ) {
if ( ! \in_array( $action['id'], $delayed_action_ids, true ) ) {
continue;
}

$delayed = (int) $collect_settings[ 'pronamic_pay_delayed_action_' . $action_id ];
// Set active status based on whether we're resuming.
$action['settings']['active'] = $is_resuming;
}

if ( 1 !== $delayed ) {
continue;
}
return $actions;
}

$action['settings']['active'] = true;
/**
* Maybe update Ninja Forms session before response.
*
* @param array $data Data.
* @retrun void
*/
public function maybe_update_session_before_response( $data ) {
// Check if there are delayed actions.
if ( false === \Ninja_Forms()->session()->get( 'pronamic_pay_has_delayed_actions' ) ) {
return;
}

$action['pronamic_pay_delayed'] = true;
// Check if resuming, because we don't want to update the session then.
$is_resuming = \defined( 'PRONAMIC_PAY_NINJA_FORMS_RESUME' ) && PRONAMIC_PAY_NINJA_FORMS_RESUME;

if ( $is_resuming ) {
return;
}

return $actions;
// Update Ninja Forms session to be able to fulfill delayed actions later.
Ninja_Forms()->session()->set( 'nf_processing_data', $data );
}

/**
Expand Down
66 changes: 66 additions & 0 deletions src/NinjaFormsHelper.php
Expand Up @@ -63,6 +63,32 @@ public static function get_collect_payment_action_settings( $form_id ) {
return null;
}

/**
* Get action IDs of delayed actions from action settings.
*
* @param array<string, mixed> $action_settings Action settings.
* @return array<int>
*/
public static function get_delayed_action_ids_from_settings( $action_settings ) {
$delayed_actions = array();

foreach ( $action_settings as $key => $value ) {
// Check settings key.
if ( 'pronamic_pay_delayed_action_' !== substr( $key, 0, 28 ) ) {
continue;
}

// Check settings key.
if ( 1 !== (int) $value ) {
continue;
}

$delayed_actions[] = (int) substr( $key, 28 );
}

return $delayed_actions;
}

/**
* Get config ID from action settings or use default config.
*
Expand Down Expand Up @@ -183,4 +209,44 @@ public static function get_page_link_from_action_settings( $action_settings, $ke

return \get_permalink( $page_id );
}

/**
* Get session cookie.
*
* @return string|null
*/
public static function get_session_cookie() {
// Determine session cookie name.
$wp_session_cookie = 'nf_wp_session';

if ( defined( '\WP_SESSION_COOKIE' ) ) {
$wp_session_cookie = \WP_SESSION_COOKIE;
}

// Get cookie from headers.
$headers = headers_list();

foreach ( $headers as $header ) {
// Check header name.
if ( 'set-cookie' !== substr( strtolower( $header ), 0, 10 ) ) {
continue;
}

// Get cookie name and value.
$cookie = \explode( ';', $header );

$cookie = trim( \substr( $cookie[0], 12 ) );

$cookie = \explode( '=', $cookie );

if ( $cookie[0] !== $wp_session_cookie ) {
continue;
}

// Return cookie value.
return $cookie[1];
}

return null;
}
}
44 changes: 19 additions & 25 deletions src/PaymentGateway.php
Expand Up @@ -129,40 +129,34 @@ public function process( $action_settings, $form_id, $data ) {
return false;
}

// Set form and action ID in payment meta for use in redirect URL.
$payment->set_meta( 'ninjaforms_payment_action_id', $action_settings['id'] );
$payment->set_meta( 'ninjaforms_payment_form_id', $form_id );

try {
$payment = Plugin::start_payment( $payment );

// Save form and action ID in payment meta for use in redirect URL.
$payment->set_meta( 'ninjaforms_payment_action_id', $action_settings['id'] );
$payment->set_meta( 'ninjaforms_payment_form_id', $form_id );

// Save session cookie in payment meta for processing delayed actions.
\Ninja_Forms()->session()->set( 'pronamic_payment_id', $payment->get_id() );

$headers = headers_list();
// Set form processing data.
$data['actions']['redirect'] = $payment->get_pay_redirect_url();
$data['actions']['success_message'] = __( 'Please wait while you are redirected to complete the payment.', 'pronamic_ideal' );

foreach ( $headers as $header ) {
if ( 'set-cookie' !== substr( strtolower( $header ), 0, 10 ) ) {
continue;
}
// Maybe prepare for delayed actions.
$delayed_action_ids = NinjaFormsHelper::get_delayed_action_ids_from_settings( $action_settings );

$cookie = \explode( ';', $header );
if ( ! empty( $delayed_action_ids ) ) {
// Update session.
\Ninja_Forms()->session()->set( 'pronamic_pay_has_delayed_actions', true );
\Ninja_Forms()->session()->set( 'nf_processing_data', $data );

$cookie = trim( \substr( $cookie[0], 12 ) );
// Set session cookie in payment meta.
$session_cookie = NinjaFormsHelper::get_session_cookie();

$cookie = \explode( '=', $cookie );
if ( null !== $session_cookie ) {
$payment->set_meta( 'ninjaforms_session_cookie', $session_cookie );

$payment->set_meta( 'ninjaforms_session_cookie', $cookie[1] );
$payment->save();
}
}

// Save payment meta.
$payment->save();

// Set form processing data.
$data['halt'] = true;
$data['actions']['redirect'] = $payment->get_pay_redirect_url();
$data['actions']['success_message'] = __( 'Please wait while you are redirected to complete the payment.', 'pronamic_ideal' );
$data['extra']['pronamic_payment_id'] = $payment->get_id();
} catch ( \Exception $e ) {
$message = sprintf( '%1$s: %2$s', $e->getCode(), $e->getMessage() );

Expand Down

0 comments on commit 4e92df7

Please sign in to comment.