| 1 |
<?php |
| 2 |
/** |
| 3 |
* Sets up the campaign list table in the admin. |
| 4 |
* |
| 5 |
* @package Charitable/Classes/Charitable_Campaign_List_Table |
| 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.5.0 |
| 10 |
* @version 1.8.1.5, 1.8.9.1, 1.8.10 |
| 11 |
*/ |
| 12 |
|
| 13 |
if ( ! defined( 'ABSPATH' ) ) { |
| 14 |
exit; |
| 15 |
} |
| 16 |
|
| 17 |
if ( ! class_exists( 'Charitable_Campaign_List_Table' ) ) : |
| 18 |
|
| 19 |
/** |
| 20 |
* Charitable_Campaign_List_Table class. |
| 21 |
* |
| 22 |
* @since 1.5.0 |
| 23 |
*/ |
| 24 |
final class Charitable_Campaign_List_Table { |
| 25 |
|
| 26 |
/** |
| 27 |
* The single instance of this class. |
| 28 |
* |
| 29 |
* @since 1.5.0 |
| 30 |
* |
| 31 |
* @var Charitable_Campaign_List_Table|null |
| 32 |
*/ |
| 33 |
private static $instance = null; |
| 34 |
|
| 35 |
/** |
| 36 |
* Post type. |
| 37 |
* |
| 38 |
* @var string |
| 39 |
*/ |
| 40 |
protected $list_table_type = 'campaign'; |
| 41 |
|
| 42 |
/** |
| 43 |
* Returns and/or create the single instance of this class. |
| 44 |
* |
| 45 |
* @since 1.5.0 |
| 46 |
* |
| 47 |
* @return Charitable_Campaign_List_Table |
| 48 |
*/ |
| 49 |
public static function get_instance() { |
| 50 |
if ( is_null( self::$instance ) ) { |
| 51 |
self::$instance = new self(); |
| 52 |
} |
| 53 |
|
| 54 |
return self::$instance; |
| 55 |
} |
| 56 |
|
| 57 |
/** |
| 58 |
* Updates body class for admin. |
| 59 |
* |
| 60 |
* @since 1.8.0 |
| 61 |
* |
| 62 |
* @param string $classes The current body classes. |
| 63 |
* |
| 64 |
* @return string |
| 65 |
*/ |
| 66 |
public function admin_body_class( $classes ) { |
| 67 |
|
| 68 |
global $pagenow; |
| 69 |
|
| 70 |
if ( in_array( $pagenow, array( 'edit.php' ), true ) && ! empty( $_GET['post_type'] ) && $_GET['post_type'] === 'campaign' ) { // phpcs:ignore. |
| 71 |
$count_posts = ( wp_count_posts( 'campaign' )->draft + wp_count_posts( 'campaign' )->publish + wp_count_posts( 'campaign' )->future + wp_count_posts( 'campaign' )->pending + wp_count_posts( 'campaign' )->private ); |
| 72 |
$classes .= ' charitable-campaigns charitable-campaigns-' . intval( $count_posts ) . '-published'; // this should be at start: charitable-campaigns charitable-campaigns-0-published. |
| 73 |
} |
| 74 |
|
| 75 |
if ( in_array( $pagenow, array( 'edit.php' ), true ) && ! empty( $_GET['post_status'] ) && $_GET['post_status'] === 'trash' ) { // phpcs:ignore. |
| 76 |
$count_posts = ( wp_count_posts( 'campaign' )->trash ); |
| 77 |
$classes .= ' charitable-trash charitable-campaigns-' . intval( $count_posts ) . '-trash'; |
| 78 |
} |
| 79 |
|
| 80 |
return $classes; |
| 81 |
} |
| 82 |
|
| 83 |
/** |
| 84 |
* Customize campaigns columns. |
| 85 |
* |
| 86 |
* @see get_column_headers |
| 87 |
* |
| 88 |
* @since 1.5.0 |
| 89 |
* |
| 90 |
* @return array |
| 91 |
*/ |
| 92 |
public function dashboard_columns() { |
| 93 |
/** |
| 94 |
* Filter the columns shown in the campaigns list table. |
| 95 |
* |
| 96 |
* @since 1.5.0 |
| 97 |
* |
| 98 |
* @param array $columns The list of columns. |
| 99 |
*/ |
| 100 |
return apply_filters( |
| 101 |
'charitable_campaign_dashboard_column_names', |
| 102 |
array( |
| 103 |
'cb' => '<input type="checkbox"/>', |
| 104 |
'title' => __( 'Title', 'charitable' ), |
| 105 |
'creator' => __( 'Creator', 'charitable' ), |
| 106 |
'donated' => __( 'Donations', 'charitable' ), |
| 107 |
'status' => __( 'Status', 'charitable' ), |
| 108 |
'end_date' => __( 'End Date', 'charitable' ), |
| 109 |
'date_created' => __( 'Date Created', 'charitable' ), |
| 110 |
'actions' => __( 'Actions', 'charitable' ), |
| 111 |
) |
| 112 |
); |
| 113 |
} |
| 114 |
|
| 115 |
/** |
| 116 |
* Add information to the dashboard campaign table listing. |
| 117 |
* |
| 118 |
* @see WP_Posts_List_Table::single_row() |
| 119 |
* |
| 120 |
* @since 1.5.0 |
| 121 |
* |
| 122 |
* @param string $column_name The name of the column to display. |
| 123 |
* @param int $post_id The current post ID. |
| 124 |
* @return void |
| 125 |
*/ |
| 126 |
public function dashboard_column_item( $column_name, $post_id ) { |
| 127 |
$campaign = charitable_get_campaign( $post_id ); |
| 128 |
$display = ''; |
| 129 |
|
| 130 |
switch ( $column_name ) { |
| 131 |
case 'ID': |
| 132 |
$display = $post_id; |
| 133 |
break; |
| 134 |
|
| 135 |
case 'creator': |
| 136 |
$creator_id = $campaign->get_campaign_creator(); |
| 137 |
$creator_name = $campaign->get_campaign_creator_name(); |
| 138 |
|
| 139 |
if ( intval( $creator_id ) > 0 ) { |
| 140 |
$display .= '<a href="' . get_edit_user_link( $creator_id ) . '" >'; |
| 141 |
$display .= '<img class="charitable-campaign-creator-avatar" alt="' . $creator_name . '" title="' . $creator_name . '" src="' . esc_url( get_avatar_url( $creator_id ) ) . '" />'; |
| 142 |
} |
| 143 |
$display .= '<span class="charitable-campaign-creator-name">' . $creator_name . '</span>'; |
| 144 |
if ( intval( $creator_id ) > 0 ) { |
| 145 |
$display .= '</a>'; |
| 146 |
} |
| 147 |
break; |
| 148 |
|
| 149 |
case 'donated': |
| 150 |
$display = charitable_format_money( $campaign->get_donated_amount() ); |
| 151 |
|
| 152 |
/* |
| 153 |
* Gated on having a GOAL, not on having an end date. |
| 154 |
* |
| 155 |
* This used to test `! $campaign->is_endless()`, which is a |
| 156 |
* question about the end date and says nothing about whether |
| 157 |
* there is a target to measure against. It got both cases |
| 158 |
* wrong: a campaign with a goal and no end date showed no bar |
| 159 |
* at all - reported in 1.8.13 testing as the goal not showing |
| 160 |
* in the campaigns list - while a campaign with an end date |
| 161 |
* and no goal drew a bar that could only ever sit at 0%, |
| 162 |
* since get_percent_donated() has no denominator. |
| 163 |
* |
| 164 |
* has_goal() is the same accessor the Charitable dashboard's |
| 165 |
* own goal column and Charitable_Campaign::get_goal() use, so |
| 166 |
* the two screens now agree about which campaigns have a |
| 167 |
* target. |
| 168 |
*/ |
| 169 |
if ( $campaign->has_goal() ) { |
| 170 |
$percent = absint( $campaign->get_percent_donated() ); |
| 171 |
if ( $percent > 100 ) { |
| 172 |
$percent = 100; |
| 173 |
} |
| 174 |
$display .= '<div class="meter"> |
| 175 |
<span style="width: ' . $percent . '%"></span> |
| 176 |
</div>'; |
| 177 |
} |
| 178 |
break; |
| 179 |
|
| 180 |
case 'date_created': |
| 181 |
$date_format = get_option( 'date_format' ); |
| 182 |
$date_format = ( '' === trim( $date_format ) ) ? 'd/m/Y' : $date_format; |
| 183 |
$display = date( $date_format, strtotime( $campaign->post_date ) ); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date |
| 184 |
break; |
| 185 |
|
| 186 |
case 'end_date': |
| 187 |
$display = $campaign->is_endless() ? '∞' : $campaign->get_end_date(); |
| 188 |
break; |
| 189 |
|
| 190 |
case 'actions': |
| 191 |
// determine if we share the preview or the actual live URL. |
| 192 |
$status = get_post_status( $post_id ); |
| 193 |
|
| 194 |
if ( 'trash' === $status ) { |
| 195 |
break; |
| 196 |
} |
| 197 |
|
| 198 |
$link = ( 'publish' === $status || 'private' === $status ) ? get_permalink( $post_id ) : charitable_get_campaign_preview_url( $post_id, true, $status ); |
| 199 |
$display = '<a class="charitable-campaign-action-button" title="' . esc_html__( 'Preview', 'charitable' ) . '" href="' . esc_url( $link ) . '" target="_blank"><img src="' . charitable()->get_path( 'assets', false ) . 'images/icons/eye.svg" width="14" height="14" alt="' . esc_html__( 'Preview', 'charitable' ) . '" /></a><a class="charitable-campaign-action-button" title="' . esc_html__( 'Trash', 'charitable' ) . '" href="' . get_delete_post_link( $post_id ) . '"><img src="' . charitable()->get_path( 'assets', false ) . 'images/icons/trash.svg" width="14" height="14" alt="' . esc_html__( 'Trash', 'charitable' ) . '" /></a>'; |
| 200 |
|
| 201 |
// <button><i class="fa fa-envelope"></i></button> |
| 202 |
|
| 203 |
break; |
| 204 |
|
| 205 |
case 'status': |
| 206 |
$status = $campaign->get_status(); |
| 207 |
|
| 208 |
if ( 'finished' === $status && $campaign->has_goal() ) { |
| 209 |
$status = $campaign->has_achieved_goal() ? 'successful' : 'unsuccessful'; |
| 210 |
} |
| 211 |
|
| 212 |
$display = '<mark class="' . esc_attr( $status ) . '">' . $status . '</mark>'; |
| 213 |
break; |
| 214 |
|
| 215 |
default: |
| 216 |
$display = ''; |
| 217 |
} |
| 218 |
|
| 219 |
/** |
| 220 |
* Filter the output of the cell. |
| 221 |
* |
| 222 |
* @since 1.5.0 |
| 223 |
* |
| 224 |
* @param string $display The content that will be displayed. |
| 225 |
* @param string $column_name The name of the column. |
| 226 |
* @param int $post_id The ID of the campaign being shown. |
| 227 |
* @param Charitable_Campaign $campaign The Charitable_Campaign object. |
| 228 |
*/ |
| 229 |
echo apply_filters( 'charitable_campaign_column_display', $display, $column_name, $post_id, $campaign ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped |
| 230 |
} |
| 231 |
|
| 232 |
/** |
| 233 |
* Modify bulk messages |
| 234 |
* |
| 235 |
* @since 1.5.0 |
| 236 |
* |
| 237 |
* @param array $bulk_messages Messages to show after bulk actions. |
| 238 |
* @param array $bulk_counts Array showing how many items were affected by the action. |
| 239 |
* @return array |
| 240 |
*/ |
| 241 |
public function bulk_messages( $bulk_messages, $bulk_counts ) { |
| 242 |
$bulk_messages[ Charitable::CAMPAIGN_POST_TYPE ] = array( |
| 243 |
/* translators: %s: number of items */ |
| 244 |
'updated' => _n( '%d campaign updated.', '%d campaigns updated.', $bulk_counts['updated'], 'charitable' ), |
| 245 |
'locked' => ( 1 == $bulk_counts['locked'] ) |
| 246 |
? __( '1 campaign not updated, somebody is editing it.', 'charitable' ) |
| 247 |
/* translators: %s: number of items */ |
| 248 |
: _n( '%s campaign not updated, somebody is editing it.', '%s campaigns not updated, somebody is editing them.', $bulk_counts['locked'], 'charitable' ), |
| 249 |
/* translators: %s: number of items */ |
| 250 |
'deleted' => _n( '%s campaign permanently deleted.', '%s campaigns permanently deleted.', $bulk_counts['deleted'], 'charitable' ), |
| 251 |
/* translators: %s: number of items */ |
| 252 |
'trashed' => _n( '%s campaign moved to the Trash.', '%s campaigns moved to the Trash.', $bulk_counts['trashed'], 'charitable' ), |
| 253 |
/* translators: %s: number of items */ |
| 254 |
'untrashed' => _n( '%s campaign restored from the Trash.', '%s campaigns restored from the Trash.', $bulk_counts['untrashed'], 'charitable' ), |
| 255 |
); |
| 256 |
|
| 257 |
return $bulk_messages; |
| 258 |
} |
| 259 |
|
| 260 |
/** |
| 261 |
* Add extra buttons after filters |
| 262 |
* |
| 263 |
* @since 1.6.0 |
| 264 |
* |
| 265 |
* @param string $which The context where this is being called. |
| 266 |
* @return void |
| 267 |
*/ |
| 268 |
public function add_export( $which ) { |
| 269 |
if ( ! current_user_can( 'export_charitable_reports' ) ) { |
| 270 |
return; |
| 271 |
} |
| 272 |
|
| 273 |
if ( 'top' === $which && $this->is_campaigns_page() ) { |
| 274 |
charitable_admin_view( 'campaigns-page/export' ); |
| 275 |
} |
| 276 |
} |
| 277 |
|
| 278 |
/** |
| 279 |
* Add extra buttons after filters |
| 280 |
* |
| 281 |
* @since 1.6.0 |
| 282 |
* |
| 283 |
* @param string $which The context where this is being called. |
| 284 |
* @return void |
| 285 |
*/ |
| 286 |
public function add_legacy_link( $which ) { |
| 287 |
if ( ! current_user_can( 'publish_posts' ) ) { |
| 288 |
return; |
| 289 |
} |
| 290 |
|
| 291 |
if ( 'top' === $which && $this->is_campaigns_page() ) { |
| 292 |
charitable_admin_view( 'campaigns-page/legacy-add' ); |
| 293 |
} |
| 294 |
} |
| 295 |
|
| 296 |
|
| 297 |
/** |
| 298 |
* Add filters above the campaigns table. |
| 299 |
* |
| 300 |
* @since 1.6.36 |
| 301 |
* |
| 302 |
* @global string $typenow The current post type. |
| 303 |
* |
| 304 |
* @return void |
| 305 |
*/ |
| 306 |
public function add_filters() { |
| 307 |
global $typenow; |
| 308 |
|
| 309 |
/* Show custom filters to filter orders by donor. */ |
| 310 |
if ( in_array( $typenow, array( Charitable::CAMPAIGN_POST_TYPE ) ) ) { // phpcs:ignore WordPress.PHP.StrictInArray.MissingTypeDeclaration |
| 311 |
charitable_admin_view( 'campaigns-page/filters' ); |
| 312 |
} |
| 313 |
} |
| 314 |
|
| 315 |
/** |
| 316 |
* Add modal template to footer. |
| 317 |
* |
| 318 |
* @since 1.6.0 |
| 319 |
* |
| 320 |
* @return void |
| 321 |
*/ |
| 322 |
public function modal_forms() { |
| 323 |
if ( $this->is_campaigns_page() ) { |
| 324 |
charitable_admin_view( 'campaigns-page/filter-form' ); |
| 325 |
charitable_admin_view( 'campaigns-page/export-form' ); |
| 326 |
} |
| 327 |
} |
| 328 |
|
| 329 |
/** |
| 330 |
* Admin scripts and styles. |
| 331 |
* |
| 332 |
* Set up the scripts & styles used for the modal. |
| 333 |
* |
| 334 |
* @since 1.6.0 |
| 335 |
* |
| 336 |
* @param string $hook The current page hook/slug. |
| 337 |
* @return void |
| 338 |
*/ |
| 339 |
public function load_scripts( $hook ) { |
| 340 |
if ( 'edit.php' != $hook ) { |
| 341 |
return; |
| 342 |
} |
| 343 |
|
| 344 |
if ( $this->is_campaigns_page() ) { |
| 345 |
wp_enqueue_style( 'lean-modal-css' ); |
| 346 |
wp_enqueue_script( 'jquery' ); |
| 347 |
wp_enqueue_script( 'lean-modal' ); |
| 348 |
wp_enqueue_script( 'charitable-admin-tables' ); |
| 349 |
} |
| 350 |
} |
| 351 |
|
| 352 |
/** |
| 353 |
* Add custom filters to the query that returns the campaigns to be displayed. |
| 354 |
* |
| 355 |
* @since 1.6.36 |
| 356 |
* |
| 357 |
* @global string $typenow The current post type. |
| 358 |
* |
| 359 |
* @param array $vars The array of args to pass to WP_Query. |
| 360 |
* @return array |
| 361 |
*/ |
| 362 |
public function filter_request_query( $vars ) { |
| 363 |
if ( ! $this->is_campaigns_page() ) { |
| 364 |
return $vars; |
| 365 |
} |
| 366 |
|
| 367 |
/* No Status: fix WP's crappy handling of "all" post status. */ |
| 368 |
if ( ! isset( $_GET['post_status'] ) || empty( $_GET['post_status'] ) || 'all' === $_GET['post_status'] ) { |
| 369 |
$vars['post_status'] = array_keys( get_post_statuses() ); |
| 370 |
$vars['perm'] = 'readable'; |
| 371 |
} else { |
| 372 |
switch ( $_GET['post_status'] ) { |
| 373 |
case 'active': |
| 374 |
$vars['post_status'] = 'publish'; |
| 375 |
$vars['meta_query'] = array( |
| 376 |
'relation' => 'OR', |
| 377 |
array( |
| 378 |
'key' => '_campaign_end_date', |
| 379 |
'value' => date( 'Y-m-d H:i:s' ), // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date |
| 380 |
'compare' => '>', |
| 381 |
'type' => 'datetime', |
| 382 |
), |
| 383 |
array( |
| 384 |
'key' => '_campaign_end_date', |
| 385 |
'value' => 0, |
| 386 |
'compare' => '=', |
| 387 |
), |
| 388 |
); |
| 389 |
break; |
| 390 |
|
| 391 |
case 'finish': |
| 392 |
$vars['post_status'] = 'publish'; |
| 393 |
$vars['meta_query'] = array( |
| 394 |
array( |
| 395 |
'key' => '_campaign_end_date', |
| 396 |
'value' => date( 'Y-m-d H:i:s' ), // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date |
| 397 |
'compare' => '<=', |
| 398 |
'type' => 'datetime', |
| 399 |
), |
| 400 |
); |
| 401 |
break; |
| 402 |
|
| 403 |
default: |
| 404 |
$vars['post_status'] = esc_attr( $_GET['post_status'] ); // phpcs:ignore |
| 405 |
$vars['perm'] = 'readable'; |
| 406 |
} |
| 407 |
} |
| 408 |
|
| 409 |
if ( ! empty( $_GET['charitable_nonce'] ) && |
| 410 |
wp_verify_nonce( esc_html( $_GET['charitable_nonce'] ), 'charitable_filter_campaigns' ) ) : // phpcs:ignore |
| 411 |
|
| 412 |
/* Set up start date query */ |
| 413 |
if ( isset( $_GET['start_date_from'] ) && ! empty( $_GET['start_date_from'] ) ) { |
| 414 |
$start_date_from = $this->get_parsed_date( esc_html( $_GET['start_date_from'] ) ); // phpcs:ignore |
| 415 |
$vars['date_query']['after'] = array( |
| 416 |
'year' => $start_date_from['year'], |
| 417 |
'month' => $start_date_from['month'], |
| 418 |
'day' => $start_date_from['day'], |
| 419 |
); |
| 420 |
} |
| 421 |
|
| 422 |
if ( isset( $_GET['start_date_to'] ) && ! empty( $_GET['start_date_to'] ) ) { |
| 423 |
$start_date_to = $this->get_parsed_date( esc_html( $_GET['start_date_to'] ) ); // phpcs:ignore |
| 424 |
$vars['date_query']['before'] = array( |
| 425 |
'year' => $start_date_to['year'], |
| 426 |
'month' => $start_date_to['month'], |
| 427 |
'day' => $start_date_to['day'], |
| 428 |
); |
| 429 |
} |
| 430 |
|
| 431 |
/* Set up end date query */ |
| 432 |
if ( isset( $_GET['end_date_from'] ) && ! empty( $_GET['end_date_from'] ) ) { |
| 433 |
$end_date_from = $this->get_parsed_date( esc_html( $_GET['end_date_from'] ) ); // phpcs:ignore |
| 434 |
$vars['meta_query'][] = array( |
| 435 |
'key' => '_campaign_end_date', |
| 436 |
'value' => sprintf( '%d-%d-%d 00:00:00', $end_date_from['year'], $end_date_from['month'], $end_date_from['day'] ), |
| 437 |
'compare' => '>=', |
| 438 |
'type' => 'datetime', |
| 439 |
); |
| 440 |
} |
| 441 |
|
| 442 |
if ( isset( $_GET['end_date_to'] ) && ! empty( $_GET['end_date_to'] ) ) { |
| 443 |
$end_date_to = $this->get_parsed_date( esc_html( $_GET['end_date_to'] ) ); // phpcs:ignore |
| 444 |
$vars['meta_query'][] = array( |
| 445 |
'key' => '_campaign_end_date', |
| 446 |
'value' => sprintf( '%d-%d-%d 00:00:00', $end_date_to['year'], $end_date_to['month'], $end_date_to['day'] ), |
| 447 |
'compare' => '<=', |
| 448 |
'type' => 'datetime', |
| 449 |
); |
| 450 |
} |
| 451 |
|
| 452 |
if ( isset( $vars['date_query'] ) ) { |
| 453 |
$vars['date_query']['inclusive'] = true; |
| 454 |
} |
| 455 |
|
| 456 |
/* Filter by campaign. */ |
| 457 |
if ( isset( $_GET['campaign_id'] ) && false !== stripos( esc_html( $_GET['charitable_nonce'] ), 'all' ) ) { // phpcs:ignore |
| 458 |
$vars['post__in'] = charitable_get_table( 'campaign_donations' )->get_donation_ids_for_campaign( intval( $_GET['campaign_id'] ) ); |
| 459 |
} |
| 460 |
|
| 461 |
endif; |
| 462 |
|
| 463 |
/* Restrict by author if user can only edit their own. */ |
| 464 |
if ( ! current_user_can( 'edit_others_campaigns' ) ) { |
| 465 |
$vars['author'] = get_current_user_id(); |
| 466 |
} |
| 467 |
|
| 468 |
/** |
| 469 |
* Filter the campaign list query vars. |
| 470 |
* |
| 471 |
* @since 1.6.36 |
| 472 |
* |
| 473 |
* @param array $vars The request query vars. |
| 474 |
*/ |
| 475 |
return apply_filters( 'charitable_filter_campaigns_list_request_vars', $vars ); |
| 476 |
} |
| 477 |
|
| 478 |
/** |
| 479 |
* Given a date, returns an array containing the date, month and year. |
| 480 |
* Updated in 1.7.0.8 to reflect a change in date format, but points to a new date format function in case someone else is using the old one. |
| 481 |
* |
| 482 |
* @since 1.6.36 |
| 483 |
* |
| 484 |
* @param string $date A date as a string that can be parsed by strtotime. |
| 485 |
* @return string[] |
| 486 |
*/ |
| 487 |
protected function get_parsed_date( $date ) { |
| 488 |
$time = charitable_sanitize_date_alt_format( $date ); |
| 489 |
|
| 490 |
$args = array( |
| 491 |
'year' => date( 'Y', $time ), // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date |
| 492 |
'month' => date( 'm', $time ), // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date |
| 493 |
'day' => date( 'd', $time ), // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date |
| 494 |
); |
| 495 |
|
| 496 |
return $args; |
| 497 |
} |
| 498 |
|
| 499 |
/** |
| 500 |
* Checks whether this is the campaigns page. |
| 501 |
* |
| 502 |
* @since 1.6.0 |
| 503 |
* |
| 504 |
* @global string $typenow The current post type. |
| 505 |
* @global string $pagenow The current admin page. |
| 506 |
* |
| 507 |
* @return boolean |
| 508 |
*/ |
| 509 |
private function is_campaigns_page() { |
| 510 |
global $typenow, $pagenow; |
| 511 |
|
| 512 |
return 'edit.php' === $pagenow && in_array( $typenow, array( Charitable::CAMPAIGN_POST_TYPE ), true ); |
| 513 |
} |
| 514 |
|
| 515 |
/** |
| 516 |
* Show blank slate. |
| 517 |
* |
| 518 |
* @since 1.8.1.5 |
| 519 |
* @version 1.8.8.6, 1.8.9.1, 1.8.10 |
| 520 |
* |
| 521 |
* @param string $which String which tablenav is being shown. |
| 522 |
* |
| 523 |
* @return void |
| 524 |
*/ |
| 525 |
public function maybe_render_blank_state( $which = '' ) { |
| 526 |
global $post_type, $typenow; |
| 527 |
|
| 528 |
// Static flag to prevent double rendering |
| 529 |
static $blank_state_rendered = false; |
| 530 |
|
| 531 |
// Use $typenow as fallback if $post_type is not set |
| 532 |
$current_post_type = $post_type ? $post_type : $typenow; |
| 533 |
|
| 534 |
// Only proceed if we're on the correct post type |
| 535 |
if ( $current_post_type !== $this->list_table_type ) { |
| 536 |
return; |
| 537 |
} |
| 538 |
|
| 539 |
// Check post count |
| 540 |
$counts = (array) wp_count_posts( $current_post_type ); |
| 541 |
unset( $counts['auto-draft'] ); |
| 542 |
$count = array_sum( $counts ); |
| 543 |
|
| 544 |
// Skip if there are posts or blank slate is disabled |
| 545 |
if ( ! defined( 'CHARITABLE_FORCE_BLANK_SLATE' ) || ! CHARITABLE_FORCE_BLANK_SLATE ) { |
| 546 |
if ( 0 < $count || ( defined( 'CHARITABLE_DISABLE_BLANK_SLATE' ) && CHARITABLE_DISABLE_BLANK_SLATE ) ) { |
| 547 |
return; |
| 548 |
} |
| 549 |
} |
| 550 |
|
| 551 |
// Prefer bottom, but render in top if bottom doesn't fire (when there are 0 posts) |
| 552 |
if ( 'bottom' === $which && ! $blank_state_rendered ) { |
| 553 |
$blank_state_rendered = true; |
| 554 |
$this->enqueue_blank_slate_assets(); |
| 555 |
$this->render_blank_state(); |
| 556 |
echo '<style type="text/css">#posts-filter .wp-list-table, #posts-filter .tablenav.top, .tablenav.bottom .actions, .wrap .subsubsub, .wrap .search-box, .wrap .tablenav-pages { display: none; } #posts-filter .tablenav.bottom { height: auto; } body.post-type-campaign .page-title-action { display: none; } </style>'; |
| 557 |
} elseif ( 'top' === $which && ! $blank_state_rendered ) { |
| 558 |
// Fallback: if bottom never fires (WordPress doesn't render it with 0 posts), render in top |
| 559 |
$blank_state_rendered = true; |
| 560 |
$this->enqueue_blank_slate_assets(); |
| 561 |
$this->render_blank_state(); |
| 562 |
echo '<style type="text/css">#posts-filter .wp-list-table, #posts-filter .tablenav.top .actions, .wrap .subsubsub, .wrap .search-box, .wrap .tablenav-pages { display: none; } #posts-filter .tablenav.top { height: auto; } body.post-type-campaign .page-title-action { display: none; } </style>'; |
| 563 |
} |
| 564 |
} |
| 565 |
|
| 566 |
/** |
| 567 |
* Renders advice in the event that no campaigns exist yet. |
| 568 |
* |
| 569 |
* @since 1.8.1.5 |
| 570 |
* @version 1.8.10 |
| 571 |
* |
| 572 |
* @return void |
| 573 |
*/ |
| 574 |
public function render_blank_state() { |
| 575 |
?> |
| 576 |
<div class="charitable-blank-slate"> |
| 577 |
<!-- Page Header --> |
| 578 |
<div class="page-header"> |
| 579 |
<h1 class="page-title"><?php esc_html_e( 'Campaigns', 'charitable' ); ?></h1> |
| 580 |
<?php if ( charitable_disable_legacy_campaigns() ) : ?> |
| 581 |
<a href="<?php echo esc_url( admin_url( 'admin.php?page=charitable-campaign-builder&view=template' ) ); ?>" class="btn-primary"><?php esc_html_e( '+ Create Campaign', 'charitable' ); ?></a> |
| 582 |
<?php else : ?> |
| 583 |
<a href="<?php echo esc_url( admin_url( 'post-new.php?post_type=campaign' ) ); ?>" class="btn-primary"><?php esc_html_e( '+ Create Legacy Campaign', 'charitable' ); ?></a> |
| 584 |
<?php endif; ?> |
| 585 |
</div> |
| 586 |
|
| 587 |
<!-- Primary Welcome Section --> |
| 588 |
<div class="welcome-card"> |
| 589 |
<h2 class="welcome-title"><?php esc_html_e( 'Ready to Start Fundraising?', 'charitable' ); ?></h2> |
| 590 |
<p class="welcome-description"> |
| 591 |
<?php esc_html_e( 'Create your first campaign to start accepting donations and building your supporter community.', 'charitable' ); ?> |
| 592 |
</p> |
| 593 |
<?php if ( charitable_disable_legacy_campaigns() ) : ?> |
| 594 |
<a href="<?php echo esc_url( admin_url( 'admin.php?page=charitable-campaign-builder&view=template' ) ); ?>" class="btn-primary btn-large"><?php esc_html_e( 'Create Your First Campaign', 'charitable' ); ?></a> |
| 595 |
<?php else : ?> |
| 596 |
<a href="<?php echo esc_url( admin_url( 'post-new.php?post_type=campaign' ) ); ?>" class="btn-primary btn-large"><?php esc_html_e( 'Create Your First Campaign', 'charitable' ); ?></a> |
| 597 |
<?php endif; ?> |
| 598 |
</div> |
| 599 |
|
| 600 |
<!-- Secondary Actions --> |
| 601 |
<div class="secondary-actions"> |
| 602 |
<div class="action-card"> |
| 603 |
<h3><?php esc_html_e( 'Already Have Campaigns Elsewhere?', 'charitable' ); ?></h3> |
| 604 |
<?php |
| 605 |
$givewp_installed = $this->is_givewp_installed(); |
| 606 |
$givewp_count = $givewp_installed ? $this->get_givewp_campaign_count() : 0; |
| 607 |
|
| 608 |
if ( $givewp_installed && $givewp_count > 0 ) : |
| 609 |
?> |
| 610 |
<p class="givewp-detection-text"> |
| 611 |
<?php |
| 612 |
printf( |
| 613 |
wp_kses( |
| 614 |
/* translators: 1: bolded "GiveWP", 2: number of campaigns. */ |
| 615 |
__( 'We detected %1$s with %2$s campaigns installed on your site. Use our import tool to import them into Charitable.', 'charitable' ), |
| 616 |
[ |
| 617 |
'strong' => [], |
| 618 |
'span' => [ 'class' => [] ], |
| 619 |
] |
| 620 |
), |
| 621 |
'<strong>GiveWP</strong>', |
| 622 |
'<span class="givewp-count">' . absint( $givewp_count ) . '</span>' |
| 623 |
); |
| 624 |
?> |
| 625 |
</p> |
| 626 |
<a href="https://www.wpcharitable.com/documentation/import-export-tool-givewp-to-charitable/" class="btn-secondary" target="_blank"><?php esc_html_e( 'Import GiveWP Campaigns', 'charitable' ); ?></a> |
| 627 |
<?php elseif ( $givewp_installed && 0 === $givewp_count ) : ?> |
| 628 |
<p class="givewp-detection-text"> |
| 629 |
<?php |
| 630 |
printf( |
| 631 |
wp_kses( |
| 632 |
/* translators: %s: bolded "GiveWP". */ |
| 633 |
__( 'Did you know you can import %s campaigns, donations, and donors right into Charitable?', 'charitable' ), |
| 634 |
[ 'strong' => [] ] |
| 635 |
), |
| 636 |
'<strong>GiveWP</strong>' |
| 637 |
); |
| 638 |
?> |
| 639 |
</p> |
| 640 |
<a href="<?php echo esc_url( admin_url( 'admin.php?page=charitable-tools&tab=import&sub_tab=givewp' ) ); ?>" class="btn-secondary"><?php esc_html_e( 'Import Tools', 'charitable' ); ?></a> |
| 641 |
<?php else : ?> |
| 642 |
<p><?php esc_html_e( 'Import your existing campaigns from your old fundraising platform to get started quickly with Charitable.', 'charitable' ); ?></p> |
| 643 |
<a href="<?php echo esc_url( admin_url( 'admin.php?page=charitable-tools&tab=import&sub_tab=charitable' ) ); ?>" class="btn-secondary"><?php esc_html_e( 'Import Campaigns', 'charitable' ); ?></a> |
| 644 |
<?php endif; ?> |
| 645 |
</div> |
| 646 |
|
| 647 |
<div class="blank-slate-feature-card"> |
| 648 |
<div class="blank-slate-feature-title-icon-row"> |
| 649 |
<div class="blank-slate-feature-icon"> |
| 650 |
<img src="<?php echo esc_url( charitable()->get_path( 'assets', false ) . 'images/icons/group.svg' ); ?>" alt="<?php esc_attr_e( 'Peer-to-Peer', 'charitable' ); ?>" width="32" height="32" /> |
| 651 |
</div> |
| 652 |
<h3 class="blank-slate-feature-title"><?php esc_html_e( 'Enable Peer-to-Peer', 'charitable' ); ?> <span class="blank-slate-pro-badge"><?php esc_html_e( 'PRO', 'charitable' ); ?></span></h3> |
| 653 |
</div> |
| 654 |
<div class="blank-slate-feature-content"> |
| 655 |
<p class="blank-slate-feature-description"><?php esc_html_e( 'Charitable Ambassadors transforms your website into a peer-to-peer fundraising or crowdfunding platform.', 'charitable' ); ?></p> |
| 656 |
<div class="blank-slate-button-row"> |
| 657 |
<?php |
| 658 |
$ambassadors_state = $this->get_ambassadors_addon_state(); |
| 659 |
|
| 660 |
if ( 'upgrade' === $ambassadors_state['button_action'] ) { |
| 661 |
$upgrade_url = isset( $ambassadors_state['upgrade_url'] ) ? $ambassadors_state['upgrade_url'] : '#'; |
| 662 |
?> |
| 663 |
<a href="<?php echo esc_url( $upgrade_url ); ?>" class="charitable-dashboard-v2-enhance-grid-button <?php echo esc_attr( $ambassadors_state['button_class'] ); ?>" data-action="upgrade" target="_blank"><?php echo esc_html( $ambassadors_state['button_text'] ); ?></a> |
| 664 |
<?php |
| 665 |
} else { |
| 666 |
$button_attributes = [ |
| 667 |
'data-action="' . esc_attr( $ambassadors_state['button_action'] ) . '"', |
| 668 |
'data-slug="charitable-ambassadors"', |
| 669 |
'data-type="charitable_addon"', |
| 670 |
]; |
| 671 |
|
| 672 |
if ( $ambassadors_state['button_disabled'] ) { |
| 673 |
$button_attributes[] = 'disabled'; |
| 674 |
} |
| 675 |
?> |
| 676 |
<button class="charitable-dashboard-v2-enhance-grid-button <?php echo esc_attr( $ambassadors_state['button_class'] ); ?>" <?php echo implode( ' ', $button_attributes ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>><?php echo esc_html( $ambassadors_state['button_text'] ); ?></button> |
| 677 |
<?php |
| 678 |
} |
| 679 |
?> |
| 680 |
<a href="https://www.wpcharitable.com/features/peer-to-peer-fundraising/" class="charitable-dashboard-v2-enhance-grid-button charitable-dashboard-v2-learn-more-button" target="_blank"><?php esc_html_e( 'Learn More', 'charitable' ); ?></a> |
| 681 |
</div> |
| 682 |
</div> |
| 683 |
</div> |
| 684 |
</div> |
| 685 |
|
| 686 |
<!-- Help Resources --> |
| 687 |
<div class="help-resources"> |
| 688 |
<h3><?php esc_html_e( 'Additional Resources', 'charitable' ); ?></h3> |
| 689 |
<ul class="help-links"> |
| 690 |
<li><a href="https://www.wpcharitable.com/documentation/start-here/?utm_campaign=liteplugin&utm_source=charitableplugin&utm_medium=campaign-page&utm_content=Start%20Here%20Guide" target="_blank"><?php esc_html_e( 'Get Started With Charitable', 'charitable' ); ?></a></li> |
| 691 |
<li><a href="https://www.wpcharitable.com/documentation/creating-your-first-campaign/?utm_campaign=liteplugin&utm_source=charitableplugin&utm_medium=campaign-page&utm_content=Campaign%20Guide" target="_blank"><?php esc_html_e( 'Creating Your First Campaign', 'charitable' ); ?></a></li> |
| 692 |
<?php if ( $givewp_installed ) : ?> |
| 693 |
<li><a href="https://www.wpcharitable.com/documentation/import-export-tool-givewp-to-charitable/?utm_campaign=liteplugin&utm_source=charitableplugin&utm_medium=campaign-page&utm_content=Import%20Guide" target="_blank"><?php esc_html_e( 'Import Campaigns from GiveWP', 'charitable' ); ?></a></li> |
| 694 |
<?php else : ?> |
| 695 |
<li><a href="https://www.wpcharitable.com/documentation/installing-extensions/?utm_campaign=liteplugin&utm_source=charitableplugin&utm_medium=campaign-page&utm_content=Extension%20Guide" target="_blank"><?php esc_html_e( 'How to Install and Activate Charitable Extensions', 'charitable' ); ?></a></li> |
| 696 |
<?php endif; ?> |
| 697 |
<?php if ( charitable_disable_legacy_campaigns() ) : ?> |
| 698 |
<li><a class="legacy-campaign-link" href="<?php echo esc_url( admin_url( 'post-new.php?post_type=campaign' ) ); ?>"><?php esc_html_e( 'Create a Legacy Campaign', 'charitable' ); ?></a></li> |
| 699 |
<?php else : ?> |
| 700 |
<li><a class="modern-campaign-link" href="<?php echo esc_url( admin_url( 'admin.php?page=charitable-campaign-builder&view=template' ) ); ?>"><?php esc_html_e( 'Create A Modern Campaign', 'charitable' ); ?></a></li> |
| 701 |
<?php endif; ?> |
| 702 |
</ul> |
| 703 |
</div> |
| 704 |
</div> |
| 705 |
<?php |
| 706 |
} |
| 707 |
|
| 708 |
/** |
| 709 |
* Enqueue dashboard assets for AJAX button functionality on blank slate. |
| 710 |
* |
| 711 |
* @since 1.8.10 |
| 712 |
* |
| 713 |
* @return void |
| 714 |
*/ |
| 715 |
private function enqueue_blank_slate_assets() { |
| 716 |
$version = charitable()->get_version(); |
| 717 |
$suffix = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min'; |
| 718 |
|
| 719 |
wp_enqueue_script( |
| 720 |
'charitable-admin-dashboard', |
| 721 |
charitable()->get_path( 'assets', false ) . 'js/admin/charitable-admin-dashboard' . $suffix . '.js', |
| 722 |
[ 'jquery' ], |
| 723 |
$version, |
| 724 |
true |
| 725 |
); |
| 726 |
|
| 727 |
wp_localize_script( |
| 728 |
'charitable-admin-dashboard', |
| 729 |
'charitable_admin', |
| 730 |
[ |
| 731 |
'nonce' => wp_create_nonce( 'charitable-admin' ), |
| 732 |
'ajaxurl' => admin_url( 'admin-ajax.php' ), |
| 733 |
] |
| 734 |
); |
| 735 |
} |
| 736 |
|
| 737 |
/** |
| 738 |
* Check if GiveWP is installed and active. |
| 739 |
* |
| 740 |
* @since 1.8.10 |
| 741 |
* |
| 742 |
* @return bool |
| 743 |
*/ |
| 744 |
private function is_givewp_installed() { |
| 745 |
if ( ! function_exists( 'is_plugin_active' ) ) { |
| 746 |
include_once ABSPATH . 'wp-admin/includes/plugin.php'; |
| 747 |
} |
| 748 |
|
| 749 |
return is_plugin_active( 'give/give.php' ); |
| 750 |
} |
| 751 |
|
| 752 |
/** |
| 753 |
* Count GiveWP forms (campaigns). |
| 754 |
* |
| 755 |
* @since 1.8.10 |
| 756 |
* |
| 757 |
* @return int |
| 758 |
*/ |
| 759 |
private function get_givewp_campaign_count() { |
| 760 |
global $wpdb; |
| 761 |
|
| 762 |
return (int) $wpdb->get_var( |
| 763 |
$wpdb->prepare( |
| 764 |
"SELECT COUNT(*) FROM {$wpdb->posts} WHERE post_type = %s AND post_status IN ('publish', 'draft', 'private')", |
| 765 |
'give_forms' |
| 766 |
) |
| 767 |
); |
| 768 |
} |
| 769 |
|
| 770 |
/** |
| 771 |
* Get the Ambassadors addon button state based on install/license status. |
| 772 |
* |
| 773 |
* @since 1.8.10 |
| 774 |
* |
| 775 |
* @return array |
| 776 |
*/ |
| 777 |
private function get_ambassadors_addon_state() { |
| 778 |
$slug = 'charitable-ambassadors'; |
| 779 |
|
| 780 |
if ( ! function_exists( 'is_plugin_active' ) ) { |
| 781 |
include_once ABSPATH . 'wp-admin/includes/plugin.php'; |
| 782 |
} |
| 783 |
|
| 784 |
$plugin_file = $slug . '/' . $slug . '.php'; |
| 785 |
$is_installed = file_exists( WP_PLUGIN_DIR . '/' . $plugin_file ); |
| 786 |
$is_active = $is_installed && is_plugin_active( $plugin_file ); |
| 787 |
$current_plan = Charitable_Addons_Directory::get_current_plan_slug(); |
| 788 |
$required_plans = [ 'pro', 'agency' ]; |
| 789 |
$has_required_plan = in_array( $current_plan, $required_plans, true ); |
| 790 |
|
| 791 |
if ( $is_installed && $is_active ) { |
| 792 |
return [ |
| 793 |
'button_text' => __( 'Installed', 'charitable' ), |
| 794 |
'button_class' => 'charitable-dashboard-v2-installed-button', |
| 795 |
'button_action' => 'installed', |
| 796 |
'button_disabled' => true, |
| 797 |
]; |
| 798 |
} |
| 799 |
|
| 800 |
if ( $is_installed && ! $is_active ) { |
| 801 |
return [ |
| 802 |
'button_text' => __( 'Activate', 'charitable' ), |
| 803 |
'button_class' => 'charitable-dashboard-v2-activate-button', |
| 804 |
'button_action' => 'activate_addon', |
| 805 |
'button_disabled' => false, |
| 806 |
]; |
| 807 |
} |
| 808 |
|
| 809 |
if ( ! $has_required_plan ) { |
| 810 |
return [ |
| 811 |
'button_text' => __( 'Upgrade To Pro', 'charitable' ), |
| 812 |
'button_class' => 'charitable-dashboard-v2-upgrade-button', |
| 813 |
'button_action' => 'upgrade', |
| 814 |
'button_disabled' => false, |
| 815 |
'upgrade_url' => 'https://wpcharitable.com/lite-upgrade/?discount=LITEUPGRADE&utm_source=WordPress&utm_campaign=liteplugin&utm_medium=blank-slate&utm_content=Ambassadors', |
| 816 |
]; |
| 817 |
} |
| 818 |
|
| 819 |
return [ |
| 820 |
'button_text' => __( 'Install & Activate', 'charitable' ), |
| 821 |
'button_class' => 'charitable-dashboard-v2-install-button', |
| 822 |
'button_action' => 'install_addon', |
| 823 |
'button_disabled' => false, |
| 824 |
]; |
| 825 |
} |
| 826 |
|
| 827 |
/** |
| 828 |
* Renders the blank slate recommendations. |
| 829 |
* |
| 830 |
* @since 1.8.1.5 |
| 831 |
* @deprecated 1.8.10 No longer used. Replaced by card-based layout in render_blank_state(). |
| 832 |
* |
| 833 |
* @return string |
| 834 |
*/ |
| 835 |
public function render_blank_slate_recommendations() { |
| 836 |
|
| 837 |
$charitable_plugins_third_party = new Charitable_Admin_Plugins_Third_Party(); |
| 838 |
$user_recommended_list = $charitable_plugins_third_party->get_recommendations( 'campaign', 3 ); |
| 839 |
|
| 840 |
if ( empty( $user_recommended_list ) ) { |
| 841 |
return false; |
| 842 |
} |
| 843 |
|
| 844 |
ob_start(); |
| 845 |
|
| 846 |
if ( ! empty( $user_recommended_list ) ) { |
| 847 |
|
| 848 |
foreach ( $user_recommended_list as $slug => $item ) { |
| 849 |
echo $this->render_blank_slate_recommendation( $slug ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped |
| 850 |
} |
| 851 |
} else { |
| 852 |
|
| 853 |
return; |
| 854 |
|
| 855 |
} |
| 856 |
|
| 857 |
$output = ob_get_clean(); |
| 858 |
|
| 859 |
return $output; |
| 860 |
} |
| 861 |
|
| 862 |
/** |
| 863 |
* Renders a blank slate recommendation. |
| 864 |
* |
| 865 |
* @since 1.8.1.5 |
| 866 |
* |
| 867 |
* @param string $slug The slug of the recommendation. |
| 868 |
* |
| 869 |
* @return string |
| 870 |
*/ |
| 871 |
public function render_blank_slate_recommendation( $slug = '' ) { |
| 872 |
|
| 873 |
// check and see if the slug refers to a Charitable addon first. |
| 874 |
$recommended_addons = get_transient( '_charitable_addons' ); // @codingStandardsIgnoreLine - testing. |
| 875 |
|
| 876 |
// Get addons data from transient or perform API query if no transient. |
| 877 |
if ( false === $recommended_addons ) { |
| 878 |
$recommended_addons = charitable_get_addons_data_from_server(); |
| 879 |
} |
| 880 |
|
| 881 |
$recommended_addon = array(); |
| 882 |
$addon_slug = $slug; |
| 883 |
|
| 884 |
if ( $recommended_addons ) { |
| 885 |
|
| 886 |
foreach ( (array) $recommended_addons as $i => $addon ) { |
| 887 |
|
| 888 |
if ( ! empty( $addon['slug'] ) && (string) $addon_slug === (string) $addon['slug'] ) { |
| 889 |
$recommended_addon = $addon; |
| 890 |
break; |
| 891 |
} |
| 892 |
} |
| 893 |
} |
| 894 |
|
| 895 |
if ( ! empty( $recommended_addon ) ) { |
| 896 |
|
| 897 |
// this is a Chartiable addon. |
| 898 |
$title = str_replace( 'Charitable', '', $recommended_addon['name'] ); |
| 899 |
$sections = ! empty( $recommended_addon['sections'] ) ? unserialize( $recommended_addon['sections'] ) : false; |
| 900 |
$description = is_array( $sections ) && ! empty( $sections['description'] ) ? $sections['description'] : ''; |
| 901 |
|
| 902 |
ob_start(); |
| 903 |
|
| 904 |
?> |
| 905 |
|
| 906 |
<div class="charitable-intergration-step charitable-addon charitable-plugin-suggestion" data-status="<?php echo esc_attr( $slug ); ?>"> |
| 907 |
<div class="instructions"> |
| 908 |
<header class="charitable-intergration-step-header"> |
| 909 |
<div class="sub-header"> |
| 910 |
<h3><?php echo esc_html( $title ); ?></h3> |
| 911 |
<span class="badge"><a href="#"><?php esc_html_e( 'Pro', 'charitable' ); ?></a></span> |
| 912 |
</div> |
| 913 |
</header> |
| 914 |
<p class="description"><?php echo wp_strip_all_tags( $description ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></p> |
| 915 |
<a href="<?php echo esc_url( admin_url( 'admin.php?page=charitable-addons&search=' . esc_attr( str_replace( '-', ' ', $slug ) ) ) ); ?>" class="charitable-button button-link charitable-addons"><?php esc_html_e( 'View Addons', 'charitable' ); ?></a> |
| 916 |
</div> |
| 917 |
<div class="step"> |
| 918 |
<div class="vertical-wrapper"> |
| 919 |
<div class="step-image"><a class="suggestion-dismiss" title="<?php esc_html_e( 'Dismiss this suggestion', 'charitable' ); ?>" data-plugin-slug="<?php echo esc_attr( $slug ); ?>" data-plugin-type="addon" href="#"><i class="" title="<?php esc_html_e( 'Dismiss this suggestion', 'charitable' ); ?>"></i></a></div> |
| 920 |
</div> |
| 921 |
</div> |
| 922 |
</div> |
| 923 |
|
| 924 |
|
| 925 |
<?php |
| 926 |
|
| 927 |
$output = ob_get_clean(); |
| 928 |
|
| 929 |
} else { |
| 930 |
|
| 931 |
// this is a third party plugin. |
| 932 |
|
| 933 |
$charitable_plugins_third_party = new Charitable_Admin_Plugins_Third_Party(); |
| 934 |
$plugin_data = $charitable_plugins_third_party->get_plugin( esc_attr( $slug ) ); |
| 935 |
|
| 936 |
if ( ! $plugin_data ) { |
| 937 |
return ''; |
| 938 |
} |
| 939 |
|
| 940 |
ob_start(); |
| 941 |
|
| 942 |
?> |
| 943 |
|
| 944 |
<div class="charitable-intergration-step charitable-third-party charitable-plugin-suggestion" data-status="<?php echo esc_attr( $slug ); ?>"> |
| 945 |
<div class="instructions"> |
| 946 |
|
| 947 |
<header class="charitable-intergration-step-header"> |
| 948 |
<div class="sub-header"> |
| 949 |
<h3><?php echo esc_html( $plugin_data['title'] ); ?></h3> |
| 950 |
<span class="badge"><a href="#"><?php esc_html_e( 'Partner', 'charitable' ); ?></a></span> |
| 951 |
</div> |
| 952 |
</header> |
| 953 |
|
| 954 |
<p class="description"><?php echo esc_html( $plugin_data['excerpt'] ); ?></p> |
| 955 |
<?php |
| 956 |
$plugin_button_html = $charitable_plugins_third_party->get_plugin_button_html( $slug, false, '' ); |
| 957 |
echo $plugin_button_html; // phpcs:ignore |
| 958 |
?> |
| 959 |
</div> |
| 960 |
<div class="step"> |
| 961 |
<div class="vertical-wrapper"> |
| 962 |
|
| 963 |
<div class="step-image"><a class="suggestion-dismiss" title="<?php esc_html_e( 'Dismiss this suggestion', 'charitable' ); ?>" data-plugin-slug="<?php echo esc_attr( $slug ); ?>" data-plugin-type="partner" href="#"><i class="" title="<?php esc_html_e( 'Dismiss this suggestion', 'charitable' ); ?>"></i></a></div> |
| 964 |
|
| 965 |
</div> |
| 966 |
</div> |
| 967 |
</div> |
| 968 |
|
| 969 |
|
| 970 |
<?php |
| 971 |
|
| 972 |
$output = ob_get_clean(); |
| 973 |
|
| 974 |
} |
| 975 |
|
| 976 |
return $output; |
| 977 |
} |
| 978 |
} |
| 979 |
|
| 980 |
endif; |
| 981 |
|