PluginProbe
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) / 1.8.11
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) v1.8.11
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 1.7.0.9 All 211 releases
charitable / includes / admin / campaign-builder / class-campaign-builder-preview.php

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

439 lines 12.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Class that sets up the Campaign builder preview abilities.
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( 'Campaign_Builder_Preview' ) ) :
19
20 /**
21 * Campaign preview.
22 *
23 * @since 1.8.0
24 * @version 1.8.8.6
25 */
26 class Campaign_Builder_Preview { // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedClassFound -- Class name is used by other code. Changing it would break existing functionality.
27
28 /**
29 * One is the loneliest number that you'll ever do.
30 *
31 * @since 1.8.0
32 *
33 * @var object
34 */
35 private static $instance;
36
37 /**
38 * Campaign data.
39 *
40 * @since 1.8.0
41 *
42 * @var array
43 */
44 public $campaign_data;
45
46 /**
47 * Constructor.
48 *
49 * @since 1.8.0
50 */
51 public function __construct() {
52
53 if ( ! $this->is_preview_page() ) {
54 return;
55 }
56
57 $this->hooks();
58 }
59
60 /**
61 * Main Instance.
62 *
63 * @since 1.8.0
64 *
65 * @return Charitable_Builder
66 */
67 public static function get_instance() {
68 if ( ! isset( self::$instance ) && ! ( self::$instance instanceof Campaign_Builder_Preview ) ) {
69
70 self::$instance = new Campaign_Builder_Preview();
71
72 }
73
74 return self::$instance;
75 }
76
77 /**
78 * Init
79 *
80 * @since 1.8.0
81 *
82 * @return void
83 */
84 public function init() {
85 }
86
87 /**
88 * Check if current page request meets requirements for campaign preview page.
89 *
90 * @since 1.8.0
91 *
92 * @return bool
93 */
94 public function is_preview_page() {
95
96 // Only proceed for the campaign preview page.
97 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
98 if ( empty( $_GET['charitable_campaign_preview'] ) ) {
99 return false;
100 }
101
102 // Check for logged-in user with correct capabilities.
103 if ( ! is_user_logged_in() ) {
104 return false;
105 }
106
107 $campaign_id = isset( $_GET['p'] ) ? absint( $_GET['p'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
108 $campaign_id = ( 0 === $campaign_id && ! empty( $_GET['charitable_campaign_preview'] ) ) ? absint( $_GET['charitable_campaign_preview'] ) : $campaign_id; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
109
110 if ( 0 === $campaign_id && ! empty( $_GET['charitable_campaign_preview'] ) && 1 === intval( $_GET['charitable_campaign_preview'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
111 global $post;
112 if ( ! empty( $post->post_id ) ) {
113 $campaign_id = absint( $post->post_id );
114 }
115 }
116
117 // check if this custom post type actually exists.
118 global $wpdb;
119 if ( ! $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE ID=%s AND post_status != 'trash'", array( $campaign_id ) ) ) ) { // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
120 return false;
121 }
122
123 // check permissions.
124 if ( ! charitable_current_user_can( 'edit_post', $campaign_id ) ) { // this was 'view_campaign_single'.
125 return false;
126 }
127
128 // Fetch campaign details.
129 $this->campaign_data = get_post_meta( $campaign_id, 'campaign_settings_v2', true );
130
131 // Check valid campaign was found.
132 if ( empty( $this->campaign_data ) || ( empty( $this->campaign_data['id'] ) && empty( absint( $_GET['charitable_campaign_preview'] ) ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
133 return false;
134 }
135
136 return true;
137 }
138
139 /**
140 * Hooks.
141 *
142 * @since 1.8.0
143 */
144 public function hooks() {
145
146 add_action( 'pre_get_posts', [ $this, 'pre_get_posts' ] );
147 add_filter( 'the_title', [ $this, 'the_title' ], 100, 1 );
148 add_filter( 'the_content', [ $this, 'the_content' ], 999 );
149 add_filter( 'get_the_excerpt', [ $this, 'the_content' ], 999 );
150 add_filter( 'home_template_hierarchy', [ $this, 'force_page_template_hierarchy' ], 999 );
151 add_filter( 'frontpage_template_hierarchy', [ $this, 'force_page_template_hierarchy' ], 999 );
152 add_filter( 'post_thumbnail_html', '__return_empty_string' );
153 add_filter( 'charitable_campaign_can_receive_donations', [ $this, 'enable_campaign_form' ], 10, 2 );
154 }
155
156 /**
157 * The campaign donation form should be enabled for a campaign preview page, so on a preview page it's "ok" for a campaign to recieve a donation.
158 *
159 * @param boolean $can Whether the campaign form accepts donations.
160 * @param mixed $the_object Charitable_Campaign.
161 *
162 * @return boolean Whether the campaign form can be enabled for the given object.
163 */
164 public function enable_campaign_form( $can, $the_object ) { // phpcs:ignore
165 return true;
166 }
167
168 /**
169 * Modify query, limit to one post.
170 *
171 * @since 1.8.0
172 *
173 * @param \WP_Query $query The WP_Query instance.
174 */
175 public function pre_get_posts( $query ) {
176
177 if ( is_admin() || ! $query->is_main_query() ) {
178 return;
179 }
180
181 $query->set( 'page_id', '' );
182 $query->set( 'post_type', 'campaign' );
183 $query->set( 'post__in', empty( $this->campaign_data['id'] ) ? [] : [ (int) $this->campaign_data['id'] ] );
184 $query->set( 'posts_per_page', 1 );
185 }
186
187 /**
188 * Customize campaign preview page title.
189 *
190 * @since 1.5.1
191 *
192 * @param string $title Page title.
193 *
194 * @return string
195 */
196 public function the_title( $title ) {
197
198 if ( in_the_loop() ) {
199 $title = sprintf( /* translators: %s - campaign title. */
200 esc_html__( '%s Preview', 'charitable' ),
201 ! empty( $this->campaign_data['settings']['campaign_title'] ) ? sanitize_text_field( $this->campaign_data['settings']['campaign_title'] ) : esc_html__( 'Campaign', 'charitable' )
202 );
203 }
204
205 return $title;
206 }
207
208 /**
209 * Customize campaign preview page content.
210 *
211 * @since 1.8.0
212 *
213 * @return string
214 */
215 public function the_content() {
216
217 if ( ! isset( $this->campaign_data['id'] ) ) {
218 return '';
219 }
220
221 if ( ! charitable_current_user_can( 'edit_posts', $this->campaign_data['id'] ) ) {
222 return '';
223 }
224
225 $links = [];
226
227 if ( charitable_current_user_can( 'edit_posts', $this->campaign_data['id'] ) ) {
228 $links[] = [
229 'url' => esc_url(
230 add_query_arg(
231 [
232 'page' => 'charitable-campaign-builder',
233 'view' => 'design',
234 'campaign_id' => absint( $this->campaign_data['id'] ),
235 ],
236 admin_url( 'admin.php' )
237 )
238 ),
239 'text' => esc_html__( 'Edit Campaign', 'charitable' ),
240 ];
241 }
242
243 if ( charitable_current_user_can( 'read', $this->campaign_data['id'] ) ) {
244 $links[] = [
245 'url' => esc_url(
246 add_query_arg(
247 [
248 'post_type' => 'donation',
249 'campaign_id' => absint( $this->campaign_data['id'] ),
250 ],
251 admin_url( 'edit.php' )
252 )
253 ),
254 'text' => esc_html__( 'View Donations', 'charitable' ),
255 ];
256 }
257
258 $links[] = [
259 'url' => esc_url(
260 charitable_utm_link( 'https://www.wpcharitable.com/documentation/', 'Campaign Preview', 'Documentation' )
261 ),
262 'text' => esc_html__( 'Documentation', 'charitable' ),
263 ];
264
265 if ( ! empty( $_GET['new_window'] ) ) { // phpcs:ignore
266 $links[] = [
267 'url' => 'javascript:window.close();',
268 'text' => esc_html__( 'Close this window', 'charitable' ),
269 ];
270 }
271
272 $content = '<div class="charitable-preview-messages"><p>';
273
274 if ( 'publish' === get_post_status( $this->campaign_data['id'] ) ) :
275
276 if ( ! empty( $_GET['charitable_campaign_preview'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
277
278 $content .= '<p>';
279
280 $content .= sprintf(
281 wp_kses(
282 /* translators: %s - Charitable doc link. */
283 __( 'You are viewing a preview of a <a href="%s" target="_blank">published campaign</a>. If this does not match your campaign page in the campaign builder, save your changes and then refresh this page. Your current theme can also effect the look of this page.', 'charitable' ),
284 [
285 'a' => [
286 'href' => [],
287 'target' => [],
288 'rel' => [],
289 ],
290 ]
291 ),
292 esc_url( get_permalink( $this->campaign_data['id'] ) )
293 );
294
295 $content .= '</p>';
296
297 $content .= '<p>' . esc_html__( 'Ssome functionality and elements (like donation buttons, forms, social sharing, etc.) are disabled.', 'charitable' ) . '</p>';
298
299 } else {
300
301 $content .= '<p>';
302
303 $content .= sprintf(
304 wp_kses(
305 /* translators: %s - Charitable doc link. */
306 __( 'This is a preview of the latest saved revision of your campaign page. If this does not match your campaign page in the campaign builder, save your changes and then refresh this page. Your current theme can also effect the look of this page.', 'charitable' ),
307 [
308 'a' => [
309 'href' => [],
310 'target' => [],
311 'rel' => [],
312 ],
313 ]
314 ),
315 esc_url( get_permalink( $this->campaign_data['id'] ) )
316 );
317
318 $content .= '</p>';
319
320 $content .= '<p>' . esc_html__( 'Ssome functionality and elements (like donation buttons, forms, social sharing, etc.) are disabled.', 'charitable' ) . '</p>';
321
322 }
323
324 array_unshift(
325 $links,
326 [
327 'url' => esc_url(
328 get_permalink( $this->campaign_data['id'] )
329 ),
330 'text' => esc_html__( 'View Live Campaign', 'charitable' ),
331 ]
332 );
333
334 elseif ( 'draft' === get_post_status( $this->campaign_data['id'] ) ) :
335
336 $content .= '<p>';
337
338 $content .= sprintf(
339 wp_kses(
340 /* translators: %s - Charitable doc link. */
341 __( 'This is a preview of the latest saved revision of your campaign page. If this does not match your campaign page in the campaign builder, save your changes and then refresh this page. Your current theme can also effect the look of this page.', 'charitable' ),
342 [
343 'a' => [
344 'href' => [],
345 'target' => [],
346 'rel' => [],
347 ],
348 ]
349 ),
350 esc_url( get_permalink( $this->campaign_data['id'] ) )
351 );
352
353 $content .= '</p>';
354
355 $content .= '<p>' . esc_html__( 'Some functionality and elements (like donation buttons, forms, social sharing, etc.) are disabled.', 'charitable' ) . '</p>';
356
357 endif;
358
359 if ( ! empty( $links ) ) {
360 $content .= '<span class="charitable-preview-notice-links">';
361
362 foreach ( $links as $key => $link ) {
363 $content .= '<a href="' . $link['url'] . '">' . $link['text'] . '</a>';
364 $l = array_keys( $links );
365
366 if ( end( $l ) !== $key ) {
367 $content .= ' <span style="display:inline-block;margin:0 6px;opacity: 0.5">|</span> ';
368 }
369 }
370
371 $content .= '</span>';
372 }
373 $content .= '</p>';
374
375 $content .= '</div>';
376
377 // if there is no campaign ID in the campaign_data, this MIGHT be an initial preview on a new campaign which means it should be in the URL.
378 $campaign_id = 0 === intval( $this->campaign_data['id'] ) && ! empty( $_GET['charitable_campaign_preview'] ) ? absint( $_GET['charitable_campaign_preview'] ) : absint( $this->campaign_data['id'] ); // phpcs:ignore
379
380 $content .= do_shortcode( '[campaign version="2" id=' . $campaign_id . ']' );
381
382 return $content;
383 }
384
385 /**
386 * Force page template types.
387 *
388 * @since 1.8.0
389 *
390 * @param array $templates A list of template candidates, in descending order of priority.
391 *
392 * @return array
393 */
394 public function force_page_template_hierarchy( $templates ) { // phpcs:ignore
395
396 return [ 'page.php', 'single.php', 'index.php' ];
397 }
398
399 /**
400 * Adjust value of the {page_title} smart tag.
401 *
402 * @since 1.7.7
403 *
404 * @param string $content Content.
405 * @param array $campaign_data Campaign data.
406 * @param array $fields List of fields.
407 * @param string $entry_id Entry ID.
408 * @param object $smart_tag_object The smart tag object or the Generic object for those cases when class unregistered.
409 *
410 * @return string
411 */
412 public function smart_tags_process_page_title_value( $content, $campaign_data, $fields, $entry_id, $smart_tag_object ) { // phpcs:ignore
413
414 return sprintf( /* translators: %s - campaign title. */
415 esc_html__( '%s Preview', 'charitable' ),
416 ! empty( $campaign_data['settings']['campaign_title'] ) ? sanitize_text_field( $campaign_data['settings']['campaign_title'] ) : esc_html__( 'Campaign', 'charitable' )
417 );
418 }
419
420 /**
421 * Force page template types.
422 *
423 * @since 1.5.1
424 * @deprecated 1.8.0
425 *
426 * @return string
427 */
428 public function template_include() {
429
430 _deprecated_function( __METHOD__, '1.8.0 of the Charitable plugin' );
431
432 return locate_template( [ 'page.php', 'single.php', 'index.php' ] );
433 }
434 }
435
436 endif;
437
438 new Campaign_Builder_Preview();
439