PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.4.1
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.4.1
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.4.1, at app/Modules/PaymentMethods/PromoGateways/Addons/AddonGatewaySettings.php

340 lines 15.2 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
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 $proRequired = !empty($config['pro_required']) && !defined('FLUENTCART_PRO_PLUGIN_VERSION');
247 if ($proRequired) {
248 $statusMessage = __('Requires Pro', 'fluent-cart');
249 $statusColor = $styles['status_warning'];
250 $upgradeUrl = esc_url($config['repo_link'] ?? 'https://fluentcart.com/pricing/');
251 $actionButton = '<a href="' . $upgradeUrl . '" target="_blank" rel="noopener noreferrer" '
252 . '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);">'
253 . $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'] . ';')
254 . __('Upgrade to Pro', 'fluent-cart')
255 . '</a>';
256 } elseif (!$isInstalled) {
257 $statusMessage = __('Not Installed', 'fluent-cart');
258 $statusColor = $styles['status_warning'];
259 $actionButton = $this->renderInstallButton(
260 $config['addon_slug'],
261 $config['addon_file'],
262 $config['addon_source'],
263 $config['repo_link'] ?? '',
264 $mode
265 );
266 } elseif ($isInstalled && !$isActive) {
267 $statusMessage = __('Installed - Not Active', 'fluent-cart');
268 $statusColor = $styles['status_info'];
269 $actionButton = $this->renderActivateButton($config['addon_file'], $mode);
270 } else {
271 $statusMessage = __('Active', 'fluent-cart');
272 $statusColor = $styles['status_success'];
273 $actionButton = $this->renderActiveBadge();
274 }
275
276 $modeClass = $mode === 'dark' ? 'fct-addon-notice-dark' : 'fct-addon-notice-light';
277 $displayStyle = $mode === 'dark' ? 'display: none;' : '';
278
279 // Build notice HTML
280 $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;">';
281
282 // Icon
283 $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;">';
284 $html .= $this->renderIcon($config['icon_path'], 'width: 32px; height: 32px; fill: ' . $styles['icon_color'] . ';');
285 $html .= '</div>';
286
287 // Title
288 $html .= '<h3 style="margin: 0 0 8px 0; font-size: 20px; font-weight: 600; color: ' . $styles['text_primary'] . ';">'
289 . esc_html($config['title'])
290 . '</h3>';
291
292 // Description
293 $html .= '<p style="margin: 0 0 20px 0; font-size: 14px; color: ' . $styles['text_secondary'] . '; line-height: 1.6;">'
294 . esc_html($config['description'])
295 . '</p>';
296
297 // Features
298 if (!empty($config['features'])) {
299 $html .= '<div style="background: ' . $styles['feature_bg'] . '; border: 1px solid ' . $styles['border_color'] . '; border-radius: 6px; padding: 18px; margin: 20px 0; text-align: left;">';
300 foreach ($config['features'] as $feature) {
301 $html .= $this->renderFeatureItem($feature, $mode);
302 }
303 $html .= '</div>';
304 }
305
306 // Status & Action
307 $html .= '<div style="background: ' . $styles['status_bg'] . '; border: 1px solid ' . $styles['border_color'] . '; border-radius: 6px; padding: 18px; margin: 20px 0;">';
308 $html .= '<div style="display: flex; align-items: center; justify-content: center; margin-bottom: 14px;">';
309 $html .= '<div style="width: 8px; height: 8px; background: ' . $statusColor . '; border-radius: 50%; margin-right: 8px;"></div>';
310 $html .= '<span style="font-size: 14px; font-weight: 500; color: ' . $styles['text_secondary'] . ';">' . esc_html($statusMessage) . '</span>';
311 $html .= '</div>';
312 $html .= '<div style="display: flex; justify-content: center;">' . $actionButton . '</div>';
313 $html .= '</div>';
314
315 // Footer
316 $html .= '<p style="margin: 0; font-size: 12px; color: ' . $styles['text_muted'] . ';">'
317 . esc_html($footerText)
318 . '</p>';
319
320 $html .= '</div>';
321 }
322
323 // Add CSS to toggle between light/dark modes
324 $html .= '<style>
325 html.dark .fct-addon-notice-light,
326 body.dark .fct-addon-notice-light,
327 [data-theme="dark"] .fct-addon-notice-light {
328 display: none !important;
329 }
330 html.dark .fct-addon-notice-dark,
331 body.dark .fct-addon-notice-dark,
332 [data-theme="dark"] .fct-addon-notice-dark {
333 display: block !important;
334 }
335 </style>';
336
337 return $html;
338 }
339 }
340