| @@ -739,8 +739,56 @@ | ||
| 739 | 739 | } |
| 740 | 740 | return $total; |
| 741 | 741 | } |
| 742 | 742 | |
| 743 | + // A $0 order is a completed free order when a real priced product was zeroed by a | |
| 744 | + // server-validated discount (both a non-discount and a discount line are present; | |
| 745 | + // discount lines come solely from getValidCoupons), or when the visitor chose one of | |
| 746 | + // the form's own $0 options. Otherwise the $0 total is an omitted or zeroed input. | |
| 747 | + public function isZeroTotalFreeOrder() | |
| 748 | + { | |
| 749 | + $hasProduct = $hasDiscount = false; | |
| 750 | + foreach ($this->getOrderItems() as $item) { | |
| 751 | + if (ArrayHelper::get($item, 'type') === 'discount') { | |
| 752 | + $hasDiscount = true; | |
| 753 | + } else { | |
| 754 | + $hasProduct = true; | |
| 755 | + } | |
| 756 | + } | |
| 757 | + return ($hasProduct && $hasDiscount) || $this->hasSelectedFreeOption(); | |
| 758 | + } | |
| 759 | + | |
| 760 | + // Validation rejects any option the form does not offer, so a selected $0 option is the site's own. | |
| 761 | + protected function hasSelectedFreeOption() | |
| 762 | + { | |
| 763 | + $data = (array) ArrayHelper::get($this->submissionData, 'response'); | |
| 764 | + foreach ((array) $this->paymentInputs as $input) { | |
| 765 | + $selected = (array) ArrayHelper::get($data, ArrayHelper::get($input, 'attributes.name'), []); | |
| 766 | + if (!$selected || !$this->isFieldVisible($input)) { | |
| 767 | + continue; | |
| 768 | + } | |
| 769 | + foreach (ArrayHelper::get($input, 'settings.pricing_options', []) as $option) { | |
| 770 | + if (in_array(sanitize_text_field($option['label']), $selected) && !(float) $option['value']) { | |
| 771 | + return true; | |
| 772 | + } | |
| 773 | + } | |
| 774 | + } | |
| 775 | + return false; | |
| 776 | + } | |
| 777 | + | |
| 778 | + // The entry is not inserted yet; stamp a free order the moment it is, before any | |
| 779 | + // payment-success consumer runs. An absent flag means an empty order. | |
| 780 | + public function flagZeroTotalOrder() | |
| 781 | + { | |
| 782 | + if (!$this->isZeroTotalFreeOrder()) { | |
| 783 | + return; | |
| 784 | + } | |
| 785 | + | |
| 786 | + add_action('fluentform/notify_on_form_submit', function ($insertId, $formData, $form) { | |
| 787 | + Helper::setSubmissionMeta($insertId, '_ff_zero_total_free_order', 'yes', $form->id); | |
| 788 | + }, 1, 3); | |
| 789 | + } | |
| 790 | + | |
| 743 | 791 | public function getPaymentType() |
| 744 | 792 | { |
| 745 | 793 | return count($this->getSubscriptionItems()) ? 'subscription' : 'product'; // return value product|subscription|donation |
| 746 | 794 | } |