Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
102 commits
Select commit Hold shift + click to select a range
4bd5d0c
Copy over and rename the Square files
Crabcyborg Dec 4, 2025
63a06d3
Add some front end JS to get it rendering an input
Crabcyborg Dec 4, 2025
2fab964
Work in progress adding support for creating orders
Crabcyborg Dec 8, 2025
043cce8
Merge branch 'master' into paypal
Crabcyborg Dec 10, 2025
d7bb8fe
Get paypal onboarding working
Crabcyborg Dec 10, 2025
6a30acf
Merge branch 'master' into paypal
Crabcyborg Dec 11, 2025
2fc4067
Work on capturing the paypal payment order
Crabcyborg Dec 11, 2025
1ccc3b6
Overwrite paypal section and render paypal section after the new sett…
Crabcyborg Dec 11, 2025
2dac3d8
Merge branch 'master' into paypal
Crabcyborg Dec 18, 2025
a733061
Set a layout, set styles to try to look closer to Formidable fields
Crabcyborg Dec 18, 2025
1abf334
Sync the submit button with the PayPal state
Crabcyborg Dec 18, 2025
94a3c68
Add the section title for the legacy paypal settings
Crabcyborg Dec 18, 2025
eba69dc
Support passing amount and currency to paypal
Crabcyborg Dec 18, 2025
0609fb7
Create the payment record
Crabcyborg Dec 18, 2025
1a99fc4
Merge branch 'master' into paypal
Crabcyborg Dec 18, 2025
d9c3b9c
Make sure number_format does not include comma
Crabcyborg Dec 18, 2025
6252952
Show the loading spinner as soon as we start creating the order
Crabcyborg Dec 18, 2025
b282401
Fix spacing
Crabcyborg Dec 19, 2025
41ea720
Save the capture ID instead and add refund endpoints
Crabcyborg Dec 19, 2025
0ee2312
Make sure psalm and rector target the paypal folder, remove some test…
Crabcyborg Dec 22, 2025
323c31c
Merge branch 'master' into paypal
Crabcyborg Dec 22, 2025
7f89459
Merge branch 'master' into paypal
Crabcyborg Dec 22, 2025
d18aaca
Play with adding a paypal checkout button
Crabcyborg Dec 22, 2025
37ef115
Merge branch 'master' into paypal
Crabcyborg Dec 30, 2025
e1ea098
Run php cs fixer
Crabcyborg Dec 30, 2025
dd28019
Run rector and phpcbf
Crabcyborg Dec 30, 2025
6e4b66a
Ignore psalm errors for paypal folder where all dirs are being ignored
Crabcyborg Dec 30, 2025
e955394
Run eslint fix
Crabcyborg Dec 30, 2025
4dc9125
Simplify the autoload logic
Crabcyborg Dec 30, 2025
4cee596
Remove background-color style from input (not supported, was triggeri…
Crabcyborg Dec 30, 2025
ca7f8a5
Add the name field and get the checkout button working
Crabcyborg Dec 30, 2025
eb08153
Working on subscriptions (wip)
Crabcyborg Dec 30, 2025
5fbadc9
Merge branch 'master' into paypal
Crabcyborg Jan 6, 2026
5f32361
Merge branch 'master' into paypal
Crabcyborg Jan 6, 2026
d33af4d
Run eslint fix
Crabcyborg Jan 6, 2026
e658e50
Merge branch 'master' into paypal
Crabcyborg Jan 7, 2026
db57d32
Move client id to a function
Crabcyborg Jan 7, 2026
859a09f
Merge branch 'master' into paypal
Crabcyborg Jan 7, 2026
f1e64a5
Remove old todo comment
Crabcyborg Jan 7, 2026
34553b5
Drop the name field and use mapped name field setting value
Crabcyborg Jan 7, 2026
9a53381
Add todo comment
Crabcyborg Jan 7, 2026
f7943e9
Merge branch 'master' into paypal
Crabcyborg Jan 7, 2026
7c1341f
Merge branch 'master' into paypal
Crabcyborg Jan 7, 2026
4224035
Drop the paypal pro tips
Crabcyborg Jan 7, 2026
e1d6913
Add the fee education to the paypal global settings page
Crabcyborg Jan 7, 2026
62bdc4f
Merge branch 'master' into paypal
Crabcyborg Jan 7, 2026
c84a3a6
Update payment setting toggle logic to support more than 2 gateways
Crabcyborg Jan 7, 2026
da2aff6
Run eslint fix
Crabcyborg Jan 7, 2026
68b3c4a
Run phpcbf
Crabcyborg Jan 7, 2026
152ca4d
Merge branch 'master' into paypal
Crabcyborg Jan 8, 2026
3a95480
Clean up, extend comment
Crabcyborg Jan 8, 2026
e2fa4b3
Merge branch 'master' into paypal
Crabcyborg Jan 8, 2026
eda6f7d
Merge branch 'master' into paypal
Crabcyborg Jan 9, 2026
f346d79
Merge branch 'master' into paypal
Crabcyborg Jan 9, 2026
6f042f0
Apply new spacing sniff
Crabcyborg Jan 9, 2026
1f3da22
Merge branch 'master' into paypal
Crabcyborg Jan 9, 2026
5d79f49
Merge branch 'master' into paypal
Crabcyborg Jan 9, 2026
45fa97b
Apply new phpcs sniffs
Crabcyborg Jan 9, 2026
e4f6126
Merge branch 'master' into paypal
Crabcyborg Jan 9, 2026
144a338
Drop some return comments in functions that technically die
Crabcyborg Jan 9, 2026
edd6827
Merge branch 'master' into paypal
Crabcyborg Jan 9, 2026
a82df22
Run new phpcs sniffs
Crabcyborg Jan 9, 2026
f12489e
Revert a strict comparison and add php cs ignore comments
Crabcyborg Jan 9, 2026
fe237a9
Work on trying to get vault setup tokens working
Crabcyborg Jan 9, 2026
ac88390
Merge branch 'master' into paypal
Crabcyborg Jan 9, 2026
51a4ec8
Merge branch 'master' into paypal
Crabcyborg Jan 9, 2026
10e2300
Merge branch 'master' into paypal
Crabcyborg Jan 12, 2026
3d818a0
Run phpcbf
Crabcyborg Jan 12, 2026
ddb3d5d
Merge branch 'master' into paypal
Crabcyborg Jan 12, 2026
496280b
Run rector process
Crabcyborg Jan 12, 2026
06435d5
Merge branch 'master' into paypal
Crabcyborg Jan 14, 2026
e7b5b12
Add more logging and switch back to testing one time payments
Crabcyborg Jan 14, 2026
70704f0
Merge branch 'master' into paypal
Crabcyborg Jan 19, 2026
3153ad7
Merge branch 'master' into paypal
Crabcyborg Jan 20, 2026
f579d3b
Apply new sniffs
Crabcyborg Jan 20, 2026
5394868
Merge branch 'master' into paypal
Crabcyborg Jan 23, 2026
3e91499
Run sniffs (update comment case)
Crabcyborg Jan 23, 2026
784f1e0
Merge branch 'master' into paypal
Crabcyborg Jan 23, 2026
2733caa
Work on getting seller status details
Crabcyborg Jan 23, 2026
0e80ec3
Show errors if PayPal status is not good
Crabcyborg Jan 23, 2026
b753964
Update comment
Crabcyborg Jan 23, 2026
cf72b54
Merge branch 'master' into paypal
Crabcyborg Jan 26, 2026
778fcc0
Working on rendering seller info
Crabcyborg Jan 26, 2026
112aa11
Merge branch 'master' into paypal
Crabcyborg Jan 26, 2026
ce81be9
Merge branch 'master' into paypal
Crabcyborg Jan 26, 2026
b2a9545
Merge branch 'master' into paypal
Crabcyborg Jan 26, 2026
3f2f56f
Move seller status to the connection box
Crabcyborg Jan 26, 2026
e0a7188
Merge branch 'master' into paypal
Crabcyborg Jan 27, 2026
4dd58ed
Always show the connect email in the seller status elements
Crabcyborg Jan 27, 2026
2d9da1f
Store a valid seller status as an option to avoid too many calls to P…
Crabcyborg Jan 27, 2026
6909c44
Merge branch 'master' into paypal
Crabcyborg Jan 27, 2026
e8ea08e
Apply some phpcbf fixes
Crabcyborg Jan 27, 2026
b901299
Only save the option if we also have the email
Crabcyborg Jan 27, 2026
8db1368
Merge branch 'master' into paypal
Crabcyborg Jan 27, 2026
729fbaf
Remove inline HTML into view files
Crabcyborg Jan 27, 2026
279c8ed
Small code cleanup changes
Crabcyborg Jan 28, 2026
8563d06
Merge branch 'master' into paypal
Crabcyborg Jan 28, 2026
8bc3a13
Fix mago issue
Crabcyborg Jan 28, 2026
5fbe6ff
Only call the PayPal API for seller status when visiting the paypal tab
Crabcyborg Jan 28, 2026
3df87f2
Merge branch 'master' into paypal
Crabcyborg Jan 29, 2026
526a504
Playing with pay later
Crabcyborg Jan 29, 2026
d3247a0
Fix some issues caught with deepscan
Crabcyborg Jan 29, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions classes/controllers/FrmHooksController.php
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ public static function load_hooks() {
FrmTransLiteHooksController::load_hooks();
FrmStrpLiteHooksController::load_hooks();
FrmSquareLiteHooksController::load_hooks();
FrmPayPalLiteHooksController::load_hooks();

// GDPR
add_filter( 'frm_is_field_required', 'FrmFieldGdpr::force_required_field', 10, 2 );
Expand Down Expand Up @@ -216,6 +217,7 @@ public static function load_admin_hooks() {
FrmTransLiteHooksController::load_admin_hooks();
FrmStrpLiteHooksController::load_admin_hooks();
FrmSquareLiteHooksController::load_admin_hooks();
FrmPayPalLiteHooksController::load_admin_hooks();
FrmSMTPController::load_hooks();
FrmOnboardingWizardController::load_admin_hooks();
FrmAddonsController::load_admin_hooks();
Expand Down
16 changes: 0 additions & 16 deletions classes/helpers/FrmTipsHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -246,22 +246,6 @@ public static function get_form_action_tip() {
'tip' => __( 'Send leads to Mailchimp for instant email follow-up.', 'formidable' ),
'call' => self::cta_label(),
),
array(
'link' => array(
'content' => 'paypal-revenue',
'page' => 'paypal-increase-revenue-tip',
),
'tip' => __( 'Accept PayPal payments and grow your sales.', 'formidable' ),
'call' => self::cta_label(),
),
array(
'link' => array(
'content' => 'paypal-fast',
'page' => 'paypal-save-time-tip',
),
'tip' => __( 'Accept payments now with PayPal integration.', 'formidable' ),
'call' => self::cta_label(),
),
array(
'link' => array(
'content' => 'registration',
Expand Down
2 changes: 1 addition & 1 deletion css/custom_theme.css.php
Original file line number Diff line number Diff line change
Expand Up @@ -1669,6 +1669,6 @@
.frm-card-errors:empty {
margin: 0;
}
<?php

<?php
echo strip_tags( FrmStylesController::get_custom_css() ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
48 changes: 18 additions & 30 deletions formidable.php
Original file line number Diff line number Diff line change
Expand Up @@ -108,43 +108,31 @@ function frm_class_autoloader( $class_name, $filepath ) {
return;
}

$filepath = $original_filepath;

if ( preg_match( '/^FrmStrpLite.+$/', $class_name ) || preg_match( '/^FrmTransLite.+$/', $class_name ) ) {
// Autoload for /stripe/ folder.
$filepath = $original_filepath . '/stripe/';

if ( preg_match( '/^.+Helper$/', $class_name ) ) {
$filepath .= 'helpers/';
} elseif ( preg_match( '/^.+Controller$/', $class_name ) ) {
$filepath .= 'controllers/';
} else {
$filepath .= 'models/';
}

$filepath .= $class_name . '.php';

if ( file_exists( $filepath ) ) {
require $filepath;
}

$filepath .= '/stripe/';
} elseif ( preg_match( '/^FrmSquareLite.+$/', $class_name ) ) {
$filepath .= '/square/';
} elseif ( preg_match( '/^FrmPayPalLite.+$/', $class_name ) ) {
$filepath .= '/paypal/';
} else {
return;
}

if ( preg_match( '/^FrmSquareLite.+$/', $class_name ) ) {
$filepath = $original_filepath . '/square/';

if ( preg_match( '/^.+Helper$/', $class_name ) ) {
$filepath .= 'helpers/';
} elseif ( preg_match( '/^.+Controller$/', $class_name ) ) {
$filepath .= 'controllers/';
} else {
$filepath .= 'models/';
}
if ( preg_match( '/^.+Helper$/', $class_name ) ) {
$filepath .= 'helpers/';
} elseif ( preg_match( '/^.+Controller$/', $class_name ) ) {
$filepath .= 'controllers/';
} else {
$filepath .= 'models/';
}

$filepath .= $class_name . '.php';
$filepath .= $class_name . '.php';

if ( file_exists( $filepath ) ) {
require $filepath;
}
if ( file_exists( $filepath ) ) {
require $filepath;
}
}

Expand Down
4 changes: 2 additions & 2 deletions js/admin/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
}

if ( 'frm-send-test-email' === e.target.id ) {
showSendTestEmailModal( e );
showSendTestEmailModal();
return;
}

Expand All @@ -62,7 +62,7 @@
document.getElementById( 'frm-email-style-value' ).value = styleKey;
}

function showSendTestEmailModal( e ) {
function showSendTestEmailModal() {
if ( ! globalVars.sendTestEmailModal ) {
globalVars.sendTestEmailModal = frmAdminBuild.initModal( '#frm-send-test-email-modal', '400px' );
}
Expand Down
24 changes: 0 additions & 24 deletions js/admin/style.js
Original file line number Diff line number Diff line change
Expand Up @@ -914,14 +914,6 @@
titleElement.textContent = newStyleName;
}

/**
* @param {string} templateKey
* @return {HTMLElement} The template card element.
*/
function getTemplateCard( templateKey ) {
return document.getElementById( 'frm_template_style_cards_wrapper' ).querySelector( '.frm-style-card[data-template-key="' + templateKey + '"]' );
}

/**
* @param {string} styleId
* @return {HTMLElement} The card element.
Expand Down Expand Up @@ -1332,22 +1324,6 @@
}
}

/**
* @param {Event} event
*/
function maybeCollapseSettings( event ) {
let expanded;
const sectionParent = event.target.parentElement;
if ( event.type === 'keydown' ) {
expanded = sectionParent.classList.toggle( 'open' );
jQuery( sectionParent.querySelector( '.accordion-section-content' ) ).toggle( ! expanded ).slideToggle( 150 ); // Animate toggle as in click/enter.
} else {
expanded = sectionParent.classList.contains( 'open' );
}

event.target.setAttribute( 'aria-expanded', expanded );
}

/**
* @param {HTMLElement} input
* @param {HTMLElement} container
Expand Down
2 changes: 1 addition & 1 deletion js/formidable.js
Original file line number Diff line number Diff line change
Expand Up @@ -2052,7 +2052,7 @@ function frmFrontFormJS() {
/*jshint validthis:true */

const fieldId = frmFrontForm.getFieldId( this, false );
if ( ! fieldId || typeof fieldId === 'undefined' ) {
if ( ! fieldId ) {
return;
}

Expand Down
42 changes: 42 additions & 0 deletions js/src/admin/addon-state.js
Original file line number Diff line number Diff line change
Expand Up @@ -248,3 +248,45 @@
circledIcon.querySelector( 'svg' )?.replaceWith( svg( { href: '#frm_checkmark_icon' } ) );
}
}

function installAddonWithCreds( e ) {
// Prevent the default action, let the user know we are attempting to install again and go with it.
e.preventDefault();

// Now let's make another Ajax request once the user has submitted their credentials.
const proceed = jQuery( this );
const el = proceed.parent().parent();
const plugin = proceed.attr( 'rel' );

proceed.addClass( 'frm_loading_button' );

jQuery.ajax( {
url: ajaxurl,
type: 'POST',
async: true,
cache: false,
dataType: 'json',
data: {
action: 'frm_install_addon',
nonce: frmAdminJs.nonce,
plugin: plugin,
hostname: el.find( '#hostname' ).val(),
username: el.find( '#username' ).val(),
password: el.find( '#password' ).val()
},
success: function( response ) {
response = response?.data ?? response;

const error = extractErrorFromAddOnResponse( response );
if ( error ) {
addonError( error, el, proceed );
return;
}

afterAddonInstall( response, proceed, message, el );
},
error: function() {
proceed.removeClass( 'frm_loading_button' );
}
} );
}

Check failure on line 292 in js/src/admin/addon-state.js

View workflow job for this annotation

GitHub Actions / Run ESLint

Newline required at end of file but not found

Check failure on line 292 in js/src/admin/addon-state.js

View workflow job for this annotation

GitHub Actions / Run ESLint

Newline required at end of file but not found

Check failure on line 292 in js/src/admin/addon-state.js

View workflow job for this annotation

GitHub Actions / Run ESLint

Newline required at end of file but not found
75 changes: 2 additions & 73 deletions js/src/admin/admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ window.frmAdminBuildJS = function() {
const frmAdminJs = frm_admin_js; // eslint-disable-line camelcase
const { tag, div, span, a, svg, img } = frmDom;
const { onClickPreventDefault } = frmDom.util;
const { doJsonFetch, doJsonPost } = frmDom.ajax;
const { doJsonPost } = frmDom.ajax;
frmAdminJs.contextualShortcodes = getContextualShortcodes();
const icons = {
save: svg( { href: '#frm_save_icon' } ),
Expand Down Expand Up @@ -2943,18 +2943,6 @@ window.frmAdminBuildJS = function() {
}
}

function scrollToField( field ) {
const newPos = field.getBoundingClientRect().top,
container = document.getElementById( 'post-body-content' );

if ( typeof animate === 'undefined' ) {
jQuery( container ).scrollTop( newPos );
} else {
// TODO: smooth scroll
jQuery( container ).animate( { scrollTop: newPos }, 500 );
}
}

function checkCalculationCreatedByUser() {
const calculation = this.value;
let warningMessage = checkMatchingParens( calculation );
Expand Down Expand Up @@ -5318,8 +5306,7 @@ window.frmAdminBuildJS = function() {

function addWatchLookupRow() {
/*jshint validthis:true */
let lastRowId,
id = jQuery( this ).closest( '.frm-single-settings' ).data( 'fid' ),
let id = jQuery( this ).closest( '.frm-single-settings' ).data( 'fid' ),
formId = thisFormId,
lookupBlockRows = document.getElementById( 'frm_watch_lookup_block_' + id ).children;
jQuery.ajax( {
Expand Down Expand Up @@ -6473,7 +6460,6 @@ window.frmAdminBuildJS = function() {
function getImageLabel( label, showLabelWithImage, imageUrl, fieldType ) {
let imageLabelClass,
originalLabel = label,
shape = fieldType === 'checkbox' ? 'square' : 'circle',
labelImage,
labelNode,
imageLabel;
Expand Down Expand Up @@ -9312,63 +9298,6 @@ window.frmAdminBuildJS = function() {
addonState.toggleAddonState( clicked, action );
}

function installAddonWithCreds( e ) {
// Prevent the default action, let the user know we are attempting to install again and go with it.
e.preventDefault();

// Now let's make another Ajax request once the user has submitted their credentials.
const proceed = jQuery( this );
const el = proceed.parent().parent();
const plugin = proceed.attr( 'rel' );

proceed.addClass( 'frm_loading_button' );

jQuery.ajax( {
url: ajaxurl,
type: 'POST',
async: true,
cache: false,
dataType: 'json',
data: {
action: 'frm_install_addon',
nonce: frmAdminJs.nonce,
plugin: plugin,
hostname: el.find( '#hostname' ).val(),
username: el.find( '#username' ).val(),
password: el.find( '#password' ).val()
},
success: function( response ) {
response = response?.data ?? response;

const error = extractErrorFromAddOnResponse( response );
if ( error ) {
addonError( error, el, proceed );
return;
}

afterAddonInstall( response, proceed, message, el );
},
error: function() {
proceed.removeClass( 'frm_loading_button' );
}
} );
}

function afterAddonInstall( response, button, message, el, saveAndReload, action = 'frm_activate_addon' ) {
const addonState = require( './addon-state' );
addonState.afterAddonInstall( response, button, message, el, saveAndReload, action );
}

function extractErrorFromAddOnResponse( response ) {
const addonState = require( './addon-state' );
return addonState.extractErrorFromAddOnResponse( response );
}

function addonError( response, el, button ) {
const addonState = require( './addon-state' );
addonState.addonError( response, el, button );
}

/* Templates */
function showActiveCampaignForm() {
loadApiEmailForm();
Expand Down
2 changes: 1 addition & 1 deletion js/src/components/class-overlay.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export class frmOverlay {

getButtons() {
const buttons = this.overlayData.buttons.map( ( button, index ) => {
if ( ! button.url || '' === button.url ) {
if ( ! button.url ) {
return '';
}
const buttonTypeClassname = 1 === index ? 'frm-button-primary' : 'frm-button-secondary';
Expand Down
Loading
Loading