You are here

public static function StripeBase::processStripe in Stripe 2.x

Processes a stripe element.

File

src/Element/StripeBase.php, line 65

Class

StripeBase
Provides the base for our Stripe elements

Namespace

Drupal\stripe\Element

Code

public static function processStripe(&$element, FormStateInterface $form_state, &$complete_form) {
  if (!$form_state
    ->isProcessingInput() && !$form_state
    ->isExecuted() && $form_state
    ->get('drupal_stripe_' . static::$type)) {
    $error = t('Only one stripe element of type @type is allowed per form.', [
      '@type' => static::$type,
    ]);

    // \Drupal::messenger()->addError($error);
    $form_state
      ->setError($element, $error);
    $element['error'] = [
      '#markup' => "<div class=\"messages messages--error\">{$error}</div>",
      '#attributes' => [
        'class' => [
          'messages',
          'messages-error',
        ],
      ],
    ];
    return $element;
  }
  $form_state
    ->set('drupal_stripe_' . static::$type, TRUE);
  $config = \Drupal::config('stripe.settings');
  $apikey = $config
    ->get('apikey.' . $config
    ->get('environment') . '.public');
  $apikeySecret = $config
    ->get('apikey.' . $config
    ->get('environment') . '.secret');
  if (empty($apikey) || empty($apikeySecret)) {
    $settings_uri = Url::fromRoute('stripe.settings')
      ->toString();
    $error = t('You must <a href="@settings_uri">configure</a> the <b>API Keys</b> on <b>%environment</b> for the stripe element to work.', [
      '%environment' => $config
        ->get('environment'),
      '@settings_uri' => $settings_uri,
    ]);
    \Drupal::messenger()
      ->addError($error);
    $element['error'] = [
      '#markup' => $error,
    ];
    return $element;
  }
  $stripe = new \Stripe\StripeClient($apikeySecret);
  $id = $element['#id'];
  $wrapper_id = 'stripe-' . implode('-', $element['#parents']) . '-wrapper';
  $button_name = 'stripe-' . implode('-', $element['#parents']) . '-button';
  $element['#tree'] = TRUE;

  // $element['card'] = [
  //   '#markup' => "<div id=\"$id-stripe-card\"></div>",
  // ];
  // $element['paymentrequest'] = [
  //   '#markup' => "<div id=\"$id-stripe-paymentrequest\"></div>",
  //   '#access' => $element['#stripe_paymentrequest'],
  // ];
  $element['stripe'] = [
    '#type' => 'container',
    '#id' => $id,
  ];
  $element['stripe']['element'] = [
    '#markup' => "<div class=\"drupal-stripe-element\"></div>",
  ];
  $element['stripe']['errors'] = [
    '#markup' => "<div class=\"drupal-stripe-errors\" role=\"alert\"></div>",
  ];
  $element['stripe']['actions'] = [
    '#process' => [
      [
        static::class,
        'processActions',
      ],
    ],
  ];
  $element['stripe']['actions']['update'] = [
    '#type' => 'submit',
    '#value' => t('Update'),
    // We specifically don't us a validate ajax callback as we want to act
    // only when the whole form validation succeddes, not otherwise
    // '#validate' => [[get_called_class(), 'validateStripeElementCallback']],
    '#submit' => [
      [
        get_called_class(),
        'submitStripeElementCallback',
      ],
    ],
    '#ajax' => [
      'callback' => [
        get_called_class(),
        'ajaxStripeElementCallback',
      ],
      'progress' => [
        'type' => 'none',
      ],
    ],
    // Disable validation, hide button, add submit button trigger class.
    '#attributes' => [
      'formnovalidate' => 'formnovalidate',
      'class' => [
        'js-hide',
        'drupal-stripe-update',
      ],
    ],
    // Issue #1342066 Document that buttons with the same #value need a unique
    // #name for the Form API to distinguish them, or change the Form API to
    // assign unique #names automatically.
    '#name' => $button_name,
  ];
  $element['stripe']['actions']['#attached']['library'][] = 'stripe/stripe';
  $element['stripe']['actions']['#attached']['drupalSettings']['stripe']['apiKey'] = $apikey;
  $settings = [];
  $payment_intent_id = $element['#value']['payment_intent'] ?? NULL;

  // If the element is configured to share the same payment intent for all
  // stripe elements in the form, attempt to find it.
  if (!$payment_intent_id && $element['#stripe_shared']) {
    $payment_intent_id = $form_state
      ->get('stripe_paymentintent');
  }
  if (!$payment_intent_id) {
    $payment_intent_create = $element['#stripe_paymentintent'] ?? [];
    $payment_intent_create += [
      'amount' => is_numeric($element['#stripe_amount']) ? $element['#stripe_amount'] : 100,
      'currency' => $element['#stripe_currency'],
    ];
    $payment_intent = $stripe->paymentIntents
      ->create($payment_intent_create);
  }
  else {
    $payment_intent = $stripe->paymentIntents
      ->retrieve($payment_intent_id);
  }

  // If the element is configured to share the same payment intent for all
  // stripe elements in the form, store it
  if ($element['#stripe_shared']) {
    $form_state
      ->set('stripe_paymentintent', $payment_intent->id);
  }
  $element['stripe']['actions']['payment_intent'] = [
    '#type' => 'hidden',
    '#value' => $payment_intent->id,
    '#attributes' => [
      'id' => "{$id}-stripe-payment-intent",
      'data-payment-intent-status' => $payment_intent->status,
      'class' => [
        'drupal-stripe-payment-intent',
      ],
    ],
  ];
  $element['stripe']['actions']['client_secret'] = [
    '#type' => 'hidden',
    '#value' => $payment_intent->client_secret,
    '#attributes' => [
      'class' => [
        'drupal-stripe-client-secret',
      ],
    ],
  ];
  $element['stripe']['actions']['trigger'] = [
    '#type' => 'hidden',
    '#attributes' => [
      'class' => [
        'drupal-stripe-trigger',
      ],
    ],
  ];
  $settings['country'] = $element['#stripe_country'];
  $settings['currency'] = $element['#stripe_currency'];
  $settings['amount'] = $element['#stripe_amount'];
  $settings['label'] = $element['#stripe_label'];
  $settings['submit_selector'] = $element['#stripe_submit_selector'];
  $settings['type'] = static::$type;
  $element['stripe']['actions']['#attached']['drupalSettings']['stripe']['elements'][$element['#id']] = $settings;

  // Add validate callback.
  $element['stripe'] += [
    '#element_validate' => [],
  ];
  array_unshift($element['stripe']['#element_validate'], [
    get_called_class(),
    'validateStripeElement',
  ]);
  if (!empty($element['#value']['trigger'])) {
    $element['stripe']['actions']['processed'] = [
      '#type' => 'value',
      '#value' => TRUE,
    ];
  }
  return $element;
}