| Current File : /home/digitaw/www/wp-content/plugins/fluentform/app/Modules/Payments/Components/Subscription.php |
<?php
namespace FluentForm\App\Modules\Payments\Components;
if (!defined('ABSPATH')) {
exit; // Exit if accessed directly.
}
use FluentForm\App\Helpers\Helper;
use FluentForm\App\Modules\Payments\PaymentHelper;
use FluentForm\Framework\Helpers\ArrayHelper;
use FluentForm\App\Modules\Form\FormFieldsParser;
use FluentForm\App\Services\FormBuilder\BaseFieldManager;
class Subscription extends BaseFieldManager
{
public function __construct(
$key = 'subscription_payment_component',
$title = 'Subscription Field',
$tags = ['custom', 'payment', 'donation', 'subscription'],
$position = 'payments'
)
{
parent::__construct(
$key,
$title,
$tags,
$position
);
add_filter('fluentform/editor_init_element_subscription_payment_component', function ($element) {
if (!isset($element['settings']['layout_class'])) {
$element['settings']['layout_class'] = '';
}
return $element;
});
add_filter('fluentform/response_render_' . $this->key, function ($response, $field, $form_id, $isHtml = false) {
if (!$isHtml) {
return $response;
}
return ArrayHelper::get($field, 'raw.settings.subscription_options.' . $response . '.name', $response);
}, 10, 4);
add_filter('fluentform/white_listed_fields', [$this, 'addWhiteListedFields'], 10, 2);
}
function getComponent()
{
return array(
'index' => 8,
'element' => $this->key,
'attributes' => array(
'type' => 'single', // single|multiple
'name' => 'payment_input',
'value' => '10'
),
'settings' => array(
'container_class' => '',
'label' => __('Subscription Item', 'fluentform'),
'admin_field_label' => '',
'label_placement' => '',
'display_type' => '',
'help_message' => '',
'is_payment_field' => 'yes',
'selection_type' => 'radio',
'subscription_options' => [
[
"bill_times" => 0,
"billing_interval" => "month",
"has_signup_fee" => "no",
"has_trial_days" => "no",
"is_default" => "yes",
"name" => __("Monthly Plan", 'fluentform'),
"plan_features" => [],
"signup_fee" => 0,
"subscription_amount" => 9.99,
"trial_days" => 0,
]
],
'price_label' => __('Price:', 'fluentform'),
'enable_quantity' => false,
'enable_image_input' => false,
'is_element_lock' => false,
'layout_class' => 'ff_list_buttons',
'validation_rules' => array(
'required' => array(
'value' => false,
'global' => true,
'message' => Helper::getGlobalDefaultMessage('required'),
'global_message' => Helper::getGlobalDefaultMessage('required'),
),
),
'conditional_logics' => array(),
),
'editor_options' => array(
'title' => __('Subscription', 'fluentform'),
'icon_class' => 'ff-edit-shopping-cart',
'element' => 'input-radio',
'template' => 'inputSubscriptionPayment'
)
);
}
public function getGeneralEditorElements()
{
return [
'label',
'label_placement',
'admin_field_label',
'placeholder',
'subscription_options',
'validation_rules',
];
}
public function getAdvancedEditorElements()
{
return [
'container_class',
'help_message',
'name',
'layout_class',
'conditional_logics'
];
}
function render($data, $form)
{
$type = ArrayHelper::get($data, 'attributes.type');
if ($type == 'single') {
$this->renderSingleItem($data, $form);
return '';
}
$this->renderMultiProduct($data, $form);
}
public function renderSingleItem($data, $form)
{
$elementName = $data['element'];
$data = apply_filters_deprecated(
'fluentform_rendering_field_data_' . $elementName,
[
$data,
$form
],
FLUENTFORM_FRAMEWORK_UPGRADE,
'fluentform/rendering_field_data_' . $elementName,
'Use fluentform/rendering_field_data_' . $elementName . ' instead of fluentform_rendering_field_data_' . $elementName
);
$data = apply_filters('fluentform/rendering_field_data_' . $elementName, $data, $form);
$plan = ArrayHelper::get($data, 'settings.subscription_options.0', []);
$plan['index'] = 0;
$isCustomAmount = ArrayHelper::get($plan, 'user_input') === 'yes';
if ($isCustomAmount) {
$plan['subscription_amount'] = ArrayHelper::get($plan, 'user_input_default_value');
}
$inputAttributes = [
'type' => 'hidden',
'name' => $data['attributes']['name'],
'value' => '0',
'class' => 'ff_payment_item ff_subscription_item',
];
$inputAttributes['id'] = $this->makeElementId($data, $form);
$currency = PaymentHelper::getFormCurrency($form->id);
$billingAttributes = $this->getPlanInputAttributes($plan);
$itemInputAttributes = wp_parse_args($billingAttributes, $inputAttributes);
$elMarkup = "<input " . $this->buildAttributes($itemInputAttributes, $form) . ">";
if ($isCustomAmount) {
$plan['user_input_label'] = ArrayHelper::get($plan, 'user_input_label');
$plan['user_input_label'] = $plan['user_input_label'] ?: ArrayHelper::get($data, 'settings.label');
$elMarkup = $this->makeCustomInputHtml($data, $plan, 'hidden', $elMarkup);
$data['settings']['label'] = ArrayHelper::get($plan, 'user_input_label', $data['settings']['label']);
$data['attributes']['id'] = ArrayHelper::get($data, 'attributes.name') . '_custom_' . $plan['index'];
}
$paymentSummary = $this->getPaymentSummaryText($plan, $form, $currency);
$elMarkup .= $paymentSummary;
$html = $this->buildElementMarkup($elMarkup, $data, $form);
$html = apply_filters_deprecated(
'fluentform_rendering_field_html_' . $elementName,
[
$html,
$data,
$form
],
FLUENTFORM_FRAMEWORK_UPGRADE,
'fluentform/rendering_field_html_' . $elementName,
'Use fluentform/rendering_field_html_' . $elementName . ' instead of fluentform_rendering_field_html_' . $elementName
);
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Content is escaped by the filter
echo apply_filters('fluentform/rendering_field_html_' . $elementName, $html, $data, $form);
}
public function renderMultiProduct($data, $form)
{
$elementName = $data['element'];
$data = apply_filters_deprecated(
'fluentform_rendering_field_data_' . $elementName,
[
$data,
$form
],
FLUENTFORM_FRAMEWORK_UPGRADE,
'fluentform/rendering_field_data_' . $elementName,
'Use fluentform/rendering_field_data_' . $elementName . ' instead of fluentform_rendering_field_data_' . $elementName
);
$data = apply_filters('fluentform/rendering_field_data_' . $elementName, $data, $form);
$currency = PaymentHelper::getFormCurrency($form->id);
$type = ArrayHelper::get($data, 'settings.selection_type', 'radio');
$data['attributes']['type'] = $type;
$data['settings']['container_class'] .= ' ff_subs_selections';
$isSmartUi = false;
if ($type == 'radio') {
$layoutClass = ArrayHelper::get($data, 'settings.layout_class');
if ($layoutClass == 'ff_list_buttons') {
$isSmartUi = true;
}
if ($layoutClass) {
$data['settings']['container_class'] .= ' ff_sub_smart_ui ' . $layoutClass;
}
}
$data['attributes']['class'] = trim(
'ff-el-form-check-input ' .
'ff-el-form-check-' . $data['attributes']['type'] . ' ' .
ArrayHelper::get($data, 'attributes.class')
);
$elMarkup = '';
$customAmountMarkup = '';
$firstTabIndex = \FluentForm\App\Helpers\Helper::getNextTabIndex();
if ($type === 'select') {
$selectAtts = [
'name' => $data['attributes']['name'],
'class' => 'ff-el-form-control ff_subscription_item ff_payment_item',
'data-subscription_item' => 'yes',
'data-name' => $data['attributes']['name'],
'id' => $this->getUniqueid(str_replace(['[', ']'], ['', ''], $data['attributes']['name'])),
'data-parent_input_name' => $data['attributes']['name'],
'data-parent_input_type' => $type,
];
if ($firstTabIndex) {
$selectAtts['tabindex'] = $firstTabIndex;
}
$elMarkup .= '<select ' . $this->buildAttributes($selectAtts, $form) . '>';
$placeholder = ArrayHelper::get($data, 'settings.placeholder', __('--Select Plan--', 'fluentform'));
$elMarkup .= '<option value>' . $placeholder . '</option>';
}
$groupId = $this->makeElementId($data, $form);
$pricingPlans = ArrayHelper::get($data, 'settings.subscription_options', []);
foreach ($pricingPlans as $index => $pricingPlan) {
$pricingPlan['index'] = $index;
$isDefaultPlan = ArrayHelper::get($pricingPlan, 'is_default') === 'yes';
$isCustomAmount = ArrayHelper::get($pricingPlan, 'user_input') === 'yes';
if ($isCustomAmount) {
$pricingPlan['subscription_amount'] = ArrayHelper::get($pricingPlan, 'user_input_default_value');
}
$billingAttributes = $this->getPlanInputAttributes($pricingPlan);
if ($type === 'select') {
$optionAtts = array_merge($billingAttributes, [
'value' => $index,
'selected' => $isDefaultPlan
]);
$optionAtts = $this->buildAttributes($optionAtts, $form);
$elMarkup .= '<option ' . $optionAtts . '>' . $pricingPlan['name'] . '</option>';
} else {
$displayType = isset($data['settings']['display_type']) ? ' ff-el-form-check-' . $data['settings']['display_type'] : '';
$parentClass = "ff-el-form-check{$displayType}";
$atts = $data['attributes'];
$atts['checked'] = $isDefaultPlan;
if ($isDefaultPlan) {
$parentClass .= ' ff_item_selected';
}
if ($firstTabIndex) {
$atts['tabindex'] = $firstTabIndex;
$firstTabIndex = '-1';
}
$atts['class'] .= ' ff_subscription_item ff_payment_item';
$atts['value'] = $index;
$atts['data-group_id'] = $groupId;
$id = $this->getUniqueid(str_replace(['[', ']'], ['', ''], $atts['name']));
$atts = $this->buildAttributes(array_merge($billingAttributes, $atts), $form);
$labelHtml = "<span class='ff_plan_name'>{$pricingPlan['name']}</span>";
if ($isSmartUi) {
$paymentSummary = $this->getPaymentSummaryText($pricingPlan, $form->id, $currency);
$summaryHtml = '<div class="ff_sub_desc">' . $paymentSummary . '</div>';
$labelHtml = "<span class='ff_plan_holder'><span class='ff_plan_title'>{$pricingPlan['name']}</span>" . $summaryHtml . "</span>";
}
$elMarkup .= "<div class='{$parentClass}'>";
$elMarkup .= "<label class='ff-el-form-check-label' for={$id}><input {$atts} id='{$id}'>" . $labelHtml . "</label>";
$elMarkup .= "</div>";
}
if ($isCustomAmount) {
$customAmountMarkup = $this->makeCustomInputHtml($data, $pricingPlan, $type, $customAmountMarkup);
}
if (!$isSmartUi) {
$paymentSummary = $this->getPaymentSummaryText($pricingPlan, $form, $currency);
$customAmountMarkup .= $paymentSummary;
}
}
if ($type === 'select') {
$elMarkup .= '</select>';
}
if ($customAmountMarkup) {
$elMarkup .= $customAmountMarkup;
}
$html = $this->buildElementMarkup($elMarkup, $data, $form);
$html = apply_filters_deprecated(
'fluentform_rendering_field_html_' . $elementName,
[
$html,
$data,
$form
],
FLUENTFORM_FRAMEWORK_UPGRADE,
'fluentform/rendering_field_html_' . $elementName,
'Use fluentform/rendering_field_html_' . $elementName . ' instead of fluentform_rendering_field_html_' . $elementName
);
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Content is escaped by the filter
echo apply_filters('fluentform/rendering_field_html_' . $elementName, $html, $data, $form);
}
private function getPaymentSummaryText($plan, $formId, $currency)
{
return PaymentHelper::getPaymentSummaryText($plan, $formId, $currency, true);
}
private function getPlanInputAttributes($plan)
{
$subscriptionAmount = $plan['subscription_amount'];
$currentBillableAmount = $subscriptionAmount;
$initialAmount = 0;
$signupFee = 0;
if ($this->hasSignupFee($plan)) {
$signupFee = $plan['signup_fee'];
}
$trialDays = false;
if ($this->hasTrial($plan)) {
$currentBillableAmount = 0;
$trialDays = ArrayHelper::get($plan, 'trial_days');
}
return [
'data-subscription_amount' => $subscriptionAmount ?: 0,
'data-billing_interval' => $plan['billing_interval'],
'data-price' => $currentBillableAmount ?: 0,
'data-payment_value' => $currentBillableAmount ?: 0,
'data-initial_amount' => $initialAmount ?: 0,
'data-signup_fee' => $signupFee,
'data-trial_days' => $trialDays,
'data-plan_name' => esc_attr($plan['name'])
];
}
private function hasTrial($plan)
{
$hasTrial = ArrayHelper::get($plan, 'has_trial_days') == 'yes';
$trialDays = ArrayHelper::get($plan, 'trial_days');
return $hasTrial && $trialDays;
}
private function hasSignupFee($plan)
{
$hasSignup = ArrayHelper::get($plan, 'has_signup_fee') == 'yes';
$signUpFee = ArrayHelper::get($plan, 'signup_fee');
return $hasSignup && $signUpFee;
}
private function makeCustomInputHtml($field, $plan, $parentInputType, $markup)
{
$htmlID = ArrayHelper::get($field, 'attributes.name') . '_custom_' . $plan['index'];
$isDefault = ArrayHelper::get($plan, 'is_default') === 'yes';
$customAmountInputAttributes = $this->buildAttributes([
'name' => $htmlID,
'type' => 'number',
'value' => ArrayHelper::get($plan, 'user_input_default_value'),
'min' => $isDefault ? ArrayHelper::get($plan, 'user_input_min_value', 0) : '0',
'data-min' => ArrayHelper::get($plan, 'user_input_min_value', 0),
'step' => 'any',
'placeholder' => ArrayHelper::get($plan, 'user_input_label'),
'class' => 'ff-el-form-control ff-custom-user-input ' . ($isDefault ? 'is-default' : ''),
'id' => $htmlID,
'data-parent_input_name' => $field['attributes']['name'],
'data-parent_input_type' => $parentInputType,
'data-plan_index' => $plan['index'],
'data-plan_trial_days' => ArrayHelper::get($plan, 'trial_days', 0)
]);
$class = $isDefault ? '' : 'hidden_field';
$style = $parentInputType === 'hidden' ? '' : "style='margin-top: 5px'";
$markup .= "<div class='ff-custom-user-input-wrapper ff-custom-user-input-wrapper-{$plan['index']} {$class}' {$style}>";
if ($parentInputType !== 'hidden') {
$markup .= "<label class='ff-el-form-check-label' for='{$htmlID}'>" . ArrayHelper::get($plan, 'user_input_label') . '</label>';
}
$markup .= "<input {$customAmountInputAttributes}>";
$markup .= '</div>';
return $markup;
}
public function addWhiteListedFields($whiteListedFields, $formId)
{
$form = wpFluent()->table('fluentform_forms')->find($formId);
if (!$form->has_payment) {
return $whiteListedFields;
}
$inputs = FormFieldsParser::getInputsByElementTypes($form, ['subscription_payment_component'], ['settings', 'attributes']);
$customInputNames = [];
foreach ($inputs as $subscriptionInput) {
$index = 0;
$subscriptionOptions = ArrayHelper::get($subscriptionInput, 'settings.subscription_options');
foreach ($subscriptionOptions as $plan) {
if (ArrayHelper::get($plan, 'user_input') === 'yes') {
$customInputNames[] = ArrayHelper::get($subscriptionInput, 'attributes.name') . '_custom_' . $index;
}
$index++;
}
}
return array_merge($whiteListedFields, $customInputNames);
}
}