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

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

330 lines 14.0 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)
15 {
16 $this->gatewaySlug = $gatewaySlug;
17 $this->methodHandler = 'fluent_cart_payment_settings_addon_gateway';
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
165 return '<button type="button" class="fct-btn fct-btn-primary fct-install-addon-btn"
166 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);"
167 data-addon-slug="' . esc_attr($addonSlug) . '"
168 data-addon-file="' . esc_attr($addonFile) . '"
169 data-repo-link="' . esc_attr($repoLink) . '"
170 data-source-type="' . esc_attr(Arr::get($addonSource, 'type', 'github')) . '"
171 data-source-link="' . esc_attr($addonSource['link'] ?? '') . '">'
172 . $this->renderIcon($downloadIcon, 'width: 16px; height: 16px; margin-right: 6px; fill: ' . $styles['button_primary_text'] . ';')
173 . __('Install & Activate', 'fluent-cart')
174 . '</button>';
175 }
176
177
178 protected function renderActivateButton($addonFile, $mode = 'light')
179 {
180 $styles = $this->getAddonNoticeStyles()[$mode];
181 $checkIcon = 'M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z';
182
183 return '<button type="button" class="fct-btn fct-btn-success fct-activate-addon-btn"
184 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);"
185 data-addon-file="' . esc_attr($addonFile) . '">'
186 . $this->renderIcon($checkIcon, 'width: 16px; height: 16px; margin-right: 6px; fill: ' . $styles['button_success_text'] . ';')
187 . __('Activate Addon', 'fluent-cart')
188 . '</button>';
189 }
190
191
192 protected function renderActiveBadge()
193 {
194 $styles = $this->getAddonNoticeStyles();
195 $checkIcon = 'M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z';
196
197 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;">'
198 . $this->renderIcon($checkIcon, 'width: 16px; height: 16px; margin-right: 6px; fill: #166534;')
199 . __('Active', 'fluent-cart')
200 . '</span>';
201 }
202
203 /**
204 * Generate addon notice HTML
205 *
206 * @param array $config Configuration array with:
207 * - title: Gateway title
208 * - description: Gateway description
209 * - features: Array of feature strings
210 * - icon_path: SVG path for the gateway icon
211 * - addon_slug: Plugin slug
212 * - addon_file: Plugin file path
213 * - addon_source: Array with 'type' and 'link'
214 *
215 * @return string HTML for the addon notice
216 */
217 public function generateAddonNotice($config)
218 {
219 // Validate configuration before proceeding
220 $validation = $this->validateAddonConfig($config);
221 if (is_wp_error($validation)) {
222 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;">'
223 . '<p>' . esc_html($validation->get_error_message()) . '</p>'
224 . '</div>';
225 }
226
227 $allStyles = $this->getAddonNoticeStyles();
228
229 // Get addon status
230 $addonStatus = PaymentAddonManager::getAddonStatus(
231 $config['addon_slug'],
232 $config['addon_file']
233 );
234
235 $isInstalled = $addonStatus['is_installed'] ?? false;
236 $isActive = $addonStatus['is_active'] ?? false;
237 $footerText = $config['footer_text'] ?? __('Free addon - Click the button above to get started', 'fluent-cart');
238
239 $html = '';
240
241 // Render both light and dark mode versions
242 foreach (['light', 'dark'] as $mode) {
243 $styles = $allStyles[$mode];
244
245 // Determine status and action button for this mode
246 if (!$isInstalled) {
247 $statusMessage = __('Not Installed', 'fluent-cart');
248 $statusColor = $styles['status_warning'];
249 $actionButton = $this->renderInstallButton(
250 $config['addon_slug'],
251 $config['addon_file'],
252 $config['addon_source'],
253 $config['repo_link'] ?? '',
254 $mode
255 );
256 } elseif ($isInstalled && !$isActive) {
257 $statusMessage = __('Installed - Not Active', 'fluent-cart');
258 $statusColor = $styles['status_info'];
259 $actionButton = $this->renderActivateButton($config['addon_file'], $mode);
260 } else {
261 $statusMessage = __('Active', 'fluent-cart');
262 $statusColor = $styles['status_success'];
263 $actionButton = $this->renderActiveBadge();
264 }
265
266 $modeClass = $mode === 'dark' ? 'fct-addon-notice-dark' : 'fct-addon-notice-light';
267 $displayStyle = $mode === 'dark' ? 'display: none;' : '';
268
269 // Build notice HTML
270 $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;">';
271
272 // Icon
273 $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;">';
274 $html .= $this->renderIcon($config['icon_path'], 'width: 32px; height: 32px; fill: ' . $styles['icon_color'] . ';');
275 $html .= '</div>';
276
277 // Title
278 $html .= '<h3 style="margin: 0 0 8px 0; font-size: 20px; font-weight: 600; color: ' . $styles['text_primary'] . ';">'
279 . esc_html($config['title'])
280 . '</h3>';
281
282 // Description
283 $html .= '<p style="margin: 0 0 20px 0; font-size: 14px; color: ' . $styles['text_secondary'] . '; line-height: 1.6;">'
284 . esc_html($config['description'])
285 . '</p>';
286
287 // Features
288 if (!empty($config['features'])) {
289 $html .= '<div style="background: ' . $styles['feature_bg'] . '; border: 1px solid ' . $styles['border_color'] . '; border-radius: 6px; padding: 18px; margin: 20px 0; text-align: left;">';
290 foreach ($config['features'] as $feature) {
291 $html .= $this->renderFeatureItem($feature, $mode);
292 }
293 $html .= '</div>';
294 }
295
296 // Status & Action
297 $html .= '<div style="background: ' . $styles['status_bg'] . '; border: 1px solid ' . $styles['border_color'] . '; border-radius: 6px; padding: 18px; margin: 20px 0;">';
298 $html .= '<div style="display: flex; align-items: center; justify-content: center; margin-bottom: 14px;">';
299 $html .= '<div style="width: 8px; height: 8px; background: ' . $statusColor . '; border-radius: 50%; margin-right: 8px;"></div>';
300 $html .= '<span style="font-size: 14px; font-weight: 500; color: ' . $styles['text_secondary'] . ';">' . esc_html($statusMessage) . '</span>';
301 $html .= '</div>';
302 $html .= '<div style="display: flex; justify-content: center;">' . $actionButton . '</div>';
303 $html .= '</div>';
304
305 // Footer
306 $html .= '<p style="margin: 0; font-size: 12px; color: ' . $styles['text_muted'] . ';">'
307 . esc_html($footerText)
308 . '</p>';
309
310 $html .= '</div>';
311 }
312
313 // Add CSS to toggle between light/dark modes
314 $html .= '<style>
315 html.dark .fct-addon-notice-light,
316 body.dark .fct-addon-notice-light,
317 [data-theme="dark"] .fct-addon-notice-light {
318 display: none !important;
319 }
320 html.dark .fct-addon-notice-dark,
321 body.dark .fct-addon-notice-dark,
322 [data-theme="dark"] .fct-addon-notice-dark {
323 display: block !important;
324 }
325 </style>';
326
327 return $html;
328 }
329 }
330