PluginProbe
SureDonation – Donation Forms, Fundraising Campaigns & Donor Management / 1.6.1
SureDonation – Donation Forms, Fundraising Campaigns & Donor Management v1.6.1
1.6.1 1.6.0 1.5.1 1.5.0 1.4.0 1.3.0 trunk 0.0.1 1.0.0 1.1.0 1.1.1 1.1.2 1.2.0
suredonation / inc / campaigns / campaign-cpt.php

campaign-cpt.php in SureDonation – Donation Forms, Fundraising Campaigns & Donor Management 1.6.1, at inc/campaigns/campaign-cpt.php

256 lines 8.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Campaign Custom Post Type
4 *
5 * @package SureDonation
6 */
7
8 namespace SureDonation\Inc\Campaigns;
9
10 use SureDonation\Inc\Helper;
11 use SureDonation\Inc\Post_Types\Donation_Form;
12 use SureDonation\Inc\Campaign_Templates\Campaign_Templates;
13 use SureDonation\Inc\Traits\Get_Instance;
14
15 // Exit if accessed directly.
16 if ( ! defined( 'ABSPATH' ) ) {
17 exit;
18 }
19
20 /**
21 * Campaign_Cpt class.
22 *
23 * @since 0.0.1
24 */
25 class Campaign_Cpt {
26 use Get_Instance;
27
28 /**
29 * Post type slug.
30 *
31 * @since 0.0.1
32 */
33 public const POST_TYPE = 'suredonation_cmpgn';
34
35 /**
36 * Meta key for the linked default form ID.
37 *
38 * @since 0.0.1
39 */
40 public const META_DEFAULT_FORM_ID = '_suredonation_default_form_id';
41
42 /**
43 * Meta key for the campaign template the campaign was created from.
44 *
45 * Set via meta_input on the create-campaign insert (before save_post fires) so
46 * the seeding hooks can resolve the template. Absent ⇒ the `general` template.
47 *
48 * @since 1.5.0
49 */
50 public const META_TEMPLATE_ID = '_suredonation_campaign_template';
51
52 /**
53 * Constructor.
54 *
55 * @since 0.0.1
56 */
57 public function __construct() {
58 add_action( 'init', [ $this, 'register_post_type' ] );
59 add_action( 'init', [ $this, 'register_campaign_meta' ] );
60 add_action( 'save_post_' . self::POST_TYPE, [ $this, 'maybe_create_default_form' ], 20, 2 );
61 }
62
63 /**
64 * Register Campaign post type.
65 *
66 * @return void
67 * @since 0.0.1
68 */
69 public function register_post_type() {
70 $labels = [
71 'name' => _x( 'Campaigns', 'Post Type General Name', 'suredonation' ),
72 'singular_name' => _x( 'Campaign', 'Post Type Singular Name', 'suredonation' ),
73 'menu_name' => __( 'Campaigns', 'suredonation' ),
74 // Product-prefixed on purpose: this label is only used by the admin
75 // bar's "+ New" menu, a shared list where a bare "Campaign" carries
76 // no product context and collides with other plugins' campaigns.
77 'name_admin_bar' => __( 'SureDonation Campaign', 'suredonation' ),
78 'archives' => __( 'Campaign Archives', 'suredonation' ),
79 'attributes' => __( 'Campaign Attributes', 'suredonation' ),
80 'parent_item_colon' => __( 'Parent Campaign:', 'suredonation' ),
81 'all_items' => __( 'All Campaigns', 'suredonation' ),
82 'add_new_item' => __( 'Add New Campaign', 'suredonation' ),
83 'add_new' => __( 'Add New', 'suredonation' ),
84 'new_item' => __( 'New Campaign', 'suredonation' ),
85 'edit_item' => __( 'Edit Campaign', 'suredonation' ),
86 'update_item' => __( 'Update Campaign', 'suredonation' ),
87 'view_item' => __( 'View Campaign', 'suredonation' ),
88 'view_items' => __( 'View Campaigns', 'suredonation' ),
89 'search_items' => __( 'Search Campaign', 'suredonation' ),
90 'not_found' => __( 'Not found', 'suredonation' ),
91 'not_found_in_trash' => __( 'Not found in Trash', 'suredonation' ),
92 'featured_image' => __( 'Campaign Image', 'suredonation' ),
93 'set_featured_image' => __( 'Set campaign image', 'suredonation' ),
94 'remove_featured_image' => __( 'Remove campaign image', 'suredonation' ),
95 'use_featured_image' => __( 'Use as campaign image', 'suredonation' ),
96 'insert_into_item' => __( 'Insert into campaign', 'suredonation' ),
97 'uploaded_to_this_item' => __( 'Uploaded to this campaign', 'suredonation' ),
98 'items_list' => __( 'Campaigns list', 'suredonation' ),
99 'items_list_navigation' => __( 'Campaigns list navigation', 'suredonation' ),
100 'filter_items_list' => __( 'Filter campaigns list', 'suredonation' ),
101 ];
102
103 $args = [
104 'label' => __( 'Campaign', 'suredonation' ),
105 'description' => __( 'Fundraising Campaigns', 'suredonation' ),
106 'labels' => $labels,
107 'supports' => [ 'title', 'editor', 'thumbnail', 'excerpt', 'custom-fields' ],
108 'hierarchical' => false,
109 'public' => true,
110 'show_ui' => true,
111 'show_in_menu' => false, // We'll add it to custom menu.
112 'menu_position' => 25,
113 'menu_icon' => 'dashicons-heart',
114 'show_in_admin_bar' => true,
115 'show_in_nav_menus' => true,
116 'can_export' => true,
117 'has_archive' => true,
118 'exclude_from_search' => false,
119 'publicly_queryable' => true,
120 'capability_type' => 'post',
121 'show_in_rest' => true,
122 'rewrite' => [
123 'slug' => 'suredonation-campaigns',
124 'with_front' => false,
125 ],
126 ];
127
128 register_post_type( self::POST_TYPE, $args );
129 }
130
131 /**
132 * Get the admin URL that opens the campaign creation drawer.
133 *
134 * Campaigns are created through the drawer in the SureDonation app — that
135 * is where the goal, currency and default form are set — so every "create a
136 * campaign" entry point resolves here instead of the bare block editor.
137 * Centralized so the admin bar and the post-new.php redirect cannot drift
138 * apart. The `action` param is consumed and cleared by the Campaigns page.
139 *
140 * @return string The admin URL for creating a campaign.
141 * @since 1.5.0
142 */
143 public static function get_create_url() {
144 return admin_url( 'admin.php?page=suredonation#/campaigns?action=new' );
145 }
146
147 /**
148 * Register campaign meta for the campaign post type.
149 *
150 * @return void
151 * @since 0.0.1
152 */
153 public function register_campaign_meta() {
154 register_post_meta(
155 self::POST_TYPE,
156 Helper::SUREDONATION_CAMPAIGN_META_KEY,
157 [
158 'type' => 'string',
159 'description' => __( 'Consolidated campaign settings.', 'suredonation' ),
160 'single' => true,
161 'show_in_rest' => [
162 'schema' => [
163 'type' => 'string',
164 'context' => [ 'edit' ],
165 ],
166 ],
167 'auth_callback' => static function () {
168 return current_user_can( 'manage_options' );
169 },
170 ]
171 );
172
173 register_post_meta(
174 self::POST_TYPE,
175 self::META_TEMPLATE_ID,
176 [
177 'type' => 'string',
178 'description' => __( 'Campaign template the campaign was created from.', 'suredonation' ),
179 'single' => true,
180 'show_in_rest' => false,
181 'sanitize_callback' => 'sanitize_key',
182 'auth_callback' => static function () {
183 return current_user_can( 'manage_options' );
184 },
185 ]
186 );
187 }
188
189 /**
190 * Create a default donation form when a campaign is first published.
191 *
192 * Only creates a form if:
193 * - The campaign is being published (not draft/pending)
194 * - No default form has been created yet for this campaign
195 *
196 * @param int $post_id Post ID.
197 * @param \WP_Post $post Post object.
198 * @return void
199 * @since 0.0.1
200 */
201 public function maybe_create_default_form( $post_id, $post ) {
202 // Skip autosave.
203 if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
204 return;
205 }
206
207 // Only proceed for published campaigns.
208 if ( 'publish' !== $post->post_status ) {
209 return;
210 }
211
212 // Check if a default form already exists for this campaign.
213 $existing_form_id = get_post_meta( $post_id, self::META_DEFAULT_FORM_ID, true );
214 if ( ! empty( $existing_form_id ) ) {
215 $existing_form_id = absint( Helper::get_string_value( $existing_form_id ) );
216 if ( 0 >= $existing_form_id ) {
217 return;
218 }
219 // Verify the form still exists.
220 $existing_form = get_post( $existing_form_id );
221 if ( $existing_form instanceof \WP_Post && Donation_Form::POST_TYPE === $existing_form->post_type ) {
222 return; // Form already exists, don't create another.
223 }
224 }
225
226 // Resolve the campaign template (falling back to `general`) and build its
227 // form markup. `general` delegates to the standard default form, so the
228 // scratch path is unchanged.
229 $registry = Campaign_Templates::get_instance();
230 $template = $registry->get( Helper::get_string_value( get_post_meta( $post_id, self::META_TEMPLATE_ID, true ) ) )
231 ?? $registry->get( Campaign_Templates::GENERAL );
232 $form_blocks = ( $template && isset( $template['get_form_blocks'] ) && is_callable( $template['get_form_blocks'] ) )
233 ? ( $template['get_form_blocks'] )()
234 : null;
235
236 // Create the default form.
237 $form_id = Donation_Form::create_default_form_for_campaign( $post_id, $post->post_title, $form_blocks );
238
239 if ( $form_id ) {
240 // Store the form ID in campaign meta.
241 update_post_meta( $post_id, self::META_DEFAULT_FORM_ID, $form_id );
242 }
243 }
244
245 /**
246 * Get the default form ID for a campaign.
247 *
248 * @param int $campaign_id Campaign ID.
249 * @return int Form ID or 0 if not found.
250 * @since 0.0.1
251 */
252 public static function get_default_form_id( $campaign_id ) {
253 return absint( Helper::get_string_value( get_post_meta( $campaign_id, self::META_DEFAULT_FORM_ID, true ) ) );
254 }
255 }
256