PluginProbe
Easy Invoice – Invoice Generator, PDF Quotes & Payments / 2.4.0
Easy Invoice – Invoice Generator, PDF Quotes & Payments v2.4.0
2.4.0 2.4.1 2.3.8 2.3.7 2.3.6 2.3.5 2.3.4 2.3.3 2.3.2 2.3.1 2.2.0 2.1.21 2.1.20 2.1.19 2.1.18 2.1.0 2.1.1 2.1.10 2.1.11 2.1.12 2.1.13 2.1.14 2.1.15 2.1.16 2.1.2 All 57 releases
easy-invoice / includes / Services / PromotionService.php

PromotionService.php in Easy Invoice – Invoice Generator, PDF Quotes & Payments 2.4.0, at includes/Services/PromotionService.php

387 lines 16.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Promotion Service
4 *
5 * @package EasyInvoice
6 * @subpackage Services
7 */
8
9 namespace EasyInvoice\Services;
10
11 /**
12 * PromotionService Class
13 *
14 * Handles promotional banner display logic for Easy Invoice Pro upgrades
15 */
16 class PromotionService {
17
18 /**
19 * Promotion banner dismissed option key
20 */
21 const DISMISSED_OPTION = 'easy_invoice_promotion_dismissed';
22
23 /**
24 * Promotion banner last shown timestamp option key
25 */
26 const LAST_SHOWN_OPTION = 'easy_invoice_promotion_last_shown';
27
28 /**
29 * Promotion banner permanently hidden option key
30 */
31 const PERMANENTLY_HIDDEN_OPTION = 'easy_invoice_promotion_permanently_hidden';
32
33 /**
34 * Minimum invoices required to show promotion
35 */
36 const MIN_INVOICES = 1;
37
38 /**
39 * Days to wait before showing again if dismissed once
40 */
41 const RESHOW_AFTER_DAYS = 15;
42
43 /**
44 * Easy Invoice Pro pricing URL
45 */
46 const PRO_PRICING_URL = 'https://matrixaddons.com/plugins/easy-invoice#pricing';
47
48 /**
49 * Initialize the promotion service
50 */
51 public static function init() {
52 // Gate every promotion surface behind `easy_invoice_show_upgrade_prompts`.
53 // White-label addon (Agency tier) flips this off so end-clients never see upsells.
54 if (!apply_filters('easy_invoice_show_upgrade_prompts', true)) {
55 return;
56 }
57
58 add_action('admin_notices', [__CLASS__, 'maybeShowPromotionBanner']);
59 add_action('wp_ajax_easy_invoice_dismiss_promotion', [__CLASS__, 'handleDismissPromotion']);
60 add_action('admin_enqueue_scripts', [__CLASS__, 'enqueueScripts']);
61 add_action('admin_menu', [__CLASS__, 'addUpgradeToProMenu']);
62
63 // Add plugin row action
64 add_filter('plugin_action_links_' . plugin_basename(EASY_INVOICE_PLUGIN_FILE), [__CLASS__, 'addPluginRowAction']);
65 }
66
67 /**
68 * Enqueue admin scripts for promotion functionality
69 */
70 public static function enqueueScripts() {
71 wp_enqueue_script('easy-invoice-promotion', EASY_INVOICE_PLUGIN_URL . 'assets/js/promotion.js', ['jquery'], EASY_INVOICE_VERSION, true);
72 wp_localize_script('easy-invoice-promotion', 'easyInvoicePromotion', [
73 'ajaxUrl' => admin_url('admin-ajax.php'),
74 'nonce' => wp_create_nonce('easy_invoice_promotion_nonce')
75 ]);
76
77 // Add plain text CSS for plugin row action
78 wp_add_inline_style('easy-invoice-promotion', '
79 .plugin-action-links a[href*="easy-invoice#pricing"] {
80 color: #ff9500 !important;
81 font-weight: 600 !important;
82 text-decoration: none !important;
83 font-size: 12px !important;
84 transition: all 0.3s ease !important;
85 }
86
87 .plugin-action-links a[href*="easy-invoice#pricing"]:hover {
88 color: #e67e00 !important;
89 text-decoration: underline !important;
90 }
91 ');
92 }
93
94 /**
95 * Check if Easy Invoice Pro is active
96 */
97 public static function isProActive() {
98 if (!function_exists('is_plugin_active')) {
99 require_once ABSPATH . 'wp-admin/includes/plugin.php';
100 }
101 return is_plugin_active('easy-invoice-pro/easy-invoice-pro.php');
102 }
103
104 /**
105 * Get the count of invoices created by the user
106 */
107 public static function getInvoiceCount() {
108 $args = [
109 'post_type' => 'easy_invoice',
110 'post_status' => ['publish', 'draft', 'pending'],
111 'posts_per_page' => -1,
112 'fields' => 'ids'
113 ];
114
115 $query = new \WP_Query($args);
116 return $query->found_posts;
117 }
118
119 /**
120 * Check if promotion should be shown
121 */
122 public static function shouldShowPromotion() {
123 // Don't show if Pro is active
124 if (self::isProActive()) {
125 return false;
126 }
127
128 // Don't show if permanently hidden
129 if (get_option(self::PERMANENTLY_HIDDEN_OPTION)) {
130 return false;
131 }
132
133 // Check if user has created enough invoices
134 $invoice_count = self::getInvoiceCount();
135 if ($invoice_count < self::MIN_INVOICES) {
136 return false;
137 }
138
139 // Check if banner was dismissed
140 $dismissed = get_option(self::DISMISSED_OPTION);
141 if ($dismissed) {
142 // Check if enough time has passed to show again
143 $last_shown = get_option(self::LAST_SHOWN_OPTION);
144 if ($last_shown) {
145 $days_since_shown = (current_time('timestamp') - strtotime($last_shown)) / DAY_IN_SECONDS;
146 if ($days_since_shown < self::RESHOW_AFTER_DAYS) {
147 return false;
148 }
149 }
150 }
151
152 return true;
153 }
154
155 /**
156 * Display the promotion banner if conditions are met
157 */
158 public static function maybeShowPromotionBanner() {
159 if (!self::shouldShowPromotion()) {
160 return;
161 }
162
163 // Update last shown timestamp
164 update_option(self::LAST_SHOWN_OPTION, current_time('mysql'));
165
166 $invoice_count = self::getInvoiceCount();
167 ?>
168 <div id="easy-invoice-promotion-notice" class="notice is-dismissible" style="background: linear-gradient(135deg, #fdf6f0 0%, #f8f9fa 50%, #fff5ee 100%); border: 1px solid #f0e6d8; border-left: 4px solid #ff9500; border-radius: 6px; margin: 15px 0; box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08); position: relative;">
169 <div style="position: absolute; top: 8px; right: 80px; background: #ff9500; color: white; padding: 2px 8px; border-radius: 10px; font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.3px;">
170 Limited Time
171 </div>
172 <div class="easy-invoice-promotion-content" style="padding: 18px;">
173 <div style="display: flex; align-items: flex-start; gap: 15px;">
174 <div style="flex: 1;">
175 <h3 style="margin: 0 0 10px 0; color: #2c3e50; font-size: 17px; font-weight: 600;">
176 🚀 Upgrade to Easy Invoice Pro - Save 20%!
177 </h3>
178 <p style="margin: 0 0 12px 0; font-size: 14px; line-height: 1.5; color: #495057;">
179 You've created <strong style="color: #ff9500;"><?php echo esc_html($invoice_count); ?></strong> invoice(s)!
180 Get <strong style="color: #ff9500;">20% OFF</strong> on Easy Invoice Pro. Unlock recurring invoices, advanced reporting, multiple payment gateways, and priority support.
181 </p>
182 <div style="background: rgba(255, 149, 0, 0.08); padding: 10px; border-radius: 4px; margin-bottom: 15px; border-left: 3px solid #ff9500;">
183 <p style="margin: 0; font-size: 13px; color: #495057; font-weight: 600;">
184 🎉 <strong>Special Offer:</strong> Save 20% on your Pro upgrade with advanced features and priority support!
185 </p>
186 </div>
187 <div style="display: flex; align-items: center; gap: 12px;">
188 <a href="<?php echo esc_url(self::PRO_PRICING_URL); ?>"
189 target="_blank"
190 class="button button-primary"
191 style="background-color: #ff9500; border-color: #ff9500; color: white; padding: 8px 20px; font-weight: 600; font-size: 14px; border-radius: 4px; text-decoration: none; box-shadow: 0 2px 6px rgba(255, 149, 0, 0.3); transition: all 0.3s ease;">
192 ⚡ Save 20% - Upgrade to Pro
193 </a>
194 <a href="#"
195 id="easy-invoice-promotion-dismiss"
196 style="color: #6c757d; text-decoration: none; font-size: 13px; transition: color 0.3s ease;">
197 Maybe later
198 </a>
199 </div>
200 </div>
201 </div>
202 </div>
203 </div>
204
205 <style>
206 #easy-invoice-promotion-notice .button:hover {
207 background-color: #e67e00 !important;
208 border-color: #e67e00 !important;
209 transform: translateY(-1px);
210 box-shadow: 0 4px 10px rgba(255, 149, 0, 0.4) !important;
211 }
212
213 #easy-invoice-promotion-dismiss:hover {
214 color: #495057 !important;
215 }
216
217 @media (max-width: 768px) {
218 #easy-invoice-promotion-notice .easy-invoice-promotion-content {
219 padding: 15px !important;
220 }
221 #easy-invoice-promotion-notice .easy-invoice-promotion-content > div {
222 flex-direction: column !important;
223 align-items: flex-start !important;
224 }
225 #easy-invoice-promotion-notice .button {
226 width: 100% !important;
227 text-align: center !important;
228 }
229 }
230 </style>
231 <?php
232 }
233
234 /**
235 * Handle AJAX request to dismiss promotion
236 */
237 public static function handleDismissPromotion() {
238 check_ajax_referer('easy_invoice_promotion_nonce', 'nonce');
239
240 if (!current_user_can('manage_options')) {
241 wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'easy-invoice'));
242 }
243
244 $dismiss_count = get_option('easy_invoice_promotion_dismiss_count', 0);
245 $dismiss_count++;
246
247 update_option('easy_invoice_promotion_dismiss_count', $dismiss_count);
248 update_option(self::DISMISSED_OPTION, true);
249
250 // If dismissed more than once, hide permanently
251 if ($dismiss_count >= 2) {
252 update_option(self::PERMANENTLY_HIDDEN_OPTION, true);
253 }
254
255 wp_send_json_success();
256 }
257
258 /**
259 * Add "Upgrade to Pro" action in plugin row
260 */
261 public static function addPluginRowAction($links) {
262 // Don't show if Pro is active
263 if (self::isProActive()) {
264 return $links;
265 }
266
267 $upgrade_link = sprintf(
268 '<a href="%s" target="_blank" style="color: #ff9500; font-weight: 600; text-decoration: none; font-size: 12px; transition: all 0.3s ease;">%s</a>',
269 esc_url(self::PRO_PRICING_URL),
270 __('Upgrade to Pro', 'easy-invoice')
271 );
272
273 // Add to the beginning of the links array
274 array_unshift($links, $upgrade_link);
275
276 return $links;
277 }
278
279 /**
280 * Add "Upgrade to Pro" menu item to main admin menu
281 */
282 public static function addUpgradeToProMenu() {
283 // Only show if Pro is not active
284 if (self::isProActive()) {
285 return;
286 }
287
288 global $submenu;
289
290 // Add the submenu item directly to the submenu array
291 $submenu['easy-invoice'][] = array(
292 __('Upgrade to Pro', 'easy-invoice'),
293 'manage_options',
294 self::PRO_PRICING_URL,
295 __('Upgrade to Pro', 'easy-invoice'),
296 999
297 );
298
299 // Add inline style to the submenu
300 add_action('admin_head', function() {
301 ?>
302 <style>
303 .wp-submenu a[href*="matrixaddons.com"] {
304 color: #fff !important;
305 font-weight: 700 !important;
306 background: linear-gradient(45deg, #ff6b35, #ff9500) !important;
307 border-radius: 4px !important;
308 margin: 2px 8px 2px 0 !important;
309 transition: all 0.3s ease !important;
310 text-shadow: 0 1px 2px rgba(0,0,0,0.2) !important;
311 box-shadow: 0 2px 6px rgba(255, 107, 53, 0.3) !important;
312 display: inline-block !important;
313 padding: 6px 12px !important;
314 }
315
316 .wp-submenu a[href*="matrixaddons.com"]:hover {
317 background: linear-gradient(45deg, #e55a2b, #e67e00) !important;
318 transform: translateX(2px) !important;
319 box-shadow: 0 4px 12px rgba(255, 107, 53, 0.5) !important;
320 }
321 </style>
322 <?php
323 });
324 }
325
326 /**
327 * Display the Upgrade to Pro page
328 */
329 public static function displayUpgradeToProPage() {
330 ?>
331 <div class="wrap">
332 <h1 style="color: #ff9500; margin-bottom: 20px;">
333 🚀 Upgrade to Easy Invoice Pro
334 </h1>
335
336 <div style="background: linear-gradient(135deg, #fdf6f0 0%, #f8f9fa 50%, #fff5ee 100%); border: 1px solid #f0e6d8; border-left: 4px solid #ff9500; border-radius: 6px; padding: 25px; margin-bottom: 25px; box-shadow: 0 2px 8px rgba(255, 149, 0, 0.15);">
337 <h2 style="color: #2c3e50; margin-bottom: 15px;">Get 20% OFF Your Pro Upgrade!</h2>
338 <p style="font-size: 16px; line-height: 1.6; color: #495057; margin-bottom: 20px;">
339 Unlock powerful features including recurring invoices, advanced reporting, multiple payment gateways, and priority support.
340 </p>
341
342 <div style="background: rgba(255, 149, 0, 0.08); padding: 15px; border-radius: 4px; margin-bottom: 20px; border-left: 3px solid #ff9500;">
343 <p style="margin: 0; font-size: 14px; color: #495057; font-weight: 600;">
344 🎉 <strong>Special Offer:</strong> Save 20% on your Pro upgrade with advanced features and priority support!
345 </p>
346 </div>
347
348 <div style="text-align: center; margin: 30px 0;">
349 <a href="<?php echo esc_url(self::PRO_PRICING_URL); ?>"
350 target="_blank"
351 class="button button-primary"
352 style="background: linear-gradient(45deg, #ff9500, #ffaa00); border: none; color: white; padding: 12px 30px; font-weight: 700; font-size: 16px; border-radius: 6px; text-decoration: none; box-shadow: 0 3px 10px rgba(255, 149, 0, 0.4); transition: all 0.3s ease;">
353 Save 20% - Upgrade to Pro Now
354 </a>
355 </div>
356 </div>
357
358 <div style="background: white; border: 1px solid #e1e5e9; border-radius: 6px; padding: 25px;">
359 <h3 style="color: #2c3e50; margin-bottom: 15px;">Why Upgrade to Pro?</h3>
360 <ul style="list-style: none; padding: 0;">
361 <li style="margin-bottom: 12px; padding-left: 25px; position: relative;">
362 <span style="position: absolute; left: 0; color: #28a745;"></span>
363 <strong>Recurring Invoices</strong> - Set up automatic recurring billing
364 </li>
365 <li style="margin-bottom: 12px; padding-left: 25px; position: relative;">
366 <span style="position: absolute; left: 0; color: #28a745;"></span>
367 <strong>Advanced Reporting</strong> - Detailed financial reports and analytics
368 </li>
369 <li style="margin-bottom: 12px; padding-left: 25px; position: relative;">
370 <span style="position: absolute; left: 0; color: #28a745;"></span>
371 <strong>Multiple Payment Gateways</strong> - Stripe, PayPal, and more
372 </li>
373 <li style="margin-bottom: 12px; padding-left: 25px; position: relative;">
374 <span style="position: absolute; left: 0; color: #28a745;"></span>
375 <strong>Invoice & Quote Builder</strong> - Advanced drag-and-drop builder
376 </li>
377 <li style="margin-bottom: 12px; padding-left: 25px; position: relative;">
378 <span style="position: absolute; left: 0; color: #28a745;"></span>
379 <strong>Priority Support</strong> - Faster response times for help
380 </li>
381 </ul>
382 </div>
383 </div>
384 <?php
385 }
386 }
387