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 / templates / class-templates.php

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

3,588 lines 134.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Main class for template management for campaign builder.
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 // Exit if accessed directly.
14 if ( ! defined( 'ABSPATH' ) ) {
15 exit;
16 }
17
18 if ( ! class_exists( 'Charitable_Campaign_Builder_Templates' ) ) :
19
20 /**
21 * Sets up the WordPress customizer.
22 *
23 * @since 1.8.0
24 */
25 class Charitable_Campaign_Builder_Templates {
26
27 /**
28 * One is the loneliest number that you'll ever do.
29 *
30 * @since 1.8.0
31 *
32 * @var object
33 */
34 private static $instance;
35
36 /**
37 * Field ID.
38 *
39 * @since 1.8.0
40 *
41 * @var integer
42 */
43 public $field_id;
44
45 /**
46 * Prepared templates list.
47 *
48 * @since 1.8.0
49 *
50 * @var array
51 */
52 private $prepared_templates = array();
53
54 /**
55 * Template categories data.
56 *
57 * @since 1.8.0
58 *
59 * @var array
60 */
61 private $categories;
62
63 /**
64 * Template addon labels data.
65 *
66 * @since 1.8.0
67 *
68 * @var array
69 */
70 private $addon_labels;
71
72 /**
73 * Is addon templates available?
74 *
75 * @since 1.8.0
76 *
77 * @var bool
78 */
79 private $is_addon_templates_available = false;
80
81 /**
82 * Is custom templates available?
83 *
84 * @since 1.8.0
85 *
86 * @var bool
87 */
88 private $is_custom_templates_available = false;
89
90 /**
91 * Storing template data (for now).
92 *
93 * @since 1.8.0
94 *
95 * @var array
96 */
97 private $templates_data = array();
98
99 /**
100 * Main Instance.
101 *
102 * @since 1.8.0
103 *
104 * @return Charitable_Builder
105 */
106 public static function get_instance() {
107
108 if ( ! isset( self::$instance ) && ! ( self::$instance instanceof Charitable_Campaign_Builder_Templates ) ) {
109
110 self::$instance = new Charitable_Campaign_Builder();
111
112 add_action( 'admin_init', array( self::$instance, 'init' ), 10 );
113 }
114
115 return self::$instance;
116 }
117
118 /**
119 * Create object instance.
120 *
121 * @since 1.8.0
122 */
123 public function __construct() {
124
125 if ( ! is_admin() ) {
126 return;
127 }
128
129 $this->field_id = 0;
130
131 $this->templates_data = $this->get_source_template_data();
132
133 $this->init();
134 }
135
136 /**
137 * Init things.
138 *
139 * @since 1.8.0
140 */
141 public function init() {
142
143 $this->hooks();
144 }
145
146 /**
147 * Hook things.
148 *
149 * @since 1.8.0
150 */
151 public function hooks() {
152
153 add_action( 'admin_print_scripts', array( $this, 'upgrade_banner_template' ) );
154 }
155
156 /**
157 * Returns the starting HTML element for a given template type.
158 *
159 * @since 1.8.0
160 *
161 * @param string $type The type of template element to retrieve.
162 * @param int $counter The counter for the template element.
163 * @param string $additional_css Additional CSS classes to add to the template element.
164 * @param array $campaign_data An array of campaign data to pass to the template element.
165 * @return string The starting HTML element for the given template type.
166 */
167 public function get_template_element_start( $type = 'row', $counter = 1, $additional_css = '', $campaign_data = array() ) {
168
169 ob_start();
170
171 switch ( $type ) {
172 case 'header':
173 ?>
174 <!-- charitable header start -->
175 <header id="charitable-preview-header-<?php echo intval( $counter ); ?>" class="charitable-preview-header <?php echo esc_attr( $additional_css ); ?>">
176 <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 ); ?>">
177 <?php
178 break;
179
180 case 'tabs':
181 $enable_tabs_css = isset( $campaign_data['layout']['advanced']['enable_tabs'] ) && '' !== trim( $campaign_data['layout']['advanced']['enable_tabs'] ) ? 'disabled' : '';
182 ?>
183 <!-- charitable tabs start -->
184 <article id="charitable-preview-tab-container" class="charitable-preview-tab-container <?php echo $enable_tabs_css; ?>"> <?php // phpcs:ignore ?>
185 <a href="#" class="charitable-hover-button charitable-field-edit" title="<?php echo esc_html__( 'Edit Area', 'charitable' ); ?>"><i class="fa fa-pencil"></i></a>
186 <?php
187 break;
188
189 default:
190 // likely a row.
191 ?>
192 <!-- charitable row/default start -->
193 <div id="charitable-preview-row-<?php echo intval( $counter ); ?>" class="charitable-preview-row <?php echo esc_attr( $additional_css ); ?>">
194 <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 ); ?>">
195 <?php
196 break;
197 }
198
199 return ob_get_clean();
200 }
201
202 /**
203 * Create closing HTML tags based on the type.
204 *
205 * @since 1.8.0
206 * @param string $type The type of template element to retrieve.
207 * @param int $counter The counter for the template element.
208 *
209 * @return string The closing HTML tags for the given template type.
210 */
211 public function get_template_element_end( $type = 'row', $counter = 1 ) { // phpcs:ignore
212
213 ob_start();
214
215 switch ( $type ) {
216 case 'header':
217 ?>
218 </div>
219 </header>
220 <!-- charitable header end -->
221 <?php
222 break;
223
224 case 'tabs':
225 ?>
226 </article>
227 <!-- charitable tabs end -->
228 <?php
229 break;
230
231 default:
232 // likely a row.
233 ?>
234 </div>
235 </div>
236 <!-- charitable row/default end -->
237 <?php
238 break;
239 }
240
241 return ob_get_clean();
242 }
243
244 /**
245 * Create fields for preview area based on an array, usually for a column of the layout..
246 *
247 * @since 1.8.0
248 *
249 * @param array $fields Fields.
250 * @param array $theme Theme data.
251 * @param array $campaign_data Campaign data.
252 * @param int $last_field_id Last field ID.
253 *
254 * @return string
255 */
256 public function render_fields( $fields, $theme, $campaign_data, $last_field_id = 0 ) {
257
258 if ( empty( $fields ) ) {
259 return;
260 }
261
262 $field_id = $last_field_id;
263
264 foreach ( $fields as $key => $field_type_data ) :
265
266 $field_type = is_array( $field_type_data ) && ! empty( $field_type_data['type'] ) ? esc_html( $field_type_data['type'] ) : esc_html( $key );
267
268 $type = 'Charitable_Field_' . str_replace( ' ', '_', ( ucwords( str_replace( '-', ' ', $field_type ) ) ) );
269
270 if ( class_exists( $type ) ) :
271
272 $class = new $type();
273
274 $field_settings = is_array( $field_type_data ) ? $field_type_data : array();
275
276 // define a default photo for the photo type block if it's passed from the theme JSON data.
277 if ( $field_type == 'photo' && ! empty( $field_settings['default'] ) && ! empty( $theme['meta']['slug'] ) ) {
278
279 $campaign_template_slug = esc_attr( $theme['meta']['slug'] );
280
281 // if the "default" parameter for the photo is passed then we attempt to pull that photo.
282 $default_filename = ! empty( $field_type_data['default'] ) ? esc_html( $field_type_data['default'] ) : 'photo.jpg';
283 $theme_thumbnail = ( false !== $default_filename ) && $campaign_template_slug ? charitable()->get_path( 'assets', true ) . 'images/campaign-builder/templates/' . $campaign_template_slug . '/' . $default_filename : false;
284
285 // see if the thumbnail or default photo exists.
286 if ( false !== $theme_thumbnail && file_exists( $theme_thumbnail ) ) {
287 $field_settings['default'] = charitable()->get_path( 'assets', false ) . 'images/campaign-builder/templates/' . $campaign_template_slug . '/' . $default_filename;
288 }
289 }
290
291 $field_settings['id'] = $field_id;
292
293 $charitable_field_css_classes = array(
294 'charitable-field',
295 'charitable-field-' . $field_type,
296 $class->can_be_edited ? 'charitable-can-edit' : 'charitable-no-edit',
297 $class->can_be_duplicated ? 'charitable-can-duplicate' : 'charitable-no-duplicate',
298 $class->can_be_deleted ? 'charitable-can-delete' : 'charitable-no-delete',
299 );
300
301 echo '<div class="' . esc_attr( 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="' . intval( $class->max_allowed ) . '" style="">'; // phpcs:ignore
302 if ( $class->can_be_edited ) :
303 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>';
304 endif;
305 if ( $class->can_be_duplicated ) :
306 echo '<a href="#" class="charitable-field-duplicate" title="Duplicate Field"><i class="fa fa-files-o" aria-hidden="true"></i></a>';
307 endif;
308 if ( $class->can_be_deleted ) :
309 echo '<a href="#" class="charitable-field-delete" title="Delete Field"><i class="fa fa-trash-o"></i></a>';
310 endif;
311
312 echo $class->field_preview( $field_settings, $campaign_data, $field_id, $theme ); // phpcs:ignore
313 echo '</div>';
314
315 else :
316
317 $this->render_missing_addon_field_preview( $field_type, $field_id, $field_type_data, $campaign_data );
318
319 endif;
320
321 ++$field_id;
322
323 endforeach;
324
325 return $field_id;
326 }
327
328 /**
329 * Sorts an array by the order of another array.
330 *
331 * @param array $tabs The array to be sorted.
332 * @param array $tab_order The array that defines the order.
333 *
334 * @return array The sorted array.
335 */
336 public function sort_array_by_array( $tabs, $tab_order ) {
337
338 $ordered = array();
339
340 foreach ( $tab_order as $key ) {
341 if ( array_key_exists( $key, $tabs ) ) {
342 $ordered[ $key ] = $tabs[ $key ];
343 unset( $tabs[ $key ] );
344 }
345 }
346
347 return $ordered + $tabs;
348 }
349
350 /**
351 * Create tabs based on the template data.
352 *
353 * @since 1.8.0
354 *
355 * @param string $tabs Tab info.
356 * @param string $theme The current theme.
357 * @param array $campaign_data Campaign data..
358 *
359 * @return string
360 */
361 public function get_template_tab_nav( $tabs = false, $theme = false, $campaign_data = false ) {
362
363 if ( ! is_admin() ) {
364 return;
365 }
366
367 if ( false === $tabs || false === $theme ) {
368 return;
369 }
370
371 ob_start();
372
373 $counter = 0;
374 $tab_id = 0;
375 $advanced = ( ! empty( $campaign_data['layout']['advanced'] ) ) ? $campaign_data['layout']['advanced'] : $theme['advanced'];
376 $tab_style = isset( $advanced['tab_style'] ) && '' !== trim( $advanced['tab_style'] ) ? $advanced['tab_style'] : 'boxed';
377 $tab_size = isset( $advanced['tab_size'] ) && '' !== trim( $advanced['tab_size'] ) ? $advanced['tab_size'] : 'medium';
378 $tab_order = ! empty( $campaign_data['tab_order'] ) ? $campaign_data['tab_order'] : false;
379
380 // sort the multi-dimenstional array of $tabs based on the values of $tab_order array.
381 if ( is_array( $tabs ) && ! empty( $tabs ) && ! empty( $tab_order ) ) {
382 $tabs = $this->sort_array_by_array( $tabs, $tab_order );
383 }
384
385 ?>
386
387 <nav class="charitable-campaign-preview-nav tab-style-<?php echo esc_attr( $tab_style ); ?> tab-size-<?php echo esc_attr( $tab_size ); ?>">
388
389 <ul class="charitable-campaign-preview-nav-list">
390
391 <?php if ( is_array( $tabs ) && ! empty( $tabs ) ) : ?>
392 <?php
393
394 $counter = 1;
395
396 /*
397 The initial structure of this array looks something like:
398
399 'title' => 'My Campaign',
400 'type' => 'html',
401 'slug' => 'default',
402 'fields' => array (
403 'campaign-description',
404 )
405
406 */
407
408 foreach ( $tabs as $tab_id => $tab_info ) :
409
410 $title = ! empty( $tab_info['title'] ) ? esc_html( $tab_info['title'] ) : false;
411 $title = false === $title && ! empty( $campaign_data['tabs'][ $tab_id ]['title'] ) ? esc_html( $campaign_data['tabs'][ $tab_id ]['title'] ) : $title;
412 $type = ( isset( $tab_info['type'] ) && '' !== trim( $tab_info['type'] ) ) ? $tab_info['type'] : 'html';
413 $class = 'tab_type_' . $type . ' ';
414 $class = ( $counter === 1 ) ? 'active' : false;
415 $show_hide_css = ! empty( $campaign_data['tabs'][ $tab_id ]['visible_nav'] ) && $campaign_data['tabs'][ $tab_id ]['visible_nav'] === 'invisible' ? 'charitable-tab-hide' : false;
416
417 ?>
418 <li id="tab_<?php echo esc_attr( $tab_id ); ?>_title" data-tab-id="<?php echo esc_attr( $tab_id ); ?>" data-tab-type="<?php echo esc_attr( $type ); ?>" class="tab_title <?php echo esc_attr( $class ); ?> <?php echo esc_attr( $show_hide_css ); ?>"><a href="#"><?php echo esc_html( $title ); ?></a></li>
419 <?php
420
421 ++$counter;
422
423 endforeach;
424
425 endif;
426 ?>
427
428 </ul>
429
430 </nav>
431
432 <?php
433
434 return ob_get_clean();
435 }
436
437 /**
438 * Create tab content based on the template data.
439 *
440 * @since 1.8.0
441 *
442 * @param array $tabs Tab info.
443 * @param string $theme The current theme.
444 * @param array $campaign_data Campaign data.
445 * @param array $row_fields Row fields.
446 * @param int $last_field_id Last field ID.
447 *
448 * @return string
449 */
450 public function get_template_tab_content( $tabs = false, $theme = false, $campaign_data = array(), $row_fields = false, $last_field_id = 0 ) {
451
452 if ( ! is_admin() ) {
453 return;
454 }
455
456 if ( false === $tabs || false === $theme || ! is_array( $tabs ) ) {
457 return;
458 }
459
460 ob_start();
461
462 $counter = 0;
463 $tab_id = 0;
464 $field_id = $last_field_id;
465 $no_tab_class = ( empty( $tabs ) || false === $tabs ) ? 'empty-tabs' : false;
466
467 ?>
468
469 <div class="tab-content <?php echo esc_attr( $no_tab_class ); ?>">
470 <ul>
471 <?php if ( $tabs ) : ?>
472 <?php
473
474 $counter = 1;
475
476 foreach ( $tabs as $tab_id => $tab_info ) :
477
478 $type = ( isset( $tab_info['type'] ) && '' !== trim( $tab_info['type'] ) ) ? $tab_info['type'] : 'html';
479 $class = 'tab_type_' . $type . ' ';
480 $class .= ( $counter === 1 ) ? 'active' : false;
481 $fields = ( ! empty( $tab_info['fields'] ) ) ? $tab_info['fields'] : false;
482 $class .= ( false === $fields ) ? ' empty-tab' : false;
483
484 ?>
485
486 <li id="tab_<?php echo intval( $tab_id ); ?>_content" class="tab_content_item <?php echo esc_attr( $class ); ?>" data-tab-type="<?php echo esc_attr( $type ); ?>" data-tab-id="<?php echo esc_attr( $tab_id ); ?>">
487
488 <div class="charitable-tab-wrap ui-sortable">
489
490 <?php echo $this->tab_empty_notice(); // phpcs:ignore ?>
491
492 <?php echo charitable_builder_tab_content_preview_by_type( $type ); // phpcs:ignore ?>
493
494 <?php
495
496 if ( ! empty( $fields ) ) :
497
498 foreach ( $fields as $key => $field_info_or_id ) :
499
500 // field_info could be just field_id OR an array of information from template JSON (type, default, headline, etc.).
501
502 if ( is_array( $field_info_or_id ) ) {
503 $field_info = $field_info_or_id;
504 $field_type = ! empty( $field_info['type'] ) ? esc_attr( $field_info['type'] ) : false;
505 $field_type_data = $field_info_or_id;
506 } else {
507 $field_id = intval( $field_info_or_id );
508 $field_type = is_array( $row_fields ) && ! empty( $row_fields[ $field_id ] ) ? esc_attr( $row_fields[ $field_id ] ) : false;
509 $field_type_data = ! empty( $campaign_data['fields'][ $field_id ] ) ? $campaign_data['fields'][ $field_id ] : false;
510 }
511
512 if ( false !== $field_type ) :
513
514 $class_type = 'Charitable_Field_' . str_replace( ' ', '_', ( ucwords( str_replace( '-', ' ', $field_type ) ) ) );
515
516 if ( class_exists( $class_type ) ) :
517
518 $class = new $class_type();
519 $field_settings = is_array( $field_type_data ) ? $field_type_data : array();
520
521 // define a default photo for the photo type block if it's passed from the theme JSON data.
522 if ( $field_type === 'photo' && ! empty( $field_settings['default'] ) && ! empty( $theme['meta']['slug'] ) ) {
523
524 $campaign_template_slug = esc_attr( $theme['meta']['slug'] );
525
526 // if the "default" parameter for the photo is passed then we attempt to pull that photo.
527 $default_filename = ! empty( $field_type_data['default'] ) ? esc_html( $field_type_data['default'] ) : 'photo.jpg';
528 $theme_thumbnail = ( false !== $default_filename ) && $campaign_template_slug ? charitable()->get_path( 'assets', true ) . 'images/campaign-builder/templates/' . $campaign_template_slug . '/' . $default_filename : false;
529
530 // see if the thumbnail or default photo exists.
531 if ( false !== $theme_thumbnail && file_exists( $theme_thumbnail ) ) {
532 $field_settings['default'] = charitable()->get_path( 'assets', false ) . 'images/campaign-builder/templates/' . $campaign_template_slug . '/' . $default_filename;
533 }
534 }
535 $field_settings['id'] = $field_id;
536
537 $charitable_field_css_classes = array(
538 'charitable-field',
539 'charitable-field-' . $field_type,
540 $class->can_be_edited ? 'charitable-can-edit' : 'charitable-no-edit',
541 $class->can_be_duplicated ? 'charitable-can-duplicate' : 'charitable-no-duplicate',
542 $class->can_be_deleted ? 'charitable-can-delete' : 'charitable-no-delete',
543 );
544
545 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
546
547 if ( $class->can_be_edited ) :
548 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_html( $class->edit_label ) . '"><i class="fa fa-pencil"></i></a>';
549 endif;
550 if ( $class->can_be_duplicated ) :
551 echo '<a href="#" class="charitable-field-duplicate" title="Duplicate Field"><i class="fa fa-files-o" aria-hidden="true"></i></a>';
552 endif;
553 if ( $class->can_be_deleted ) :
554 echo '<a href="#" class="charitable-field-delete" title="Delete Field"><i class="fa fa-trash-o"></i></a>';
555 endif;
556 echo $class->field_preview( $field_settings, $campaign_data, $field_id, 'preview', $theme ); // phpcs:ignore
557 echo '</div>';
558
559 else :
560
561 $this->render_missing_addon_field_preview( $field_type, $field_id, $field_type_data, $campaign_data );
562
563 endif; // class exists.
564
565 endif; // if type isn't false.
566
567 ++$field_id;
568
569 endforeach;
570
571 endif;
572
573 ?>
574 </div>
575
576 </li>
577
578 <?php
579
580 ++$counter;
581
582 endforeach;
583 ?>
584 <?php else : ?>
585 <li id="tab_<?php echo esc_attr( $tab_id ); ?>_content" class="tab_content_item active" data-tab-id="0" data-tab-type="html"></li>
586 <?php endif; ?>
587 </ul>
588 <?php if ( $no_tab_class ) : ?>
589 <p class="no-tab-notice"><?php echo $this->no_tab_empty_notice(); // phpcs:ignore ?></p>
590 <?php endif; ?>
591 </div>
592
593 <?php
594
595 echo ob_get_clean(); // phpcs:ignore
596
597 return absint( $field_id - 1 );
598 }
599
600 /**
601 * Display missing addon message.
602 *
603 * @since 1.8.0
604 *
605 * @param string $field_type Tab info.
606 * @param integer $field_id The current theme.
607 * @param array $field_type_data The field type data.
608 * @param array $campaign_data The campaign data.
609 *
610 * @return void
611 */
612 public function render_missing_addon_field_preview( $field_type = false, $field_id = false, $field_type_data = false, $campaign_data = false ) {
613
614 $field_label = ( false !== $field_type ) ? (string) $this->get_addon_field_label( $field_type ) : false;
615 $field_label = ( false === $field_label || '' === trim( $field_label ) ) ? 'unknown' : $field_label;
616
617 $addon_label = ( false !== $field_type ) ? (string) $this->get_addon_label( $field_type ) : false;
618 $addon_label = ( false === $addon_label || '' === trim( $addon_label ) ) ? 'unknown' : $addon_label;
619
620 $template_id = ! empty( $campaign_data['template_id'] ) ? esc_attr( $campaign_data['template_id'] ) : false;
621 $template_id = $template_id === false & ! empty( $_POST['id'] ) ? esc_attr( $_POST['id'] ) : $template_id; // phpcs:ignore
622
623 // Get a background image, preferrabbly supplied.
624 $background_image_url = $this->get_addon_placeholder_image( $field_type );
625 $css_style = false !== $background_image_url ? 'background-image: url(' . $background_image_url . ');' : false;
626 $search_term = $this->get_addon_search_term( $field_type );
627
628 $field_id = intval( $field_id );
629
630 echo '<div class="charitable-field charitable-field-missing charitable-field-' . esc_attr( $field_type ) . '" id="charitable-field-' . intval( $field_id ) . '" data-field-id="' . intval( $field_id ) . '" data-field-type="' . esc_attr( $field_type ) . '">';
631
632 echo '<a href="#" class="charitable-field-delete" title="Delete Field"><i class="fa fa-trash-o"></i></a>';
633
634 echo '<div class="charitable-missing-addon-bg" style="' . esc_attr( $css_style ) . '"></div>';
635
636 echo '<div class="charitable-missing-addon-content">';
637
638 if ( charitable_is_pro() ) {
639
640 $display_html = $this->get_addon_install_or_activate_buttons( $field_type );
641
642 if ( ! empty( $display_html['title'] ) ) {
643 echo $display_html['title']; // phpcs:ignore
644 } else {
645 echo '<h2>We\'re sorry, the <strong>' . esc_html( $field_label ) . '</strong> does not seem to be available.</h2>';
646 }
647
648 if ( ! empty( $display_html['description'] ) ) {
649 echo $display_html['description']; // phpcs:ignore
650 } else {
651 echo '<p>Please make sure that you have the latest version of the <strong>' . esc_html( $addon_label ) . '</strong> addon installed and activated.</p>';
652 }
653
654 echo '<div class="education-buttons">';
655
656 if ( ! empty( $display_html['buttons'] ) ) {
657 echo $display_html['buttons']; // phpcs:ignore
658 } else {
659 echo '<a class="button-link" target="_blank" href="' . esc_url( admin_url( 'admin.php?page=charitable-addons&search=' . $search_term ) ) . '">' . esc_html__( 'View Addons', 'charitable' ) . '</a>';
660 }
661
662 echo '</div>';
663
664 } else {
665
666 echo '<h2>We\'re sorry, the <strong>' . esc_html( $field_label ) . '</strong> is not available on your plan.</h2> <p>Please upgrade to the PRO plan to unlock all these awesome features.</p>';
667
668 echo '<div class="education-buttons">
669 <a class="button-link" target="_blank" href="https://wpcharitable.com/lite-vs-pro/">' . esc_html__( 'Learn More', 'charitable' ) . '</a> <button type="button" class="btn btn-confirm update-to-pro-link">' . esc_html__( 'Upgrade to PRO', 'charitable' ) . '</button>
670 </div>';
671
672 }
673
674 echo '<a href="#" class="charitable-field-delete" title="Delete Field"><i class="fa fa-trash-o"></i></a>';
675 echo '</div>';
676 echo '</div>';
677 }
678
679 /**
680 * Display missing addon message and button(s).
681 *
682 * @since 1.8.0.4
683 *
684 * @param string $field_type The field type.
685 *
686 * @return array|bool
687 */
688 public function get_addon_install_or_activate_buttons( $field_type = false ) {
689
690 if ( false === $field_type ) {
691 return false;
692 }
693
694 // get the list of installed plugins and charitable addon information.
695 $installed_plugins = get_plugins();
696 $addon_information = $this->get_addon_information( $field_type );
697
698 // grab the list of active plugins only once, don't need it in the loop.
699 $active_plugins = apply_filters( 'active_plugins', get_option( 'active_plugins' ) ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- 'active_plugins' is a WordPress core hook.
700
701 if ( false === $addon_information ) {
702 return false;
703 }
704
705 $slug = ! empty( $addon_information['slug'] ) ? esc_attr( $addon_information['slug'] ) : false;
706
707 if ( false === $slug ) {
708 return false;
709 }
710
711 // Determine the plugin basename.
712 $plugin_basename = $this->get_plugin_basename_from_slug( $addon_information['slug'] );
713
714 if ( isset( $installed_plugins[ $plugin_basename ] ) && ! is_plugin_active( $plugin_basename ) ) {
715
716 // if the plugin exists (installed, visible in the plugin list in WP admin) but not activated.
717
718 return array(
719 'title' => '<h2>We\'re sorry, the <strong>' . esc_html( $addon_information['name'] ) . '</strong> addon does not seem to be available.</h2>',
720 'description' => '<p>It appears you have <strong>' . esc_html( $addon_information['name'] ) . '</strong> installed but it needs to be activated.</p>',
721 'buttons' => '<a class="button-link charitable-not-activated" data-plugin-url="' . esc_attr( $addon_information['slug'] ) . '/' . esc_attr( $addon_information['slug'] ) . '.php" data-name="' . $addon_information['name'] . '" data-slug="' . $addon_information['slug'] . '" data-field-icon="" href="#">' . esc_html__( 'Activate ', 'charitable' ) . esc_html( $addon_information['name'] ) . '</a>',
722 );
723 } elseif ( is_array( $active_plugins ) && ! in_array( 'charitable-' . $slug . '/charitable-' . $slug . '.php', $active_plugins, true ) ) {
724
725 // if pro is active AND the plugin is NOT activated, then that's another CSS class to encourage an install.
726
727 return array(
728 'title' => '<h2>We\'re sorry, the <strong>' . esc_html( $addon_information['name'] ) . '</strong> addon does not seem to be available.</h2>',
729 'description' => '<p>It appears you need <strong>' . esc_html( $addon_information['name'] ) . '</strong> to be installed and activated.</p>',
730 'buttons' => '<a class="button-link charitable-not-installed" data-plugin-url="' . $addon_information['install'] . '" data-name="' . $addon_information['name'] . '" data-slug="" data-field-icon="" href="#">' . esc_html__( 'Install &amp; Activate ', 'charitable' ) . esc_html( $addon_information['name'] ) . '</a>',
731 'install_url' => ! empty( $addon_information['install'] ) ? esc_url( $addon_information['install'] ) : false,
732 );
733 }
734
735 return false;
736 }
737
738
739 /**
740 * Get information about the addon used to display the missing addon message.
741 *
742 * @since 1.8.0.4
743 *
744 * @param string $field_type The field type.
745 *
746 * @return array|bool
747 */
748 public function get_addon_information( $field_type = false ) {
749
750 if ( false === $field_type ) {
751 return false;
752 }
753
754 // Attempt to self-correct. If the $field_type doesn't start with 'charitable-', add it.
755 if ( false === strpos( strtolower( $field_type ), 'charitable-' ) ) {
756 $field_type = 'charitable-' . $field_type;
757 }
758
759 // grab the list of active plugins only once, don't need it in the loop.
760 $active_plugins = apply_filters( 'active_plugins', get_option( 'active_plugins' ) ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- 'active_plugins' is a WordPress core hook.
761
762 // get license stuff once.
763 $charitable_addons = get_transient( '_charitable_addons' ); // @codingStandardsIgnoreLine - testing.
764
765 // Get addons data from transient or perform API query if no transient.
766 if ( false === $charitable_addons ) {
767 $charitable_addons = charitable_get_addons_data_from_server();
768 }
769
770 if ( ! is_array( $charitable_addons ) || empty( $charitable_addons ) ) {
771 return;
772 }
773
774 foreach ( $charitable_addons as $charitable_addon ) {
775 if ( ! empty( $charitable_addon['slug'] ) &&
776 ( strtolower( $field_type ) === strtolower( $charitable_addon['slug'] )
777 || strtolower( $field_type ) . 's' === strtolower( $charitable_addon['slug'] ) // covers in case the field type is 'video' when the slug is actually 'charitable-videos' (pural).
778 )
779 ) {
780 return $charitable_addon;
781 }
782 // This is to cover the case where the field type for example is 'charitable-ambassadors-team' but the slug is 'charitable-ambassadors'.
783 if ( substr_count( $field_type, '-' ) > 1 ) {
784 $modified_field_type = substr( $field_type, 0, strrpos( $field_type, '-' ) );
785 if ( ! empty( $charitable_addon['slug'] ) && strtolower( $modified_field_type ) === strtolower( $charitable_addon['slug'] ) ) {
786 return $charitable_addon;
787 }
788 }
789 }
790
791 return false;
792 }
793
794 /**
795 * Retrieve the plugin basename from the plugin slug.
796 *
797 * @since 1.7.0
798 *
799 * @param string $slug The plugin slug.
800 * @return string The plugin basename if found, else the plugin slug.
801 */
802 public function get_plugin_basename_from_slug( $slug ) {
803
804 $keys = array_keys( get_plugins() );
805
806 foreach ( $keys as $key ) {
807 if ( preg_match( '|^' . $slug . '|', $key ) ) {
808 return $key;
809 }
810 }
811
812 return $slug;
813 }
814
815 /**
816 * Get addoon field label.
817 *
818 * @since 1.8.0
819 *
820 * @param string $field_type The field type.
821 *
822 * @return array
823 */
824 public function get_addon_field_label( $field_type = false ) {
825
826 $field_type_labels = $this->get_addon_field_labels();
827
828 if ( array_key_exists( $field_type, $field_type_labels ) ) {
829 return esc_html( $field_type_labels[ $field_type ]['field_label'] );
830 }
831
832 // Try a variation.
833 if ( array_key_exists( 'charitable-' . $field_type, $field_type_labels ) ) {
834 return esc_html( $field_type_labels[ 'charitable-' . $field_type ]['field_label'] );
835 }
836
837 // Try a variation.
838 if ( array_key_exists( 'charitable-' . $field_type . 's', $field_type_labels ) ) {
839 return esc_html( $field_type_labels[ 'charitable-' . $field_type . 's' ]['field_label'] );
840 }
841
842 return false;
843 }
844
845 /**
846 * Get addoon label.
847 *
848 * @since 1.8.0
849 *
850 * @param string $field_type The field type.
851 *
852 * @return array
853 */
854 public function get_addon_label( $field_type = false ) {
855
856 $field_type_labels = $this->get_addon_field_labels();
857
858 if ( array_key_exists( $field_type, $field_type_labels ) ) {
859 return esc_html( $field_type_labels[ $field_type ]['addon_label'] );
860 }
861
862 // Try a variation.
863 if ( array_key_exists( 'charitable-' . $field_type, $field_type_labels ) ) {
864 return esc_html( $field_type_labels[ 'charitable-' . $field_type ]['addon_label'] );
865 }
866
867 // Try a variation.
868 if ( array_key_exists( 'charitable-' . $field_type . 's', $field_type_labels ) ) {
869 return esc_html( $field_type_labels[ 'charitable-' . $field_type . 's' ]['addon_label'] );
870 }
871
872 return false;
873 }
874
875 /**
876 * Get the search term that will show the correct addon if the user clicks on "View addons" in the preview
877 *
878 * @since 1.8.0
879 *
880 * @param string $addon_slug The addon slug.
881 *
882 * @return string
883 */
884 public function get_addon_search_term( $addon_slug = false ) {
885
886 if ( false === $addon_slug ) {
887 return false;
888 }
889
890 $addon_labels = $this->get_addon_field_labels();
891
892 if ( ! empty( $addon_labels[ $addon_slug ] ) ) {
893 return strtolower( $addon_labels[ $addon_slug ]['admin_search'] );
894 }
895
896 // not found? take a guess.
897 $search_term = str_replace( 'charitable-', '', $addon_slug );
898
899 return strtolower( $search_term );
900 }
901
902 /**
903 * Get the placeholder image that appears in preview when the user doesn't have the addon activated.
904 *
905 * @since 1.8.0
906 *
907 * @param string $addon_slug The addon slug.
908 *
909 * @return string
910 */
911 public function get_addon_placeholder_image( $addon_slug = false ) {
912
913 if ( false === $addon_slug ) {
914 return false;
915 }
916
917 $addon_labels = $this->get_addon_field_labels();
918
919 if ( ! empty( $addon_labels[ $addon_slug ] ) ) {
920 return strtolower( $addon_labels[ $addon_slug ]['placeholder_img'] );
921 }
922
923 return false;
924 }
925
926 /**
927 * Get addon field labels.
928 *
929 * @since 1.8.0
930 *
931 * @return array
932 */
933 public function get_addon_field_labels() {
934
935 $this->addon_labels = apply_filters(
936 'charitable_campaign_builder_addon_labels',
937 array(
938 'ambassadors-team' => array(
939 'field_label' => 'Team Field',
940 'addon_label' => 'Ambassadors Addon',
941 'url' => false,
942 'plan' => 'pro',
943 'admin_search' => 'ambassador',
944 'placeholder_img' => charitable()->get_path( 'directory', false ) . 'assets/images/campaign-builder/placeholders/field-team.jpg',
945 ),
946 'video' => array(
947 'field_label' => 'Video Field',
948 'addon_label' => 'Video Addon',
949 'url' => false,
950 'plan' => 'basic',
951 'admin_search' => 'video',
952 'placeholder_img' => charitable()->get_path( 'directory', false ) . 'assets/images/campaign-builder/placeholders/field-video.jpg',
953 ),
954 'updates-main' => array(
955 'field_label' => 'Updates Field',
956 'addon_label' => 'Simple Updates Addon',
957 'url' => false,
958 'plan' => 'pro',
959 'admin_search' => 'updates',
960 'placeholder_img' => charitable()->get_path( 'directory', false ) . 'assets/images/campaign-builder/placeholders/field-updates.jpg',
961 ),
962 'comments-main' => array(
963 'field_label' => 'Comments Field',
964 'addon_label' => 'Comments Addon',
965 'url' => false,
966 'plan' => 'pro',
967 'admin_search' => 'comments',
968 'placeholder_img' => charitable()->get_path( 'directory', false ) . 'assets/images/campaign-builder/placeholders/field-comments.jpg',
969 ),
970 )
971 );
972
973 return $this->addon_labels;
974 }
975
976 /**
977 * Get the preview of a campaign builder template.
978 *
979 * @since 1.8.0
980 *
981 * @param string|bool $template_id The ID of the template to preview.
982 * @param string|bool $theme The theme to use for the preview.
983 * @param array|bool $campaign_data The data to use for the campaign.
984 * @param bool $exclude_wrappers Whether to exclude the template wrappers or not.
985 *
986 * @return string The HTML preview of the template.
987 */
988 public function get_template_preview( $template_id = false, $theme = false, $campaign_data = false, $exclude_wrappers = false ) {
989
990 if ( false === $template_id ) {
991 return false;
992 }
993
994 ob_start();
995
996 $this->field_id = 0;
997 $column_counter = 0;
998 $element_counter = 0;
999 $section_counter = 0;
1000 $field_id = 0;
1001 $last_field_id = 0;
1002
1003 $layout = isset( $theme['layout'] ) ? $theme['layout'] : false;
1004
1005 // if this is a "default" theme or there's no layout (odd) then display the "no fields preview".
1006 $no_preview_css_class = ( empty( $layout ) || ! is_array( $layout ) || ( ! empty( $theme['meta']['template_type'] ) && is_array( $theme['meta']['template_type'] ) && in_array( 'default', $theme['meta']['template_type'], true ) ) ) ? false : 'charitable-hidden';
1007 $design_wrap_css_class = ( false === $no_preview_css_class ) ? ' no-fields-mode ' : false;
1008
1009 if ( false !== $exclude_wrappers ) {
1010 ?>
1011
1012 <div>
1013 <div>
1014
1015 <?php } else { ?>
1016
1017 <div class="charitable-design-wrap<?php echo esc_attr( $design_wrap_css_class ); ?>" id="charitable-design-wrap">
1018
1019 <?php /* loading screen, sometimes needed for color previewing */ ?>
1020
1021 <div class="charitable-campaign-preview-loader"><i class="charitable-loading-spinner charitable-loading-black charitable-loading-inline"></i></div>
1022
1023 <div class="charitable-campaign-preview charitable-campaign-preview-container">
1024
1025 <?php } ?>
1026
1027 <?php
1028
1029 if ( ! empty( $layout ) && is_array( $layout ) ) {
1030
1031 foreach ( $layout as $row ) {
1032
1033 $additional_css = ! empty( $row['css_class'] ) ? esc_attr( $row['css_class'] ) : '';
1034 $row_fields = ! empty( $row['fields'] ) ? $row['fields'] : false;
1035
1036 echo $this->get_template_element_start( $row['type'], $element_counter, $additional_css ); // phpcs:ignore
1037
1038 $tabs_rendered = false;
1039
1040 foreach ( $row['columns'] as $column ) {
1041
1042 echo '<!-- column START -->';
1043
1044 echo '<div data-column-id="' . intval( $column_counter ) . '" class="column charitable-field-column">';
1045
1046 foreach ( $column as $section ) {
1047
1048 echo '<!-- section START -->';
1049
1050 ob_start();
1051
1052 switch ( $section['type'] ) {
1053 case 'fields':
1054 if ( $tabs_rendered ) {
1055 ++$last_field_id;
1056 }
1057 $last_field_id = (int) $this->render_fields( $section['fields'], $theme, $campaign_data, $last_field_id );
1058 break;
1059 case 'header':
1060 $last_field_id = (int) $this->render_fields( $section['fields'], $theme, $campaign_data, $last_field_id );
1061 break;
1062 case 'tabs':
1063 echo $this->get_template_element_start( 'tabs', null, null, $campaign_data ); // phpcs:ignore
1064 $campaign_tabs = ! empty( $campaign_data['tabs'] ) ? $campaign_data['tabs'] : array();
1065 echo $this->get_template_tab_nav( $section['tabs'], $theme, $campaign_tabs ); // phpcs:ignore
1066 $last_field_id = (int) $this->get_template_tab_content( $section['tabs'], $theme, $campaign_data, $row_fields, $last_field_id );
1067 echo $this->get_template_element_end( 'tabs' ); // phpcs:ignore
1068 $tabs_rendered = true;
1069 break;
1070 default:
1071 do_action( 'charitable_campaign_builder_preview_section_' . $section['type'], $section, $row, $theme, $campaign_data );
1072 break;
1073 }
1074
1075 $field_html = ob_get_clean();
1076
1077 $section_css_class = ( '' === $field_html && ( empty( $row['css_class'] ) || strpos( $row['css_class'], 'no-field-target' ) === false ) ) ? 'charitable-field-target' : '';
1078 $section_css_class .= ( empty( $row['css_class'] ) || strpos( $row['css_class'], 'no-field-wrap' ) === false ) ? ' charitable-field-wrap' : '';
1079
1080 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 ) . '">';
1081
1082 echo '<div class="charitable-drag-new-block-here"><p>Drag New Block Here.</p></div>';
1083
1084 echo $field_html; // phpcs:ignore
1085
1086 ++$section_counter;
1087
1088 echo '</div>';
1089
1090 echo '<!-- section END -->';
1091 }
1092
1093 ++$column_counter;
1094
1095 echo '</div>';
1096
1097 echo '<!-- column END -->';
1098 }
1099
1100 echo $this->get_template_element_end( $row['type'], $element_counter ); // phpcs:ignore
1101
1102 ++$element_counter;
1103 }
1104 }
1105
1106 return ob_get_clean();
1107 }
1108
1109 /**
1110 * Returns the default start of a column.
1111 *
1112 * @return string The HTML markup for the start of a column.
1113 */
1114 public function get_default_column_start() {
1115
1116 ob_start();
1117
1118 ?>
1119
1120 <div data-column-id="0" class="column charitable-field-column">
1121
1122 <?php
1123
1124 return ob_get_clean();
1125 }
1126
1127 /**
1128 * Returns the default end of a column.
1129 *
1130 * @return string The HTML markup for the end of a column.
1131 */
1132 public function get_default_column_end() {
1133
1134 ob_start();
1135
1136 ?>
1137
1138 </div>
1139
1140 <?php
1141
1142 return ob_get_clean();
1143 }
1144
1145 /**
1146 * Output the 'fields' or 'blocks' for the template.
1147 *
1148 * @since 1.8.0
1149 *
1150 * @param string $template_id Template slug.
1151 * @param string $theme The current theme.
1152 * @param array $campaign_data The campaign data.
1153 *
1154 * @return string
1155 */
1156 public function get_template_field_options( $template_id = false, $theme = false, $campaign_data = false ) {
1157
1158 ob_start();
1159
1160 $field_id = 0;
1161 $layout = (array) $theme['layout'];
1162
1163 // If there is no description for this campaign, then this (assumingly) must be a new campaign and we should check and see if there's a description that comes with the template.
1164 if ( false !== $template_id && ! isset( $campaign_data['settings']['general']['description'] ) ) {
1165
1166 if ( ! empty( $this->templates_data['templates'][ $template_id ]['settings']['general']['description'] ) ) {
1167 $campaign_data['settings']['general']['description'] = $this->templates_data['templates'][ $template_id ]['settings']['general']['description'];
1168 }
1169 }
1170
1171 foreach ( $layout as $row ) {
1172 foreach ( $row['columns'] as $column ) {
1173 foreach ( $column as $section_key => $section ) {
1174
1175 switch ( $section['type'] ) {
1176 case 'fields':
1177 foreach ( $section['fields'] as $key => $field_type_data ) :
1178
1179 $field_type = is_array( $field_type_data ) && ! empty( $field_type_data['type'] ) ? esc_attr( $field_type_data['type'] ) : esc_attr( $key );
1180
1181 $type = 'Charitable_Field_' . str_replace( ' ', '_', ( ucwords( str_replace( '-', ' ', $field_type ) ) ) );
1182
1183 if ( is_array( $field_type_data ) ) {
1184 $campaign_data['fields'][ $field_id ] = $field_type_data;
1185 }
1186
1187 if ( class_exists( $type ) ) :
1188 $class = new $type();
1189 if ( method_exists( $class, 'settings_display' ) ) {
1190 echo $class->settings_display( $field_id, $campaign_data ); // phpcs:ignore --- second param was $this->campaign_data, but that isn't available.
1191 }
1192 endif;
1193 ++$field_id;
1194 endforeach;
1195 break;
1196 case 'tabs':
1197 foreach ( $section['tabs'] as $tab_index => $tab ) :
1198 foreach ( $tab['fields'] as $key => $field_type_data ) :
1199
1200 $field_type = is_array( $field_type_data ) && ! empty( $field_type_data['type'] ) ? esc_attr( $field_type_data['type'] ) : esc_attr( $key );
1201
1202 // header.
1203 $type = 'Charitable_Field_' . str_replace( ' ', '_', ( ucwords( str_replace( '-', ' ', $field_type ) ) ) );
1204
1205 if ( is_array( $field_type_data ) ) {
1206 $campaign_data['fields'][ $field_id ] = $field_type_data;
1207 }
1208
1209 if ( class_exists( $type ) ) :
1210 $class = new $type();
1211 if ( method_exists( $class, 'settings_display' ) ) {
1212 echo $class->settings_display( $field_id, $campaign_data ); // phpcs:ignore --- second param was $this->campaign_data, but that isn't available.
1213 }
1214 endif;
1215
1216 ++$field_id;
1217
1218 endforeach;
1219 endforeach;
1220 break;
1221 default:
1222 break;
1223 }
1224 }
1225 }
1226 }
1227
1228 return ob_get_clean();
1229 }
1230
1231 /**
1232 * Output tab options for the left sidebar.
1233 *
1234 * @since 1.8.0
1235 *
1236 * @param integer $template_id Tab info.
1237 * @param string $theme The current theme.
1238 * @param array $campaign_data Campaign data.
1239 *
1240 * @return string
1241 */
1242 public function get_template_tab_options( $template_id = false, $theme = false, $campaign_data = false ) { // phpcs:ignore
1243
1244 ob_start();
1245
1246 $max_tab_title_length = apply_filters( 'charitable_builder_design_tab_title_length', 20 );
1247
1248 $layout = (array) $theme['layout'];
1249 $tabs = array();
1250
1251 // Currently only one tab area per template, so we need to locate that tab area (if it exists) in the layout.
1252 foreach ( $layout as $row ) {
1253 foreach ( $row['columns'] as $column ) {
1254 foreach ( $column as $section ) {
1255 if ( $section['type'] === 'tabs' && ! empty( $section['tabs'] ) ) {
1256 $tabs = $section['tabs'];
1257 continue;
1258 }
1259 }
1260 }
1261 }
1262
1263 $number_of_tabs = count( $tabs );
1264 $hide_tab_nav_disabled = $number_of_tabs > 1 ? 'disabled="disabled"' : false;
1265
1266 ?>
1267
1268 <?php $enable_tabs = 'enabled'; ?>
1269
1270 <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">
1271 <span class="charitable-toggle-control">
1272 <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' ); ?> />
1273 <label class="charitable-toggle-control-icon" for="charitable-panel-field-settings-charitable-campaign-enable-tabs"></label>
1274 <label for="charitable-panel-field-settings-charitable-campaign-enable-tabs">Hide tab section. </label>
1275 <?php echo charitable_get_tooltip_html( esc_html__( 'Remove tabs from your public campaign page but not delete any items in the preview.', 'charitable' ), 'tooltipstered' ); // phpcs:ignore ?>
1276 </span>
1277 </div>
1278
1279 <hr />
1280
1281 <!-- group -->
1282 <div class="charitable-group charitable-layout-options-tab-group charitable-closed charitable-new-tab hidden" data-group_id="2">
1283 <div class="charitable-general-layout-heading" data-group="general-layout-tab">
1284 <a href="#" class="charitable-draggable"><i class="fa fa-bars"></i></a>
1285 <span>[ <?php echo esc_html__( 'New Tab', 'charitable' ); ?> ]</span>
1286 <a href="#" class="charitable-toggleable-group"><i class="fa fa-angle-down charitable-angle-down"></i></a>
1287 <a href="#" class="charitable-tab-group-delete" title="Delete Tab"><i class="fa fa-trash-o" aria-hidden="true"></i></a>
1288
1289 </div>
1290 <!-- rows -->
1291 <div class="charitable-group-rows">
1292 <!-- row -->
1293 <div class="charitable-group-row charitable-tab-title-row" id="tabs_xxx_row_title" data-field-id="">
1294 <label for=""><?php echo esc_html__( 'Title', 'charitable' ); ?> <?php echo charitable_get_tooltip_html( false, 'tooltipstered' ); // phpcs:ignore ?>
1295 <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 ); ?>">
1296 </div>
1297 <div class="charitable-group-row charitable-tab-title-row" id="tabs_xxx_row_visible_nav" data-field-id="">
1298 <span class="charitable-toggle-control">
1299 <input type="checkbox" id="tabs_xxx_visible_nav" class="charitable-settings-tab-visible-nav" name="tabs__xxx__visible_nav" value="invisible" <?php echo esc_attr( $hide_tab_nav_disabled ); ?> />
1300 <label class="charitable-toggle-control-icon" for="tabs_xxx_visible_nav"></label>
1301 <label for="tabs_xxx_visible_nav"><?php echo esc_html__( 'Hide tab navigation.', 'charitable' ); ?> </label>
1302 <?php echo charitable_get_tooltip_html( esc_html__( 'Hide the tab in the navigation bar (only if you have one tab in your design).', 'charitable' ), 'tooltipstered' ); // phpcs:ignore ?>
1303 </span>
1304 </div>
1305 </div>
1306 <!-- end rows -->
1307 </div> <!-- end group -->
1308 <?php
1309
1310 if ( $tabs ) {
1311
1312 $counter = 0;
1313
1314 foreach ( $tabs as $tab_id => $tab_info ) :
1315
1316 $group_id = ( strtolower( $tab_id ) === 'campaign' ) ? 0 : $tab_id;
1317 $group_name_var = ( $tab_id === 'campaign' ) ? $group_id : $group_id;
1318 $group_title = isset( $tab_info['title'] ) && '' !== trim( $tab_info['title'] ) ? $tab_info['title'] : '[ New Tab ]';
1319 $group_header = ( $tab_id === 'campaign' ) ? 'Campaign' : $group_title;
1320 $group_desc = isset( $tab_info['desc'] ) && '' !== trim( $tab_info['desc'] ) ? $tab_info['desc'] : false;
1321 $group_classes = isset( $tab_info['title'] ) && '' !== trim( $tab_info['title'] ) ? false : 'charitable-new-tab';
1322 $data_group = ( $tab_id === 'campaign' ) ? 'general-layout-tab' : 'general-layout-tab'; // general-layout-campaign.
1323 $active = $counter === 0 ? 'active' : false;
1324 $closed = $counter === 0 ? 'charitable-open' : 'charitable-closed';
1325 $arrow_icon = ! $active ? 'fa fa-angle-down charitable-angle-right' : 'fa fa-angle-down charitable-angle-down';
1326 $type = ( isset( $tab_info['type'] ) && '' !== trim( $tab_info['type'] ) ) ? $tab_info['type'] : 'html';
1327 $row_class = 'html' !== $type ? 'hidden' : false;
1328
1329 $visible_nav_checked = ! empty( $tab_info['visible_nav'] ) && 'invisible' === $tab_info['visible_nav'] ? 'checked="checked"' : '';
1330 $visible_nav_checked = ( false !== $hide_tab_nav_disabled ) ? '' : $visible_nav_checked;
1331 $disabled_css = ( false !== $hide_tab_nav_disabled ) ? 'charitable-disabled' : false;
1332
1333 ?>
1334
1335 <!-- group -->
1336 <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 ); ?>">
1337 <div class="charitable-general-layout-heading" data-group="<?php echo esc_attr( $data_group ); ?>">
1338 <a href="#" class="charitable-draggable"><i class="fa fa-bars"></i></a>
1339 <span><?php echo esc_html( $group_header ); ?></span>
1340 <a href="#" class="charitable-toggleable-group"><i class="<?php echo esc_attr( $arrow_icon ); ?>"></i></a>
1341 <a href="#" class="charitable-tab-group-delete" title="<?php esc_attr_e( 'Delete Tab', 'charitable' ); ?>"><i class="fa fa-trash-o" aria-hidden="true"></i></a>
1342
1343 </div>
1344 <!-- rows -->
1345 <div class="charitable-group-rows">
1346 <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 ); ?>">
1347 <label for=""><?php echo esc_html__( 'Title', 'charitable' ); ?> <?php echo charitable_get_tooltip_html( false, 'tooltipstered' ); // phpcs:ignore ?>
1348 <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 ); ?>">
1349 </div>
1350 <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 ); ?>">
1351 <span class="charitable-toggle-control">
1352 <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" name="tabs__<?php echo esc_attr( $group_name_var ); ?>__visible_nav" value="invisible" <?php echo esc_attr( $visible_nav_checked ); ?> <?php echo esc_attr( $visible_nav_checked ); ?> />
1353 <label class="charitable-toggle-control-icon <?php echo esc_attr( $disabled_css ); ?>" for="charitable-panel-field-settings-charitable-campaign-<?php echo esc_attr( $group_name_var ); ?>__visible_nav"></label>
1354 <label class="<?php echo esc_attr( $disabled_css ); ?>" for="charitable-panel-field-settings-charitable-campaign-<?php echo esc_attr( $group_name_var ); ?>__visible_nav">Hide tab navigation. </label>
1355 <?php echo charitable_get_tooltip_html( esc_html__( 'Hide the tab in the navigation bar (only if you have one tab in your design).', 'charitable' ), 'tooltipstered' ); // phpcs:ignore ?>
1356 </span>
1357 </div>
1358 </div>
1359 <!-- end rows -->
1360 </div> <!-- end group -->
1361
1362 <?php ++$counter; ?>
1363
1364 <?php
1365 endforeach;
1366
1367 } else {
1368 ?>
1369
1370 <!-- group -->
1371 <div class="charitable-group charitable-layout-options-tab-group charitable-layout-options-general-group active" data-group_id="0"> <!-- open or closed -->
1372 <a href="#" class="charitable-general-layout-heading charitable-toggleable-group" data-group="general-layout-campaign">
1373 <span><?php echo esc_html__( 'Campaign', 'charitable' ); ?></span>
1374 <i class="fa fa-angle-down"></i>
1375 </a>
1376 <!-- rows -->
1377 <div class="charitable-group-rows">
1378 <input type="hidden" name="tabs__campaign__type" value="html" />
1379 <!-- row -->
1380 <div class="charitable-group-row" id="" data-field-id="">
1381 <label for="">Title <?php echo charitable_get_tooltip_html( false, 'tooltipstered' ); // phpcs:ignore ?>
1382 <input type="text" class="" id="charitable-field-option-4-name" name="tabs__campaign__title" value="" placeholder="">
1383 </div>
1384 <!-- row -->
1385 <div class="charitable-group-row" id="" data-field-id="">
1386 <label for="">Description <?php echo charitable_get_tooltip_html( false, 'tooltipstered' ); // phpcs:ignore ?>
1387 <textarea class="" id="" name="tabs__campaign__desc" rows="3"></textarea>
1388 </div>
1389 </div>
1390 <!-- end rows -->
1391 </div> <!-- end group -->
1392 <?php } ?>
1393
1394 <!-- button? -->
1395 <button class="charitable-tab-groups-add charitable-btn charitable-btn-sm"><?php echo esc_html__( '+ Add New Tab', 'charitable' ); ?></button>
1396 <!-- end button -->
1397
1398 <?php
1399 return ob_get_clean();
1400 }
1401
1402 /**
1403 * Retreive data of a particular theme.
1404 *
1405 * @since 1.8.0
1406 *
1407 * @param string $template_id Template slug.
1408 * @param array $campaign_data Campaign data.
1409 * @param bool $no_cache Whether to bypass the cache or not. True to bypass the cache. False to use the cache. Default is false.
1410 *
1411 * @return array
1412 */
1413 public function get_template_data( $template_id = false, $campaign_data = array(), $no_cache = false ) {
1414
1415 if ( false === $template_id ) {
1416 $template_id = charitable_campaign_builder_default_template();
1417 }
1418
1419 $templates_data = $this->get_templates_data( $template_id, $campaign_data, $no_cache );
1420 $template_data = ! empty( $templates_data['templates'][ $template_id ] ) ? (array) $templates_data['templates'][ $template_id ] : false;
1421
1422 return $template_data;
1423 }
1424
1425 /**
1426 * Retreive data of all available campaign builder templates from the database (or generate).
1427 *
1428 * @since 1.8.0
1429 * @since 1.8.1.3 Added $no_cache parameter.
1430 *
1431 * @param string $template_id Template slug.
1432 * @param array $campaign_data Campaign data.
1433 * @param bool $no_cache Whether to bypass the cache or not. True to bypass the cache. False to use the cache. Default is false.
1434 *
1435 * @return array
1436 */
1437 public function get_templates_data( $template_id = false, $campaign_data = array(), $no_cache = false ) {
1438
1439 $templates_data = $no_cache || ( charitable_is_debug() ) || ( defined( 'CHARITABLE_BUILDER_NO_CACHE_TEMPLATE' ) && CHARITABLE_BUILDER_NO_CACHE_TEMPLATE ) ? false : get_option( 'charitable_campaign_builder_templates' );
1440
1441 if ( empty( $templates_data ) ) {
1442
1443 // if we cannot locate, we will create the basic choices and add them into the WordPress option, while returning the data.
1444 $templates_data = $this->get_source_template_data();
1445
1446 foreach ( $templates_data['templates'] as $key => $values ) :
1447
1448 if ( is_admin() ) :
1449 $templates_data['templates'][ $key ]['preview'] = $this->get_template_preview( $key, $templates_data['templates'][ $key ], $campaign_data );
1450 $templates_data['templates'][ $key ]['field_options'] = $this->get_template_field_options( $key, $templates_data['templates'][ $key ], $campaign_data );
1451 $templates_data['templates'][ $key ]['tab_options'] = $this->get_template_tab_options( $key, $templates_data['templates'][ $key ], $campaign_data );
1452 $templates_data['templates'][ $key ]['advanced']['show_field_names'] = charitable_show_field_names_by_default( $key ) ? 'show' : 'hide';
1453 $templates_data['templates'][ $key ]['advanced']['preview_mode'] = charitable_show_preview_mode_by_default( $key ) ? 'normal' : 'minimum';
1454 endif;
1455 endforeach;
1456
1457 if ( ( charitable_is_debug() ) || ( defined( 'CHARITABLE_BUILDER_NO_CACHE_TEMPLATE' ) && CHARITABLE_BUILDER_NO_CACHE_TEMPLATE ) ) {
1458 delete_option( 'charitable_campaign_builder_templates', $templates_data );
1459 } else {
1460 // update the WordPress option.
1461 update_option( 'charitable_campaign_builder_templates', $templates_data );
1462 }
1463 }
1464
1465 return apply_filters( 'charitable_campaign_builder_template_data', $templates_data );
1466 }
1467
1468
1469 /**
1470 * Get the meta field data for a given template.
1471 *
1472 * @param string $field_name The name of the meta field.
1473 * @param int|bool $template_id The ID of the template to get the meta field data for.
1474 * @return mixed The value of the meta field.
1475 */
1476 public function get_template_data_meta_field( $field_name = '', $template_id = false ) {
1477
1478 if ( '' === trim( $field_name ) ) {
1479 return false;
1480 }
1481
1482 if ( false === $template_id ) {
1483 $template_id = charitable_campaign_builder_default_template();
1484 }
1485
1486 $template_data = $this->get_template_data( $template_id );
1487
1488 return ! empty( $template_data['meta'][ $field_name ] ) ? $template_data['meta'][ $field_name ] : false;
1489 }
1490
1491 /**
1492 * Out the HTML that does the display of items and sidebar search/categories of the builder.
1493 *
1494 * @since 1.8.0
1495 * @version 1.8.1.12 Broke off HTML into function to generate sections (blank vs templated).
1496 *
1497 * @return array
1498 */
1499 public function output_templates_panel() {
1500
1501 ob_start();
1502
1503 $current_template_id = false;
1504 $template_items = array(
1505 'single_column' => 0,
1506 'template' => 0,
1507 );
1508
1509 if ( isset( $_GET['campaign_id'] ) && 0 !== intval( $_GET['campaign_id'] ) ) { // phpcs:ignore
1510
1511 $template_data = charitable_get_template_data_from_campaign( abs( $_GET['campaign_id'] ) ); // phpcs:ignore
1512 $current_template_id = isset( $template_data['template_id'] ) ? $template_data['template_id'] : false;
1513
1514 }
1515
1516 $this->prepare_templates_data();
1517
1518 ?>
1519
1520 <div id="charitable-template-container" class="charitable-template-options">
1521
1522 <div class="charitable-setup-templates-sidebar">
1523
1524 <div class="charitable-setup-templates-search-wrap">
1525 <i class="fa fa-search"></i>
1526 <i class="fa fa-close"></i>
1527 <label>
1528 <input type="text" id="charitable-setup-template-search" value="" placeholder="Search Templates">
1529 </label>
1530 </div>
1531
1532 <ul class="charitable-setup-templates-categories">
1533 <?php $this->template_categories(); ?>
1534 </ul>
1535
1536 <div class="charitable-setup-templates-feedback">
1537 <h6><?php echo esc_html__( "Don't See What You're Looking For?", 'charitable' ); ?></h6>
1538 <p>
1539 <?php
1540 printf(
1541 /* translators: 1: Template ID */
1542 '<a href="#" class="send-feedback">%1$s</a> %2$s',
1543 esc_html__( 'Let us know', 'charitable' ),
1544 esc_html__( 'what templates to add in the future.', 'charitable' ) // no comma here to avoid fatal on old PHP versions (for now).
1545 );
1546 ?>
1547 </p>
1548
1549 </div>
1550
1551 </div>
1552
1553 <div id="charitable-template-list" class="charitable-template-list"> <!-- start template list -->
1554
1555 <div class="charitable-template-list-container">
1556
1557 <?php
1558
1559 if ( ! empty( $this->prepared_templates ) ) :
1560
1561 foreach ( $this->prepared_templates as $campaign_template_slug => $campaign_template_data ) :
1562
1563 if ( is_array( $campaign_template_data['meta']['template_type'] ) && array_intersect( array( 'blank' ), $campaign_template_data['meta']['template_type'] ) ) {
1564
1565 ++$template_items['single_column'];
1566
1567 } else {
1568
1569 ++$template_items['template'];
1570
1571 }
1572
1573 endforeach;
1574
1575 if ( $template_items['single_column'] > 0 ) :
1576
1577 echo '<div class="charitable-template-list-section charitable-template-list-section-blank">
1578 <h4>' . esc_html__( 'Start from scratch with a blank template...', 'charitable' ) . '</h4>
1579 </div>';
1580
1581 foreach ( $this->prepared_templates as $campaign_template_slug => $campaign_template_data ) :
1582
1583 $this->output_template_item( $campaign_template_slug, $campaign_template_data, array( 'blank' ), array(), $current_template_id );
1584
1585 endforeach;
1586
1587 endif;
1588
1589 if ( $template_items['template'] > 0 ) :
1590
1591 echo '<div class="charitable-template-list-section charitable-template-list-section-prebuilt">
1592 <h4>' . esc_html__( '...or select from a prebuilt template and be up and running in minutes!', 'charitable' ) . '</h4>
1593 </div>';
1594
1595 foreach ( $this->prepared_templates as $campaign_template_slug => $campaign_template_data ) :
1596
1597 $this->output_template_item( $campaign_template_slug, $campaign_template_data, false, array( 'blank' ), $current_template_id );
1598
1599 endforeach;
1600
1601 endif;
1602
1603 ?>
1604
1605 <?php else : ?>
1606
1607 <div class="charitable-error">
1608
1609 <p><?php echo esc_html__( 'Unable to locate templates for campaigns. Contact support.', 'charitable' ); ?></p>
1610
1611 </div>
1612
1613 <?php endif; ?>
1614
1615 </div>
1616
1617 <div class="charitable-templates-no-results" style="display: none;">
1618 <p><?php echo esc_html__( 'Sorry, we didn\'t find any templates that match your criteria.', 'charitable' ); ?></p>
1619 </div>
1620
1621 </div> <!-- end template list -->
1622
1623 </div>
1624
1625 <?php
1626
1627 return ob_get_clean();
1628 }
1629
1630 /**
1631 * HTML output for a single template item in the list.
1632 *
1633 * @since 1.8.1.12
1634 *
1635 * @param string $campaign_template_slug The template slug.
1636 * @param array $campaign_template_data The template data.
1637 * @param array $filter_include The categories to include.
1638 * @param array $filter_exclude The categories to exclude.
1639 * @param bool $current_template_id The current template ID.
1640 */
1641 private function output_template_item( $campaign_template_slug = '', $campaign_template_data = array(), $filter_include = array(), $filter_exclude = array(), $current_template_id = false ) {
1642
1643 $create_update_term = isset( $_GET['campaign_id'] ) && 0 !== intval( $_GET['campaign_id'] ) ? esc_html__( 'Restart Campaign', 'charitable' ) : esc_html__( 'Create Campaign', 'charitable' ); // phpcs:ignore
1644
1645 if ( '' === trim( $campaign_template_slug ) || empty( $campaign_template_data ) ) {
1646 return false;
1647 }
1648
1649 // If we are filtering for template categories and this template is not in the list ('template_type'), then return false.
1650 if ( ! empty( $filter_include ) && is_array( $campaign_template_data['meta']['template_type'] ) && ! empty( $campaign_template_data['meta']['template_type'] ) ) {
1651 // If none of the elements in the $filter_include array are in the template_type, return.
1652 if ( ! array_intersect( $filter_include, $campaign_template_data['meta']['template_type'] ) ) {
1653 return false;
1654 }
1655 }
1656
1657 // If we are filtering for items to exclude, then we will return false if any of the elements in the $filter_exclude array are in the template_type.
1658 if ( ! empty( $filter_exclude ) && is_array( $campaign_template_data['meta']['template_type'] ) && ! empty( $campaign_template_data['meta']['template_type'] ) ) {
1659 // If any of the elements in the $filter_exclude array are in the template_type, return.
1660 if ( array_intersect( $filter_exclude, $campaign_template_data['meta']['template_type'] ) ) {
1661 return false;
1662 }
1663 }
1664
1665 $primary = isset( $campaign_template_data['meta']['colors']['primary'] ) && ! empty( $campaign_template_data['meta']['colors']['primary'] ) ? esc_attr( $campaign_template_data['meta']['colors']['primary'] ) : false;
1666 $secondary = isset( $campaign_template_data['meta']['colors']['secondary'] ) && ! empty( $campaign_template_data['meta']['colors']['secondary'] ) ? esc_attr( $campaign_template_data['meta']['colors']['secondary'] ) : false;
1667 $tertiary = isset( $campaign_template_data['meta']['colors']['tertiary'] ) && ! empty( $campaign_template_data['meta']['colors']['tertiary'] ) ? esc_attr( $campaign_template_data['meta']['colors']['tertiary'] ) : false;
1668 $button_color = isset( $campaign_template_data['meta']['colors']['button_bg'] ) && ! empty( $campaign_template_data['meta']['colors']['button_bg'] ) ? esc_attr( $campaign_template_data['meta']['colors']['button_bg'] ) : false;
1669
1670 $template_categories = ! empty( $campaign_template_data['meta']['categories'] ) ? implode( ', ', $campaign_template_data['meta']['categories'] ) : false; // todo: santitize.
1671 $template_tags = ! empty( $campaign_template_data['meta']['search_tags'] ) ? implode( ', ', $campaign_template_data['meta']['search_tags'] ) : false; // todo: santitize.
1672 $suffixes = ! empty( $campaign_template_data['meta']['suffixes'] ) ? serialize( $campaign_template_data['meta']['suffixes'] ) : false; // todo: santitize.
1673
1674 $show_only_for_lite = ! empty( $campaign_template_data['dependencies']['is_lite'] ) ? true : false;
1675
1676 if ( charitable_is_pro() && $show_only_for_lite ) {
1677 return;
1678 }
1679
1680 if ( isset( $campaign_template_data['thumbnail_url'] ) && false !== $campaign_template_data['thumbnail_url'] ) {
1681
1682 $template_thumbnail_html = '<div class="charitable-template-thumbnail charitable-template-thumbnail-' . $campaign_template_slug . '" style="background-image: url(' . $campaign_template_data['thumbnail_url'] . ')"></div>';
1683
1684 } elseif ( file_exists( charitable()->get_path( 'assets', true ) . 'images/campaign-builder/templates/' . $campaign_template_slug . '/thumbnail.png' ) ) {
1685
1686 $template_thumbnail_html = '<div class="charitable-template-thumbnail charitable-template-thumbnail-' . $campaign_template_slug . '" style="background-image: url(' . charitable()->get_path( 'assets', false ) . 'images/campaign-builder/templates/' . $campaign_template_slug . '/thumbnail.png)"></div>';
1687
1688 } else {
1689
1690 $template_thumbnail_html = '<div class="charitable-template-thumbnail charitable-template-thumbnail-' . $campaign_template_slug . '" style="background-image: url(' . charitable()->get_path( 'assets', false ) . 'images/campaign-builder/templates/feedback.png)"></div>';
1691
1692 }
1693
1694 $create_update_css = isset( $_GET['campaign_id'] ) && 0 !== intval( $_GET['campaign_id'] ) ? 'update-campaign' : 'create-campaign'; // phpcs:ignore
1695 $template_code = esc_attr( $campaign_template_slug );
1696 $template_preview_url = charitable()->get_path( 'assets', false ) . 'images/campaign-builder/templates/' . $template_code . '/preview.png';
1697 $template_description = esc_html( wp_strip_all_tags( $campaign_template_data['meta']['description'] ) );
1698 $template_types = is_array( $campaign_template_data['meta']['template_type'] ) && ! empty( $campaign_template_data['meta']['template_type'] ) ? implode( ' ', $campaign_template_data['meta']['template_type'] ) : false;
1699 $template_types = ( false === $template_types && false !== $campaign_template_data['meta']['template_type'] ) ? esc_attr( $campaign_template_data['meta']['template_type'] ) : $template_types;
1700 ?>
1701
1702 <div class="charitable-template-list-container-item charitable-template-<?php echo esc_attr( $campaign_template_slug ); ?> <?php echo esc_attr( $template_types ); ?>">
1703
1704 <div class="charitable-template
1705 <?php
1706 if ( $current_template_id && $campaign_template_slug === $current_template_id ) :
1707 ?>
1708 active<?php endif; ?>" data-template-code="<?php echo esc_attr( $template_code ); ?>" data-template-preview-url="<?php echo esc_url( $template_preview_url ); ?>" data-template-description="<?php echo esc_attr( $template_description ); ?>" data-template-label="<?php echo esc_html( $campaign_template_data['meta']['label'] ); ?>" data-template-type="<?php echo esc_attr( $template_types ); ?>" data-template-categories="<?php echo esc_attr( $template_categories ); ?>" data-template-tags="<?php echo esc_attr( $template_tags ); ?>" data-template-primary="<?php echo esc_attr( $primary ); ?>" data-template-secondary="<?php echo esc_attr( $secondary ); ?>" data-template-tertiary="<?php echo esc_attr( $tertiary ); ?>" data-template-button="<?php echo esc_attr( $button_color ); ?>" data-template-suffixes="<?php echo htmlspecialchars( $suffixes ); // phpcs:ignore ?>">
1709
1710 <div class="charitable-banner-container
1711 <?php
1712 if ( ! $current_template_id || $campaign_template_slug !== $current_template_id ) :
1713 ?>
1714 charitable-hidden<?php endif; ?>">
1715 <div class="charitable-banner"><?php echo esc_html__( 'Active', 'charitable' ); ?></div>
1716 </div>
1717
1718 <div class="template-thumbnail placeholder">
1719 <?php if ( 'lite-to-pro' !== $campaign_template_slug ) { ?>
1720 <div class="template-buttons
1721 <?php
1722 if ( $current_template_id && $campaign_template_slug === $current_template_id ) :
1723 ?>
1724 charitable-hidden<?php endif; ?>">
1725 <a href="#" class="button <?php echo esc_attr( $create_update_css ); ?>"><?php echo esc_html( $create_update_term ); ?></a>
1726 <?php if ( ! isset( $campaign_template_data['meta']['preview'] ) || false !== $campaign_template_data['meta']['preview'] ) : ?>
1727 <a href="#" class="button preview-campaign"><?php echo esc_html__( 'Preview', 'charitable' ); ?></a>
1728 <?php endif; ?>
1729 </div>
1730 <?php } else { ?>
1731 <div class="template-buttons">
1732 <a href="#" class="button send-feedback"><?php echo esc_html__( 'Send Feedback', 'charitable' ); ?></a>
1733 </div>
1734 <?php } ?>
1735
1736 <?php echo $template_thumbnail_html; // phpcs:ignore ?>
1737
1738 </div>
1739 <?php printf( '<h4>%s</h4>', $campaign_template_data['meta']['label'] ); // phpcs:ignore ?>
1740 <?php printf( '<p>%s</p>', $campaign_template_data['meta']['description'] ); // phpcs:ignore ?>
1741
1742 </div>
1743
1744 </div>
1745
1746 <?php
1747 }
1748
1749 /**
1750 * Prepare templates data for output.
1751 *
1752 * @since 1.8.0
1753 * @version 1.8.1.12
1754 */
1755 private function prepare_templates_data() {
1756
1757 $templates = $this->get_templates_data();
1758 $single_templates = array();
1759
1760 if ( empty( $templates ) || empty( $templates['templates'] ) ) {
1761 return;
1762 }
1763
1764 ksort( $templates['templates'] );
1765
1766 // move any "simple" template to the front.
1767 foreach ( $templates['templates'] as $template_name => $template_info ) :
1768 if ( ! empty( $template_info['meta']['template_type'] ) && is_array( $template_info['meta']['template_type'] ) && in_array( 'simple', $template_info['meta']['template_type'] ) ) {
1769 $single_templates['templates'][ $template_name ] = $template_info;
1770 unset( $templates['templates'][ $template_name ] );
1771 }
1772 endforeach;
1773
1774 ksort( $single_templates['templates'] );
1775
1776 $templates['templates'] = array_merge( $single_templates['templates'], $templates['templates'] );
1777
1778 // Loop through each available template.
1779 foreach ( $templates['templates'] as $id => $template ) {
1780
1781 $this->prepared_templates[ $id ] = $this->prepare_template_render_arguments( $template );
1782
1783 }
1784 }
1785
1786 /**
1787 * Prepare arguments for rendering template item.
1788 *
1789 * @since 1.8.0
1790 *
1791 * @param array $template Template data.
1792 *
1793 * @return array Arguments.
1794 */
1795 private function prepare_template_render_arguments( $template ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.MaxExceeded
1796
1797 return $template;
1798 }
1799
1800 /**
1801 * Generate and display categories menu.
1802 *
1803 * @since 1.8.0
1804 */
1805 public function template_categories() {
1806
1807 $templates_count = $this->get_count_in_categories();
1808
1809 $generic_categories = array(
1810 'all' => esc_html__( 'All Templates', 'charitable' ),
1811 );
1812
1813 if ( isset( $templates_count['all'], $templates_count['available'] ) && $templates_count['all'] !== $templates_count['available'] ) {
1814 $generic_categories['available'] = esc_html__( 'Available Templates', 'charitable' );
1815 }
1816
1817 $generic_categories['favorites'] = esc_html__( 'Favorite Templates', 'charitable' );
1818 $generic_categories['new'] = esc_html__( 'New Templates', 'charitable' );
1819 $generic_categories['single'] = esc_html__( 'Single', 'charitable' );
1820 $generic_categories['peer-to-peer'] = esc_html__( 'Peer-to-Peer', 'charitable' );
1821
1822 $generic_categories = apply_filters( 'charitable_campaign_builder_template_generic_categories', $generic_categories );
1823
1824 $this->output_categories( $generic_categories, $templates_count );
1825
1826 printf( '<li class="divider"></li>' );
1827
1828 $common_categories = array();
1829
1830 if ( $this->is_custom_templates_available ) {
1831 $common_categories['custom'] = esc_html__( 'Custom Templates', 'charitable' );
1832 }
1833
1834 if ( $this->is_addon_templates_available ) {
1835 $common_categories['addons'] = esc_html__( 'Addon Templates', 'charitable' );
1836 }
1837
1838 $categories = array_merge(
1839 $common_categories,
1840 $this->get_categories()
1841 );
1842
1843 $this->output_categories( $categories, $templates_count );
1844 }
1845
1846 /**
1847 * Output categories list.
1848 *
1849 * @since 1.8.0
1850 *
1851 * @param array $categories Categories list.
1852 * @param array $templates_count Templates count by categories.
1853 *
1854 * @return void
1855 */
1856 private function output_categories( $categories, $templates_count ) {
1857
1858 foreach ( $categories as $slug => $name ) {
1859
1860 $class = '';
1861
1862 if ( $slug === 'all' ) {
1863 $class = ' class="active"';
1864 } elseif ( empty( $templates_count[ $slug ] ) ) {
1865 $class = ' class="charitable-hidden"';
1866 }
1867
1868 $count = isset( $templates_count[ $slug ] ) ? $templates_count[ $slug ] : '0';
1869
1870 printf(
1871 '<li data-category="%1$s"%2$s>%3$s<span>%4$s</span></li>',
1872 esc_attr( $slug ),
1873 $class, // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1874 esc_html( $name ),
1875 esc_html( $count )
1876 );
1877 }
1878 }
1879
1880 /**
1881 * Get categories data.
1882 *
1883 * @since 1.8.0
1884 *
1885 * @return array
1886 */
1887 public function get_categories() {
1888
1889 $this->categories = apply_filters(
1890 'charitable_campaign_builder_template_categories',
1891 array(
1892 'animal-pets' => esc_html__( 'Animal / Pets', 'charitable' ),
1893 'club-organizations' => esc_html__( 'Club / Organizations', 'charitable' ),
1894 'environmental' => esc_html__( 'Environmental', 'charitable' ),
1895 'events' => esc_html__( 'Events', 'charitable' ),
1896 'family' => esc_html__( 'Family', 'charitable' ),
1897 'legal' => esc_html__( 'Legal', 'charitable' ),
1898 'medical' => esc_html__( 'Medical', 'charitable' ),
1899 'political' => esc_html__( 'Political', 'charitable' ),
1900 'special-occasions' => esc_html__( 'Special Occasions', 'charitable' ),
1901 'sports' => esc_html__( 'Sports', 'charitable' ),
1902 'youth' => esc_html__( 'Youth', 'charitable' ),
1903 )
1904 );
1905
1906 return $this->categories;
1907 }
1908
1909 /**
1910 * Get categories templates count.
1911 *
1912 * @since 1.8.0
1913 *
1914 * @return array
1915 */
1916 private function get_count_in_categories() {
1917
1918 $all_categories = array();
1919 $available_templates_count = 0;
1920 $favorites_templates_count = 0;
1921
1922 foreach ( $this->prepared_templates as $template_id => $template_data ) {
1923
1924 $template_meta = $template_data['meta'];
1925 $categories = $template_meta['categories'];
1926
1927 if ( $template_meta['has_access'] ) {
1928 ++$available_templates_count;
1929 }
1930
1931 if ( $template_meta['favorite'] ) {
1932 ++$favorites_templates_count;
1933 }
1934
1935 if ( is_array( $categories ) ) {
1936 // loop through $categories and add to $all_categories.
1937 foreach ( $categories as $category ) {
1938 $all_categories[] = $category;
1939 }
1940 continue;
1941 }
1942
1943 $all_categories[] = $categories;
1944 }
1945
1946 $categories_count = array_count_values( $all_categories );
1947 $categories_count['all'] = count( $this->prepared_templates );
1948 $categories_count['available'] = $available_templates_count;
1949 $categories_count['favorites'] = $favorites_templates_count;
1950
1951 return $categories_count;
1952 }
1953
1954 /**
1955 * Retrieves the source template data for the campaign builder, which hopefully ends up cached.
1956 *
1957 * @access private
1958 * @return array The source template data.
1959 */
1960 public function get_source_template_data() {
1961
1962 return array(
1963 'version' => '1.0.0',
1964 'date_added' => time(),
1965 'templates' => array(
1966 'simple-1-col' => array(
1967 'meta' => array(
1968 'label' => 'Simple 1 Column',
1969 'slug' => 'simple-1-column',
1970 'description' => 'A simple one column campaign template to build from.',
1971 'template_type' => array( 'single', 'simple', 'blank' ),
1972 'search_tags' => array(
1973 'default',
1974 'simple',
1975 'blank',
1976 'clean',
1977 ),
1978 'categories' => array(
1979 'default',
1980 ),
1981 'created' => '2023-10-05', // Y-m-d.
1982 'version' => '1.0',
1983 'author' => 'David Bisset',
1984 'dependencies' => false, // not used yet.
1985 'has_access' => true, // not used yet, but false if the user can't select it.
1986 'favorite' => false,
1987 'preview' => false, // show a "preview" button, default would be true.
1988 'colors' => array(
1989 'primary' => '#000000',
1990 'secondary' => '#2B66D1',
1991 'tertiary' => '#F99E36',
1992 'accent' => false,
1993 'button_bg' => '#5AA152',
1994 ),
1995 'parent_theme' => false, // not used yet.
1996 'thumbnail_url' => false, // overrides default location to look for thumbnails in template page.
1997 ),
1998 'layout' => array(
1999 array( // row.
2000 'type' => 'row',
2001 'columns' => array(
2002 array( // column.
2003 array( // section.
2004 'type' => 'fields',
2005 'fields' => array(),
2006 ),
2007 ),
2008 ),
2009 ),
2010 array( // row.
2011 'type' => 'row',
2012 'css_class' => 'no-padding no-field-target no-field-wrap',
2013 'columns' => array(
2014 array( // column.
2015 array( // section.
2016 'type' => 'tabs',
2017 'tabs' => array(
2018 array(
2019 'title' => 'Overview',
2020 'type' => '',
2021 'slug' => 'default',
2022 'fields' => array(),
2023 ),
2024 ),
2025 ),
2026 ),
2027 ),
2028 ),
2029 ),
2030 'advanced' => array(
2031 'tab_style' => 'boxed',
2032 'tab_size' => 'medium',
2033 ),
2034 'settings' => array(
2035 'general' => array(
2036 'description' => '<p><strong>This is a description of your campaign.</strong></p><p>Write one or two short paragraphs about what you want to accomplish and perhaps brief of origin of this campaign, past campaigns, and feature key people and events that will enspire people to give to your cause.</p>',
2037 ),
2038 ),
2039 ),
2040 'simple-2-col' => array(
2041 'meta' => array(
2042 'label' => 'Simple 2 Column',
2043 'slug' => 'simple-2-column',
2044 'description' => 'A simple two column campaign template to build from.',
2045 'template_type' => array( 'single', 'simple', 'blank' ),
2046 'search_tags' => array(
2047 'default',
2048 'simple',
2049 'blank',
2050 'clean',
2051 ),
2052 'categories' => array(
2053 'default',
2054 ),
2055 'created' => '2023-10-05', // Y-m-d.
2056 'version' => '1.0',
2057 'author' => 'David Bisset',
2058 'dependencies' => false, // not used yet.
2059 'has_access' => true, // not used yet, but false if the user can't select it.
2060 'favorite' => false,
2061 'preview' => false, // show a "preview" button, default would be true.
2062 'colors' => array(
2063 'primary' => '#000000',
2064 'secondary' => '#2B66D1',
2065 'tertiary' => '#F99E36',
2066 'accent' => false,
2067 'button_bg' => '#5AA152',
2068 ),
2069 'parent_theme' => false, // not used yet.
2070 'thumbnail_url' => false, // overrides default location to look for thumbnails in template page.
2071 ),
2072 'layout' => array(
2073 array( // row.
2074 'type' => 'row',
2075 'columns' => array(
2076 array( // column.
2077 array( // section.
2078 'type' => 'fields',
2079 'fields' => array(),
2080 ),
2081 ),
2082 array( // column.
2083 array( // section.
2084 'type' => 'fields',
2085 'fields' => array(),
2086 ),
2087 ),
2088 ),
2089 ),
2090 array( // row.
2091 'type' => 'row',
2092 'css_class' => 'no-padding no-field-target no-field-wrap',
2093 'columns' => array(
2094 array( // column.
2095 array( // section.
2096 'type' => 'tabs',
2097 'tabs' => array(
2098 array(
2099 'title' => 'Overview',
2100 'type' => '',
2101 'slug' => 'default',
2102 'fields' => array(),
2103 ),
2104 ),
2105 ),
2106 ),
2107 ),
2108 ),
2109 ),
2110 'advanced' => array(
2111 'tab_style' => 'boxed',
2112 'tab_size' => 'medium',
2113 ),
2114 'settings' => array(
2115 'general' => array(
2116 'description' => '<p><strong>This is a description of your campaign.</strong></p><p>Write one or two short paragraphs about what you want to accomplish and perhaps brief of origin of this campaign, past campaigns, and feature key people and events that will enspire people to give to your cause.</p>',
2117 ),
2118 ),
2119 ),
2120 'simple-2-col-header' => array(
2121 'meta' => array(
2122 'label' => 'Simple 2 Column w/ header',
2123 'slug' => 'simple-2-column-header',
2124 'description' => 'A simple two column layout with a header.',
2125 'template_type' => array( 'single', 'simple', 'blank' ),
2126 'search_tags' => array(
2127 'default',
2128 'simple',
2129 'blank',
2130 'clean',
2131 ),
2132 'categories' => array(
2133 'default',
2134 ),
2135 'created' => '2023-10-05', // Y-m-d.
2136 'version' => '1.0',
2137 'author' => 'David Bisset',
2138 'dependencies' => false, // not used yet.
2139 'has_access' => true, // not used yet, but false if the user can't select it.
2140 'favorite' => false,
2141 'preview' => false, // show a "preview" button, default would be true.
2142 'colors' => array(
2143 'primary' => '#000000',
2144 'secondary' => '#2B66D1',
2145 'tertiary' => '#F99E36',
2146 'accent' => false,
2147 'button_bg' => '#5AA152',
2148 ),
2149 'parent_theme' => false, // not used yet.
2150 'thumbnail_url' => false, // overrides default location to look for thumbnails in template page.
2151 ),
2152 'layout' => array(
2153 array( // row.
2154 'type' => 'header',
2155 'css_class' => 'charitable-header',
2156 'columns' => array(
2157 array( // column.
2158 array( // section.
2159 'type' => 'fields',
2160 'fields' => array(),
2161 ),
2162 ),
2163 ),
2164 ),
2165 array( // row.
2166 'type' => 'row',
2167 'columns' => array(
2168 array( // column.
2169 array( // section.
2170 'type' => 'fields',
2171 'fields' => array(),
2172 ),
2173 ),
2174 array( // column.
2175 array( // section.
2176 'type' => 'fields',
2177 'fields' => array(),
2178 ),
2179 ),
2180 ),
2181 ),
2182 array( // row.
2183 'type' => 'row',
2184 'css_class' => 'no-padding no-field-target no-field-wrap',
2185 'columns' => array(
2186 array( // column.
2187 array( // section.
2188 'type' => 'tabs',
2189 'tabs' => array(
2190 array(
2191 'title' => 'Overview',
2192 'type' => '',
2193 'slug' => 'default',
2194 'fields' => array(),
2195 ),
2196 ),
2197 ),
2198 ),
2199 ),
2200 ),
2201 ),
2202 'advanced' => array(
2203 'tab_style' => 'boxed',
2204 'tab_size' => 'medium',
2205 ),
2206 'settings' => array(
2207 'general' => array(
2208 'description' => '<p><strong>This is a description of your campaign.</strong></p><p>Write one or two short paragraphs about what you want to accomplish and perhaps brief of origin of this campaign, past campaigns, and feature key people and events that will enspire people to give to your cause.</p>',
2209 ),
2210 ),
2211 ),
2212 'youth-sports' => array(
2213 'meta' => array(
2214 'label' => 'Youth Sports',
2215 'slug' => 'youth-sports',
2216 'description' => 'Accept donations for a local school\'s sports or athletics team.',
2217 'template_type' => array( 'single', 'prebuilt' ),
2218 'search_tags' => array(
2219 'youth',
2220 'sports',
2221 'blue',
2222 ),
2223 'categories' => array(
2224 'sports',
2225 'youth',
2226 'special-occasions',
2227 ),
2228 'created' => '2023-10-05', // Y-m-d.
2229 'version' => '1.0',
2230 'author' => 'David Bisset',
2231 'dependencies' => false, // not used yet.
2232 'has_access' => true, // not used yet, but false if the user can't select it.
2233 'favorite' => false,
2234 'colors' => array(
2235 'primary' => '#102963',
2236 'secondary' => '#0D0D0D',
2237 'tertiary' => '#989898',
2238 'accent' => false,
2239 'button_bg' => '#ec5f25',
2240 ),
2241 'parent_theme' => false, // not used yet.
2242 'thumbnail_url' => false, // overrides default location to look for thumbnails in template page.
2243 ),
2244 'layout' => array(
2245 array( // row.
2246 'type' => 'row',
2247 'columns' => array(
2248 array( // column.
2249 array( // section.
2250 'type' => 'fields',
2251 'fields' => array(
2252 array(
2253 'type' => 'photo',
2254 'default' => 'photo.jpg',
2255 ),
2256 array(
2257 'type' => 'campaign-summary',
2258 ),
2259 ),
2260 ),
2261 ),
2262 array(
2263 array( // section.
2264 'type' => 'fields',
2265 'fields' => array(
2266 array(
2267 'type' => 'campaign-title',
2268 ),
2269 array(
2270 'type' => 'progress-bar',
2271 'show_hide' => array(
2272 'show_donated' => true,
2273 'show_goal' => true,
2274 ),
2275 'css_class' => 'sample-css-class',
2276 'label_donate' => ' ',
2277 'label_goal' => 'Goal USD: ',
2278 'meta_position' => 'top',
2279 ),
2280 array(
2281 'type' => 'donate-amount',
2282 'headline' => 'Select An Amount',
2283 ),
2284 array(
2285 'type' => 'donate-button',
2286 'button_label' => 'Donate Now',
2287 ),
2288 ),
2289 ),
2290 ),
2291 ),
2292 ),
2293 array( // row.
2294 'type' => 'row',
2295 'css_class' => 'no-padding no-field-target no-field-wrap',
2296 'columns' => array(
2297 array( // column.
2298 array( // section.
2299 'type' => 'tabs',
2300 'tabs' => array(
2301 array(
2302 'title' => 'Overview',
2303 'type' => '',
2304 'slug' => 'default',
2305 'fields' => array(
2306 array(
2307 'type' => 'campaign-description',
2308 'headline' => 'Make every minute on the field count ⚾',
2309 'content' => '<p>We are announcing a campaign to bolster our local youth sports team, comprised of enthusiastic youngsters aged 8-12. Your support will enable us to update their uniforms, provide essential supplies, ensure a safe playing environment, and offer security measures on the field. Additionally, your contributions will go towards accommodations for parents and teachers, fostering a supportive community atmosphere where these young athletes can thrive. Join us in nurturing the next generation of athletes, empowering them with the resources and encouragement they need to excel both on and off the field.</p><p>Together, let\'s create a positive and inspiring environment for our youth, fostering a love for sports and teamwork that will last a lifetime.😄</p>',
2310 ),
2311 array(
2312 'type' => 'ambassadors-team',
2313 'headline' => 'Top Team Members',
2314 'columns' => 6,
2315 'upgrade-img-bg' => 'field-team.jpg',
2316 ),
2317 ),
2318 ),
2319 array(
2320 'title' => 'Updates',
2321 'type' => '',
2322 'slug' => 'updates',
2323 'fields' => array(
2324 'updates-main' => array(
2325 'headline' => 'Top Team Members',
2326 'columns' => 6,
2327 ),
2328 ),
2329 ),
2330 array(
2331 'title' => 'Comments',
2332 'type' => '',
2333 'slug' => 'comments',
2334 'fields' => array(
2335 'comments-main' => array(
2336 'headline' => 'Top Team Members',
2337 'columns' => 6,
2338 ),
2339 ),
2340 ),
2341 ),
2342 ),
2343 ),
2344 ),
2345 ),
2346 ),
2347 'advanced' => array(
2348 'tab_style' => 'minimum',
2349 'tab_size' => 'small',
2350 ),
2351 'settings' => array(
2352 'general' => array(
2353 'description' => '<p>We are announcing a campaign to bolster our local youth sports team, comprised of enthusiastic youngsters aged 8-12. Your support will enable us to update their uniforms, provide essential supplies, ensure a safe playing environment, and offer security measures on the field. Additionally, your contributions will go towards accommodations for parents and teachers, fostering a supportive community atmosphere where these young athletes can thrive. Join us in nurturing the next generation of athletes, empowering them with the resources and encouragement they need to excel both on and off the field.</p><p>Together, let\'s create a positive and inspiring environment for our youth, fostering a love for sports and teamwork that will last a lifetime.😄</p>',
2354 ),
2355 ),
2356 ),
2357 'school-trip' => array(
2358 'meta' => array(
2359 'label' => 'School Trip',
2360 'slug' => 'school-trip',
2361 'description' => 'Raise funds for a school trip or fundraiser.',
2362 'template_type' => array( 'single', 'prebuilt' ),
2363 'search_tags' => array(
2364 'youth',
2365 'sports',
2366 'green',
2367 'brown',
2368 ),
2369 'categories' => array(
2370 'sports',
2371 'youth',
2372 'events',
2373 ),
2374 'created' => '2023-10-05', // Y-m-d.
2375 'version' => '1.0',
2376 'author' => 'David Bisset',
2377 'dependencies' => false, // not used yet.
2378 'has_access' => true, // not used yet, but false if the user can't select it.
2379 'favorite' => false,
2380 'colors' => array(
2381 'primary' => '#7A8347',
2382 'secondary' => '#000000',
2383 'tertiary' => '#5F5F5F',
2384 'accent' => false,
2385 'button_bg' => '#7A8347',
2386 ),
2387 'parent_theme' => false, // not used yet.
2388 'thumbnail_url' => false, // overrides default location to look for thumbnails in template page.
2389 'suffixes' => array(
2390 'social-links' => '-white',
2391 'social-sharing' => '-white',
2392 ),
2393 ),
2394 'layout' => array(
2395 array( // row.
2396 'type' => 'header',
2397 'css_class' => 'charitable-header',
2398 'columns' => array(
2399 array( // column.
2400 array( // section.
2401 'type' => 'fields',
2402 'fields' => array(
2403 array(
2404 'type' => 'text',
2405 'headline' => 'Help the youth learn with an adventure',
2406 'content' => 'Join us in giving our students the opportunity to explore, learn, and grow on this incredible journey!',
2407 'align' => 'center',
2408 ),
2409 ),
2410 ),
2411 ),
2412 ),
2413 ),
2414 array( // row.
2415 'type' => 'row',
2416 'columns' => array(
2417 array( // column.
2418 array( // section.
2419 'type' => 'fields',
2420 'fields' => array(
2421 array(
2422 'type' => 'campaign-description',
2423 'headline' => 'Raise fund for our school trip!',
2424 'content' => '<p>We are announcing a campaign to make the dream of a once-in-a-lifetime field trip come true for our graduating 5th graders: an unforgettable adventure in California! Your support will enable us to purchase necessary supplies, ensure safe travel, and provide accommodations for both parents and teachers accompanying the students. With your contribution, we can create lasting memories and valuable learning experiences, fostering a sense of camaraderie and curiosity that will stay with these young minds for a lifetime.</p>',
2425 ),
2426 array(
2427 'type' => 'photo',
2428 'default' => 'trip-1.jpg',
2429 ),
2430 ),
2431 ),
2432 ),
2433 array( // column.
2434 array( // section.
2435 'type' => 'fields',
2436 'fields' => array(
2437 array(
2438 'type' => 'photo',
2439 'default' => 'trip-2.jpg',
2440 ),
2441 array(
2442 'type' => 'campaign-summary',
2443 ),
2444 array(
2445 'type' => 'text',
2446 'headline' => 'Together, we can inspire these young minds and equip them with the tools they need to make a positive impact on the world.',
2447 'content' => 'Your generosity will not only provide the means for this adventure but will also contribute to the overall educational enrichment of our students. This trip isn\'t just a mere excursion; it\'s a chance for our 5th graders to expand their horizons, learn about different cultures, and engage with historical and natural wonders that will enhance their academic understanding. ',
2448 ),
2449 array(
2450 'type' => 'progress-bar',
2451 'show_hide' => array(
2452 'show_donated' => true,
2453 'show_goal' => true,
2454 ),
2455 'css_class' => 'sample-css-class',
2456 'label_donate' => 'Funded: ',
2457 'label_goal' => 'Goal: ',
2458 'meta_position' => 'top',
2459 ),
2460 array(
2461 'type' => 'social-links',
2462 'headline' => 'Follow on',
2463 'facebook_url' => 'https://facebook.com/',
2464 'twitter_url' => 'https://twitter.com/',
2465 ),
2466 ),
2467 ),
2468 ),
2469 ),
2470 ),
2471 array( // row.
2472 'type' => 'row',
2473 'css_class' => 'no-padding no-field-target no-field-wrap',
2474 'columns' => array(
2475 array( // column.
2476 array( // section.
2477 'type' => 'tabs',
2478 'tabs' => array(
2479 array(
2480 'title' => 'Donate Now',
2481 'type' => '',
2482 'slug' => 'default',
2483 'fields' => array(
2484 array(
2485 'type' => 'donation-form',
2486 ),
2487 ),
2488 ),
2489 ),
2490 ),
2491 ),
2492 ),
2493 ),
2494 ),
2495 'advanced' => array(
2496 'tab_style' => 'boxed',
2497 'tab_size' => 'medium',
2498 ),
2499 'settings' => array(
2500 'general' => array(
2501 'description' => '<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliqui.Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliqui.Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod</p>',
2502 ),
2503 ),
2504 ),
2505 'animal-sanctuary' => array(
2506 'meta' => array(
2507 'label' => 'Animal Sanctuary',
2508 'slug' => 'animal-sanctuary',
2509 'description' => 'Get funds for your mission to rescue or rehabilitate.',
2510 'template_type' => array( 'single', 'prebuilt' ),
2511 'search_tags' => array(
2512 'animal-pets',
2513 'environmental',
2514 'blue',
2515 ),
2516 'categories' => array(
2517 'animal-pets',
2518 'environmental',
2519 ),
2520 'created' => '2023-10-05', // Y-m-d.
2521 'version' => '1.0',
2522 'author' => 'David Bisset',
2523 'dependencies' => false, // not used yet.
2524 'has_access' => true, // not used yet, but false if the user can't select it.
2525 'favorite' => false,
2526 'colors' => array(
2527 'primary' => '#805F93',
2528 'secondary' => '#1D1C1C',
2529 'tertiary' => '#808080',
2530 'accent' => false,
2531 'button_bg' => '#805F93',
2532 ),
2533 'parent_theme' => false, // not used yet.
2534 'thumbnail_url' => false, // overrides default location to look for thumbnails in template page.
2535 'suffixes' => array(
2536 'social-sharing' => '-dark',
2537 'social-links' => '-dark',
2538 ),
2539 ),
2540 'layout' => array(
2541 array( // row.
2542 'type' => 'row',
2543 'columns' => array(
2544 array( // column.
2545 array( // section.
2546 'type' => 'fields',
2547 'fields' => array(
2548 array(
2549 'type' => 'photo',
2550 'default' => 'photo-1.jpg',
2551 ),
2552 array(
2553 'type' => 'campaign-description',
2554 'headline' => 'Donate today to support our mission to rescue, rehabilitate, and rehome',
2555 'content' => '<p>I\'m thrilled to launch our new campaign aimed at supporting an incredible cause: an animal sanctuary dedicated to rescuing abandoned and lost animals and finding them loving homes. With your help, we aim to raise funds to maintain this sanctuary, providing a safe haven for these adorable pets and ensuring they receive the care they deserve. Your contributions will not only help us sustain the facility but also enable us to actively seek new, caring families for these animals, giving them a chance at a brighter and happier future. Together, we can make a real difference in the lives of these innocent creatures.</p>',
2556 ),
2557 array(
2558 'type' => 'campaign-summary',
2559 ),
2560 array(
2561 'type' => 'donate-button',
2562 'button_label' => 'Donate Now',
2563 ),
2564 ),
2565 ),
2566 ),
2567 array( // column.
2568 array( // section.
2569 'type' => 'fields',
2570 'fields' => array(
2571 array(
2572 'type' => 'organizer',
2573 'role_or_title' => 'Organizer',
2574 'content' => '',
2575 ),
2576 array(
2577 'type' => 'social-sharing',
2578 'headline' => 'Share Now',
2579 'facebook_url' => 'https://facebook.com/',
2580 'twitter_url' => 'https://twitter.com/',
2581 ),
2582 array(
2583 'type' => 'social-links',
2584 'headline' => 'Follow Now',
2585 'facebook_url' => 'https://facebook.com/',
2586 'twitter_url' => 'https://twitter.com/',
2587 'instagram_url' => 'https://instagram.com/',
2588 ),
2589 ),
2590 ),
2591 ),
2592 ),
2593 ),
2594 array( // row.
2595 'type' => 'row',
2596 'css_class' => 'no-padding no-field-target no-field-wrap',
2597 'columns' => array(
2598 array( // column.
2599 array( // section.
2600 'type' => 'tabs',
2601 'tabs' => array(
2602 array(
2603 'title' => 'Overview',
2604 'type' => '',
2605 'slug' => 'default',
2606 'fields' => array(
2607 array(
2608 'type' => 'text',
2609 'headline' => 'About Us',
2610 'content' => 'We are an animal santuary established in 2007.',
2611 ),
2612 ),
2613 ),
2614 ),
2615 ),
2616 ),
2617 ),
2618 ),
2619 ),
2620 'advanced' => array(
2621 'tab_style' => 'boxed',
2622 'tab_size' => 'medium',
2623 ),
2624 'settings' => array(
2625 'general' => array(
2626 'description' => '<p>I\'m thrilled to launch our new campaign aimed at supporting an incredible cause: an animal sanctuary dedicated to rescuing abandoned and lost animals and finding them loving homes. With your help, we aim to raise funds to maintain this sanctuary, providing a safe haven for these adorable pets and ensuring they receive the care they deserve. Your contributions will not only help us sustain the facility but also enable us to actively seek new, caring families for these animals, giving them a chance at a brighter and happier future. Together, we can make a real difference in the lives of these innocent creatures.</p>',
2627 ),
2628 ),
2629 ),
2630 'save-the-museum' => array(
2631 'meta' => array(
2632 'label' => 'Save The Museum',
2633 'slug' => 'save-the-museum',
2634 'description' => 'Save a historical building, residence, or important landmark.',
2635 'template_type' => array( 'single', 'prebuilt' ),
2636 'search_tags' => array(
2637 'legal',
2638 'special-occasions',
2639 'blue',
2640 ),
2641 'categories' => array(
2642 'legal',
2643 'club-organizations',
2644 'special-occasions',
2645 ),
2646 'created' => '2023-10-05', // Y-m-d.
2647 'version' => '1.0',
2648 'author' => 'David Bisset',
2649 'dependencies' => false, // not used yet.
2650 'has_access' => true, // not used yet, but false if the user can't select it.
2651 'favorite' => false,
2652 'colors' => array(
2653 'primary' => '#F58A07',
2654 'secondary' => '#1D3444',
2655 'tertiary' => '#5B5B5B',
2656 'accent' => false,
2657 'button_bg' => '#FFFFFF',
2658 ),
2659 'parent_theme' => false, // not used yet.
2660 'thumbnail_url' => false, // overrides default location to look for thumbnails in template page.
2661 'suffixes' => array(
2662 'social-sharing' => '-dark',
2663 'social-links' => '-dark',
2664 ),
2665 ),
2666 'layout' => array(
2667 array( // row.
2668 'type' => 'row',
2669 'columns' => array(
2670 array( // column.
2671 array( // section.
2672 'type' => 'fields',
2673 'fields' => array(
2674 array(
2675 'type' => 'photo',
2676 'default' => 'photo-1.jpg',
2677 ),
2678 array(
2679 'type' => 'campaign-description',
2680 'headline' => 'About This Project',
2681 'content' => '<p>In 1918 the top floor of the Lyric Theatre was converted into a hospital to care for the sick and dying during the Spanish Flu Epidemic. A nurse, Mrs. Lapp, was forced to care for all of families upstairs. Today nearly 100 years later the top floor of the Lyric remains unused and it’s sole occupant is the spirit of Nurse Lapp. We are trying to save this abandoned building with the help of you all.</p>',
2682 ),
2683 ),
2684 ),
2685 ),
2686 array( // column.
2687 array( // section.
2688 'type' => 'fields',
2689 'fields' => array(
2690 array(
2691 'type' => 'campaign-title',
2692 ),
2693 array(
2694 'type' => 'progress-bar',
2695 'show_hide' => array(
2696 'show_donated' => true,
2697 'show_goal' => false,
2698 ),
2699 'css_class' => 'sample-css-class',
2700 'label_donate' => 'Funded ',
2701 'label_goal' => 'Goal USD: ',
2702 'meta_position' => 'top',
2703 ),
2704 array(
2705 'type' => 'campaign-summary',
2706 ),
2707 array(
2708 'type' => 'donate-button',
2709 'button_label' => 'Donate Now',
2710 ),
2711 array(
2712 'type' => 'social-links',
2713 'headline' => 'Follow on',
2714 'facebook_url' => 'https://facebook.com/',
2715 'twitter_url' => 'https://twitter.com/',
2716 ),
2717 ),
2718 ),
2719 ),
2720 ),
2721 ),
2722 array( // row.
2723 'type' => 'row',
2724 'css_class' => 'no-padding no-field-target no-field-wrap',
2725 'columns' => array(
2726 array( // column.
2727 array( // section.
2728 'type' => 'tabs',
2729 'tabs' => array(
2730 array(
2731 'title' => 'Overview',
2732 'type' => '',
2733 'slug' => 'default',
2734 'fields' => array(
2735 array(
2736 'type' => 'text',
2737 'headline' => 'Save the Lyrique Building',
2738 'content' => '<p>Mrs. Lapp\'s spirit is said to linger in the hushed corners of the Lyric Theatre, her presence felt by those who dare to venture to the top floor. Visitors claim to have heard soft whispers and felt a comforting presence, as if she\'s still watching over the space she once tended to with such dedication. The abandoned building stands as a testament to the resilience of the human spirit during times of crisis, and it has become a symbol of hope and survival. Efforts to preserve the Lyric Theatre are fueled by the desire to honor Mrs. Lapp\'s legacy and the countless lives she touched.</p><p>The community has rallied together, sharing stories of her bravery and compassion, inspiring a new generation to join the cause. With each donation and volunteer effort, the echoes of the past grow stronger, uniting people across time in a shared mission to save this historical landmark and the memory of Nurse Lapp, reminding us all of the power of compassion and community in the face of adversity.</p>',
2739 ),
2740 array(
2741 'type' => 'photo',
2742 'default' => 'photo-2.jpg',
2743 ),
2744 ),
2745 ),
2746 array(
2747 'title' => 'Updates',
2748 'type' => '',
2749 'slug' => 'updates',
2750 'fields' => array(
2751 'updates-main' => array(
2752 'headline' => 'Top Team Members',
2753 'columns' => 6,
2754 ),
2755 ),
2756 ),
2757 array(
2758 'title' => 'Comments',
2759 'type' => '',
2760 'slug' => 'comments',
2761 'fields' => array(
2762 'comments-main' => array(
2763 'headline' => 'Top Team Members',
2764 'columns' => 6,
2765 ),
2766 ),
2767 ),
2768 ),
2769 ),
2770 ),
2771 ),
2772 ),
2773 ),
2774 'advanced' => array(
2775 'tab_style' => 'boxed',
2776 'tab_size' => 'medium',
2777 ),
2778 'settings' => array(
2779 'general' => array(
2780 'description' => '<p>In 1918 the top floor of the Lyric Theatre was converted into a hospital to care for the sick and dying during the Spanish Flu Epidemic. A nurse, Mrs. Lapp, was forced to care for all of families upstairs. Today nearly 100 years later the top floor of the Lyric remains unused and it’s sole occupant is the spirit of Nurse Lapp. We are trying to save this abandoned building with the help of you all.</p>',
2781 ),
2782 ),
2783 ),
2784 'environmental' => array(
2785 'meta' => array(
2786 'label' => 'Environmental',
2787 'slug' => 'environmental',
2788 'description' => 'Preserve nature and the earth for future generations.',
2789 'template_type' => array( 'single', 'prebuilt' ),
2790 'search_tags' => array(
2791 'environmental',
2792 'animal-pets',
2793 'blue',
2794 ),
2795 'categories' => array(
2796 'environmental',
2797 'animal-pets',
2798 ),
2799 'created' => '2023-10-05', // Y-m-d.
2800 'version' => '1.0',
2801 'author' => 'David Bisset',
2802 'dependencies' => false, // not used yet.
2803 'has_access' => true, // not used yet, but false if the user can't select it.
2804 'favorite' => false,
2805 'colors' => array(
2806 'primary' => '#F9F6EE',
2807 'secondary' => '#24231E',
2808 'tertiary' => '#61AA4F',
2809 'accent' => false,
2810 'button_bg' => '#61AA4F',
2811 ),
2812 'parent_theme' => false, // not used yet.
2813 'thumbnail_url' => false, // overrides default location to look for thumbnails in template page.
2814 'suffixes' => array(
2815 'social-sharing' => '-dark',
2816 'social-links' => '-dark',
2817 ),
2818 ),
2819 'layout' => array(
2820 array( // row.
2821 'type' => 'row',
2822 'columns' => array(
2823 array( // column.
2824 array( // section.
2825 'type' => 'fields',
2826 'fields' => array(
2827 array(
2828 'type' => 'photo',
2829 'default' => 'photo-1.jpg',
2830 ),
2831 ),
2832 ),
2833 ),
2834 array( // column.
2835 array( // section.
2836 'type' => 'fields',
2837 'fields' => array(
2838 array(
2839 'type' => 'text',
2840 'headline' => 'Save Earth',
2841 'content' => 'Together, let\'s reclaim the serenity of our shorelines and ensure a cleaner, greener future for generations to come.',
2842 'width_percentage' => 100,
2843 'align' => 'left',
2844 ),
2845 array(
2846 'type' => 'campaign-description',
2847 'headline' => 'Help Preserving The Earth For Future Generations',
2848 'content' => '<p>We are announcing a campaign dedicated to restoring the natural beauty of our local beach, which has sadly fallen victim to years of neglect and pollution. Our non-profit is on a mission to raise funds for cleaning supplies, vehicles, and essential costs to orchestrate a massive cleanup effort. By contributing, you\'re not just supporting a cleaner beach but also promoting environmental health and community pride. </p>',
2849 'width_percentage' => 100,
2850 'align' => 'left',
2851 ),
2852 array(
2853 'type' => 'campaign-summary',
2854 'width_percentage' => 100,
2855 'align' => 'left',
2856 ),
2857 array(
2858 'type' => 'donate-button',
2859 'button_label' => 'Donate Now',
2860 'width_percentage' => 100,
2861 'align' => 'left',
2862 ),
2863 array(
2864 'type' => 'social-links',
2865 'headline' => ' ',
2866 'facebook_url' => 'https://facebook.com/',
2867 'twitter_url' => 'https://twitter.com/',
2868 'align' => 'left',
2869 ),
2870 ),
2871 ),
2872 ),
2873 ),
2874 ),
2875 array( // row.
2876 'type' => 'row',
2877 'css_class' => 'no-padding no-field-target no-field-wrap',
2878 'columns' => array(
2879 array( // column.
2880 array( // section.
2881 'type' => 'tabs',
2882 'tabs' => array(
2883 array(
2884 'title' => 'Overview',
2885 'type' => '',
2886 'slug' => 'default',
2887 'fields' => array(
2888 array(
2889 'type' => 'text',
2890 'headline' => 'Keep the scene green by taking the lead',
2891 'content' => 'Your support will make a significant impact, enabling us to organize community clean-up events where volunteers, equipped with the necessary resources, can work together to remove garbage and restore the beach to its natural state. Additionally, your contributions will empower us to implement educational programs aimed at raising awareness about the importance of environmental conservation. We believe that through collective action, we can not only clean up our beloved beach but also inspire a lasting change in our community\'s attitudes towards environmental responsibility. Every donation, no matter how big or small, brings us one step closer to a cleaner, healthier environment for everyone. Join us in this vital endeavor, and let\'s create a positive ripple effect that benefits both our local ecosystem and the people who call this community home.',
2892 ),
2893 array(
2894 'type' => 'photo',
2895 'default' => 'photo-2.jpg',
2896 'align' => 'center',
2897 ),
2898 ),
2899 ),
2900 ),
2901 ),
2902 ),
2903 ),
2904 ),
2905 ),
2906 'advanced' => array(
2907 'tab_style' => 'boxed',
2908 'tab_size' => 'medium',
2909 ),
2910 'settings' => array(
2911 'general' => array(
2912 'description' => '<p>We are announcing a campaign dedicated to restoring the natural beauty of our local beach, which has sadly fallen victim to years of neglect and pollution. Our non-profit is on a mission to raise funds for cleaning supplies, vehicles, and essential costs to orchestrate a massive cleanup effort. By contributing, you\'re not just supporting a cleaner beach but also promoting environmental health and community pride.</p>',
2913 ),
2914 ),
2915 ),
2916 'disaster-relief' => array(
2917 'meta' => array(
2918 'label' => 'Disaster Relief',
2919 'slug' => 'disaster-relief',
2920 'description' => 'Help those effected by natural disasters.',
2921 'template_type' => array( 'single', 'prebuilt' ),
2922 'search_tags' => array(
2923 'environmental',
2924 'medical',
2925 'family',
2926 'blue',
2927 ),
2928 'categories' => array(
2929 'environmental',
2930 'medical',
2931 'family',
2932 ),
2933 'created' => '2023-10-05', // Y-m-d.
2934 'version' => '1.0',
2935 'author' => 'David Bisset',
2936 'dependencies' => false, // not used yet.
2937 'has_access' => true, // not used yet, but false if the user can't select it.
2938 'favorite' => false,
2939 'colors' => array(
2940 'primary' => '#9F190E',
2941 'secondary' => '#202020',
2942 'tertiary' => '#FFFFFF',
2943 'accent' => false,
2944 'button_bg' => '#9F190E',
2945 ),
2946 'parent_theme' => false, // not used yet.
2947 'thumbnail_url' => false, // overrides default location to look for thumbnails in template page.
2948 'suffixes' => array(),
2949 ),
2950 'layout' => array(
2951 array( // row.
2952 'type' => 'row',
2953 'columns' => array(
2954 array( // column.
2955 array( // section.
2956 'type' => 'fields',
2957 'fields' => array(
2958 array(
2959 'type' => 'photo',
2960 'default' => 'photo-1.jpg',
2961 ),
2962 array(
2963 'type' => 'progress-bar',
2964 'show_hide' => array(
2965 'show_donated' => true,
2966 'show_goal' => true,
2967 ),
2968 'css_class' => 'sample-css-class',
2969 'label_donate' => ' ',
2970 'label_goal' => 'Goal USD: ',
2971 'meta_position' => 'top',
2972 ),
2973 ),
2974 ),
2975 ),
2976 array( // column.
2977 array( // section.
2978 'type' => 'fields',
2979 'fields' => array(
2980 array(
2981 'type' => 'text',
2982 'headline' => 'Donate Today',
2983 'content' => 'This project will only be funded if at least $270,000 is raised by December 22, 2025.',
2984 ),
2985 array(
2986 'type' => 'campaign-summary',
2987 ),
2988 array(
2989 'type' => 'donate-button',
2990 'button_label' => 'Donate Now',
2991 'width_percentage' => 100,
2992 ),
2993 array(
2994 'type' => 'social-sharing',
2995 'headline' => 'Share',
2996 'facebook_url' => 'https://facebook.com/',
2997 'twitter_url' => 'https://twitter.com/',
2998 'align' => 'left',
2999 ),
3000 array(
3001 'type' => 'social-links',
3002 'headline' => 'Follow on',
3003 'facebook_url' => 'https://facebook.com/',
3004 'twitter_url' => 'https://twitter.com/',
3005 'align' => 'left',
3006 ),
3007 ),
3008 ),
3009 ),
3010 ),
3011 ),
3012 array( // row.
3013 'type' => 'row',
3014 'css_class' => 'no-padding no-field-target no-field-wrap',
3015 'columns' => array(
3016 array( // column.
3017 array( // section.
3018 'type' => 'tabs',
3019 'tabs' => array(
3020 array(
3021 'title' => 'Overview',
3022 'type' => '',
3023 'slug' => 'default',
3024 'fields' => array(
3025 array(
3026 'type' => 'campaign-description',
3027 'headline' => 'About This Campaign',
3028 'content' => '<p>We are announcing a new campaign aimed at providing crucial support to the victims of a recent devastating natural disaster. Together, we are rallying behind our fellow community members, raising funds through this non-profit initiative to help them rebuild homes, restore essential services, and reclaim their lives. Join us in making a difference, as every contribution brings us one step closer to bringing hope and stability back to those in need..</p>',
3029 'align' => 'left',
3030 ),
3031 array(
3032 'type' => 'photo',
3033 'default' => 'photo-2.jpg',
3034 ),
3035 ),
3036 ),
3037 ),
3038 ),
3039 ),
3040 ),
3041 ),
3042 ),
3043 'advanced' => array(
3044 'tab_style' => 'boxed',
3045 'tab_size' => 'medium',
3046 ),
3047 'settings' => array(
3048 'general' => array(
3049 'description' => '<p>We are announcing a new campaign aimed at providing crucial support to the victims of a recent devastating natural disaster. Together, we are rallying behind our fellow community members, raising funds through this non-profit initiative to help them rebuild homes, restore essential services, and reclaim their lives. Join us in making a difference, as every contribution brings us one step closer to bringing hope and stability back to those in need.</p>',
3050 ),
3051 ),
3052 ),
3053 'club-organization' => array(
3054 'meta' => array(
3055 'label' => 'Club / Organization',
3056 'slug' => 'club-organization',
3057 'description' => 'Fund programs or help increase funds for a worthy organization.',
3058 'template_type' => array( 'single', 'prebuilt' ),
3059 'search_tags' => array(
3060 'club-organizations',
3061 'school',
3062 'blue',
3063 ),
3064 'categories' => array(
3065 'club-organizations',
3066 'school',
3067 'sports',
3068 ),
3069 'created' => '2023-10-05', // Y-m-d.
3070 'version' => '1.0',
3071 'author' => 'David Bisset',
3072 'dependencies' => false, // not used yet.
3073 'has_access' => true, // not used yet, but false if the user can't select it.
3074 'favorite' => false,
3075 'colors' => array(
3076 'primary' => '#474735',
3077 'secondary' => '#B1A17C',
3078 'tertiary' => '#F4F0EE',
3079 'accent' => false,
3080 'button_bg' => '#B49A5F',
3081 ),
3082 'parent_theme' => false, // not used yet.
3083 'thumbnail_url' => false, // overrides default location to look for thumbnails in template page.
3084 'suffixes' => array(),
3085 ),
3086 'layout' => array(
3087 array( // row.
3088 'type' => 'row',
3089 'columns' => array(
3090 array( // column.
3091 array( // section.
3092 'type' => 'fields',
3093 'fields' => array(
3094 array(
3095 'type' => 'photo',
3096 'default' => 'photo-1.jpg',
3097 ),
3098 ),
3099 ),
3100 ),
3101 array( // column.
3102 array( // section.
3103 'type' => 'fields',
3104 'fields' => array(
3105 array(
3106 'type' => 'campaign-description',
3107 'headline' => 'About This Club',
3108 'content' => '<p>We are announcing a campaign to support our cherished local country club, a haven for our community, especially our elderly residents. Our non-profit is passionately rallying for funds to ensure the maintenance of this vital space and to sustain the heartwarming annual events that bring together generations. By contributing, you\'re preserving a beloved institution that unites the young and the old, fostering a sense of belonging and community spirit. Join us in safeguarding this haven for all ages!</p>',
3109 'width_percentage' => 100,
3110 'align' => 'left',
3111 ),
3112 array(
3113 'type' => 'progress-bar',
3114 'show_hide' => array(
3115 'show_donated' => true,
3116 'show_goal' => true,
3117 ),
3118 'css_class' => 'sample-css-class',
3119 'label_donate' => ' ',
3120 'label_goal' => 'Goal USD: ',
3121 'meta_position' => 'top',
3122 'width_percentage' => 100,
3123 'align' => 'left',
3124 ),
3125 array(
3126 'type' => 'campaign-summary',
3127 'width_percentage' => 100,
3128 'align' => 'left',
3129 ),
3130 array(
3131 'type' => 'donate-button',
3132 'button_label' => 'Donate Now',
3133 'width_percentage' => 40,
3134 'align' => 'center',
3135 ),
3136 ),
3137 ),
3138 ),
3139 ),
3140 ),
3141 array( // row.
3142 'type' => 'row',
3143 'css_class' => 'no-padding no-field-target no-field-wrap',
3144 'columns' => array(
3145 array( // column.
3146 array( // section.
3147 'type' => 'tabs',
3148 'tabs' => array(
3149 array(
3150 'title' => 'Overview',
3151 'type' => '',
3152 'slug' => 'default',
3153 'fields' => array(
3154 array(
3155 'type' => 'text',
3156 'headline' => 'With 100% of donations going towards grants and programs',
3157 'content' => 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliqui.Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
3158 ),
3159 array(
3160 'type' => 'photo',
3161 'default' => 'photo-2.jpg',
3162 ),
3163 ),
3164 ),
3165 array(
3166 'title' => 'Updates',
3167 'type' => '',
3168 'slug' => 'updates',
3169 'fields' => array(
3170 array(
3171 'type' => 'updates-main',
3172 'headline' => 'Top Team Members',
3173 'columns' => 6,
3174 ),
3175 ),
3176 ),
3177 array(
3178 'title' => 'Comments',
3179 'type' => '',
3180 'slug' => 'comments',
3181 'fields' => array(
3182 array(
3183 'type' => 'comments-main',
3184 'headline' => 'Top Team Members',
3185 'columns' => 6,
3186 ),
3187 ),
3188 ),
3189 ),
3190 ),
3191 ),
3192 ),
3193 ),
3194 ),
3195 'advanced' => array(
3196 'tab_style' => 'boxed',
3197 'tab_size' => 'medium',
3198 ),
3199 'settings' => array(
3200 'general' => array(
3201 'description' => '<p>We are announcing a campaign to support our cherished local country club, a haven for our community, especially our elderly residents. Our non-profit is passionately rallying for funds to ensure the maintenance of this vital space and to sustain the heartwarming annual events that bring together generations. By contributing, you\'re preserving a beloved institution that unites the young and the old, fostering a sense of belonging and community spirit. Join us in safeguarding this haven for all ages!</p>',
3202 ),
3203 ),
3204 ),
3205 'medical-causes' => array(
3206 'meta' => array(
3207 'label' => 'Medical Causes',
3208 'slug' => 'medical-causes',
3209 'description' => 'Have a goal for more research, better treatment or a cure.',
3210 'template_type' => array( 'single', 'prebuilt' ),
3211 'search_tags' => array(
3212 'medical',
3213 'family',
3214 'blue',
3215 ),
3216 'categories' => array(
3217 'medical',
3218 'family',
3219 ),
3220 'created' => '2023-10-05', // Y-m-d.
3221 'version' => '1.0',
3222 'author' => 'David Bisset',
3223 'dependencies' => false, // not used yet.
3224 'has_access' => true, // not used yet, but false if the user can't select it.
3225 'favorite' => false,
3226 'colors' => array(
3227 'primary' => '#192E45',
3228 'secondary' => '#215DB7',
3229 'tertiary' => '#48A9F5',
3230 'accent' => false,
3231 'button_bg' => '#48A9F5',
3232 ),
3233 'parent_theme' => false, // not used yet.
3234 'thumbnail_url' => false, // overrides default location to look for thumbnails in template page.
3235 'suffixes' => array(),
3236 ),
3237 'layout' => array(
3238 array( // row.
3239 'type' => 'row',
3240 'columns' => array(
3241 array( // column.
3242 array( // section.
3243 'type' => 'fields',
3244 'fields' => array(
3245 array(
3246 'type' => 'video',
3247 'headline' => '',
3248 'upgrade-img-bg' => 'field-charitable-videos.jpg',
3249 ),
3250 ),
3251 ),
3252 ),
3253 array( // column.
3254 array( // section.
3255 'type' => 'fields',
3256 'fields' => array(
3257 array(
3258 'type' => 'campaign-title',
3259 ),
3260 array(
3261 'type' => 'text',
3262 'headline' => 'Cancer Research Program',
3263 'content' => 'By donating to this cause, you can improve the lives of a variety of different people in your community and feel good about doing it.',
3264 ),
3265 array(
3266 'type' => 'progress-bar',
3267 'show_hide' => array(
3268 'show_donated' => true,
3269 'show_goal' => true,
3270 ),
3271 'css_class' => 'sample-css-class',
3272 'label_donate' => ' ',
3273 'label_goal' => 'Goal USD: ',
3274 'meta_position' => 'top',
3275 ),
3276 array(
3277 'type' => 'campaign-summary',
3278 ),
3279 array(
3280 'type' => 'donate-button',
3281 'button_label' => 'Donate Now',
3282 'align' => 'left',
3283 'width_percentage' => 50,
3284 ),
3285 ),
3286 ),
3287 ),
3288 ),
3289 ),
3290 array( // row.
3291 'type' => 'row',
3292 'css_class' => 'no-padding no-field-target no-field-wrap',
3293 'columns' => array(
3294 array( // column.
3295 array( // section.
3296 'type' => 'tabs',
3297 'tabs' => array(
3298 array(
3299 'title' => 'Overview',
3300 'type' => '',
3301 'slug' => 'overview',
3302 'fields' => array(
3303 array(
3304 'type' => 'campaign-description',
3305 'headline' => 'About Our Organization',
3306 'content' => '<p>We are announcing a campaign dedicated to supporting our local hospital\'s crucial cancer research initiatives, focusing on children under 18, women, and minority communities. Our non-profit is passionately rallying for funds to maintain this specialized facility and sustain popular fundraisers accessible to our community. By contributing, you\'re directly investing in cutting-edge research, ensuring that young lives are given a fighting chance, and addressing healthcare disparities. Join us in this noble cause, as together, we strive to create a healthier future for our youth, women, and minority members.</p>',
3307 'width_percentage' => 100,
3308 'align' => 'left',
3309 ),
3310 array(
3311 'type' => 'photo',
3312 'default' => 'photo-1.jpg',
3313 ),
3314 array(
3315 'type' => 'text',
3316 'headline' => 'Thinking differently is a proven strategy for changing the world',
3317 'content' => '<p>Your support will not only fund vital research but also provide essential resources for specialized treatments, counseling, and support services tailored to the unique needs of young patients, women, and minorities battling cancer. By contributing to this campaign, you\'re helping us bridge the gaps in healthcare access, ensuring that everyone, regardless of age, gender, or ethnicity, receives the best possible care and support during their challenging journey.</p><p>Together, we can make a significant difference in the lives of those affected by cancer, offering them hope, strength, and the promise of a brighter, healthier tomorrow. Join us in our fight against cancer, and let\'s create a community where every individual receives the care and compassion they deserve.</p>',
3318 ),
3319 array(
3320 'type' => 'photo',
3321 'default' => 'photo-2.jpg',
3322 ),
3323 ),
3324 ),
3325 array(
3326 'title' => 'Comments',
3327 'type' => '',
3328 'slug' => 'comments',
3329 'fields' => array(),
3330 ),
3331 array(
3332 'title' => 'Reviews',
3333 'type' => '',
3334 'slug' => 'reviews',
3335 'fields' => array(),
3336 ),
3337 ),
3338 ),
3339 ),
3340 ),
3341 ),
3342 ),
3343 'advanced' => array(
3344 'tab_style' => 'boxed',
3345 'tab_size' => 'medium',
3346 ),
3347 'settings' => array(
3348 'general' => array(
3349 'description' => '<p>We are announcing a campaign dedicated to supporting our local hospital\'s crucial cancer research initiatives, focusing on children under 18, women, and minority communities. Our non-profit is passionately rallying for funds to maintain this specialized facility and sustain popular fundraisers accessible to our community. By contributing, you\'re directly investing in cutting-edge research, ensuring that young lives are given a fighting chance, and addressing healthcare disparities. Join us in this noble cause, as together, we strive to create a healthier future for our youth, women, and minority members.</p>',
3350 ),
3351 ),
3352 ),
3353 'medical-bills' => array(
3354 'meta' => array(
3355 'label' => 'Medical Bills',
3356 'slug' => 'medical-bills',
3357 'description' => 'Raise funds to devote towards medical treatment of a friend or family member.',
3358 'template_type' => array( 'single', 'prebuilt' ),
3359 'search_tags' => array(
3360 'medical',
3361 'family',
3362 'blue',
3363 ),
3364 'categories' => array(
3365 'medical',
3366 'family',
3367 ),
3368 'created' => '2023-10-05', // Y-m-d.
3369 'version' => '1.0',
3370 'author' => 'David Bisset',
3371 'dependencies' => false, // not used yet.
3372 'has_access' => true, // not used yet, but false if the user can't select it.
3373 'favorite' => false,
3374 'colors' => array(
3375 'primary' => '#5C8AF3',
3376 'secondary' => '#21458F',
3377 'tertiary' => '#F7F7F7',
3378 'accent' => false,
3379 'button_bg' => '#5C8AF3',
3380 ),
3381 'parent_theme' => false, // not used yet.
3382 'thumbnail_url' => false, // overrides default location to look for thumbnails in template page.
3383 ),
3384 'layout' => array(
3385 array( // row.
3386 'type' => 'header',
3387 'columns' => array(
3388 array( // column.
3389 array( // section.
3390 'type' => 'fields',
3391 'fields' => array(
3392 array(
3393 'type' => 'campaign-title',
3394 'align' => 'center',
3395 ),
3396 ),
3397 ),
3398 ),
3399 ),
3400 ),
3401 array( // row.
3402 'type' => 'row',
3403 'css_class' => '', // 'css_class' => 'no-padding no-field-target no-field-wrap',
3404 'columns' => array(
3405 array( // column.
3406 array( // section.
3407 'type' => 'tabs',
3408 'tabs' => array(
3409 array(
3410 'title' => 'Overview',
3411 'type' => '',
3412 'slug' => 'default',
3413 'fields' => array(
3414 array(
3415 'type' => 'campaign-description',
3416 'headline' => '',
3417 'content' => '<p>On June 12, 2023 Brook’s wife Maleena was admitted to hospital while 20 weeks pregnant, where she was diagnosed with Stage 4 B-cell Lymphoma. At just 22 years old, she has been confronted with a life-altering diagnosis and is now facing a grueling fight. After experiencing inflammation and pain in her legs in March, Brooke spoke with her GP and sought treatment from chiropractors and physios.</p>',
3418 'width_percentage' => 100,
3419 'align' => 'left',
3420 ),
3421 array(
3422 'type' => 'photo',
3423 'default' => 'photo-2.jpg',
3424 ),
3425 array(
3426 'type' => 'text',
3427 'headline' => ' ',
3428 'content' => 'Devastated by Maleena\'s diagnosis, Brooke found himself navigating a whirlwind of emotions and responsibilities. He became Maleena\'s unwavering pillar of support, attending every doctor\'s appointment and chemotherapy session with her, his heart aching at the sight of his young wife enduring such pain. The couple, once planning nursery decorations and baby names, now found themselves discussing treatment options and potential outcomes. Despite the overwhelming fear and uncertainty, they clung to each other, drawing strength from their love and the life growing inside Maleena. Friends and family rallied around them, offering words of encouragement and practical help, reminding them that they were not alone in this battle. In the face of adversity, Brooke and Maleena vowed to fight together, holding onto hope and cherishing every moment they had together, knowing that their love would be the guiding light in the darkest of times.',
3429 ),
3430 array(
3431 'type' => 'photo',
3432 'default' => 'photo-1.jpg',
3433 ),
3434 ),
3435 ),
3436 array(
3437 'title' => 'Updates',
3438 'type' => '',
3439 'slug' => 'updates',
3440 'fields' => array(
3441 array(
3442 'type' => 'text',
3443 'headline' => ' ',
3444 'content' => 'This is on second tab.',
3445 ),
3446 ),
3447 ),
3448 array(
3449 'title' => 'Comments',
3450 'type' => '',
3451 'slug' => 'comments',
3452 'fields' => array(
3453 array(
3454 'type' => 'text',
3455 'headline' => ' ',
3456 'content' => 'This is on third tab.',
3457 ),
3458 ),
3459 ),
3460 ),
3461 ),
3462 ),
3463 array( // column.
3464 array( // section.
3465 'type' => 'fields',
3466 'fields' => array(
3467 array(
3468 'type' => 'campaign-summary',
3469 ),
3470 array(
3471 'type' => 'progress-bar',
3472 'show_hide' => array(
3473 'show_donated' => true,
3474 'show_goal' => true,
3475 ),
3476 'css_class' => 'sample-css-class',
3477 'label_donate' => ' ',
3478 'label_goal' => 'Goal USD: ',
3479 'meta_position' => 'top',
3480 ),
3481 array(
3482 'type' => 'text',
3483 'headline' => ' ',
3484 'content' => 'This project will only be funded if at least $270,000 is raised by December 22, 2025.',
3485 ),
3486 array(
3487 'type' => 'donate-button',
3488 'button_label' => 'Donate Now',
3489 'width_percentage' => 75,
3490 'align' => 'center',
3491 ),
3492 array(
3493 'type' => 'organizer',
3494 'role_or_title' => 'Organizer',
3495 'content' => '',
3496 ),
3497 ),
3498 ),
3499 ),
3500 ),
3501 ),
3502 ),
3503 'advanced' => array(
3504 'tab_style' => 'boxed',
3505 'tab_size' => 'medium',
3506 ),
3507 'settings' => array(
3508 'general' => array(
3509 'description' => '<p>On June 12, 2023 Brook’s wife Maleena was admitted to hospital while 20 weeks pregnant, where she was diagnosed with Stage 4 B-cell Lymphoma. At just 22 years old, she has been confronted with a life-altering diagnosis and is now facing a grueling fight. After experiencing inflammation and pain in her legs in March, Brooke spoke with her GP and sought treatment from chiropractors and physios.</p>',
3510 ),
3511 ),
3512 ),
3513
3514 ),
3515 );
3516 }
3517
3518 /**
3519 * Template for upgrade banner.
3520 *
3521 * @since 1.8.0
3522 */
3523 public function upgrade_banner_template() {
3524
3525 if ( charitable_is_pro() ) {
3526 return;
3527 }
3528
3529 $medium = esc_html__( 'Campaign Builder Templates', 'charitable' );
3530
3531 ?>
3532 <script type="text/html" id="tmpl-charitable-templates-upgrade-banner">
3533 <div class="charitable-template-upgrade-banner">
3534 <div class="charitable-template-content">
3535 <h3>
3536 <?php
3537 printf( esc_html__( 'Super Charge Your Campaigns And Donations With Pro Addons!', 'charitable' ) );
3538 ?>
3539 </h3>
3540
3541 <p>
3542 <?php
3543 // translators: %s is the amount saved.
3544 printf( esc_html__( 'With Charitable addons you can enable crowdfunding, provide additional payment methods, add videos, offer recurring donations, and more. As thanks to you for being a lite user you can unlock access and save up to $%s, automatically applied at checkout! ', 'charitable' ), '<strong>300.00</strong>' );
3545 ?>
3546 </p>
3547 </div>
3548 <div class="charitable-template-upgrade-button">
3549 <a href="<?php echo esc_url( charitable_pro_upgrade_url( $medium ) ); ?>" class="charitable-btn charitable-btn-orange charitable-btn-md" target="_blank" rel="noopener noreferrer"><?php esc_html_e( 'Upgrade to PRO', 'charitable' ); ?></a>
3550 </div>
3551 </div>
3552 </script>
3553 <?php
3554 }
3555
3556 /**
3557 * Tab Empty Notice.
3558 *
3559 * @since 1.8.0
3560 */
3561 public function tab_empty_notice() {
3562
3563 return sprintf(
3564 /* translators: 1: Template ID */
3565 '<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>',
3566 '#'
3567 );
3568 }
3569
3570 /**
3571 * No Empty Notice.
3572 *
3573 * @since 1.8.0
3574 */
3575 public function no_tab_empty_notice() {
3576
3577 return sprintf(
3578 /* translators: 1: Template ID */
3579 __( '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>.',
3580 '#'
3581 );
3582 }
3583 }
3584
3585 endif;
3586
3587 new Charitable_Campaign_Builder_Templates();
3588