PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.5.3
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.5.3
1.6.5 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 All 48 releases
fluent-cart / app / Modules / PaymentMethods / PromoGateways / Addons / AddonGatewaySettings.php

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

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