PluginProbe
Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More / 2.2.1
Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More v2.2.1
2.3.4 2.3.3 2.3.2 2.3.1 2.3.0 2.2.2 2.2.1 2.2.0 2.1.2 2.1.1 trunk 0.0.1 0.0.2 0.0.3 0.0.4 0.0.5 0.0.6 0.0.7 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 All 66 releases
better-payment / includes / Campaign / CPT.php

CPT.php in Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More 2.2.1, at includes/Campaign/CPT.php

338 lines 13.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Better_Payment\Lite\Campaign;
4
5 use Better_Payment\Lite\Admin\DB;
6 use Better_Payment\Lite\Controller;
7 use Better_Payment\Lite\Campaign\Elements\ElementRegistry;
8 use Better_Payment\Lite\Campaign\Templates\TemplateManager;
9
10 if ( ! defined( 'ABSPATH' ) ) {
11 exit;
12 }
13
14 /**
15 * Registers the bp_campaign Custom Post Type and the
16 * hidden campaign builder admin page.
17 */
18 class CPT extends Controller {
19
20 /**
21 * Register the CPT and the builder admin page.
22 */
23 public function register() {
24 $args = apply_filters( 'better_payment/campaign/cpt_args', [
25 'label' => __( 'Campaigns', 'better-payment' ),
26 'labels' => [
27 'name' => __( 'Campaigns', 'better-payment' ),
28 'singular_name' => __( 'Campaign', 'better-payment' ),
29 'add_new' => __( 'Add New', 'better-payment' ),
30 'add_new_item' => __( 'Add New Campaign', 'better-payment' ),
31 'edit_item' => __( 'Edit Campaign', 'better-payment' ),
32 'new_item' => __( 'New Campaign', 'better-payment' ),
33 'view_item' => __( 'View Campaign', 'better-payment' ),
34 'search_items' => __( 'Search Campaigns', 'better-payment' ),
35 'not_found' => __( 'No campaigns found', 'better-payment' ),
36 'not_found_in_trash' => __( 'No campaigns found in trash', 'better-payment' ),
37 ],
38 'public' => true,
39 'publicly_queryable' => true,
40 'show_ui' => true,
41 'show_in_menu' => false,
42 'show_in_rest' => true,
43 'rewrite' => [ 'slug' => 'bp-campaign', 'with_front' => false ],
44 'supports' => [ 'title', 'thumbnail' ],
45 'has_archive' => false,
46 'menu_icon' => 'dashicons-heart',
47 ] );
48
49 register_post_type( 'bp_campaign', $args );
50 }
51
52 /**
53 * Register the campaign builder page under the Better Payment menu.
54 *
55 * Registered as a real submenu of 'better-payment-admin' (not orphaned with
56 * empty parent) so WordPress keeps the sidebar open and the Campaigns item
57 * highlighted automatically. The submenu link is hidden via CSS so it doesn't
58 * appear as a visible menu entry.
59 */
60 public function register_builder_page() {
61 add_submenu_page(
62 'better-payment-admin',
63 __( 'Campaign Builder', 'better-payment' ),
64 __( 'Campaign Builder', 'better-payment' ),
65 'manage_options',
66 'bp-campaign-builder',
67 [ $this, 'render_builder_page' ]
68 );
69
70 // Hide the submenu link — it should never appear in the sidebar.
71 add_action( 'admin_head', static function () {
72 echo '<style>#adminmenu a[href="admin.php?page=bp-campaign-builder"]{display:none!important}</style>';
73 } );
74
75 // Redirect the active-submenu highlight from the hidden "Campaign Builder"
76 // entry to the visible "Campaigns" tab so it appears selected in the sidebar.
77 add_filter( 'submenu_file', static function ( $submenu_file ) {
78 if ( isset( $_GET['page'] ) && 'bp-campaign-builder' === $_GET['page'] ) {
79 return 'better-payment-admin&tab=campaigns';
80 }
81 return $submenu_file;
82 } );
83 }
84
85 /**
86 * Inject the Campaigns entry into the Better Payment submenu list
87 * immediately after Transactions.
88 *
89 * @param array $list
90 * @param string $prefix
91 * @return array
92 */
93 public function inject_campaigns_submenu( array $list, string $prefix ): array {
94 $new = [];
95 $transactions_key = $prefix . '-admin&tab=transactions';
96
97 foreach ( $list as $slug => $item ) {
98 $new[ $slug ] = $item;
99
100 if ( $slug === $transactions_key ) {
101 $new['edit.php?post_type=bp_campaign'] = [
102 'title' => __( 'Campaigns', 'better-payment' ),
103 'capability' => 'manage_options',
104 'callback' => '',
105 ];
106 }
107 }
108
109 return $new;
110 }
111
112 /**
113 * Render the campaign builder page shell — React app mounts here.
114 */
115 public function render_builder_page() {
116 $campaign_id = isset( $_GET['campaign_id'] ) ? absint( $_GET['campaign_id'] ) : 0;
117 $campaign = $campaign_id ? get_post( $campaign_id ) : null;
118
119 if ( $campaign && $campaign->post_type !== 'bp_campaign' ) {
120 $campaign = null;
121 $campaign_id = 0;
122 }
123
124 wp_enqueue_script( 'bp-campaign-builder' );
125 wp_enqueue_style( 'bp-campaign-builder' );
126
127 $nonce = wp_create_nonce( 'wp_rest' );
128
129 ?>
130 <div id="bp-campaign-builder"
131 data-campaign-id="<?php echo esc_attr( $campaign_id ); ?>"
132 data-rest-url="<?php echo esc_url( rest_url( 'better-payment/v1/' ) ); ?>"
133 data-nonce="<?php echo esc_attr( $nonce ); ?>"
134 data-admin-url="<?php echo esc_url( admin_url() ); ?>"
135 data-campaigns-url="<?php echo esc_url( admin_url( 'admin.php?page=better-payment-admin&tab=campaigns' ) ); ?>"
136 ></div>
137 <?php
138 }
139
140 /**
141 * Rewrite the edit link for bp_campaign posts to point to the builder.
142 * Covers row-action "Edit", title links, and any get_edit_post_link() call.
143 *
144 * @param string $url
145 * @param int $post_id
146 * @param string $_context
147 * @return string
148 */
149 public function filter_edit_link( string $url, int $post_id, string $_context ): string {
150 if ( get_post_type( $post_id ) !== 'bp_campaign' ) {
151 return $url;
152 }
153
154 return esc_url( admin_url( 'admin.php?page=bp-campaign-builder&campaign_id=' . $post_id ) );
155 }
156
157 /**
158 * Redirect edit.php?post_type=bp_campaign to the custom campaigns tab so
159 * users never land on the raw WP post list screen.
160 * Skipped for AJAX and REST requests.
161 */
162 public function redirect_cpt_list() {
163 if ( wp_doing_ajax() ) {
164 return;
165 }
166
167 $post_type = isset( $_GET['post_type'] ) ? sanitize_key( $_GET['post_type'] ) : '';
168
169 if (
170 'edit.php' === $GLOBALS['pagenow']
171 && $post_type === 'bp_campaign'
172 ) {
173 wp_safe_redirect( admin_url( 'admin.php?page=better-payment-admin&tab=campaigns' ) );
174 exit;
175 }
176 }
177
178 /**
179 * Redirect post.php?action=edit for bp_campaign in case the old URL is
180 * reached directly (bookmarks, browser history, etc.).
181 */
182 public function redirect_edit_post() {
183 $action = isset( $_GET['action'] ) ? sanitize_key( $_GET['action'] ) : '';
184 $post_id = isset( $_GET['post'] ) ? absint( $_GET['post'] ) : 0;
185
186 if ( $action !== 'edit' || ! $post_id ) {
187 return;
188 }
189
190 if ( get_post_type( $post_id ) !== 'bp_campaign' ) {
191 return;
192 }
193
194 wp_safe_redirect( admin_url( 'admin.php?page=bp-campaign-builder&campaign_id=' . $post_id ) );
195 exit;
196 }
197
198 /**
199 * Redirect post-new.php for bp_campaign to the campaigns list so the
200 * template-select modal flow is used instead of the classic editor.
201 */
202 public function redirect_new_post() {
203 if (
204 isset( $_GET['post_type'] ) &&
205 sanitize_key( $_GET['post_type'] ) === 'bp_campaign'
206 ) {
207 wp_safe_redirect( admin_url( 'edit.php?post_type=bp_campaign' ) );
208 exit;
209 }
210 }
211
212 /**
213 * Enqueue the campaign-list script and its template data on the
214 * bp_campaign post list table page.
215 */
216 public function enqueue_list_assets( string $hook ) {
217 if ( $hook !== 'edit.php' ) {
218 return;
219 }
220
221 $post_type = isset( $_GET['post_type'] ) ? sanitize_key( $_GET['post_type'] ) : '';
222 if ( $post_type !== 'bp_campaign' ) {
223 return;
224 }
225
226 $version = defined( 'WP_DEBUG' ) && WP_DEBUG ? time() : BETTER_PAYMENT_VERSION;
227
228 wp_enqueue_script(
229 'bp-campaign-list',
230 BETTER_PAYMENT_ASSETS . '/admin/campaign-list/campaign-list.min.js',
231 [ 'react', 'react-dom', 'wp-element', 'wp-i18n' ],
232 $version,
233 true
234 );
235
236 wp_enqueue_style(
237 'bp-campaign-list',
238 BETTER_PAYMENT_ASSETS . '/admin/campaign-list/campaign-list.min.css',
239 [],
240 $version
241 );
242
243 wp_localize_script( 'bp-campaign-list', 'betterPaymentCampaignData', [
244 'templates' => array_values( TemplateManager::get_all() ),
245 'restUrl' => rest_url( 'better-payment/v1/' ),
246 'nonce' => wp_create_nonce( 'wp_rest' ),
247 'adminUrl' => admin_url(),
248 ] );
249 }
250
251 /**
252 * Enqueue campaign builder assets on the builder page only.
253 */
254 public function enqueue_builder_assets() {
255 $page = isset( $_GET['page'] ) ? sanitize_text_field( $_GET['page'] ) : '';
256
257 if ( $page !== 'bp-campaign-builder' ) {
258 return;
259 }
260
261 $version = defined( 'WP_DEBUG' ) && WP_DEBUG ? time() : BETTER_PAYMENT_VERSION;
262
263 wp_register_script(
264 'bp-campaign-builder',
265 BETTER_PAYMENT_ASSETS . '/admin/campaign-builder/campaign-builder.min.js',
266 [ 'react', 'react-dom', 'wp-element', 'wp-api-fetch', 'wp-i18n' ],
267 $version,
268 true
269 );
270
271 wp_register_style(
272 'bp-campaign-builder',
273 BETTER_PAYMENT_ASSETS . '/admin/campaign-builder/campaign-builder.min.css',
274 [],
275 $version
276 );
277
278 // Load campaign display CSS so the preview modal renders correctly.
279 $display_css = BETTER_PAYMENT_PATH . '/assets/blocks/campaign-display/style.min.css';
280 if ( file_exists( $display_css ) ) {
281 wp_enqueue_style(
282 'better-payment-campaign-display-style',
283 BETTER_PAYMENT_ASSETS . '/blocks/campaign-display/style.min.css',
284 [],
285 filemtime( $display_css )
286 );
287 }
288
289 wp_enqueue_media();
290
291 // Zero out all WP admin chrome spacing so the builder fills edge-to-edge.
292 // The footer styling mirrors the Better Payment admin footer (see
293 // ReactAdmin::get_footer_version) so the builder page\'s branded footer
294 // looks identical to the other dashboard pages — the heavy React admin
295 // stylesheet is not loaded here, so the rules are inlined.
296 wp_add_inline_style( 'bp-campaign-builder', '
297 #wpcontent { padding-left: 0 !important; }
298 #adminmenushadow { display: none !important; }
299 /* Match the WP admin surfaces to the builder background ($bg
300 #f4f5f8) so the empty band below a short builder blends in
301 instead of showing WordPress\'s default #f0f0f1. body/#wpwrap are
302 the elements that stay full-height — the content-column elements
303 (#wpcontent/#wpbody/#wpbody-content) collapse to the builder
304 height, so recoloring only those leaves the body grey exposed. */
305 body.wp-admin, #wpwrap, #wpcontent, #wpbody, #wpbody-content { background: #f4f5f8 !important; }
306 /* Editor tab is a uniform white workspace (white canvas + white
307 sidebar), so whiten the backstop too — App.js toggles
308 body.bp-cb-tab-editor with the active tab. */
309 body.bp-cb-tab-editor, body.bp-cb-tab-editor #wpwrap, body.bp-cb-tab-editor #wpcontent, body.bp-cb-tab-editor #wpbody, body.bp-cb-tab-editor #wpbody-content { background: #fff !important; }
310 #wpbody-content { overflow: hidden !important; padding: 0 !important; }
311 #wpbody-content .wrap { margin: 0 !important; padding: 0 !important; max-width: none !important; }
312 #wpfooter .alignright { gap: 30px; display: flex; }
313 #wpfooter .alignright, #wpfooter .alignleft { color: #6a758c; font-weight: 400; font-size: 14px; }
314 #wpfooter .alignright a, #wpfooter .alignleft a { font-weight: 500; color: #6b59ee; }
315 #wpfooter .alignright .bp-footer-version, #wpfooter .alignleft .bp-footer-version { padding: 4px 8px; border-radius: 20px; margin: 0 8px; color: #6b59ee; background-color: #fcfcfc; }
316 #wpfooter .alignright .bp-footer-version-divider, #wpfooter .alignleft .bp-footer-version-divider { position: relative; }
317 #wpfooter .alignright .bp-footer-version-divider::after, #wpfooter .alignleft .bp-footer-version-divider::after { position: absolute; content: ""; background-color: #b9bfca; padding: 1px; top: 2px; bottom: 2px; right: -11px; }
318 #wpfooter .bp-free-version { display: flex; align-items: center; gap: 2px; }
319 ' );
320
321 // Global currency from plugin settings — builder uses this everywhere.
322 $global_currency = DB::get_settings( 'better_payment_settings_general_general_currency' );
323 if ( ! is_string( $global_currency ) || $global_currency === '' ) {
324 $global_currency = 'USD';
325 }
326
327 // Localize element registry, templates, and global settings to JS builder.
328 wp_localize_script( 'bp-campaign-builder', 'betterPaymentCampaignData', [
329 'elements' => array_values( ElementRegistry::get_all() ),
330 'templates' => array_values( TemplateManager::get_all() ),
331 'globalCurrency' => $global_currency,
332 'restUrl' => rest_url( 'better-payment/v1/' ),
333 'nonce' => wp_create_nonce( 'wp_rest' ),
334 'pluginUrl' => plugins_url( '', BETTER_PAYMENT_BASENAME ),
335 ] );
336 }
337 }
338