PluginProbe
Countdown Timer – Widget Countdown / trunk
Countdown Timer – Widget Countdown vtrunk
2.2.6 2.2.7 2.2.8 2.2.9 2.3.0 2.3.1 2.3.2 2.3.3 2.3.4 2.3.5 2.3.6 2.3.7 2.3.8 2.3.9 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.4.5 2.4.6 2.4.7 2.4.8 2.4.9 2.5.0 All 182 releases
widget-countdown / includes / Core / Installer.php

Installer.php in Countdown Timer – Widget Countdown trunk, at includes/Core/Installer.php

343 lines 14.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if ( ! defined( 'ABSPATH' ) ) exit;
3
4 /**
5 * Installer — database table creation and default data seeding.
6 *
7 * Called on plugin activation and by ensure_tables() safety net.
8 * Replaces the old install_databese.php with cleaner code.
9 */
10 class Wpda_Countdown_Installer {
11
12 private $timer_repo;
13 private $theme_repo;
14
15 public function __construct(
16 Wpda_Countdown_Timer_Repository $timer_repo,
17 Wpda_Countdown_Theme_Repository $theme_repo
18 ) {
19 $this->timer_repo = $timer_repo;
20 $this->theme_repo = $theme_repo;
21 }
22
23 /**
24 * Run full installation: create tables + seed defaults.
25 */
26 public function install() {
27 $this->create_timer_table();
28 $this->create_theme_table();
29 }
30
31 /**
32 * Safety check — runs on every admin page + plugin load.
33 * Uses an option sentinel so the SHOW TABLES probe only happens once per
34 * successful verification. If tables are missing or the sentinel says
35 * they weren't confirmed yet, runs the full installer. Also cleans up
36 * any duplicate "Classic B&W" rows in case the installer ran twice.
37 */
38 public function ensure_tables() {
39 if ( get_option( 'wpda_countdown_tables_ready' ) === '1'
40 && $this->timer_repo->table_exists()
41 && $this->theme_repo->table_exists() ) {
42 return;
43 }
44 $this->install();
45 if ( $this->timer_repo->table_exists() && $this->theme_repo->table_exists() ) {
46 $this->cleanup_duplicate_base_theme();
47 update_option( 'wpda_countdown_tables_ready', '1' );
48 }
49 }
50
51 /**
52 * Self-heal: if multiple rows named "Classic B&W" exist (a race between
53 * activation and plugins_loaded seeding, or a double-install), keep the
54 * one with the lowest id and drop the rest.
55 */
56 private function cleanup_duplicate_base_theme() {
57 global $wpdb;
58 $table = $this->theme_repo->get_table_name();
59 $ids = $wpdb->get_col( $wpdb->prepare(
60 "SELECT id FROM {$table} WHERE name = %s ORDER BY id ASC",
61 'Classic B&W'
62 ) );
63 if ( count( $ids ) <= 1 ) return;
64 $keep = (int) array_shift( $ids );
65 foreach ( $ids as $dup_id ) {
66 $wpdb->delete( $table, array( 'id' => (int) $dup_id ), array( '%d' ) );
67 }
68 // Make sure the kept row stays marked as default.
69 $wpdb->update( $table, array( 'default' => 1 ), array( 'id' => $keep ), array( '%d' ), array( '%d' ) );
70 }
71
72 // ─── Timer table ───────────────────────────────────────────
73
74 private function create_timer_table() {
75 global $wpdb;
76 require_once ABSPATH . 'wp-admin/includes/upgrade.php';
77
78 $table = $this->timer_repo->get_table_name();
79 $charset = $wpdb->get_charset_collate();
80
81 dbDelta( "CREATE TABLE IF NOT EXISTS {$table} (
82 `id` int(10) NOT NULL AUTO_INCREMENT,
83 `name` varchar(512) NOT NULL,
84 `option_value` longtext NOT NULL,
85 UNIQUE KEY id (id)
86 ) {$charset};" );
87
88 $this->seed_default_timers();
89 }
90
91 private function seed_default_timers() {
92 if ( $this->timer_repo->count() > 0 ) return;
93
94 $base = array(
95 'version' => '1.2',
96 'timer_start_time' => date( 'd/m/Y', strtotime( '-1 day' ) ) . ' 00:00',
97 'timer_end_date' => date( 'd/m/Y', strtotime( '+30 day' ) ) . ' 00:00',
98 'timer_timezone' => date_default_timezone_get() === 'UTC' ? 'Europe/London' : date_default_timezone_get(),
99 'timer_coundown_repeat' => 'none',
100 'after_countdown_repeat_time' => array( 'hour' => '1', 'minute' => '0' ),
101 'repeat_hourly_interval' => '3',
102 'repeat_daily_quantity' => '1',
103 'repeat_weekly_days' => array( 'mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun' ),
104 'repeat_monthly_day' => '1',
105 'repeat_countdown_start_time' => '00:00',
106 'repeat_countdown_end_time' => '23:59',
107 'repeat_end' => 'never',
108 'repeat_ending_after' => '10',
109 'repeat_ending_after_date' => date( 'd/m/Y', strtotime( '+30 days' ) ) . ' 00:00',
110 'after_countdown_end_type' => 'text',
111 'after_countdown_text' => '<h3>Time is up!</h3>',
112 'after_countdown_redirect' => '',
113 'after_countdown_button_text' => 'Shop Now',
114 'after_countdown_button_url' => '',
115 'after_countdown_css_selector' => '',
116 'before_countup_start_type' => 'none',
117 'before_countup_text' => '',
118 'before_countup_redirect' => '',
119 'top_countdown_show_html' => '',
120 'bottom_countdown_show_html' => '',
121 );
122
123 if ( WPDA_COUNTDOWN_IS_PRO ) {
124 $timers = array(
125 array(
126 'name' => 'Evergreen 10 min countdown',
127 'data' => array_merge( $base, array(
128 'name' => 'Evergreen 10 min countdown',
129 'timer_coundown_type' => 'evergreen_countdown',
130 'timer_seesion_time' => array( 'day' => '0', 'hour' => '0', 'minute' => '10' ),
131 'evergreen_expire_mode' => 'duration',
132 'evergreen_restart' => 'delay',
133 'evergreen_restart_delay' => array( 'hour' => '24', 'minute' => '0' ),
134 'evergreen_daily_expire_time' => '23:59',
135 'after_countdown_text' => '<h3>Offer expired!</h3><p>Come back tomorrow for a new deal.</p>',
136 ) ),
137 ),
138 array(
139 'name' => 'Evergreen daily midnight',
140 'data' => array_merge( $base, array(
141 'name' => 'Evergreen daily midnight',
142 'timer_coundown_type' => 'evergreen_countdown',
143 'timer_seesion_time' => array( 'day' => '0', 'hour' => '0', 'minute' => '1' ),
144 'evergreen_expire_mode' => 'daily_time',
145 'evergreen_restart' => 'none',
146 'evergreen_restart_delay' => array( 'hour' => '0', 'minute' => '0' ),
147 'evergreen_daily_expire_time' => '23:59',
148 'after_countdown_text' => '<h3>Today\'s deal has ended</h3>',
149 ) ),
150 ),
151 array(
152 'name' => 'Evergreen 1 hour countup',
153 'data' => array_merge( $base, array(
154 'name' => 'Evergreen 1 hour countup',
155 'timer_coundown_type' => 'evergreen_countup',
156 'timer_seesion_time' => array( 'day' => '0', 'hour' => '1', 'minute' => '0' ),
157 'evergreen_expire_mode' => 'duration',
158 'evergreen_restart' => 'immediate',
159 'evergreen_restart_delay' => array( 'hour' => '0', 'minute' => '0' ),
160 'evergreen_daily_expire_time' => '23:59',
161 'after_countdown_end_type' => 'hide',
162 'after_countdown_text' => '',
163 ) ),
164 ),
165 );
166 } else {
167 // Free — a single simple countdown timer
168 $timers = array(
169 array(
170 'name' => 'My first countdown',
171 'data' => array_merge( $base, array(
172 'name' => 'My first countdown',
173 'timer_coundown_type' => 'countdown',
174 ) ),
175 ),
176 );
177 }
178
179 foreach ( $timers as $t ) {
180 $this->timer_repo->insert( $t['name'], $t['data'] );
181 }
182 }
183
184 // ─── Theme table ───────────────────────────────────────────
185
186 private function create_theme_table() {
187 global $wpdb;
188 require_once ABSPATH . 'wp-admin/includes/upgrade.php';
189
190 $table = $this->theme_repo->get_table_name();
191 $charset = $wpdb->get_charset_collate();
192
193 dbDelta( "CREATE TABLE IF NOT EXISTS {$table} (
194 `id` int(10) NOT NULL AUTO_INCREMENT,
195 `name` varchar(512) NOT NULL,
196 `option_value` longtext NOT NULL,
197 `default` tinyint(4) NOT NULL,
198 UNIQUE KEY id (id)
199 ) {$charset};" );
200
201 $this->seed_base_theme();
202 if ( WPDA_COUNTDOWN_IS_PRO ) {
203 $this->seed_pro_themes();
204 }
205 }
206
207 private function seed_base_theme() {
208 // Two-stage guard against duplicate seeding:
209 // 1. count() — normal fast path (skip if any theme exists).
210 // 2. name-specific check — catches race conditions where two calls
211 // (activation hook + plugins_loaded safety net) both see count=0
212 // before either insert commits, or where an older install left
213 // the themes table present but empty.
214 if ( $this->theme_repo->count() > 0 ) return;
215 global $wpdb;
216 $exists = $wpdb->get_var( $wpdb->prepare(
217 "SELECT id FROM {$this->theme_repo->get_table_name()} WHERE name = %s LIMIT 1",
218 'Classic B&W'
219 ) );
220 if ( $exists ) return;
221
222 // Classic B&W — the shared base theme for Free and Pro. Values pulled
223 // from the production DB after hand-tuning against the theme-isolation
224 // CSS reset, so what's seeded now matches the intended rendered design.
225 $name = 'Classic B&W';
226 $data = array(
227 'name' => $name,
228 'countdown_type' => 'standart',
229 // Common layout
230 'countdown_global_width' => '100',
231 'countdown_global_width_metrick' => '%',
232 'countdown_horizontal_position' => 'center',
233 'countdown_date_display' => array( 'day' => 'day', 'hour' => 'hour', 'minut' => 'minut', 'second' => 'second' ),
234 'countdown_text_type' => 'po_mo',
235 'text_for_weeks' => 'Weeks',
236 'text_for_day' => 'Days',
237 'text_for_hour' => 'Hours',
238 'text_for_minute' => 'Minutes',
239 'text_for_second' => 'Seconds',
240 // Standard
241 'countdown_standart_elements_width' => '60',
242 'countdown_standart_elements_distance' => '15',
243 'countdown_standart_time_bg_color' => '#FFFFFF',
244 'countdown_standart_time_text_bg_color' => '#000000',
245 'countdown_standart_time_font_size' => '34',
246 'countdown_standart_time_text_font_size' => '10',
247 'countdown_standart_time_color' => '#000000',
248 'countdown_standart_time_text_color' => '#FFFFFF',
249 'countdown_standart_time_font_famely' => 'Garamond,Hoefler Text,Times New Roman,Times,serif',
250 'countdown_standart_time_text_font_famely' => 'Consolas,Andale Mono,Monaco,Courier,Courier New,Verdana,sans-serif',
251 'countdown_standart_time_padding' => array( 'top' => '2', 'right' => '14', 'bottom' => '2', 'left' => '14' ),
252 'countdown_standart_time_text_padding' => array( 'top' => '2', 'right' => '5', 'bottom' => '2', 'left' => '5' ),
253 'countdown_standart_time_margin' => array( 'top' => '0', 'right' => '0', 'bottom' => '0', 'left' => '0' ),
254 'countdown_standart_time_text_margin' => array( 'top' => '2', 'right' => '0', 'bottom' => '0', 'left' => '0' ),
255 'countdown_standart_time_border_width' => '1',
256 'countdown_standart_time_text_border_width' => '0',
257 'countdown_standart_time_border_radius' => '4',
258 'countdown_standart_time_text_border_radius' => '2',
259 'countdown_standart_time_border_color' => '#333333',
260 'countdown_standart_time_text_border_color' => '#000000',
261 'countdown_standart_animation_type' => 'none',
262 'countdown_standart_gorup_animation' => 'group',
263 'countdown_standart_display_inline' => '0',
264 // Vertical (pro) — placeholders so frontend renders correctly if user switches to vertical
265 'countdown_vertical_elements_distance' => '12',
266 'countdown_vertical_background_color' => '#FFFFFF',
267 'countdown_vertical_time_font_size' => '5',
268 'countdown_vertical_time_color' => '#FFFFFF',
269 'countdown_vertical_time_font_famely' => 'Arial,Helvetica Neue,Helvetica,sans-serif',
270 'countdown_vertical_time_border_width' => '1',
271 'countdown_vertical_time_border_color' => '#000000',
272 'countdown_vertical_time_text_bg_color' => '#FFFFFF',
273 'countdown_vertical_time_text_font_size' => '5',
274 'countdown_vertical_time_text_color' => '#FFFFFF',
275 'countdown_vertical_time_text_font_famely' => 'Arial,Helvetica Neue,Helvetica,sans-serif',
276 'countdown_vertical_time_text_padding' => array( 'top' => '0', 'right' => '0', 'bottom' => '0', 'left' => '0' ),
277 'countdown_vertical_time_text_margin' => array( 'top' => '0', 'right' => '0', 'bottom' => '0', 'left' => '0' ),
278 'countdown_vertical_time_text_border_width' => '0',
279 'countdown_vertical_time_text_border_radius' => '0',
280 'countdown_vertical_time_text_border_color' => '#FFFFFF',
281 'countdown_vertical_display_inline' => '0',
282 'countdown_vertical_gorup_animation' => 'group',
283 'countdown_vertical_animation_type' => 'none',
284 // Circle (pro)
285 'countdown_circle_elements_width_height' => '120',
286 'countdown_circle_elements_distance' => '12',
287 'countdown_circle_background_color' => '#ffffff',
288 'countdown_circle_background_color_opacity' => '100',
289 'countdown_circle_border_color_outside' => '#e0e0e0',
290 'countdown_circle_border_color_inside' => '#2271b1',
291 'countdown_circle_width_parcents' => '8',
292 'countdown_circle_type_of_rounding' => 'round',
293 'countdown_circle_border_direction' => 'right',
294 'countdown_circle_time_font_size' => '28',
295 'countdown_circle_time_text_font_size' => '12',
296 'countdown_circle_time_color' => '#1d2327',
297 'countdown_circle_time_text_color' => '#50575e',
298 'countdown_circle_time_font_famely' => 'Arial,Helvetica Neue,Helvetica,sans-serif',
299 'countdown_circle_display_inline' => '0',
300 'countdown_circle_gorup_animation' => 'group',
301 'countdown_circle_animation_type' => 'none',
302 // Flip (pro)
303 'countdown_flip_card_bg' => '#1d2327',
304 'countdown_flip_card_color' => '#ffffff',
305 'countdown_flip_label_color' => '#50575e',
306 'countdown_flip_card_width' => '70',
307 'countdown_flip_card_height' => '80',
308 'countdown_flip_font_size' => '36',
309 'countdown_flip_gap' => '12',
310 'countdown_flip_border_radius' => '8',
311 'countdown_flip_font_family' => 'Arial,Helvetica Neue,Helvetica,sans-serif',
312 'countdown_flip_display_inline' => '0',
313 'countdown_flip_gorup_animation' => 'group',
314 'countdown_flip_animation_type' => 'none',
315 );
316
317 $this->theme_repo->insert( $name, $data, true );
318 }
319
320 private function seed_pro_themes() {
321 if ( get_option( 'wpda_countdown_pro_themes_installed' ) ) return;
322
323 $themes_file = wpda_countdown_plugin_path . 'includes/default_themes.php';
324 if ( ! file_exists( $themes_file ) ) return;
325
326 $themes = include $themes_file;
327 if ( ! is_array( $themes ) ) return;
328
329 $has_default = $this->theme_repo->get_default_id();
330
331 foreach ( $themes as $theme ) {
332 $data = $theme['data'];
333 $data['name'] = $theme['name'];
334 $is_default = ( $theme['default'] && ! $has_default ) ? true : false;
335 if ( $is_default ) $has_default = true;
336
337 $this->theme_repo->insert( $theme['name'], $data, $is_default );
338 }
339
340 update_option( 'wpda_countdown_pro_themes_installed', '1' );
341 }
342 }
343