| 1 |
<?php |
| 2 |
|
| 3 |
namespace Give\ThirdPartySupport\Elementor\Actions; |
| 4 |
|
| 5 |
use Give\Campaigns\Models\Campaign; |
| 6 |
use Give\Campaigns\Models\CampaignPage; |
| 7 |
use Give\ThirdPartySupport\Elementor\Widgets\V2\ElementorCampaignDonationsWidget\ElementorCampaignDonationsWidget; |
| 8 |
use Give\ThirdPartySupport\Elementor\Widgets\V2\ElementorCampaignDonorsWidget\ElementorCampaignDonorsWidget; |
| 9 |
use Give\ThirdPartySupport\Elementor\Widgets\V2\ElementorCampaignGoalWidget\ElementorCampaignGoalWidget; |
| 10 |
use Give\ThirdPartySupport\Elementor\Widgets\V2\ElementorDonationFormWidget\ElementorDonationFormWidget; |
| 11 |
use Give\ThirdPartySupport\Elementor\Widgets\V2\ElementorCampaignStatsWidget\ElementorCampaignStatsWidget; |
| 12 |
|
| 13 |
/** |
| 14 |
* Automatically setup Elementor template data for campaign pages |
| 15 |
* |
| 16 |
* This class automatically populates campaign pages with our custom Elementor |
| 17 |
* template layout when Elementor is active, providing a seamless experience |
| 18 |
* for users creating campaign pages. |
| 19 |
* |
| 20 |
* @since 4.7.0 |
| 21 |
*/ |
| 22 |
class SetupElementorCampaignTemplate |
| 23 |
{ |
| 24 |
/** |
| 25 |
* Setup Elementor template data for campaign page |
| 26 |
* |
| 27 |
* @since 4.7.0 |
| 28 |
*/ |
| 29 |
public function __invoke(CampaignPage $campaignPage): void |
| 30 |
{ |
| 31 |
// Allow users to disable auto-setup via filter |
| 32 |
if (!apply_filters('givewp_auto_setup_elementor_campaign_template', true)) { |
| 33 |
return; |
| 34 |
} |
| 35 |
|
| 36 |
// Only proceed if Elementor is active |
| 37 |
if (!$this->isElementorActive()) { |
| 38 |
return; |
| 39 |
} |
| 40 |
|
| 41 |
// Only setup for new campaign pages that don't already have Elementor data |
| 42 |
if ($this->campaignPageHasElementorData($campaignPage->id)) { |
| 43 |
return; |
| 44 |
} |
| 45 |
|
| 46 |
$campaign = $campaignPage->campaign(); |
| 47 |
if (!$campaign) { |
| 48 |
return; |
| 49 |
} |
| 50 |
|
| 51 |
$this->setupElementorData($campaignPage->id, $campaign->id, $campaign->shortDescription); |
| 52 |
} |
| 53 |
|
| 54 |
/** |
| 55 |
* Check if Elementor is active and available |
| 56 |
* |
| 57 |
* @since 4.7.0 |
| 58 |
*/ |
| 59 |
private function isElementorActive(): bool |
| 60 |
{ |
| 61 |
return class_exists('\Elementor\Plugin') && defined('ELEMENTOR_VERSION'); |
| 62 |
} |
| 63 |
|
| 64 |
/** |
| 65 |
* Check if campaign page already has Elementor data |
| 66 |
* |
| 67 |
* @since 4.7.0 |
| 68 |
*/ |
| 69 |
private function campaignPageHasElementorData(int $pageId): bool |
| 70 |
{ |
| 71 |
$elementorData = get_post_meta($pageId, '_elementor_data', true); |
| 72 |
return !empty($elementorData) && $elementorData !== '[]'; |
| 73 |
} |
| 74 |
|
| 75 |
/** |
| 76 |
* Setup Elementor data and meta keys for the campaign page |
| 77 |
* |
| 78 |
* @since 4.7.0 |
| 79 |
*/ |
| 80 |
private function setupElementorData(int $pageId, int $campaignId, string $shortDescription): void |
| 81 |
{ |
| 82 |
// Get the template data structure |
| 83 |
$templateData = $this->getElementorTemplateData($campaignId, $shortDescription); |
| 84 |
|
| 85 |
// Convert to JSON and add proper slashing for WordPress |
| 86 |
$jsonData = wp_slash(wp_json_encode($templateData)); |
| 87 |
|
| 88 |
// Set the main Elementor data |
| 89 |
update_post_meta($pageId, '_elementor_data', $jsonData); |
| 90 |
|
| 91 |
// Set Elementor edit mode to enable editing |
| 92 |
update_post_meta($pageId, '_elementor_edit_mode', 'builder'); |
| 93 |
|
| 94 |
// Set template type |
| 95 |
update_post_meta($pageId, '_elementor_template_type', 'page'); |
| 96 |
|
| 97 |
// Set Elementor version |
| 98 |
if (defined('ELEMENTOR_VERSION')) { |
| 99 |
update_post_meta($pageId, '_elementor_version', ELEMENTOR_VERSION); |
| 100 |
} |
| 101 |
|
| 102 |
// Add our custom meta to track this as an auto-generated template |
| 103 |
update_post_meta($pageId, '_givewp_elementor_auto_template', true); |
| 104 |
update_post_meta($pageId, '_givewp_elementor_template_version', '1.0.0'); |
| 105 |
} |
| 106 |
|
| 107 |
/** |
| 108 |
* Get Elementor template data structure |
| 109 |
* |
| 110 |
* @since 4.7.0 |
| 111 |
* @return array |
| 112 |
*/ |
| 113 |
private function getElementorTemplateData(int $campaignId, string $shortDescription): array |
| 114 |
{ |
| 115 |
$campaign = Campaign::find($campaignId); |
| 116 |
if (!$campaign) { |
| 117 |
return []; |
| 118 |
} |
| 119 |
|
| 120 |
$campaignDefaultFormId = $campaign->defaultFormId; |
| 121 |
$campaignImageUrl = $campaign->image; |
| 122 |
$campaignImageId = null; |
| 123 |
if ($campaign->image && $imageId = attachment_url_to_postid($campaign->image)) { |
| 124 |
$campaignImageId = $imageId; |
| 125 |
} |
| 126 |
|
| 127 |
return [ |
| 128 |
[ |
| 129 |
'id' => $this->generateElementorId(), |
| 130 |
'elType' => 'section', |
| 131 |
'settings' => [ |
| 132 |
'layout' => 'boxed', |
| 133 |
'gap' => 'default', |
| 134 |
'content_width' => [ |
| 135 |
'unit' => '%', |
| 136 |
'size' => 100 |
| 137 |
], |
| 138 |
'margin' => [ |
| 139 |
'unit' => 'px', |
| 140 |
'top' => '0', |
| 141 |
'right' => '0', |
| 142 |
'bottom' => '40', |
| 143 |
'left' => '0' |
| 144 |
] |
| 145 |
], |
| 146 |
'elements' => [ |
| 147 |
// Left Column (60% - Post Featured Image) |
| 148 |
[ |
| 149 |
'id' => $this->generateElementorId(), |
| 150 |
'elType' => 'column', |
| 151 |
'settings' => [ |
| 152 |
'_column_size' => 60, |
| 153 |
'space_between_widgets' => '0' |
| 154 |
], |
| 155 |
'elements' => [ |
| 156 |
[ |
| 157 |
'id' => $this->generateElementorId(), |
| 158 |
'elType' => 'widget', |
| 159 |
'widgetType' => 'image', |
| 160 |
'settings' => [ |
| 161 |
'image' => [ |
| 162 |
'id' => $campaignImageId, |
| 163 |
'url' => $campaignImageUrl |
| 164 |
], |
| 165 |
'image_size' => 'full', |
| 166 |
'width' => [ |
| 167 |
'unit' => '%', |
| 168 |
'size' => 100 |
| 169 |
], |
| 170 |
'height' => [ |
| 171 |
'unit' => '%', |
| 172 |
'size' => 100 |
| 173 |
], |
| 174 |
'object-fit' => 'cover', |
| 175 |
'image_border_border' => 'default', |
| 176 |
'image_border_radius' => [ |
| 177 |
'unit' => 'px', |
| 178 |
'top' => 8, |
| 179 |
'right' => 8, |
| 180 |
'bottom' => 8, |
| 181 |
'left' => 8, |
| 182 |
'isLinked' => true |
| 183 |
], |
| 184 |
'height_inner' => [ |
| 185 |
'unit' => 'px', |
| 186 |
'size' => 0 |
| 187 |
], |
| 188 |
'aspect_ratio' => '16:9' |
| 189 |
] |
| 190 |
] |
| 191 |
] |
| 192 |
], |
| 193 |
// Right Column (40% - Goal, Stats, Donate Button) |
| 194 |
[ |
| 195 |
'id' => $this->generateElementorId(), |
| 196 |
'elType' => 'column', |
| 197 |
'settings' => [ |
| 198 |
'_column_size' => 40, |
| 199 |
'space_between_widgets' => '20' |
| 200 |
], |
| 201 |
'elements' => [ |
| 202 |
// Campaign Goal |
| 203 |
[ |
| 204 |
'id' => $this->generateElementorId(), |
| 205 |
'elType' => 'widget', |
| 206 |
'widgetType' => give(ElementorCampaignGoalWidget::class)->get_name(), |
| 207 |
'settings' => [ |
| 208 |
'campaign_id' => $campaignId |
| 209 |
] |
| 210 |
], |
| 211 |
// Campaign Stats |
| 212 |
[ |
| 213 |
'id' => $this->generateElementorId(), |
| 214 |
'elType' => 'widget', |
| 215 |
'widgetType' => give(ElementorCampaignStatsWidget::class)->get_name(), |
| 216 |
'settings' => [ |
| 217 |
'campaign_id' => $campaignId, |
| 218 |
'statistic' => 'top-donation' |
| 219 |
] |
| 220 |
], |
| 221 |
[ |
| 222 |
'id' => $this->generateElementorId(), |
| 223 |
'elType' => 'widget', |
| 224 |
'widgetType' => give(ElementorCampaignStatsWidget::class)->get_name(), |
| 225 |
'settings' => [ |
| 226 |
'campaign_id' => $campaignId, |
| 227 |
'statistic' => 'average-donation' |
| 228 |
] |
| 229 |
], |
| 230 |
// Donate Button |
| 231 |
[ |
| 232 |
'id' => $this->generateElementorId(), |
| 233 |
'elType' => 'widget', |
| 234 |
'widgetType' => give(ElementorDonationFormWidget::class)->get_name(), |
| 235 |
'settings' => [ |
| 236 |
'form_id' => $campaignDefaultFormId, |
| 237 |
'display_style' => 'modal' |
| 238 |
] |
| 239 |
] |
| 240 |
] |
| 241 |
] |
| 242 |
] |
| 243 |
], |
| 244 |
// Description Section |
| 245 |
[ |
| 246 |
'id' => $this->generateElementorId(), |
| 247 |
'elType' => 'section', |
| 248 |
'settings' => [ |
| 249 |
'layout' => 'boxed', |
| 250 |
'margin' => [ |
| 251 |
'unit' => 'px', |
| 252 |
'top' => '40', |
| 253 |
'bottom' => '40' |
| 254 |
] |
| 255 |
], |
| 256 |
'elements' => [ |
| 257 |
[ |
| 258 |
'id' => $this->generateElementorId(), |
| 259 |
'elType' => 'column', |
| 260 |
'settings' => [ |
| 261 |
'_column_size' => 100 |
| 262 |
], |
| 263 |
'elements' => [ |
| 264 |
[ |
| 265 |
'id' => $this->generateElementorId(), |
| 266 |
'elType' => 'widget', |
| 267 |
'widgetType' => 'text-editor', |
| 268 |
'settings' => [ |
| 269 |
'editor' => $shortDescription ?: '' |
| 270 |
] |
| 271 |
] |
| 272 |
] |
| 273 |
] |
| 274 |
] |
| 275 |
], |
| 276 |
// Donations Section |
| 277 |
[ |
| 278 |
'id' => $this->generateElementorId(), |
| 279 |
'elType' => 'section', |
| 280 |
'settings' => [ |
| 281 |
'layout' => 'boxed', |
| 282 |
'margin' => [ |
| 283 |
'unit' => 'px', |
| 284 |
'bottom' => '40' |
| 285 |
] |
| 286 |
], |
| 287 |
'elements' => [ |
| 288 |
[ |
| 289 |
'id' => $this->generateElementorId(), |
| 290 |
'elType' => 'column', |
| 291 |
'settings' => [ |
| 292 |
'_column_size' => 100 |
| 293 |
], |
| 294 |
'elements' => [ |
| 295 |
[ |
| 296 |
'id' => $this->generateElementorId(), |
| 297 |
'elType' => 'widget', |
| 298 |
'widgetType' => give(ElementorCampaignDonationsWidget::class)->get_name(), |
| 299 |
'settings' => [ |
| 300 |
'campaign_id' => $campaignId, |
| 301 |
'show_anonymous' => 'yes', |
| 302 |
'show_icon' => 'yes', |
| 303 |
'show_button' => 'yes', |
| 304 |
'donate_button_text' => 'Donate', |
| 305 |
'sort_by' => 'recent-donations', |
| 306 |
'donations_per_page' => 5, |
| 307 |
'load_more_button_text' => 'Load more' |
| 308 |
] |
| 309 |
] |
| 310 |
] |
| 311 |
] |
| 312 |
] |
| 313 |
], |
| 314 |
// Donors Section |
| 315 |
[ |
| 316 |
'id' => $this->generateElementorId(), |
| 317 |
'elType' => 'section', |
| 318 |
'settings' => [ |
| 319 |
'layout' => 'boxed' |
| 320 |
], |
| 321 |
'elements' => [ |
| 322 |
[ |
| 323 |
'id' => $this->generateElementorId(), |
| 324 |
'elType' => 'column', |
| 325 |
'settings' => [ |
| 326 |
'_column_size' => 100 |
| 327 |
], |
| 328 |
'elements' => [ |
| 329 |
[ |
| 330 |
'id' => $this->generateElementorId(), |
| 331 |
'elType' => 'widget', |
| 332 |
'widgetType' => give(ElementorCampaignDonorsWidget::class)->get_name(), |
| 333 |
'settings' => [ |
| 334 |
'campaign_id' => $campaignId, |
| 335 |
'show_anonymous' => 'yes', |
| 336 |
'show_company_name' => 'yes', |
| 337 |
'show_avatar' => 'yes', |
| 338 |
'show_button' => 'yes', |
| 339 |
'donate_button_text' => 'Join the list', |
| 340 |
'sort_by' => 'top-donors', |
| 341 |
'donors_per_page' => 5, |
| 342 |
'load_more_button_text' => 'Load more' |
| 343 |
] |
| 344 |
] |
| 345 |
] |
| 346 |
] |
| 347 |
] |
| 348 |
] |
| 349 |
]; |
| 350 |
} |
| 351 |
|
| 352 |
/** |
| 353 |
* Generate a random Elementor-style ID |
| 354 |
* |
| 355 |
* @since 4.7.0 |
| 356 |
*/ |
| 357 |
private function generateElementorId(): string |
| 358 |
{ |
| 359 |
return substr(md5(uniqid('', true)), 0, 7); |
| 360 |
} |
| 361 |
} |
| 362 |
|