JFIF $ d d 7 * Z qn )ZP 0 !1 A "#a$2Qr D8 a Ri [f \m I ykI w0 c u F c Rı?lO7 к _f˓ [C $殷WF< _W ԣ s Kc ëI zyQy /_LK ℂ ;C",p F A : /] =H ~ , l s / 9 ć: [=/#f ; ) x { ٛE Q )~ = 𘙲r*2~ a _V = ' ku m F D } KYYC )( { * g& f `툪 r y ` = ^ c J. I ]( * `wq 1dđ #̩ ͑ 0 ; H ] u 搂 @:~ ו K L N s h } O I R* 8 :2 ! lD JV o ( 3 = M ( z Ȱ+i *N A r6K n S l ) ! J J Ӂ* % ݉?|D } d5: eP0 R; {$X' x F @ .ÊB {,WJ uQ ɲRI ;9 Q E琯 6 2fT .DU J ;*c P A\IL Nj! J ۱+ O\ ͔ ] ޒ S J ȧ c%A N ol ՎprU L Zԛe r E2= X D Xg VQeӓ k y P7 U* o m Q I s ,K `) 6\G3t?pgjr m ۛجw luGt f h 9uyP 0D;Uڽ"OXl i f $ ) &|ML 0 Z rm1 [ H XP l P R0 'G=i 2N +0 e 2 ]] 9 VT P O 7 h(F * 癈 ' = Q VZD F,d ߬ ~ T X G[ `le 69C R(!S2! P < 0 x < !1AQ "Raq 02Br #S CTb ? Ζ "]mH5WR 7 k.ۛ ! } Q~ + yԏ z |@ T20 S~ K e k *zF f^2X *( @ 8 r ? C I uI|֓>^Ex LgNU Y+{.R Ѫ τV YT D I 6 2 '8Y2 7'\T P.6 d &˦ @V q i |8 -O Ε ] ʔ U= T L 8= ;6c | !qfF3 a ů& ~$ l} 'NW U s$U k^S V : U#6w + +s &r+n ڐ { @ 29gL u " T Ù M=6 (^ "7 r}=6Yݾ lC u hquymp Ǧ G jhs ǜNl ɻ} o 7 #S6 a w 4 ! OS r D 5 7 % | ?x> L | / nD 6?/8 w # [ ) L 7 +6〼T A T g ! %5 Mm Z /c -{1_Je "| ^$ 'O & ޱմ < H vNqϡQ$ < 6 &Nݛ ֨tǻN (9 n ru~'όN sMG& ,uH Kw *Ī 5@ u6 BԒ i YN * f 0 _ GhKW u lT <nj- 0{ M L~ | /a v\ E = ?1 \ɟuq Ђ Y O a K ޡP q $ H8o Q˼EV ~ k 0 h' L Pp M -M" m^ !6l nմ 쮝C U T . ! :vMǨb h ډ Vc r @~p # !1QAa q ? AL0L x LU 4 d ; x " 16ad0 7.\ߋ 0 = P l v/ " c A Ay A|2pO8"d MV #1] = \ " ˡ ] k v I9 d ۓ & q ) ǐq E ꞅ v "P )q X &Q З non]я u ג./ ; gZ$ M QР 2M ]h ni 0 P $ێ 3CɏGjώy : m c # S_ l@ '_ \m|C 2`K _ 1 cIvGc $? PCQ S+D ? K aײ k Fr b 8 ύ NEدg ĝ U 3 6 #Ik+ v { v i ( ވ ? a e) X xy/*@Q Ǽ Ծ ) $ IWO l c G; !i k{ gOŀ L ('x T rb $ w) R $ & N1E td U3Uȉ1p M"N* (DNy d96.(jQ) X 5 c QɎMy W ? Q *!R > 6=7)Xj 5`J ] e 8%t ! + ' ! 1Q 5 !1 AQaq ё #2 "0BRb ? G t^ ## .l lQ T $ v , ,m 㵜5u bV =sY+ @d { N ! dn O < .- B; _w J t 6;Q Jd. Q c%p{ 1 ,sND dF H I0 Гo X ш e黅X ۢ F :)[ F G X ƹ / w _c MeD ,ʡc c . W D tA $ j@ : ) - #u c1< @ۗ9F ) KJ- hpP] _ x [ q B lb p ʖ w q " LFGd ƶ * s +ډ_Zc " ? % t[I P 6 J ]# =ɺ V v v CGs Gh1 > )6 |e y ? L ӣ m,4 G W Ui ` ] uJVo VDG< SB 6ϏQ @ TiU l y O U 0 kfV ~ ~}S Z @ *WU Ui ## ; s /[ = ! 7}" W N ] ' (L ! ~ y5 g9T̅J kbM' +s :S +B) v @ M j e C f j E 0 Y\Qn z G 1 д~ W o{T 9?` Rm yhsy3 !HAD ] m c1 ~ 2 L S u7x T ;j$ `} 4-> L# vzŏ I L S ֭ T { r jGK C ; b pU= - ` Bs K. S F w4 M q] Z dH S 0 ) tLg
<?php
/**
* Base panel class.
*
* @since 1.0.0
*/
abstract class WPForms_Builder_Panel {
/**
* Full name of the panel.
*
* @since 1.0.0
*
* @var string
*/
public $name;
/**
* Slug.
*
* @since 1.0.0
*
* @var string
*/
public $slug;
/**
* Font Awesome Icon used for the editor button, eg "fa-list".
*
* @since 1.0.0
*
* @var mixed
*/
public $icon = false;
/**
* Priority order the field button should show inside the "Add Fields" tab.
*
* @since 1.0.0
*
* @var int
*/
public $order = 50;
/**
* If panel contains a sidebar element or is full width.
*
* @since 1.0.0
*
* @var bool
*/
public $sidebar = false;
/**
* Determine whether the panel content will be loaded on demand.
*
* @since 1.8.6
*
* @var bool
*/
public $on_demand = false;
/**
* Contain form object if we have one.
*
* @since 1.0.0
*
* @var object
*/
public $form;
/**
* Contain array of the form data (post_content).
*
* @since 1.0.0
*
* @var array
*/
public $form_data;
/**
* Class instance.
*
* @since 1.7.7
*
* @var static
*/
private static $instance;
/**
* Primary class constructor.
*
* @since 1.0.0
*/
public function __construct() {
// Load form if found.
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
$form_id = isset( $_GET['form_id'] ) ? absint( $_GET['form_id'] ) : false;
$this->form = wpforms()->obj( 'form' )->get( $form_id );
$this->form_data = $this->form ? wpforms_decode( $this->form->post_content ) : false;
// Get current revision, if available.
$revision = wpforms()->obj( 'revisions' )->get_revision();
// If we're viewing a valid revision, replace the form data so the Form Builder shows correct state.
if ( $revision && isset( $revision->post_content ) ) {
$this->form_data = wpforms_decode( $revision->post_content );
}
// Bootstrap.
$this->init();
// Save instance.
self::$instance = $this;
// Primary panel button.
add_action( 'wpforms_builder_panel_buttons', [ $this, 'button' ], $this->order, 2 );
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
$is_active = $this->slug === sanitize_key( $_GET['view'] ?? 'setup' );
if ( $this->on_demand && ! $is_active ) {
// Load panel loader enqueues.
add_action( 'admin_enqueue_scripts', [ $this, 'enqueues_loader' ] );
}
// Load payments panel enqueues.
add_action( 'wpforms_builder_enqueues', [ $this, 'enqueues_payments' ] );
// Load panel specific enqueues.
add_action( 'admin_enqueue_scripts', [ $this, 'enqueues' ], 15 );
if ( $is_active || ! $this->on_demand ) {
// Output.
add_action( 'wpforms_builder_panels', [ $this, 'panel_output' ], $this->order, 2 );
}
}
/**
* Get class instance.
*
* @since 1.7.7
*
* @return static
*/
public static function instance() {
if ( self::$instance === null || ! self::$instance instanceof static ) {
self::$instance = new static();
}
return self::$instance;
}
/**
* All systems go. Used by children.
*
* @since 1.0.0
*/
public function init() {
}
/**
* Enqueue assets for the builder. Used by children.
*
* @since 1.0.0
*/
public function enqueues() {
}
/**
* Enqueue panel loader assets.
*
* @since 1.8.6
*/
public function enqueues_loader() {
$min = wpforms_get_min_suffix();
wp_enqueue_script(
'wpforms-builder-panel-loader',
WPFORMS_PLUGIN_URL . "assets/js/admin/builder/panel-loader{$min}.js",
[ 'wpforms-builder' ],
WPFORMS_VERSION,
true
);
}
/**
* Enqueue assets for the payments panel.
*
* @since 1.9.5
*/
public function enqueues_payments() {
$min = wpforms_get_min_suffix();
wp_enqueue_script(
'wpforms-builder-payments-utils',
WPFORMS_PLUGIN_URL . "assets/js/admin/builder/payments-utils{$min}.js",
[ 'wpforms-builder' ],
WPFORMS_VERSION,
true
);
$strings = [
'payments_plan_placeholder' => esc_html__( 'Plan Name', 'wpforms-lite' ),
'payments_disabled_recurring' => esc_html__( 'You can only use one payment type at a time. If you\'d like to enable Recurring Payments, please disable One-Time Payments.', 'wpforms-lite' ),
'payments_disabled_one_time' => esc_html__( 'You can only use one payment type at a time. If you\'d like to enable One-Time Payments, please disable Recurring Payments.', 'wpforms-lite' ),
/* translators: %s - Payment gateway name, e.g. "Stripe". */
'connect_confirm_save' => esc_html__( 'Your form must be saved before you can connect to %s. Save and continue?', 'wpforms-lite' ),
];
wp_localize_script(
'wpforms-builder-payments-utils',
'wpforms_builder_payments_utils',
$strings
);
}
/**
* Primary panel button in the left panel navigation.
*
* @since 1.0.0
*
* @param mixed $form
* @param string $view
*/
public function button( $form, $view ) {
$active = $view === $this->slug ? 'active' : '';
?>
<button class="wpforms-panel-<?php echo esc_attr( $this->slug ); ?>-button <?php echo esc_attr( $active ); ?>" data-panel="<?php echo esc_attr( $this->slug ); ?>">
<i class="fa <?php echo esc_attr( $this->icon ); ?>"></i>
<span><?php echo esc_html( $this->name ); ?></span>
</button>
<?php
}
/**
* Output the contents of the panel.
*
* @since 1.0.0
*
* @param object $form Current form object.
* @param string $view Active Form Builder view (panel).
*/
public function panel_output( $form, $view ) {
$wrap = $this->sidebar ? 'wpforms-panel-sidebar-content' : 'wpforms-panel-full-content';
$classes = [ 'wpforms-panel' ];
// Determine whether the form data is corrupted and a dedicated alert message needs to be shown,
// keep the revisions panel to be able to restore the form.
$is_form_corrupted = is_array( $this->form_data ) && empty( $this->form_data ) && $this->slug !== 'revisions';
if ( in_array( $this->slug, [ 'fields', 'revisions' ], true ) ) {
$classes[] = 'wpforms-panel-fields';
}
if ( $view === $this->slug ) {
$classes[] = 'active';
}
if ( $is_form_corrupted ) {
$classes[] = 'wpforms-panel-corrupted-data';
}
printf( '<div class="%s" id="wpforms-panel-%s">', wpforms_sanitize_classes( $classes, true ), esc_attr( $this->slug ) );
printf( '<div class="%s">', esc_attr( $wrap ) );
if ( $this->sidebar === true && ! $is_form_corrupted ) {
if ( $this->slug === 'fields' ) {
echo '<div class="wpforms-panel-sidebar-toggle"><div class="wpforms-panel-sidebar-toggle-vertical-line"></div><div class="wpforms-panel-sidebar-toggle-icon"><i class="fa fa-angle-left"></i></div></div>';
}
echo '<div class="wpforms-panel-sidebar">';
do_action( 'wpforms_builder_before_panel_sidebar', $this->form, $this->slug );
$this->panel_sidebar();
do_action( 'wpforms_builder_after_panel_sidebar', $this->form, $this->slug );
echo '</div>';
/**
* Allow adding custom content after the panel sidebar in the Form Builder.
*
* @since 1.9.7
*
* @param object $form Current form object.
* @param string $slug Current panel slug.
*/
do_action( 'wpforms_builder_panel_sidebar_after', $this->form, $this->slug );
}
echo '<div class="wpforms-panel-content-wrap">';
echo '<div class="wpforms-panel-content">';
if ( $is_form_corrupted ) {
$this->form_corrupted_message();
} else {
/**
* Allow adding custom content before the panel content in the Form Builder.
*
* @since 1.0.0
*
* @param object $form Current form object.
* @param string $slug Current panel slug.
*/
do_action( 'wpforms_builder_before_panel_content', $this->form, $this->slug ); // phpcs:ignore WPForms.PHP.ValidateHooks.InvalidHookName
$this->panel_content();
/**
* Allow adding custom content after the panel content in the Form Builder.
*
* @since 1.0.0
*
* @param object $form Current form object.
* @param string $slug Current panel slug.
*/
do_action( 'wpforms_builder_after_panel_content', $this->form, $this->slug ); // phpcs:ignore WPForms.PHP.ValidateHooks.InvalidHookName
}
echo '</div>';
echo '</div>';
echo '</div>';
echo '</div>';
}
/**
* Output the panel's sidebar if we have one.
*
* @since 1.0.0
*/
public function panel_sidebar() {
}
/**
* Output panel sidebar sections.
*
* @since 1.0.0
*
* @param string $name Sidebar section name.
* @param string $slug Sidebar section slug.
* @param string $icon Sidebar section icon.
*/
public function panel_sidebar_section( $name, $slug, $icon = '' ) {
$default_classes = [
'wpforms-panel-sidebar-section',
'wpforms-panel-sidebar-section-' . $slug,
];
if ( $slug === 'default' ) {
$default_classes[] = 'default';
}
if ( ! empty( $icon ) ) {
$default_classes[] = 'icon';
}
/**
* Allow adding custom CSS classes to a sidebar section in the Form Builder.
*
* @since 1.7.7.2
*
* @param array $classes Sidebar section classes.
* @param string $name Sidebar section name.
* @param string $slug Sidebar section slug.
* @param string $icon Sidebar section icon.
*/
$classes = (array) apply_filters( 'wpforms_builder_panel_sidebar_section_classes', [], $name, $slug, $icon );
$classes = array_merge( $default_classes, $classes );
echo '<a href="#" class="' . wpforms_sanitize_classes( $classes, true ) . '" data-section="' . esc_attr( $slug ) . '">';
if ( ! empty( $icon ) ) {
echo '<img src="' . esc_url( $icon ) . '">';
}
echo esc_html( $name );
echo '<i class="fa fa-angle-right wpforms-toggle-arrow"></i>';
echo '</a>';
}
/**
* Output the panel's primary content.
*
* @since 1.0.0
*/
public function panel_content() {
}
/**
* Error message for a corrupted form.
*
* @since 1.9.7
*/
private function form_corrupted_message(): void {
?>
<div class="wpforms-builder-preview-corrupted-data-content">
<div class="wpforms-builder-corrupted-data-title">
<h2>
<?php esc_html_e( 'Corrupted Form Data', 'wpforms-lite' ); ?>
</h2>
</div>
<div>
<p>
<?php
printf(
wp_kses(
__( 'A critical error has occurred, preventing your form from loading. This issue may arise from incorrect code in a third-party theme or plugin, or from invalid characters in your form. You can attempt to restore a previous version of your form using <a href="#" class="wpforms-panel-content-revisions-link">Form Revisions</a>.', 'wpforms-lite' ),
[
'a' => [
'href' => [],
'class' => [],
],
]
)
);
?>
</p>
<br>
<p>
<?php
printf(
wp_kses( /* translators: %s - WPForms contact support link. */
__( 'If the issue persists, <a href="%s" target="_blank" rel="noopener noreferrer">please contact support</a>.', 'wpforms-lite' ),
[
'a' => [
'href' => [],
'target' => [],
'rel' => [],
],
]
),
esc_url( wpforms_utm_link( 'https://wpforms.com/account/support/', 'Corrupted Form Data' ) )
);
?>
</p>
</div>
</div>
<?php
}
}