PluginProbe
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) / 1.8.11.3
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) v1.8.11.3
1.8.13.1 1.8.13 1.8.12.3 1.8.12.2 1.8.12.1 1.8.12 1.8.11.3 1.8.11.2 1.8.11.1 1.8.11 1.6.6 1.6.60 1.6.7 1.6.8 1.6.9 1.7.0 1.7.0.1 1.7.0.11 1.7.0.12 1.7.0.14 1.7.0.2 1.7.0.3 1.7.0.5 1.7.0.6 1.7.0.7 All 212 releases
charitable / includes / admin / campaign-builder / panels / class-design.php

class-design.php in Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) 1.8.11.3, at includes/admin/campaign-builder/panels/class-design.php

1,270 lines 52.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Design class management panel.
4 *
5 * @package Charitable
6 * @author David Bisset
7 * @copyright Copyright (c) 2023, WP Charitable LLC
8 * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9 * @since 1.8.0
10 * @version 1.8.0
11 */
12
13 if ( ! defined( 'ABSPATH' ) ) {
14 exit;
15 }
16
17 if ( ! class_exists( 'Charitable_Builder_Panel_Design' ) ) :
18
19 /**
20 * Design class management panel.
21 *
22 * @package Charitable
23 * @author David Bisset
24 * @copyright Copyright (c) 2023, WP Charitable LLC
25 * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
26 * @since 1.8.0
27 * @version 1.8.0
28 */
29 class Charitable_Builder_Panel_Design extends Charitable_Builder_Panel {
30
31 /**
32 * Form data and settings.
33 *
34 * @since 1.8.0
35 *
36 * @var array
37 */
38 public $campaign_data;
39
40 /**
41 * Template addon labels data.
42 *
43 * @since 1.8.0
44 *
45 * @var array
46 */
47 private $addon_labels;
48
49 /**
50 * All systems go.
51 *
52 * @since 1.8.0
53 */
54 public function init() {
55
56 // Define panel information.
57 $this->name = esc_html__( 'Design', 'charitable' );
58 $this->slug = 'design';
59 $this->icon = 'panel_design.svg';
60 $this->order = 20;
61 $this->sidebar = true;
62
63 add_action( 'charitable_builder_fields', [ $this, 'fields' ] );
64 add_action( 'charitable_builder_fields_options', [ $this, 'fields_options' ] );
65 add_action( 'charitable_builder_preview', [ $this, 'preview' ] );
66
67 // Template for Campaign builder previews.
68 add_action( 'charitable_builder_print_footer_scripts', [ $this, 'design_preview_templates' ] );
69 }
70
71 /**
72 * Enqueue assets for the Design panel.
73 *
74 * @since 1.8.0
75 */
76 public function enqueues() {
77
78 $min = charitable_get_min_suffix();
79
80 wp_enqueue_script(
81 'charitable-builder-drag-fields',
82 charitable()->get_path( 'directory', false ) . "assets/js/campaign-builder/drag-fields{$min}.js",
83 [ 'charitable-builder' ],
84 charitable()->get_version(),
85 true
86 );
87 }
88
89 /**
90 * Output the Field panel sidebar.
91 *
92 * @since 1.8.0
93 */
94 public function panel_sidebar() {
95
96 // This should never be called unless we are on the campaign builder page.
97 if ( ! campaign_is_campaign_builder_admin_page() ) {
98 return;
99 }
100 ?>
101 <ul class="charitable-tabs charitable-clear">
102
103 <li class="charitable-tab" id="add-layout">
104 <a href="#" class="active">
105 <?php esc_html_e( 'Add Layout', 'charitable' ); ?>
106 </a>
107 </li>
108
109 <li class="charitable-tab" id="layout-options">
110 <a href="#">
111 <?php esc_html_e( 'Layout Options', 'charitable' ); ?>
112 </a>
113 </li>
114
115 </ul>
116
117
118 <?php
119
120 $display_tour_divs = Charitable_Campaign_Builder::get_instance()->display_tour_divs();
121
122 if ( $display_tour_divs ) :
123 ?>
124
125 <div id="charitable-tour-block-1" class="charitable-tour-block"></div>
126 <div id="charitable-tour-block-2" class="charitable-tour-block"></div>
127 <div id="charitable-tour-block-3" class="charitable-tour-block"></div>
128
129 <?php endif; ?>
130
131 <div class="charitable-add-fields charitable-tab-content">
132 <?php do_action( 'charitable_builder_fields', $this->campaign_data ); ?>
133 </div>
134
135 <div id="charitable-field-options" class="charitable-field-options charitable-tab-content">
136 <?php do_action( 'charitable_builder_fields_options', $this->campaign_data ); ?>
137 </div>
138
139 <?php
140 }
141
142 /**
143 * Output the Field panel primary content.
144 *
145 * @since 1.8.0
146 */
147 public function panel_content() {
148
149 // todo: think if there is campaign data to load if this is a brand new campaign?
150
151 $template_id = isset( $this->campaign_data['template_id'] ) ? esc_attr( $this->campaign_data['template_id'] ) : charitable_campaign_builder_default_template();
152 $campaign_id = isset( $this->campaign_data['campaign_id'] ) ? esc_attr( $this->campaign_data['campaign_id'] ) : false;
153 $campaign_title = isset( $this->campaign_data['title'] ) ? esc_html( $this->campaign_data['title'] ) : esc_html( $this->campaign->post_title );
154
155 $builder_template = new Charitable_Campaign_Builder_Templates();
156 $template_data = $builder_template->get_template_data( $template_id );
157
158 /* get status */
159 $campaign = $campaign_id ? charitable_get_campaign( $campaign_id ) : false;
160 $status = $campaign ? $campaign->get_status() : false;
161 if ( 'finished' === $status && $campaign->has_goal() ) {
162 $status = $campaign->has_achieved_goal() ? 'successful' : 'unsuccessful';
163 }
164 $campaign_status = $campaign ? '<mark class="charitable-builder-status-' . esc_attr( $status ) . '">' . $status . '</mark>' : false;
165
166 /* establish any classes to add to preview wrap upon load */
167 $preview_wrap_classes = array( 'charitable-preview-wrap' );
168 if ( ! empty( $this->campaign_data['layout']['advanced']['show_field_names'] ) && 'hide' === $this->campaign_data['layout']['advanced']['show_field_names'] ) {
169 $preview_wrap_classes[] = 'charitable-preview-hide-field-names';
170 }
171 if ( ! empty( $this->campaign_data['layout']['advanced']['preview_mode'] ) && 'minimum' === $this->campaign_data['layout']['advanced']['preview_mode'] ) {
172 $preview_wrap_classes[] = 'charitable-preview-minimum-preview';
173 }
174 $preview_wrap_classes = trim( implode( ' ', $preview_wrap_classes ) );
175 ?>
176
177 <div class="<?php echo esc_attr( $preview_wrap_classes ); ?>">
178
179 <div class="charitable-preview charitable-builder-template-<?php echo esc_attr( $template_id ); ?>">
180
181 <div class="charitable-preview-top-bar">
182 <div class="charitable-preview-top-bar-inner-left">
183 <h2 class="charitable-form-name">
184 <?php echo esc_html( stripslashes( $campaign_title ) ); ?>
185 </h2>
186 </div>
187 <div class="charitable-preview-top-bar-inner-right">
188 <?php if ( 0 !== intval( $campaign_id ) && $campaign_status && 'draft' !== $campaign_status ) : ?>
189 <span class="charitable-view-campaign-external-link"><a href="<?php echo esc_url( get_permalink( $campaign_id ) ); ?>" target="_blank" title="View Campaign Page"><?php /* <i class="fa fa-eye"></i> */ ?></a></span>
190 <?php endif; ?>
191 </div>
192 </div>
193
194 <div class="charitable-no-design-holder charitable-hidden"></div>
195
196 <div class="charitable-design-wrap" id="charitable-design-wrap">
197 <?php do_action( 'charitable_builder_preview', $this->campaign ); ?>
198 </div>
199
200 <?php
201 // This action is documented in includes/class-frontend.php.
202 do_action( 'charitable_display_submit_after', $this->campaign_data, 'submit' ); // phpcs:ignore Charitable.PHP.ValidateHooks.InvalidHookName
203
204 ?>
205
206 <?php charitable_builder_debug_data( $this->campaign_data ); ?>
207 </div>
208
209 </div>
210
211 <?php
212 }
213
214 /**
215 * Builder field buttons.
216 *
217 * @since 1.8.0
218 * @param array $campaign_data Campaign Data.
219 */
220 public function fields( $campaign_data = false ) {
221
222 $fields = [
223 'recommended' => [
224 'group_name' => esc_html__( 'Recommended', 'charitable' ),
225 'description' => false,
226 'fields' => [],
227 ],
228 'standard' => [
229 'group_name' => esc_html__( 'Standard', 'charitable' ),
230 'description' => false,
231 'fields' => [],
232 ],
233 'pro' => [
234 'group_name' => esc_html__( 'Pro', 'charitable' ),
235 'description' => false,
236 'fields' => [],
237 ],
238 ];
239
240 /**
241 * Allows developers to modify content of the the Add Field tab.
242 *
243 * With this filter developers can add their own fields or even fields groups.
244 *
245 * @since 1.8.0
246 *
247 * @param array $fields {
248 * Design data multidimensional array.
249 *
250 * @param array $recommended Recommended fields group.
251 * @param string $group_name Group name.
252 * @param array $fields Design array.
253 *
254 * @param array $standard Standard fields group.
255 * @param string $group_name Group name.
256 * @param array $fields Design array.
257 *
258 * @param array $pro Pro fields group.
259 * @param string $group_name Group name.
260 * @param array $fields Design array.
261 * }
262 */
263
264 $fields = apply_filters( 'charitable_builder_design_buttons', $fields );
265
266 // If there is campaign data, make a list of fields already in use which might determine what CSS classes (etC) gets passed to the buttons on the left.
267 $fields_in_template = array();
268 if ( false !== $campaign_data ) {
269 if ( ! empty( $campaign_data['layout']['rows'] ) ) {
270 foreach ( $campaign_data['layout']['rows'] as $row ) {
271 if ( ! empty( $row['fields'] ) ) {
272 $fields_in_template = array_merge( $fields_in_template, $row['fields'] );
273 }
274 }
275 }
276 }
277
278 $donation_form_display = charitable_get_option( 'donation_form_display' );
279
280 // Output the buttons.
281 foreach ( $fields as $id => $group ) {
282
283 usort( $group['fields'], [ $this, 'field_order' ] );
284
285 echo '<div class="charitable-add-fields-group charitable-add-fields-group-' . esc_attr( $id ) . '">';
286
287 echo '<a href="#" class="charitable-add-fields-heading charitable-add-fields-heading-' . esc_attr( $id ) . '" data-group="' . esc_attr( $id ) . '">';
288
289 echo '<span>' . esc_html( $group['group_name'] ) . '</span>';
290
291 if ( $group['description'] ) :
292 echo '<span class="charitable-group-description"><small>' . esc_html( $group['description'] ) . '</small></span>';
293 endif;
294
295 echo '<i class="fa fa-angle-down charitable-toggleable-group"></i>';
296
297 echo '</a>';
298
299 echo '<div class="charitable-group-rows"><div class="charitable-add-fields-buttons">';
300
301 foreach ( $group['fields'] as $field ) {
302
303 // If we are loading an already established campaign template, then the 'is the add button disabled' needs/should try to happen in the PHP rendering side.
304 $add_field_button_classes = array( 'charitable-add-fields-button' );
305 $maybe_disable_add_button = $this->maybe_disable_add_button( $field['type'], $fields_in_template, $campaign_data, $donation_form_display );
306
307 if ( ! empty( $campaign_data ) && false !== $maybe_disable_add_button ) {
308 $add_field_button_classes[] = 'charitable-disabled';
309
310 if ( strlen( $maybe_disable_add_button ) > 1 ) {
311 $add_field_button_classes[] = 'charitable-disabled' . $maybe_disable_add_button;
312 }
313 }
314
315 $add_field_button_classes[] = 'charitable-has-field';
316
317 /**
318 * Attributes of the form field button on the Add Design tab in the Campaign Builder.
319 *
320 * @since 1.8.0
321 *
322 * @param array $attributes Field attributes.
323 * @param array $field Field data.
324 * @param array $form_data Form data.
325 */
326 $atts = apply_filters(
327 'charitable_builder_field_button_attributes',
328 [
329 'id' => 'charitable-add-fields-' . $field['type'],
330 'class' => $add_field_button_classes,
331 'data' => [
332 'field-type' => $field['type'],
333 'field-icon' => $field['icon'],
334 ],
335 'font-prefix' => 'fa',
336 'atts' => [],
337 ],
338 $field,
339 $this->campaign_data,
340 $fields_in_template
341 );
342
343 if ( ! empty( $field['class'] ) ) {
344 $atts['class'][] = $field['class'];
345 }
346
347 echo '<div class="charitable-add-fields-button-wrap">';
348
349 // Deal with recommended checkmarks.
350 if ( 'recommended' === $id ) {
351 $checked_or_not = ( 'recommended' === $id && in_array( $field['type'], $fields_in_template, true ) ) ? 'checked' : 'unchecked';
352 echo '<div class="charitable-check ' . $checked_or_not . '"></div>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
353 }
354
355 echo '<button ' . charitable_html_attributes( $atts['id'], $atts['class'], $atts['data'], $atts['atts'] ) . '>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
356 if ( $field['icon'] ) {
357 echo '<i class="' . esc_attr( $atts['font-prefix'] ) . ' ' . esc_attr( $field['icon'] ) . '"></i> ';
358 }
359 echo esc_html( $field['name'] );
360 echo '</button>';
361
362 echo '</div>';
363 }
364
365 echo '</div>
366 </div>';
367
368 echo '</div>';
369 }
370 }
371
372 /**
373 * Determine if we need to disable an add field button in the builder (left).
374 *
375 * @since 1.8.0
376 *
377 * @param string $button_type The type of button to check.
378 * @param bool $fields_in_template Whether the fields are in the template.
379 * @param bool $campaign_data The campaign data.
380 * @param bool $donation_form_display Whether the donation form is displayed.
381 */
382 public function maybe_disable_add_button( $button_type = '', $fields_in_template = false, $campaign_data = false, $donation_form_display = false ) {
383
384 if ( '' === trim( $button_type ) || false === $fields_in_template ) {
385 return false;
386 }
387
388 // If "modal" is set to true and the field is a form or donate amount, immedately reject because these elements shouldn't be available when the donation form is a modal.
389 if ( 'modal' === $donation_form_display ) {
390 if ( $button_type === 'donation-form' || $button_type === 'donate-amount' ) {
391 return '-modal';
392 }
393 } elseif ( 'same_page' === $donation_form_display ) {
394 if ( $button_type === 'donation-form' || $button_type === 'donate-amount' || $button_type === 'donate-button' ) {
395 return '-same_page';
396 }
397 }
398
399 // check the field deny list.
400 $deny_list = array(
401 'donation-form' => array(
402 'donate-button' => 0,
403 'donation-form' => 0,
404 'donate-amount' => 0,
405 ),
406 'donate-button' => array(
407 'donation-form' => 0,
408 ),
409 'donate-amount' => array(
410 'donation-form' => 0,
411 ),
412 );
413
414 // for example: donate-amount should be enabled unless donation form is present.
415 foreach ( $deny_list as $field_exists => $fields_to_check ) {
416 foreach ( $fields_to_check as $field_to_check => $field_amount_limit ) {
417 // if the key of the sub array isn't 'donate-amount' skip this.
418 if ( $field_to_check !== $button_type ) {
419 continue;
420 }
421
422 // ok, we found 'donate-amount' but 'donation-form' doesn't exist, so skip this.
423 if ( ! in_array( $field_exists, $fields_in_template, true ) ) {
424 continue;
425 }
426
427 $vals = array_count_values( $fields_in_template );
428
429 // ok if donation form exists determine how many 'donate-amount' are allowed to exist before disabling the add field in the builder.
430 if ( isset( $vals[ $field_to_check ] ) && $field_amount_limit <= $vals[ $field_to_check ] ) {
431 return true;
432 }
433 }
434 }
435
436 return false;
437 }
438
439 /**
440 * Editor Field Options.
441 *
442 * @since 1.8.0
443 */
444 public function fields_options() {
445
446 // Check to make sure the form actually has fields created already.
447 if ( empty( $this->campaign_data['design'] ) ) {
448 $this->general_design_options();
449
450 return;
451 }
452
453 $fields = $this->campaign_data['design'];
454
455 foreach ( $fields as $field ) {
456
457 $class = apply_filters( 'charitable_builder_field_option_class', '', $field );
458
459 printf( '<div class="charitable-design-option charitable-design-option-%s %s" id="charitable-design-option-%d" data-design-id="%d">', sanitize_html_class( $field['type'] ), charitable_sanitize_classes( $class ), (int) $field['id'], (int) $field['id'] ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
460
461 printf( '<input type="hidden" name="fields[%d][id]" value="%d" class="charitable-design-option-hidden-id">', (int) $field['id'], (int) $field['id'] );
462
463 printf( '<input type="hidden" name="fields[%d][type]" value="%s" class="charitable-design-option-hidden-type">', (int) $field['id'], esc_attr( $field['type'] ) );
464
465 do_action( "charitable_builder_design_options_{$field['type']}", $field );
466
467 echo '</div>';
468 }
469 }
470
471 /**
472 * Generate HTML for hidden inputs from given data.
473 *
474 * @since 1.8.0
475 *
476 * @param array $data Field array data.
477 * @param string $name Input name prefix.
478 */
479 private function generate_hidden_inputs( $data = [], $name = '' ) {
480
481 if ( ! is_array( $data ) || empty( $data ) ) {
482 return;
483 }
484
485 foreach ( $data as $key => $value ) {
486 if ( $key === 'id' ) {
487 continue;
488 }
489
490 $key = ! empty( $data['id'] ) ? sprintf( '[%s][%s]', $data['id'], $key ) : sprintf( '[%s]', $key );
491
492 if ( ! empty( $name ) ) {
493 $key = trim( $name ) . $key;
494 }
495
496 if ( is_array( $value ) ) {
497 $this->generate_hidden_inputs( $value, $key );
498 } else {
499 printf( "<input type='hidden' name='%s' value='%s' />", esc_attr( $key ), esc_attr( $value ) );
500 }
501 }
502 }
503
504 /**
505 * No fields options markup.
506 *
507 * @since 1.6.0
508 */
509 public function no_design_options() {
510
511 printf(
512 '<p class="no-design charitable-alert charitable-alert-warning">%s</p>',
513 esc_html__( 'You don\'t have any fields yet.', 'charitable' )
514 );
515 }
516
517 /**
518 * No fields preview placeholder markup.
519 *
520 * @since 1.8.0
521 */
522 public function no_design_preview() {
523 }
524
525 /**
526 * No fields options markup.
527 *
528 * @since 1.8.0
529 */
530 public function general_design_options() {
531
532 // layout options
533 // -> general.
534 // -> advanced.
535
536 $tabs = isset( $this->campaign_data['tabs'] ) ? $this->campaign_data['tabs'] : false;
537 $max_tab_title_length = apply_filters( 'charitable_builder_design_tab_title_length', 20 );
538
539 ?>
540
541 <!-- sub tab -->
542 <div class="charitable-layout-options-tab charitable-layout-options-tab-general active" id="">
543 <a href="#" class="charitable-group-toggle charitable-layout-options-group-toggle"><?php echo esc_html__( 'General', 'charitable' ); ?></a>
544 <!-- container -->
545 <div class="charitable-layout-options-group-inner">
546
547 <div class="charitable-select-field-notice"><?php echo esc_html__( 'Select a field in the preview area to set it\'s settings.', 'charitable' ); ?></div>
548 <?php
549
550 if ( ! empty( $this->campaign_data['layout']['rows'] ) ) :
551
552 foreach ( $this->campaign_data['layout']['rows'] as $row_id => $row ) :
553
554 // header.
555 if ( isset( $row['fields'] ) ) {
556
557 $row_type = $row['type'];
558
559 if ( 'row' === $row_type || 'header' === $row_type ) {
560
561 foreach ( $row['fields'] as $field_id => $field_type ) {
562
563 $type = 'Charitable_Field_' . str_replace( ' ', '_', ( ucwords( str_replace( '-', ' ', $field_type ) ) ) );
564
565 if ( class_exists( $type ) ) :
566 $class = new $type();
567 if ( method_exists( $class, 'settings_display' ) ) {
568 echo $class->settings_display( $field_id, $this->campaign_data ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
569 }
570 endif;
571 }
572 } elseif ( 'tabs' === $row_type ) {
573
574 foreach ( $row['tabs'] as $tab_id => $tab ) {
575
576 foreach ( $tab as $field_id_key => $field_id ) {
577
578 $field_type = $this->campaign_data['layout']['rows'][ $row_id ]['fields'][ $field_id ];
579
580 $type = 'Charitable_Field_' . str_replace( ' ', '_', ( ucwords( str_replace( '-', ' ', $field_type ) ) ) );
581
582 if ( class_exists( $type ) ) :
583 $class = new $type();
584 if ( method_exists( $class, 'settings_display' ) ) {
585 echo $class->settings_display( $field_id, $this->campaign_data ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
586 }
587 endif;
588 }
589 }
590 }
591 }
592
593 endforeach;
594
595 endif;
596 ?>
597 </div>
598 </div> <!-- end tab -->
599
600 <!-- sub tab -->
601 <div class="charitable-layout-options-tab charitable-layout-options-tab-tabs" id="">
602 <a href="#" class="charitable-group-toggle charitable-layout-options-tabs-toggle"><?php echo esc_html__( 'Tabs', 'charitable' ); ?></a>
603 <!-- container -->
604 <div class="charitable-layout-options-group-inner class-design">
605
606 <?php $enable_tabs = isset( $this->campaign_data['layout']['advanced']['enable_tabs'] ) && '' !== trim( $this->campaign_data['layout']['advanced']['enable_tabs'] ) ? $this->campaign_data['layout']['advanced']['enable_tabs'] : 'enabled'; ?>
607
608 <div data-field-id="" id="charitable-group-row-design-layout-options-tabs-enable" class="charitable-panel-field charitable-panel-field-toggle " data-ajax-label="enable_tabs">
609 <span class="charitable-toggle-control">
610 <input type="checkbox" id="charitable-panel-field-settings-charitable-campaign-enable-tabs" name="layout__advanced__enable_tabs" data-advanced-field-id="enable_tabs" value="disabled" <?php checked( $enable_tabs, 'disabled' ); ?> />
611 <label class="charitable-toggle-control-icon" for="charitable-panel-field-settings-charitable-campaign-enable-tabs"></label>
612 <label for="charitable-panel-field-settings-charitable-campaign-enable-tabs"><?php echo esc_html__( 'Hide All Tabs.', 'charitable' ); ?> </label>
613 <?php echo charitable_get_tooltip_html( __( 'Turn this on to remove tabs from your campaign page.', 'charitable' ), 'tooltipstered' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
614 </span>
615 </div>
616
617 <hr />
618
619 <!-- group -->
620 <div class="charitable-group charitable-layout-options-tab-group charitable-closed charitable-new-tab hidden" data-group_id="2">
621 <div class="charitable-general-layout-heading" data-group="general-layout-tab">
622 <a href="#" class="charitable-draggable"><i class="fa fa-bars"></i></a>
623 <span>[ <?php echo esc_html__( 'New Tab', 'charitable' ); ?> ]</span>
624 <a href="#" class="charitable-toggleable-group"><i class="fa fa-angle-down charitable-angle-down"></i></a>
625 <a href="#" class="charitable-tab-group-delete" title="Delete Tab"><i class="fa fa-trash-o" aria-hidden="true"></i></a>
626
627 </div>
628 <!-- rows -->
629 <div class="charitable-group-rows">
630 <!-- row -->
631 <div class="charitable-group-row charitable-tab-title-row" id="tabs_xxx_row_title" data-field-id="">
632 <label for=""><?php echo esc_html__( 'Title', 'charitable' ); ?>
633 <?php echo charitable_get_tooltip_html( __( 'Title appears on the tab in the tab navigation.', 'charitable' ), 'tooltipstered' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
634 <input type="text" class="" id="tabs_xxx_title" name="tabs__xxx__title" value="" placeholder="<?php echo esc_html__( 'Tab Title', 'charitable' ); ?> " maxlength="<?php echo intval( $max_tab_title_length ); ?>">
635 </div>
636 <div class="charitable-group-row charitable-tab-title-row" id="tabs_xxx_row_visible_nav" data-tab-id="">
637 <span class="charitable-toggle-control">
638 <input type="checkbox" id="tabs_xxx_visible_nav" class="charitable-settings-tab-visible-nav" name="tabs__xxx__visible_nav" value="invisible" />
639 <label class="charitable-toggle-control-icon" for="tabs_xxx_visible_nav"></label>
640 <label for="tabs_xxx_visible_nav"><?php echo esc_html__( 'Hide tab navigation.', 'charitable' ); ?></label>
641 <?php echo charitable_get_tooltip_html( __( 'Hide the tab in the navigation bar (only if you have one tab in your design).', 'charitable' ), 'tooltipstered' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
642 </span>
643 </div>
644 </div>
645 <!-- end rows -->
646 </div> <!-- end group -->
647 <?php
648
649 // This outputs the tab interface in layout options -> tabs.
650
651 if ( $tabs ) {
652
653 $counter = 0;
654
655 $number_of_tabs = count( $tabs );
656 $hide_tab_nav_disabled = $number_of_tabs > 1 ? 'disabled="disabled"' : false;
657
658 foreach ( $tabs as $tab_id => $tab_info ) :
659
660 $group_id = ( strtolower( $tab_id ) === 'campaign' ) ? 0 : $tab_id;
661 $group_name_var = ( $tab_id === 'campaign' ) ? $group_id : $group_id;
662 $group_title = isset( $tab_info['title'] ) && '' !== trim( $tab_info['title'] ) ? $tab_info['title'] : '[ New Tab ]';
663 $group_header = ( $tab_id === 'campaign' ) ? 'Campaign' : $group_title;
664 $group_desc = isset( $tab_info['desc'] ) && '' !== trim( $tab_info['desc'] ) ? $tab_info['desc'] : false;
665 $group_classes = isset( $tab_info['title'] ) && '' !== trim( $tab_info['title'] ) ? false : 'charitable-new-tab';
666 $data_group = ( $tab_id === 'campaign' ) ? 'general-layout-tab' : 'general-layout-tab';
667 $active = $counter === 0 ? 'active' : false;
668 $closed = $counter === 0 ? 'charitable-open' : 'charitable-closed';
669 $arrow_icon = ! $active ? 'fa fa-angle-down charitable-angle-right' : 'fa fa-angle-down charitable-angle-down';
670 $type = ( isset( $tab_info['type'] ) && '' !== trim( $tab_info['type'] ) ) ? $tab_info['type'] : 'html';
671 $row_class = 'html' !== $type ? 'hidden' : false;
672
673 $visible_nav = ! empty( $tab_info['visible_nav'] ) && 'invisible' === $tab_info['visible_nav'] ? 'checked="checked"' : '';
674 $visible_nav_checked = ! empty( $tab_info['visible_nav'] ) && 'invisible' === $tab_info['visible_nav'] ? 'checked="checked"' : '';
675 $visible_nav_checked = ( false !== $hide_tab_nav_disabled ) ? '' : $visible_nav_checked;
676 $disabled_css = ( false !== $hide_tab_nav_disabled ) ? 'charitable-disabled' : false;
677
678 ?>
679
680 <!-- group -->
681 <div class="charitable-group charitable-layout-options-tab-group <?php echo esc_attr( $group_classes ); ?> <?php echo esc_attr( $closed ); ?> <?php echo esc_attr( $active ); ?>" data-group_id="<?php echo esc_attr( $group_id ); ?>">
682 <div class="charitable-general-layout-heading" data-group="<?php echo esc_attr( $data_group ); ?>">
683 <a href="#" class="charitable-draggable"><i class="fa fa-bars"></i></a>
684 <span><?php echo esc_html( $group_header ); ?></span>
685 <a href="#" class="charitable-toggleable-group"><i class="<?php echo esc_attr( $arrow_icon ); ?>"></i></a>
686 <a href="#" class="charitable-tab-group-delete" title="Delete Tab"><i class="fa fa-trash-o" aria-hidden="true"></i></a>
687
688 </div>
689 <!-- rows -->
690 <div class="charitable-group-rows">
691 <!-- row -->
692 <div class="charitable-group-row charitable-tab-title-row" id="row_tabs__<?php echo esc_attr( $group_name_var ); ?>__title" data-tab-id="<?php echo esc_attr( $group_name_var ); ?>">
693 <label for=""><?php echo esc_html__( 'Title', 'charitable' ); ?> <?php echo charitable_get_tooltip_html( false, 'tooltipstered' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
694 <input type="text" class="" id="" name="tabs__<?php echo esc_attr( $group_name_var ); ?>__title" value="<?php echo esc_attr( $group_title ); ?>" placeholder="" maxlength="<?php echo intval( $max_tab_title_length ); ?>">
695 </div>
696 <div class="charitable-group-row charitable-tab-title-row" id="row_tabs__<?php echo esc_attr( $group_name_var ); ?>__visible_nav" data-tab-id="<?php echo esc_attr( $group_name_var ); ?>">
697 <span class="charitable-toggle-control">
698 <input type="checkbox" id="charitable-panel-field-settings-charitable-campaign-<?php echo esc_attr( $group_name_var ); ?>__visible_nav" class="charitable-settings-tab-visible-nav"
699 name="tabs__<?php echo esc_attr( $group_name_var ); ?>__visible_nav" value="invisible" <?php echo esc_attr( $visible_nav_checked ); ?> />
700 <label class="charitable-toggle-control-icon" for="charitable-panel-field-settings-charitable-campaign-<?php echo esc_attr( $group_name_var ); ?>__visible_nav"></label>
701 <label class="<?php echo esc_attr( $disabled_css ); ?>" for="charitable-panel-field-settings-charitable-campaign-<?php echo esc_attr( $group_name_var ); ?>__visible_nav"><?php echo esc_html__( 'Hide tab navigation.', 'charitable' ); ?></label>
702 <?php echo charitable_get_tooltip_html( __( 'Hide the tab in the navigation bar (only if you have one tab in your design).', 'charitable' ), 'tooltipstered' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
703 </span>
704 </div>
705 <!-- row -->
706 </div>
707 <!-- end rows -->
708 </div> <!-- end group -->
709
710 <?php ++$counter; ?>
711
712 <?php
713 endforeach;
714
715 }
716
717 ?>
718 <!-- button -->
719 <button class="charitable-tab-groups-add charitable-btn charitable-btn-sm"><?php echo esc_html__( '+ Add New Tab', 'charitable' ); ?></button>
720 <!-- end button -->
721 </div> <!-- end container -->
722 </div> <!-- end tab -->
723
724 <?php
725
726 $tab_style = isset( $this->campaign_data['layout']['advanced']['tab_style'] ) && '' !== trim( $this->campaign_data['layout']['advanced']['tab_style'] ) ? $this->campaign_data['layout']['advanced']['tab_style'] : 'boxed';
727 $tab_size = isset( $this->campaign_data['layout']['advanced']['tab_size'] ) && '' !== trim( $this->campaign_data['layout']['advanced']['tab_size'] ) ? $this->campaign_data['layout']['advanced']['tab_size'] : 'medium';
728 $preview_mode = isset( $this->campaign_data['layout']['advanced']['preview_mode'] ) && '' !== trim( $this->campaign_data['layout']['advanced']['preview_mode'] ) ? $this->campaign_data['layout']['advanced']['preview_mode'] : 'normal';
729
730 $show_field_names_default = charitable_show_field_names_by_default() ? 'show' : 'hide';
731 $show_field_names = isset( $this->campaign_data['layout']['advanced']['show_field_names'] ) && '' !== trim( $this->campaign_data['layout']['advanced']['show_field_names'] ) ? $this->campaign_data['layout']['advanced']['show_field_names'] : $show_field_names_default;
732
733 // todo: filter these.
734
735 $theme_color_primary = isset( $this->campaign_data['layout']['advanced']['theme_color_primary'] ) && '' !== trim( $this->campaign_data['layout']['advanced']['theme_color_primary'] ) ? $this->campaign_data['layout']['advanced']['theme_color_primary'] : '';
736 $theme_color_secondary = isset( $this->campaign_data['layout']['advanced']['theme_color_secondary'] ) && '' !== trim( $this->campaign_data['layout']['advanced']['theme_color_secondary'] ) ? $this->campaign_data['layout']['advanced']['theme_color_secondary'] : '';
737 $theme_color_tertiary = isset( $this->campaign_data['layout']['advanced']['theme_color_tertiary'] ) && '' !== trim( $this->campaign_data['layout']['advanced']['theme_color_tertiary'] ) ? $this->campaign_data['layout']['advanced']['theme_color_tertiary'] : '';
738 $theme_color_button = isset( $this->campaign_data['layout']['advanced']['theme_color_button'] ) && '' !== trim( $this->campaign_data['layout']['advanced']['theme_color_button'] ) ? $this->campaign_data['layout']['advanced']['theme_color_button'] : '';
739
740 // tab enabled/disabled.
741 $enable_tabs_css = isset( $this->campaign_data['layout']['advanced']['enable_tabs'] ) && '' !== trim( $this->campaign_data['layout']['advanced']['enable_tabs'] ) ? 'disabled' : '';
742
743 ?>
744
745 <!-- sub tab -->
746 <div class="charitable-layout-options-tab charitable-layout-options-tab-advanced" id="">
747 <a href="#" class="charitable-group-toggle charitable-layout-options-group-toggle"><?php echo esc_html__( 'Advanced', 'charitable' ); ?> </a>
748 <!-- container -->
749 <div class="charitable-layout-options-group-inner">
750 <!-- group -->
751 <div class="charitable-group charitable-layout-options-advanced-group">
752 <!-- rows -->
753 <div class="charitable-group-rows row-first">
754 <!-- row -->
755 <div class="charitable-group-row" id="charitable-group-row-design-layout-options-advanced-tab-style">
756 <label for="charitable-design-layout-options-advanced-tab-style"><?php echo esc_html__( 'Tab Style', 'charitable' ); ?> <?php echo charitable_get_tooltip_html( esc_html__( 'Overall tab size in the template.', 'charitable' ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
757 </label>
758 <select class="charitable-design-layout-options-advanced-tab-style <?php echo esc_attr( $enable_tabs_css ); ?>" id="charitable-design-layout-options-advanced-tab-style" name="layout__advanced__tab_style" data-advanced-field-id="tab_style" <?php echo esc_attr( $enable_tabs_css ); ?>>
759 <option value="boxed" <?php selected( $tab_style, 'boxed' ); ?>><?php echo esc_html__( 'Boxed', 'charitable' ); ?></option>
760 <option value="rounded" <?php selected( $tab_style, 'rounded' ); ?>><?php echo esc_html__( 'Rounded', 'charitable' ); ?></option>
761 <option value="minimum" <?php selected( $tab_style, 'minimum' ); ?>><?php echo esc_html__( 'Minimum', 'charitable' ); ?></option>
762 </select>
763 </div>
764 <!-- row -->
765 <div class="charitable-group-row" id="charitable-group-row-design-layout-options-advanced-tab-size">
766 <label for="charitable-design-layout-options-advanced-tab-size"><?php echo esc_html__( 'Tab Size', 'charitable' ); ?> <?php echo charitable_get_tooltip_html( esc_html__( 'Overall text size inside the tab.', 'charitable' ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
767 </label>
768 <select class="charitable-design-layout-options-advanced-tab-size <?php echo esc_attr( $enable_tabs_css ); ?>" id="charitable-design-layout-options-advanced-tab-size" name="layout__advanced__tab_size" data-advanced-field-id="tab_size" <?php echo esc_attr( $enable_tabs_css ); ?>>
769 <option value="small" <?php selected( $tab_size, 'small' ); ?>><?php echo esc_html__( 'Small', 'charitable' ); ?></option>
770 <option value="medium" <?php selected( $tab_size, 'medium' ); ?>><?php echo esc_html__( 'Medium', 'charitable' ); ?></option>
771 <option value="large" <?php selected( $tab_size, 'large' ); ?>><?php echo esc_html__( 'Large', 'charitable' ); ?></option>
772 </select>
773 </div>
774 <!-- row -->
775 <div class="charitable-group-row" id="charitable-group-row-design-layout-options-advanced-show-field-names">
776 <label for="charitable-design-layout-options-advanced-show-field-names"><?php echo esc_html__( 'Field Names', 'charitable' ); ?> <?php echo charitable_get_tooltip_html( esc_html__( 'Show the text that shows the field types in the preview area..', 'charitable' ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
777 </label>
778 <select class="charitable-design-layout-options-show-field-names" id="charitable-design-layout-options-show-field-names" name="layout__advanced__show_field_names" data-advanced-field-id="show_field_names">
779 <option value="show" <?php selected( $show_field_names, 'show' ); ?>><?php echo esc_html__( 'Show', 'charitable' ); ?></option>
780 <option value="hide" <?php selected( $show_field_names, 'hide' ); ?>><?php echo esc_html__( 'Hide', 'charitable' ); ?></option>
781 </select>
782 </div>
783 <!-- row -->
784 <div class="charitable-group-row" id="charitable-group-row-design-layout-options-advanced-preview-mode">
785 <label for="charitable-design-layout-options-advanced-preview-mode"><?php echo esc_html__( 'Preview Mode', 'charitable' ); ?> <?php echo charitable_get_tooltip_html( esc_html__( 'Show the text that shows the field types in the preview area..', 'charitable' ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
786 </label>
787 <select class="charitable-design-layout-options-preview-mode" id="charitable-design-layout-options-preview-mode" name="layout__advanced__preview_mode" data-advanced-field-id="preview_mode">
788 <option value="normal" <?php selected( $preview_mode, 'normal' ); ?>><?php echo esc_html__( 'Normal', 'charitable' ); ?></option>
789 <option value="minimum" <?php selected( $preview_mode, 'minimum' ); ?>><?php echo esc_html__( 'Minimum', 'charitable' ); ?></option>
790 </select>
791 </div>
792 <!-- row -->
793 <div class="charitable-group-row" id="charitable-group-row-design-layout-options-advanced-theme-colors">
794
795 <label for="charitable-design-layout-options-advanced-theme-colors"><?php echo esc_html__( 'Theme Colors', 'charitable' ); ?> <?php echo charitable_get_tooltip_html( esc_html__( 'Adjust the primary colors of the theme.', 'charitable' ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
796 </label>
797
798 <div class="charitable-group-row">
799
800 <div class="charitable-design-layout-options-advanced-theme-color coloris-layout primary" data-label="<?php echo esc_html__( 'Primary:', 'charitable' ); ?>">
801 <label for="layout__advanced__theme_color_primary"><?php echo esc_html__( 'Primary', 'charitable' ); ?></label>
802 <input type="text" class="coloris instance2 primary" name="layout__advanced__theme_color_primary" data-label="primary" value="<?php echo esc_attr( $theme_color_primary ); ?>" />
803 <!-- <a class="reset-link" href="#"><?php echo esc_html__( 'Reset', 'charitable' ); ?></a> -->
804 </div>
805 <div class="charitable-design-layout-options-advanced-theme-color coloris-layout secondary" data-label="<?php echo esc_html__( 'Secondary:', 'charitable' ); ?>">
806 <label for="layout__advanced__theme_color_secondary"><?php echo esc_html__( 'Secondary', 'charitable' ); ?></label>
807 <input type="text" class="coloris instance2 secondary" name="layout__advanced__theme_color_secondary" data-label="secondary" value="<?php echo esc_attr( $theme_color_secondary ); ?>" />
808 <!-- <a class="reset-link" href="#"><?php echo esc_html__( 'Reset', 'charitable' ); ?></a> -->
809 </div>
810 <div class="charitable-design-layout-options-advanced-theme-color coloris-layout tertiary" data-label="<?php echo esc_html__( 'Tertiary:', 'charitable' ); ?>">
811 <label for="layout__advanced__theme_color_tertiary"><?php echo esc_html__( 'Tertiary', 'charitable' ); ?></label>
812 <input type="text" class="coloris instance2 tertiary" name="layout__advanced__theme_color_tertiary" data-label="tertiary" value="<?php echo esc_attr( $theme_color_tertiary ); ?>" />
813 <!-- <a class="reset-link" href="#"><?php echo esc_html__( 'Reset', 'charitable' ); ?></a> -->
814 </div>
815 <div class="charitable-design-layout-options-advanced-theme-color coloris-layout button-color" data-label="<?php echo esc_html__( 'Button:', 'charitable' ); ?>">
816 <label for="layout__advanced__theme_color_button"><?php echo esc_html__( 'Button', 'charitable' ); ?></label>
817 <input type="text" class="coloris instance2 button-color" name="layout__advanced__theme_color_button" data-label="button" value="<?php echo esc_attr( $theme_color_button ); ?>" />
818 <!-- <a class="reset-link" href="#"><?php echo esc_html__( 'Reset', 'charitable' ); ?></a> -->
819 </div>
820 </div>
821
822 </div>
823 <!-- row -->
824 </div>
825 <!-- end rows -->
826 </div>
827 </div> <!-- end container -->
828 </div> <!-- end tab -->
829
830 <?php
831 }
832
833 /**
834 * Returns the starting HTML element for a given template type.
835 *
836 * @since 1.8.0
837 *
838 * @param string $type The type of template element to retrieve.
839 * @param int $counter The counter for the template element.
840 * @param string $additional_css Additional CSS classes to add to the template element.
841 * @param array $campaign_data An array of campaign data to pass to the template element.
842 * @return string The starting HTML element for the given template type.
843 */
844 public function get_template_element_start( $type = 'row', $counter = 1, $additional_css = '', $campaign_data = array() ) {
845
846 ob_start();
847
848 $counter = intval( $counter );
849 $type = esc_attr( $type );
850
851 switch ( $type ) {
852 case 'header':
853 ?>
854 <!-- charitable header start -->
855 <header id="charitable-preview-header-<?php echo intval( $counter ); ?>" class="charitable-preview-header <?php echo esc_attr( $additional_css ); ?>">
856 <div class="row" data-row-id="<?php echo intval( $counter ); ?>" data-row-type="<?php echo esc_attr( $type ); ?>" data-row-css="<?php echo esc_attr( $additional_css ); ?>">
857 <?php
858 break;
859
860 case 'tabs':
861 $enable_tabs_css = isset( $campaign_data['layout']['advanced']['enable_tabs'] ) && '' !== trim( $campaign_data['layout']['advanced']['enable_tabs'] ) ? 'disabled' : '';
862 ?>
863 <!-- charitable tabs start -->
864 <article id="charitable-preview-tab-container" class="charitable-preview-tab-container <?php echo $enable_tabs_css; ?>"> <?php // phpcs:ignore ?>
865 <a href="#" class="charitable-hover-button charitable-field-edit" title="<?php echo esc_html__( 'Edit Area', 'charitable' ); ?>"><i class="fa fa-pencil"></i></a>
866 <?php
867 break;
868
869 default:
870 // likely a row.
871 ?>
872 <!-- charitable row/default start -->
873 <div id="charitable-preview-row-<?php echo $counter; ?>" class="charitable-preview-row <?php echo $additional_css; ?>"> <?php // phpcs:ignore ?>
874 <div class="row" data-row-id="<?php echo $counter; ?>" data-row-type="<?php echo esc_attr( $type ); ?>" data-row-css="<?php echo $additional_css; ?>"> <?php // phpcs:ignore ?>
875 <?php
876 break;
877 }
878
879 return ob_get_clean();
880 }
881
882 /**
883 * Create closing HTML tags based on the type.
884 *
885 * @since 1.8.0
886 *
887 * @param string $type The type of template element to retrieve.
888 * @param int $counter The counter for the template element.
889 * @return string The closing HTML element for the given template type.
890 */
891 public function get_template_element_end( $type = 'row', $counter = 1 ) {
892
893 ob_start();
894
895 switch ( $type ) {
896 case 'header':
897 ?>
898 </div>
899 </header>
900 <!-- charitable header end -->
901 <?php
902 break;
903
904 case 'tabs':
905 ?>
906 </article>
907 <!-- charitable tabs end -->
908 <?php
909 break;
910
911 default:
912 // likely a row.
913 ?>
914 </div>
915 </div>
916 <!-- charitable row/default end -->
917 <?php
918 break;
919 }
920
921 return ob_get_clean();
922 }
923
924 /**
925 * Generate preview of campaign in the admin campaign builder (right side).
926 *
927 * @since 1.8.0
928 */
929 public function preview() {
930
931 if ( ! is_admin() ) {
932 return;
933 }
934
935 $builder_template = new Charitable_Campaign_Builder_Templates();
936
937 ob_start();
938
939 $rows = (array) isset( $this->campaign_data['layout'] ) && ! empty( $this->campaign_data['layout']['rows'] ) ? $this->campaign_data['layout']['rows'] : array();
940 $theme = ! empty( $rows ) && ! empty( $this->campaign_data['template_id'] ) ? $builder_template->get_template_data( $this->campaign_data['template_id'] ) : false;
941
942 $element_counter = 0;
943 $column_counter = 0;
944 $section_counter = 0;
945 $last_field_id = 0;
946
947 ?>
948
949 <div class="charitable-campaign-preview container">
950
951 <?php
952
953 if ( ! empty( $rows ) ) :
954
955 foreach ( $rows as $row_id => $row ) :
956
957 $additional_css = ! empty( $row['css_class'] ) ? esc_attr( $row['css_class'] ) : '';
958
959 echo $this->get_template_element_start( $row['type'], intval( $row_id ), esc_html( $additional_css ) ); // phpcs:ignore
960
961 foreach ( $row['columns'] as $column_id => $column ) :
962
963 echo '<!-- column START -->';
964
965 echo '<div data-column-id="' . intval( $column_counter ) . '" class="column charitable-field-column">';
966
967 if ( ! empty( $column['sections'] ) ) {
968
969 $section_css_class = 'charitable-field-target-inactive';
970 $is_section_empty = true;
971
972 // do a initial look to see if all sections in this column have no fields, and add the default CSS class accordingly.
973 foreach ( $column['sections'] as $section_id => $section ) {
974 $is_section_empty = ( $section['type'] === 'tabs' ) || ( $section['type'] === 'fields' && ! empty( $section['fields'] ) ) ? false : $is_section_empty;
975 }
976
977 foreach ( $column['sections'] as $section_id => $section ) {
978
979 echo '<!-- section START -->';
980
981 $section_css_class = $is_section_empty ? 'charitable-field-target' : 'charitable-field-target-inactive';
982 $section_css_class = ( ! empty( $row['css_class'] ) && strpos( $row['css_class'], 'no-field-target' ) !== false ) ? false : $section_css_class;
983 $section_css_class_no_wrap = empty( $row['css_class'] ) || strpos( $row['css_class'], 'no-field-wrap' ) === false ? ' charitable-field-wrap' : '';
984 $section_css_class_no_wrap = ( $section['type'] === 'tabs' ) ? '' : $section_css_class_no_wrap;
985
986 echo '<div data-section-id="' . intval( $section_counter ) . '" data-section-type="' . esc_attr( $section['type'] ) . '" class="section charitable-field-section ' . esc_attr( $section_css_class ) . ' ' . esc_attr( $section_css_class_no_wrap ) . '">';
987
988 echo '<div class="charitable-drag-new-block-here"><p>Drag New Block Here.</p></div>';
989
990 switch ( $section['type'] ) {
991 case 'fields':
992 $this->render_fields( $section['fields'], $theme, $this->campaign_data, $row['fields'] );
993 break;
994 case 'header':
995 $this->render_fields( $section['fields'], $theme, $this->campaign_data, $row['fields'] );
996 break;
997 case 'tabs':
998 echo $this->get_template_element_start( 'tabs', null, null, $this->campaign_data ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
999 echo $builder_template->get_template_tab_nav( $section['tabs'], $theme, $this->campaign_data ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1000 $last_field_id = $builder_template->get_template_tab_content( $section['tabs'], $theme, $this->campaign_data, $row['fields'], $last_field_id );
1001 echo $this->get_template_element_end( 'tabs' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1002 break;
1003 default:
1004 do_action( 'charitable_campaign_builder_preview_section_' . $section['type'], $section, $row, $theme, $this->campaign_data );
1005 break;
1006 }
1007
1008 ++$section_counter;
1009
1010 echo '</div>';
1011
1012 echo '<!-- section END -->';
1013
1014 }
1015 } else {
1016
1017 $section_css_class = ( empty( $row['css_class'] ) || strpos( $row['css_class'], 'no-field-target' ) === false ) ? 'charitable-field-target' : false;
1018
1019 echo '<div data-section-id="' . intval( $section_counter ) . '" data-section-type="fields" class="section charitable-field-section charitable-field-wrap ' . esc_attr( $section_css_class ) . '">';
1020
1021 echo '<div class="charitable-drag-new-block-here"><p>Drag New Block Here.</p></div>';
1022
1023 ++$section_counter;
1024
1025 echo '</div>';
1026
1027 echo '<!-- section END -->';
1028
1029 }
1030
1031 ++$column_counter;
1032
1033 echo '</div>';
1034
1035 echo '<!-- column END -->';
1036
1037 endforeach;
1038
1039 echo $this->get_template_element_end( $row['type'], intval( $element_counter ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1040
1041 ++$element_counter;
1042
1043 endforeach;
1044
1045 endif;
1046
1047 ?>
1048
1049 </div>
1050
1051 <?php
1052
1053 $preview = ob_get_clean();
1054
1055 echo $preview; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1056 }
1057
1058 /**
1059 * Create fields for preview area based on an array, usually for a column of the layout.
1060 *
1061 * @since 1.8.0
1062 *
1063 * @param array $fields Fields.
1064 * @param array $theme Theme data.
1065 * @param array $campaign_data Campaign data.
1066 * @param array $row_field_data Row data.
1067 *
1068 * @return string
1069 */
1070 public function render_fields( $fields, $theme, $campaign_data, $row_field_data ) {
1071
1072 if ( empty( $fields ) ) {
1073 return;
1074 }
1075
1076 foreach ( $fields as $key => $field_id ) :
1077
1078 $field_type = is_array( $row_field_data ) && ! empty( $row_field_data[ $field_id ] ) ? esc_attr( $row_field_data[ $field_id ] ) : esc_attr( $key );
1079 $field_type_data = $campaign_data['fields'][ $field_id ];
1080
1081 $type = 'Charitable_Field_' . str_replace( ' ', '_', ( ucwords( str_replace( '-', ' ', $field_type ) ) ) );
1082
1083 if ( class_exists( $type ) ) :
1084
1085 $class = new $type();
1086
1087 $field_settings = is_array( $field_type_data ) ? $field_type_data : array();
1088
1089 // define a default photo for the photo type block if it's passed from the theme JSON data.
1090 if ( $field_type == 'photo' && ! empty( $field_settings['default'] ) && ! empty( $theme['meta']['slug'] ) ) {
1091
1092 $campaign_template_slug = esc_attr( $theme['meta']['slug'] );
1093
1094 // if the "default" parameter for the photo is passed then we attempt to pull that photo.
1095 $default_filename = ! empty( $field_type_data['default'] ) ? esc_html( $field_type_data['default'] ) : 'photo.jpg';
1096 $theme_thumbnail = ( false !== $default_filename ) && $campaign_template_slug ? charitable()->get_path( 'assets', true ) . 'images/campaign-builder/templates/' . $campaign_template_slug . '/' . $default_filename : false;
1097
1098 // see if the thumbnail or default photo exists.
1099 if ( false !== $theme_thumbnail && file_exists( $theme_thumbnail ) ) {
1100 $field_settings['default'] = charitable()->get_path( 'assets', false ) . 'images/campaign-builder/templates/' . $campaign_template_slug . '/' . $default_filename;
1101 }
1102 }
1103
1104 $field_settings['id'] = $field_id;
1105
1106 $charitable_field_css_classes = array(
1107 'charitable-field',
1108 'charitable-field-' . $field_type,
1109 $class->can_be_edited ? 'charitable-can-edit' : 'charitable-no-edit',
1110 $class->can_be_duplicated ? 'charitable-can-duplicate' : 'charitable-no-duplicate',
1111 $class->can_be_deleted ? 'charitable-can-delete' : 'charitable-no-delete',
1112 );
1113
1114 echo '<div class="' . implode( ' ', $charitable_field_css_classes ) . '" id="charitable-field-' . intval( $field_id ) . '" data-field-id="' . intval( $field_id ) . '" data-field-type="' . esc_attr( $field_type ) . '" data-field-max="' . esc_attr( $class->max_allowed ) . '" style="">'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1115 if ( $class->can_be_edited ) :
1116 echo '<a href="#" class="charitable-field-edit" data-type="' . esc_attr( $class->edit_type ) . '" data-section="' . esc_attr( $class->edit_section ) . '" data-edit-field-id="' . esc_attr( $class->edit_field_id ) . '" title="' . esc_attr( $class->edit_label ) . '"><i class="fa fa-pencil"></i></a>';
1117 endif;
1118 if ( $class->can_be_duplicated ) :
1119 echo '<a href="#" class="charitable-field-duplicate" title="Duplicate Field"><i class="fa fa-files-o" aria-hidden="true"></i></a>';
1120 endif;
1121 if ( $class->can_be_deleted ) :
1122 echo '<a href="#" class="charitable-field-delete" title="Delete Field"><i class="fa fa-trash-o"></i></a>';
1123 endif;
1124
1125 echo $class->field_preview( $field_settings, $campaign_data, $field_id, $theme ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1126 echo '</div>';
1127
1128 else :
1129
1130 $builder_template = new Charitable_Campaign_Builder_Templates();
1131
1132 $builder_template->render_missing_addon_field_preview( $field_type, $field_id, $field_type_data, $campaign_data );
1133
1134 endif;
1135
1136 endforeach;
1137 }
1138
1139 /**
1140 * Get addoon field label.
1141 *
1142 * @since 1.8.0
1143 * @param string $field_type Field type.
1144 *
1145 * @return array
1146 */
1147 public function get_addon_field_label( $field_type = false ) {
1148
1149 $field_type_labels = $this->get_addon_field_labels();
1150
1151 if ( array_key_exists( $field_type, $field_type_labels ) ) {
1152 return esc_html( $field_type_labels[ $field_type ]['field_label'] );
1153 }
1154
1155 // Try a variation.
1156 if ( array_key_exists( 'charitable-' . $field_type, $field_type_labels ) ) {
1157 return esc_html( $field_type_labels[ 'charitable-' . $field_type ]['field_label'] );
1158 }
1159
1160 // Try a variation.
1161 if ( array_key_exists( 'charitable-' . $field_type . 's', $field_type_labels ) ) {
1162 return esc_html( $field_type_labels[ 'charitable-' . $field_type . 's' ]['field_label'] );
1163 }
1164
1165 return false;
1166 }
1167
1168 /**
1169 * Get addoon label.
1170 *
1171 * @since 1.8.0
1172 * @param string $field_type Field type.
1173 *
1174 * @return array
1175 */
1176 public function get_addon_label( $field_type = false ) {
1177
1178 $field_type_labels = $this->get_addon_field_labels();
1179
1180 if ( array_key_exists( $field_type, $field_type_labels ) ) {
1181 return esc_html( $field_type_labels[ $field_type ]['addon_label'] );
1182 }
1183
1184 return false;
1185 }
1186
1187 /**
1188 * Get addoon field labels.
1189 *
1190 * @since 1.8.0
1191 *
1192 * @return array
1193 */
1194 public function get_addon_field_labels() {
1195
1196 $this->addon_labels = apply_filters(
1197 'charitable_campaign_builder_addon_labels',
1198 array(
1199 'ambassadors-team' => array(
1200 'field_label' => 'Team Field',
1201 'addon_label' => 'Ambassadors Addon',
1202 'url' => false,
1203 'plan' => 'pro',
1204 ),
1205 'updates-main' => array(
1206 'field_label' => 'Updates Field',
1207 'addon_label' => 'Simple Updates Addon',
1208 'url' => false,
1209 'plan' => 'pro',
1210 ),
1211 'comments-main' => array(
1212 'field_label' => 'Comments Field',
1213 'addon_label' => 'Comments Addon',
1214 'url' => false,
1215 'plan' => 'pro',
1216 ),
1217 )
1218 );
1219
1220 return $this->addon_labels;
1221 }
1222
1223 /**
1224 * Sort Add Field buttons by order provided.
1225 *
1226 * @since 1.8.0
1227 *
1228 * @param array $a First item.
1229 * @param array $b Second item.
1230 *
1231 * @return array
1232 */
1233 public function field_order( $a, $b ) {
1234
1235 return $a['order'] - $b['order'];
1236 }
1237
1238 /**
1239 * Tab Empty Notice.
1240 *
1241 * @since 1.8.0
1242 */
1243 public function tab_empty_notice() {
1244
1245 return sprintf(
1246 /* translators: 1: Template ID */
1247 '<p class="empty-tab-notice">' . __( 'This tab is empty. Drag a block from the left into this area or ', 'charitable' ) . '<br/><strong><a href="%1$s" class="charitable-configure-tab-settings">' . __( 'configure tab settings', 'charitable' ) . '</a></strong>.</p>',
1248 '#'
1249 );
1250 }
1251
1252 /**
1253 * No Empty Notice.
1254 *
1255 * @since 1.8.0
1256 */
1257 public function no_tab_empty_notice() {
1258
1259 return sprintf(
1260 /* translators: 1: Template ID */
1261 '<p class="empty-tab-notice">' . __( 'There are no tabs yet for this template. You can ', 'charitable' ) . '<br/><strong><a href="%1$s" class="charitable-configure-tab-settings">' . __( 'configure tab settings', 'charitable' ) . '</a> to add a new tab</strong>.</p>',
1262 '#'
1263 );
1264 }
1265 }
1266
1267 endif;
1268
1269 new Charitable_Builder_Panel_Design();
1270