PluginProbe
Timetics – Appointment Booking Calendar & Scheduling / 1.0.49
Timetics – Appointment Booking Calendar & Scheduling v1.0.49
1.0.61 1.0.60 1.0.59 1.0.58 1.0.57 1.0.56 trunk 1.0.0 1.0.1 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.15 1.0.16 1.0.17 1.0.18 1.0.19 1.0.2 1.0.20 1.0.21 1.0.22 1.0.23 1.0.24 All 62 releases
← All changes | bootstrap.php +6 -129 1.0.601.0.49 View file →
@@ -174,15 +174,14 @@
174 174 /**
175 175 * Define constant if not already set.
176 176 *
177 177 * @since 1.0.0
178 - * @param string $timetics_constant_name Constant name.
178 + * @param string $name Constant name.
179 179 * @param string|bool $value Constant value.
180 180 */
181 - private function define( $timetics_constant_name, $value ) {
182 - if ( ! defined( $timetics_constant_name ) ) {
183 - // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.VariableConstantNameFound -- Constant name is dynamic but prefixed by caller
184 - define( $timetics_constant_name, $value );
181 + private function define( $name, $value ) {
182 + if ( ! defined( $name ) ) {
183 + define( $name, $value );
185 184 }
186 185 }
187 186
188 187 /**
@@ -228,15 +227,13 @@
228 227
229 228 // Register scripts and styles first
230 229 if ( $this->is_request( 'admin' ) ) {
231 230 add_action( 'admin_enqueue_scripts', [ $this, 'admin_scripts' ] );
232 - add_action( 'admin_enqueue_scripts', [ $this, 'preload_js_translations' ], 5 );
233 231 add_action( 'admin_footer', [ $this, 'admin_helpscout_beacon' ] );
234 232 }
235 233
236 234 if ( $this->is_request( 'frontend' ) ) {
237 235 add_action( 'wp_enqueue_scripts', array( $this, 'frontend_scripts' ) );
238 - add_action( 'wp_enqueue_scripts', [ $this, 'preload_js_translations' ], 5 );
239 236 }
240 237
241 238 // Register admin menu
242 239 Core\Admin\Menu::instance()->init();
@@ -263,109 +260,8 @@
263 260 return "https://arraytics.com/timetics/";
264 261 }
265 262
266 263 /**
267 - * Preload PHP-loaded translations into wp.i18n before any bundle runs.
268 - *
269 - * Why: webpack bundles collapse many source files into one. wp_set_script_translations()
270 - * looks up a JSON file hashed from the registered bundle URL, but Loco and wp i18n make-json
271 - * shard JSON by source-file path. The hashes never match, so per-script JSON loading silently
272 - * fails. Reading the textdomain that load_text_domain() already populated and injecting it via
273 - * setLocaleData() bypasses the hash mismatch entirely — every __() call across every bundle
274 - * resolves from in-memory data set before any React component renders.
275 - */
276 - public function preload_js_translations() {
277 - $locale = determine_locale();
278 - $plural_forms = 'nplurals=2; plural=(n != 1);';
279 -
280 - // Read .mo first — canonical, always-fresh source that Loco rewrites on every save.
281 - // .l10n.php cache often lags behind .mo because Loco does not regenerate it.
282 - $messages = $this->extract_mo_messages( $locale, $plural_forms );
283 -
284 - // Merge .l10n.php on top (covers WP 6.5+ system-translated plugins where only .l10n.php exists).
285 - foreach ( [
286 - WP_LANG_DIR . '/loco/plugins/timetics-' . $locale . '.l10n.php',
287 - TIMETICS_PLUGIN_DIR . 'languages/timetics-' . $locale . '.l10n.php',
288 - WP_LANG_DIR . '/plugins/timetics-' . $locale . '.l10n.php',
289 - ] as $file ) {
290 - if ( ! is_readable( $file ) ) {
291 - continue;
292 - }
293 - $data = include $file;
294 - if ( ! is_array( $data ) || empty( $data['messages'] ) ) {
295 - continue;
296 - }
297 - $messages = array_merge( $messages, $data['messages'] );
298 - if ( ! empty( $data['plural-forms'] ) ) {
299 - $plural_forms = $data['plural-forms'];
300 - }
301 - }
302 -
303 - if ( empty( $messages ) ) {
304 - return;
305 - }
306 -
307 - $locale_data = [
308 - '' => [
309 - 'domain' => 'timetics',
310 - 'lang' => $locale,
311 - 'plural-forms' => $plural_forms,
312 - ],
313 - ];
314 -
315 - foreach ( $messages as $msgid => $msgstr ) {
316 - if ( is_string( $msgid ) && $msgid !== '' && is_string( $msgstr ) && $msgstr !== '' ) {
317 - $locale_data[ $msgid ] = [ $msgstr ];
318 - }
319 - }
320 -
321 - wp_add_inline_script(
322 - 'wp-i18n',
323 - sprintf(
324 - 'wp.i18n.setLocaleData( %s, "timetics" );',
325 - wp_json_encode( $locale_data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES )
326 - ),
327 - 'after'
328 - );
329 - }
330 -
331 - /**
332 - * Fallback: parse .mo file to extract all translations.
333 - */
334 - private function extract_mo_messages( $locale, &$plural_forms ) {
335 - $candidates = [
336 - WP_LANG_DIR . '/loco/plugins/timetics-' . $locale . '.mo',
337 - TIMETICS_PLUGIN_DIR . 'languages/timetics-' . $locale . '.mo',
338 - WP_LANG_DIR . '/plugins/timetics-' . $locale . '.mo',
339 - ];
340 -
341 - $messages = [];
342 -
343 - foreach ( $candidates as $mofile ) {
344 - if ( ! is_readable( $mofile ) ) {
345 - continue;
346 - }
347 - if ( ! class_exists( 'MO' ) ) {
348 - require_once ABSPATH . WPINC . '/pomo/mo.php';
349 - }
350 - $mo = new \MO();
351 - if ( ! $mo->import_from_file( $mofile ) ) {
352 - continue;
353 - }
354 - if ( ! empty( $mo->headers['Plural-Forms'] ) ) {
355 - $plural_forms = $mo->headers['Plural-Forms'];
356 - }
357 - foreach ( $mo->entries as $msgid => $entry ) {
358 - if ( ! empty( $entry->translations[0] ) ) {
359 - $messages[ $msgid ] = $entry->translations[0];
360 - }
361 - }
362 - }
363 -
364 - return $messages;
365 - }
366 -
367 - /**
368 264 * Register scripts and styles for admin
369 265 *
370 266 * @return void
371 267 */
@@ -405,9 +301,8 @@
405 301 }
406 302
407 303 wp_enqueue_script( 'timetics-dashboard-scripts', TIMETICS_ASSETS_URL . 'js/dashboard.js', [ 'wp-plugins', 'wp-i18n', 'wp-element', 'wp-dom', 'wp-data', 'wp-color-picker' ], TIMETICS_VERSION, true );
408 304
409 - wp_set_script_translations( 'timetics-dashboard-scripts', 'timetics', TIMETICS_PLUGIN_DIR . 'languages/' );
410 305
411 306 $localize_obj = array(
412 307 'site_url' => site_url(),
413 308 'admin_url' => admin_url(),
@@ -442,25 +337,8 @@
442 337
443 338 wp_register_style( 'timetics-vendor', TIMETICS_ASSETS_URL . 'css/vendor.css', [], TIMETICS_VERSION, 'all' );
444 339 wp_register_style( 'timetics-frontend', TIMETICS_ASSETS_URL . 'css/frontend.css', [], TIMETICS_VERSION, 'all' );
445 340
446 - global $post;
447 - if ( $post ) {
448 - $is_timetics_cpt = ( 'timetics-appointment' === get_post_type( $post ) );
449 - $timetics_shortcodes = [ 'timetics-booking-form', 'timetics-meeting-list', 'timetics-user-dashboard', 'timetics-category' ];
450 - $has_timetics_shortcode = false;
451 - foreach ( $timetics_shortcodes as $shortcode ) {
452 - if ( has_shortcode( $post->post_content, $shortcode ) ) {
453 - $has_timetics_shortcode = true;
454 - break;
455 - }
456 - }
457 - if ( $is_timetics_cpt || $has_timetics_shortcode ) {
458 - wp_enqueue_style( 'timetics-vendor' );
459 - wp_enqueue_style( 'timetics-frontend' );
460 - }
461 - }
462 -
463 341 wp_register_script( 'timetics-flatpickr-scripts', TIMETICS_ASSETS_URL . 'js/vendors/flatpickr.js', [ 'wp-plugins', 'wp-i18n', 'wp-element', 'wp-dom', 'wp-data' ], TIMETICS_VERSION, true );
464 342 wp_enqueue_script( 'timetics-packages', TIMETICS_ASSETS_URL . 'js/packages.js', [ 'timetics-flatpickr-scripts' ], TIMETICS_VERSION, true );
465 343
466 344 wp_register_script( 'timetics-frontend-scripts', TIMETICS_ASSETS_URL . 'js/frontend.js', [ 'jquery', 'wp-plugins', 'wp-i18n', 'wp-element', 'wp-dom', 'wp-data' ], TIMETICS_VERSION, true );
@@ -542,10 +420,9 @@
542 420 *
543 421 * @return void
544 422 */
545 423 public function handle_buy_pro_module() {
546 - // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only page parameter check, no form processing
547 - $page = isset( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : '';
424 + $page = isset( $_GET['page'] ) ? sanitize_text_field( $_GET['page'] ) : '';
548 425
549 426
550 427 if ( 'timetics' !== $page ) {
551 428 return;
@@ -607,9 +484,9 @@
607 484 color: "#0060e5",
608 485 });
609 486 window.Beacon('init', '4be24aa2-ee50-483c-a90c-db4216664d65');
610 487 window.Beacon('on', 'ready', function(){
611 - window.Beacon('close');
488 + window.Beacon('show');
612 489 });
613 490
614 491 </script>
615 492 <?php