PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.6.4
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.6.4
1.6.4 1.6.3 1.6.2 1.6.1 1.6.0 1.5.4 1.5.5 1.5.3 1.5.2 1.5.1 1.5.0 1.4.2 1.4.1 1.4.0 1.3.28 1.3.27 1.3.26 1.3.25 1.3.23 1.3.22 1.3.21 1.3.20 1.3.19 trunk 1.2.0 All 47 releases
fluent-cart / app / Modules / PaymentMethods / PromoGateways / Addons / AddonGatewaySettings.php

AddonGatewaySettings.php in FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler 1.6.4, at app/Modules/PaymentMethods/PromoGateways/Addons/AddonGatewaySettings.php

342 lines 15.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentCart\App\Modules\PaymentMethods\PromoGateways\Addons;
4
5 use FluentCart\App\Helpers\Helper;
6 use FluentCart\App\Modules\PaymentMethods\Core\BaseGatewaySettings;
7 use FluentCart\App\Services\PluginInstaller\PaymentAddonManager;
8 use FluentCart\Framework\Support\Arr;
9
10 class AddonGatewaySettings extends BaseGatewaySettings
11 {
12 protected $gatewaySlug;
13 protected $customStyles = [];
14
15 public function __construct($gatewaySlug, $methodHandler = 'fluent_cart_payment_settings_addon_gateway')
16 {
17 $this->gatewaySlug = $gatewaySlug;
18 $this->methodHandler = $methodHandler;
19 parent::__construct();
20 }
21
22
23 public function setCustomStyles($styles)
24 {
25 $this->customStyles = $styles;
26 }
27
28 public static function getDefaults()
29 {
30 return [
31 'is_active' => 'no'
32 ];
33 }
34
35 public function get($key = null)
36 {
37 if ($key === 'is_active') {
38 return 'no';
39 }
40
41 if ($key) {
42 return isset($this->settings[$key]) ? $this->settings[$key] : null;
43 }
44
45 return $this->settings;
46 }
47
48 /**
49 * Validate addon configuration
50 *
51 * @param array $config
52 * @return array|\WP_Error
53 */
54 public function validateAddonConfig($config)
55 {
56 $requiredKeys = ['title', 'description', 'addon_slug', 'addon_file', 'addon_source'];
57
58 foreach ($requiredKeys as $key) {
59 if (empty($config[$key])) {
60 return new \WP_Error(
61 'missing_config',
62 sprintf(__('Missing required configuration key: %s', 'fluent-cart'), $key)
63 );
64 }
65 }
66
67 // Validate addon_source structure
68 if (!is_array($config['addon_source']) || empty($config['addon_source']['type'])) {
69 return new \WP_Error(
70 'invalid_source',
71 __('Invalid addon_source configuration', 'fluent-cart')
72 );
73 }
74
75 return $config;
76 }
77
78 public function getMode()
79 {
80 return 'test';
81 }
82
83 public function isActive(): bool
84 {
85 return false;
86 }
87
88
89 protected function getAddonNoticeStyles()
90 {
91 $defaults = [
92 'light' => [
93 'primary_gradient' => 'linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%)',
94 'text_primary' => '#1e293b',
95 'text_secondary' => '#475569',
96 'text_muted' => '#64748b',
97 'icon_bg' => '#dbeafe',
98 'icon_color' => '#3b82f6',
99 'feature_icon' => '#10b981',
100 'status_warning' => '#f59e0b',
101 'status_info' => '#3b82f6',
102 'status_success' => '#10b981',
103 'button_primary_bg' => '#3b82f6',
104 'button_primary_text' => '#ffffff',
105 'button_success_bg' => '#10b981',
106 'button_success_text' => '#ffffff',
107 'border_color' => '#e2e8f0',
108 'feature_bg' => '#ffffff',
109 'status_bg' => '#ffffff'
110 ],
111 'dark' => [
112 'primary_gradient' => 'linear-gradient(135deg, #1e293b 0%, #0f172a 100%)',
113 'text_primary' => '#f1f5f9',
114 'text_secondary' => '#cbd5e1',
115 'text_muted' => '#94a3b8',
116 'icon_bg' => 'rgba(59, 130, 246, 0.15)',
117 'icon_color' => '#60a5fa',
118 'feature_icon' => '#34d399',
119 'status_warning' => '#fbbf24',
120 'status_info' => '#60a5fa',
121 'status_success' => '#34d399',
122 'button_primary_bg' => '#3b82f6',
123 'button_primary_text' => '#ffffff',
124 'button_success_bg' => '#10b981',
125 'button_success_text' => '#ffffff',
126 'border_color' => '#334155',
127 'feature_bg' => 'rgba(15, 23, 42, 0.5)',
128 'status_bg' => 'rgba(15, 23, 42, 0.5)'
129 ]
130 ];
131
132 if (!empty($this->customStyles)) {
133 $defaults['light'] = array_merge($defaults['light'], $this->customStyles['light'] ?? []);
134 $defaults['dark'] = array_merge($defaults['dark'], $this->customStyles['dark'] ?? []);
135 }
136
137 return $defaults;
138 }
139
140 protected function renderIcon($svgPath, $styles = '')
141 {
142 return '<svg style="' . $styles . '" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="' . $svgPath . '"/></svg>';
143 }
144
145
146 protected function renderFeatureItem($text, $mode = 'light')
147 {
148 $styles = $this->getAddonNoticeStyles()[$mode];
149 $checkIcon = $this->renderIcon(
150 'M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z',
151 'width: 18px; height: 18px; fill: ' . $styles['feature_icon'] . '; margin-right: 10px; flex-shrink: 0;'
152 );
153
154 return '<div style="display: flex; align-items: center; margin-bottom: 10px;">'
155 . $checkIcon
156 . '<span style="font-size: 14px; color: ' . $styles['text_secondary'] . ';">' . esc_html($text) . '</span>'
157 . '</div>';
158 }
159
160
161 protected function renderInstallButton($addonSlug, $addonFile, $addonSource, $repoLink, $mode = 'light')
162 {
163 $styles = $this->getAddonNoticeStyles()[$mode];
164 $downloadIcon = 'M13 10H18L12 16L6 10H11V3H13V10M4 19H20V12H22V20C22 20.5304 21.7893 21.0391 21.4142 21.4142C21.0391 21.7893 20.5304 22 20 22H4C3.46957 22 2.96086 21.7893 2.58579 21.4142C2.21071 21.0391 2 20.5304 2 20V12H4V19Z';
165 $buttonLabel = defined('FLUENTCART_PRO_PLUGIN_VERSION') ? __('Install & Activate', 'fluent-cart') : __('Download', 'fluent-cart');
166
167 return '<button type="button" class="fct-btn fct-btn-primary fct-install-addon-btn"
168 style="display: inline-flex; align-items: center; background: ' . $styles['button_primary_bg'] . '; color: ' . $styles['button_primary_text'] . '; padding: 10px 24px; border-radius: 6px; border: none; font-weight: 500; font-size: 14px; cursor: pointer; transition: all 0.2s; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);"
169 data-addon-slug="' . esc_attr($addonSlug) . '"
170 data-addon-file="' . esc_attr($addonFile) . '"
171 data-repo-link="' . esc_attr($repoLink) . '"
172 data-source-type="' . esc_attr(Arr::get($addonSource, 'type', 'github')) . '"
173 data-source-link="' . esc_attr($addonSource['link'] ?? '') . '">'
174 . $this->renderIcon($downloadIcon, 'width: 16px; height: 16px; margin-right: 6px; fill: ' . $styles['button_primary_text'] . ';')
175 . $buttonLabel
176 . '</button>';
177 }
178
179
180 protected function renderActivateButton($addonFile, $mode = 'light')
181 {
182 $styles = $this->getAddonNoticeStyles()[$mode];
183 $checkIcon = 'M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z';
184
185 return '<button type="button" class="fct-btn fct-btn-success fct-activate-addon-btn"
186 style="display: inline-flex; align-items: center; background: ' . $styles['button_success_bg'] . '; color: ' . $styles['button_success_text'] . '; padding: 10px 24px; border-radius: 6px; border: none; font-weight: 500; font-size: 14px; cursor: pointer; transition: all 0.2s; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);"
187 data-addon-file="' . esc_attr($addonFile) . '">'
188 . $this->renderIcon($checkIcon, 'width: 16px; height: 16px; margin-right: 6px; fill: ' . $styles['button_success_text'] . ';')
189 . __('Activate Addon', 'fluent-cart')
190 . '</button>';
191 }
192
193
194 protected function renderActiveBadge()
195 {
196 $styles = $this->getAddonNoticeStyles();
197 $checkIcon = 'M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z';
198
199 return '<span class="fct-badge fct-badge-success" style="display: inline-flex; align-items: center; background: #dcfce7; color: #166534; padding: 8px 16px; border-radius: 6px; font-weight: 500; font-size: 14px; border: 1px solid #bbf7d0;">'
200 . $this->renderIcon($checkIcon, 'width: 16px; height: 16px; margin-right: 6px; fill: #166534;')
201 . __('Active', 'fluent-cart')
202 . '</span>';
203 }
204
205 /**
206 * Generate addon notice HTML
207 *
208 * @param array $config Configuration array with:
209 * - title: Gateway title
210 * - description: Gateway description
211 * - features: Array of feature strings
212 * - icon_path: SVG path for the gateway icon
213 * - addon_slug: Plugin slug
214 * - addon_file: Plugin file path
215 * - addon_source: Array with 'type' and 'link'
216 *
217 * @return string HTML for the addon notice
218 */
219 public function generateAddonNotice($config)
220 {
221 // Validate configuration before proceeding
222 $validation = $this->validateAddonConfig($config);
223 if (is_wp_error($validation)) {
224 return '<div class="fct-addon-notice fct-addon-notice-error" style="background: #fef2f2; border: 1px solid #fecaca; border-radius: 8px; padding: 20px; color: #991b1b; text-align: center; margin: 20px 0;">'
225 . '<p>' . esc_html($validation->get_error_message()) . '</p>'
226 . '</div>';
227 }
228
229 $allStyles = $this->getAddonNoticeStyles();
230
231 // Get addon status
232 $addonStatus = PaymentAddonManager::getAddonStatus(
233 $config['addon_slug'],
234 $config['addon_file']
235 );
236
237 $isInstalled = $addonStatus['is_installed'] ?? false;
238 $isActive = $addonStatus['is_active'] ?? false;
239 $footerText = $config['footer_text'] ?? __('Free addon - Click the button above to get started', 'fluent-cart');
240
241 $html = '';
242
243 // Render both light and dark mode versions
244 foreach (['light', 'dark'] as $mode) {
245 $styles = $allStyles[$mode];
246
247 // Determine status and action button for this mode
248 $proRequired = !empty($config['pro_required']) && !defined('FLUENTCART_PRO_PLUGIN_VERSION');
249 if ($proRequired) {
250 $statusMessage = __('Requires Pro', 'fluent-cart');
251 $statusColor = $styles['status_warning'];
252 $upgradeUrl = esc_url($config['repo_link'] ?? Helper::getUpgradeUrl('feature_lock_gateway_' . $this->gatewaySlug));
253 $actionButton = '<a href="' . $upgradeUrl . '" target="_blank" rel="noopener noreferrer" '
254 . 'style="display: inline-flex; align-items: center; background: ' . $styles['button_primary_bg'] . '; color: ' . $styles['button_primary_text'] . '; padding: 10px 24px; border-radius: 6px; font-weight: 500; font-size: 14px; text-decoration: none; box-shadow: 0 1px 3px rgba(0,0,0,0.1);">'
255 . $this->renderIcon('M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4zm0 4l5 2.18V11c0 3.5-2.33 6.79-5 7.93-2.67-1.14-5-4.43-5-7.93V7.18L12 5z', 'width: 16px; height: 16px; margin-right: 6px; fill: ' . $styles['button_primary_text'] . ';')
256 . __('Upgrade to Pro', 'fluent-cart')
257 . '</a>';
258 } elseif (!$isInstalled) {
259 $statusMessage = __('Not Installed', 'fluent-cart');
260 $statusColor = $styles['status_warning'];
261 $actionButton = $this->renderInstallButton(
262 $config['addon_slug'],
263 $config['addon_file'],
264 $config['addon_source'],
265 $config['repo_link'] ?? '',
266 $mode
267 );
268 } elseif ($isInstalled && !$isActive) {
269 $statusMessage = __('Installed - Not Active', 'fluent-cart');
270 $statusColor = $styles['status_info'];
271 $actionButton = $this->renderActivateButton($config['addon_file'], $mode);
272 } else {
273 $statusMessage = __('Active', 'fluent-cart');
274 $statusColor = $styles['status_success'];
275 $actionButton = $this->renderActiveBadge();
276 }
277
278 $modeClass = $mode === 'dark' ? 'fct-addon-notice-dark' : 'fct-addon-notice-light';
279 $displayStyle = $mode === 'dark' ? 'display: none;' : '';
280
281 // Build notice HTML
282 $html .= '<div class="fct-addon-notice ' . $modeClass . '" style="' . $displayStyle . ' background: ' . $styles['primary_gradient'] . '; border: 1px solid ' . $styles['border_color'] . '; border-radius: 8px; padding: 28px; color: ' . $styles['text_primary'] . '; text-align: center; margin: 20px 0;">';
283
284 // Icon
285 $html .= '<div style="background: ' . $styles['icon_bg'] . '; width: 64px; height: 64px; border-radius: 12px; margin: 0 auto 20px; display: flex; align-items: center; justify-content: center;">';
286 $html .= $this->renderIcon($config['icon_path'], 'width: 32px; height: 32px; fill: ' . $styles['icon_color'] . ';');
287 $html .= '</div>';
288
289 // Title
290 $html .= '<h3 style="margin: 0 0 8px 0; font-size: 20px; font-weight: 600; color: ' . $styles['text_primary'] . ';">'
291 . esc_html($config['title'])
292 . '</h3>';
293
294 // Description
295 $html .= '<p style="margin: 0 0 20px 0; font-size: 14px; color: ' . $styles['text_secondary'] . '; line-height: 1.6;">'
296 . esc_html($config['description'])
297 . '</p>';
298
299 // Features
300 if (!empty($config['features'])) {
301 $html .= '<div style="background: ' . $styles['feature_bg'] . '; border: 1px solid ' . $styles['border_color'] . '; border-radius: 6px; padding: 18px; margin: 20px 0; text-align: left;">';
302 foreach ($config['features'] as $feature) {
303 $html .= $this->renderFeatureItem($feature, $mode);
304 }
305 $html .= '</div>';
306 }
307
308 // Status & Action
309 $html .= '<div style="background: ' . $styles['status_bg'] . '; border: 1px solid ' . $styles['border_color'] . '; border-radius: 6px; padding: 18px; margin: 20px 0;">';
310 $html .= '<div style="display: flex; align-items: center; justify-content: center; margin-bottom: 14px;">';
311 $html .= '<div style="width: 8px; height: 8px; background: ' . $statusColor . '; border-radius: 50%; margin-right: 8px;"></div>';
312 $html .= '<span style="font-size: 14px; font-weight: 500; color: ' . $styles['text_secondary'] . ';">' . esc_html($statusMessage) . '</span>';
313 $html .= '</div>';
314 $html .= '<div style="display: flex; justify-content: center;">' . $actionButton . '</div>';
315 $html .= '</div>';
316
317 // Footer
318 $html .= '<p style="margin: 0; font-size: 12px; color: ' . $styles['text_muted'] . ';">'
319 . esc_html($footerText)
320 . '</p>';
321
322 $html .= '</div>';
323 }
324
325 // Add CSS to toggle between light/dark modes
326 $html .= '<style>
327 html.dark .fct-addon-notice-light,
328 body.dark .fct-addon-notice-light,
329 [data-theme="dark"] .fct-addon-notice-light {
330 display: none !important;
331 }
332 html.dark .fct-addon-notice-dark,
333 body.dark .fct-addon-notice-dark,
334 [data-theme="dark"] .fct-addon-notice-dark {
335 display: block !important;
336 }
337 </style>';
338
339 return $html;
340 }
341 }
342