PluginProbe
Solace Extra / 1.6.1
Solace Extra v1.6.1
1.7.1 1.7.0 1.6.2 1.6.1 1.6.0 1.5.3 trunk 1.0.8 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.7 1.1.8 1.1.9 1.2.1 1.2.2 1.3.0 1.3.1 1.3.2 1.3.3 1.5.0 1.5.1 All 26 releases
solace-extra / solace-extra.php

solace-extra.php in Solace Extra 1.6.1, at solace-extra.php

812 lines 31.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * The plugin bootstrap file
4 *
5 * This file is read by WordPress to generate the plugin information in the plugin
6 * admin area. This file also includes all of the dependencies used by the plugin,
7 * registers the activation and deactivation functions, and defines a function
8 * that starts the plugin.
9 *
10 * @link https://solacewp.com
11 * @since 1.1.6
12 * @package Solace_Extra
13 *
14 * Plugin Name: Solace Extra
15 * Plugin URI: https://solacewp.com/
16 * Description: Additional features for Solace Theme
17 * Version: 1.6.1
18 * Requires PHP: 7.4
19 * Author: Solace
20 * Author URI: https://solacewp.com/
21 * License: GPL-2.0+
22 * License URI: http://www.gnu.org/licenses/gpl-2.0.txt
23 * Text Domain: solace-extra
24 * Domain Path: /languages
25 */
26
27 use \Elementor\Plugin as Elementor_Plugin;
28
29 // If this file is called directly, abort.
30 if ( ! defined( 'WPINC' ) ) {
31 die;
32 }
33
34 defined( 'ABSPATH' ) || exit;
35
36 /**
37 * Currently plugin version.
38 * Start at version 1.0.0 and use SemVer - https://semver.org
39 * Rename this for your plugin and update it as you release new versions.
40 */
41 define( 'SOLACE_EXTRA_VERSION', '1.6.1' );
42 define( 'SOLACE_EXTRA_DIR', plugin_dir_url( __FILE__ ) );
43 define( 'SOLACE_EXTRA_DIR_PATH', plugin_dir_path( __FILE__ ) );
44 define( 'SOLACE_EXTRA_ASSETS_URL', plugin_dir_url( __FILE__ ) . 'assets/' );
45 define( 'SOLACE_EXTRA_SLUG', dirname( plugin_basename( __FILE__ ) ) );
46 define( 'SOLACE_EXTRA_API_BASE_URL', 'https://solacewp.com/wp-json/solace/v1/' );
47 define( 'SOLACE_EXTRA_DEMO_IMPORT_URL', 'https://solacewp.com/' );
48 define( 'SOLACE_EXTRA_ELEMENTOR_ADDONS__FILE__', __FILE__ );
49 define( 'SOLACE_EXTRA_ELEMENTOR_ADDONS_BASE', plugin_basename( __FILE__ ) );
50 define( 'SOLACE_EXTRA_ELEMENTOR_ADDONS_DIR_PATH', plugin_dir_path( SOLACE_EXTRA_ELEMENTOR_ADDONS__FILE__ ) );
51 define( 'SOLACE_EXTRA_ELEMENTOR_ADDONS_DIR_URL', plugin_dir_url( SOLACE_EXTRA_ELEMENTOR_ADDONS__FILE__ ) );
52 define( 'SOLACE_EXTRA_ELEMENTOR_ADDONS_ASSETS', trailingslashit( SOLACE_EXTRA_ELEMENTOR_ADDONS_DIR_URL . 'assets' ) );
53 define( 'SOLACE_EXTRA_ELEMENTOR_ADDONS_WIDGET', trailingslashit( SOLACE_EXTRA_ELEMENTOR_ADDONS_DIR_PATH . 'widgets' ) );
54
55 // require plugin_dir_path( __FILE__ ) . 'classes/class-library-manager.php';
56 // require plugin_dir_path( __FILE__ ) . 'classes/class-library-source.php';
57
58 define( 'SOLACE_SITE_URL', urlencode( home_url() ) );
59 define( 'SOLACE_UPGRADE_BASE_URL', 'https://pro.solacewp.com/' );
60
61 define( 'SOLACE_UPGRADE_URL',
62 add_query_arg(
63 array(
64 'utm_source' => 'plugin',
65 'utm_medium' => 'upgrade_link',
66 'utm_campaign' => 'solace_free_to_pro',
67 'version' => SOLACE_EXTRA_VERSION,
68 'site_url' => SOLACE_SITE_URL,
69 ),
70 SOLACE_UPGRADE_BASE_URL
71 )
72 );
73 define( 'SOLACE_SUPPORT_URL',
74 add_query_arg(
75 array(
76 'utm_source' => 'plugin',
77 'utm_medium' => 'support_link',
78 'utm_campaign' => 'solace_free_to_pro',
79 'version' => SOLACE_EXTRA_VERSION,
80 'site_url' => SOLACE_SITE_URL,
81 ),
82 SOLACE_UPGRADE_BASE_URL . 'my-account/my-tickets'
83 )
84 );
85
86 global $solace_is_run_in_shortcode;
87
88 // set_time_limit(0);
89
90 /**
91 * The code that runs during plugin activation.
92 * This action is documented in includes/class-solace-extra-activator.php
93 */
94 function solace_extra_activate() {
95 add_option( 'solace_extra_redirect_after_activation_option', true );
96 require_once plugin_dir_path( __FILE__ ) . 'includes/class-solace-extra-activator.php';
97 Solace_Extra_Activator::activate();
98 }
99
100 /**
101 * The code that runs during plugin deactivation.
102 * This action is documented in includes/class-solace-extra-deactivator.php
103 */
104 function solace_extra_deactivate() {
105
106 // Delete the 'solace_disable_admin_notices' cookie directly
107 if ( isset( $_COOKIE['solace_disable_admin_notices'] ) ) {
108 // Set the cookie with an expiration time in the past to delete it
109 setcookie( 'solace_disable_admin_notices', '', time() - 3600 );
110 }
111
112 require_once plugin_dir_path( __FILE__ ) . 'includes/class-solace-extra-deactivator.php';
113 Solace_Extra_Deactivator::deactivate();
114 }
115
116 register_activation_hook( __FILE__, 'solace_extra_activate' );
117 register_deactivation_hook( __FILE__, 'solace_extra_deactivate' );
118
119 function solace_hide_hostinger_easy_onboarding_notice() {
120 echo '<style>
121 .hostinger-onboarding,
122 .hostinger-onboarding-reminder,
123 .hostinger-onboarding-notice,
124 #hostinger-easy-onboarding,
125 .hstm-admin-notice {
126 display: none !important;
127 }
128 </style>';
129 }
130
131 function solace_hostinger_easy_onboarding_notice() {
132 if ( ! function_exists( 'is_plugin_active' ) ) {
133 include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
134 }
135
136 if ( is_plugin_active( 'hostinger-easy-onboarding/hostinger-easy-onboarding.php' ) ) {
137 add_action( 'admin_head', 'solace_hide_hostinger_easy_onboarding_notice' );
138 }
139 }
140 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
141 if ( isset( $_GET['singleproduct'] ) ) {
142 add_action( 'admin_init', 'solace_hostinger_easy_onboarding_notice' );
143 }
144
145
146 /**
147 * The core plugin class that is used to define internationalization,
148 * admin-specific hooks, and public-facing site hooks.
149 */
150 require plugin_dir_path( __FILE__ ) . 'includes/class-solace-extra.php';
151
152 if (class_exists('Elementor\Plugin')) {
153 require plugin_dir_path( __FILE__ ) . 'elementor/widgets/elementor.php';
154 require_once( __DIR__ . '/elementor/widgets/controls/gradient-text.php' );
155 require_once( __DIR__ . '/elementor/widgets/functions.php' );
156 require_once( __DIR__ . '/elementor/widgets/woocommerce/functions.php' );
157
158 /**
159 * Registers Elementor widgets for the Solace Extra plugin.
160 *
161 * This function registers the Elementor List Widget and oEmbed Widget for use within the Solace Extra plugin.
162 *
163 * @param Elementor\Elements_Manager $widgets_manager The Elementor widgets manager.
164 */
165 function solace_extra_register_widget_elementor( $widgets_manager ) {
166 require_once( __DIR__ . '/elementor/widgets/widget/nav-menu/nav-menu.php' );
167 require_once( __DIR__ . '/elementor/widgets/widget/purchase-summary/purchase-summary.php' );
168 require_once( __DIR__ . '/elementor/widgets/widget/site-logo/site-logo.php' );
169 require_once( __DIR__ . '/elementor/widgets/widget/shop/shop.php' );
170 require_once( __DIR__ . '/elementor/widgets/widget/shop/cart.php' );
171 require_once( __DIR__ . '/elementor/widgets/widget/shop/minicart.php' );
172 require_once( __DIR__ . '/elementor/widgets/widget/shop/checkout.php' );
173 require_once( __DIR__ . '/elementor/widgets/widget/shop/myaccount.php' );
174 require_once( __DIR__ . '/elementor/widgets/widget/shop/related-product.php' );
175 require_once( __DIR__ . '/elementor/widgets/widget/shop/product-addtocart.php' );
176 require_once( __DIR__ . '/elementor/widgets/widget/shop/producttab.php' );
177 require_once( __DIR__ . '/elementor/widgets/widget/shop/separator.php' );
178 require_once( __DIR__ . '/elementor/widgets/widget/archive-posts/archive-posts.php' );
179 // require_once( __DIR__ . '/elementor/widgets/widget/form-builder/form-builder.php' );
180 require_once( __DIR__ . '/elementor/widgets/widget/post-author/post-author.php' );
181 require_once( __DIR__ . '/elementor/widgets/widget/post-categories/post-categories.php' );
182 // require_once( __DIR__ . '/elementor/widgets/widget/post-date/post-date.php' );
183 require_once( __DIR__ . '/elementor/widgets/widget/post-excerpt/post-excerpt.php' );
184 require_once( __DIR__ . '/elementor/widgets/widget/post-title/post-title.php' );
185 require_once( __DIR__ . '/elementor/widgets/widget/post-featuredimage/featuredimage.php' );
186 require_once( __DIR__ . '/elementor/widgets/widget/post-fullcontent/fullcontent.php' );
187 require_once( __DIR__ . '/elementor/widgets/widget/post-tags/post-tags.php' );
188 require_once( __DIR__ . '/elementor/widgets/widget/post-datetime/post-datetime.php' );
189 require_once( __DIR__ . '/elementor/widgets/widget/post-comments/post-comments.php' );
190 require_once( __DIR__ . '/elementor/widgets/widget/post-breadcrumb/post-breadcrumb.php' );
191 require_once( __DIR__ . '/elementor/widgets/widget/post-navigation/post-navigation.php' );
192 require_once( __DIR__ . '/elementor/widgets/widget/social-share/social-share.php' );
193 require_once( __DIR__ . '/elementor/widgets/widget/post-relatedpost/post-relatedpost.php' );
194
195 // Define the WooCommerce widgets directory.
196 $woocommerce_dir = __DIR__ . '/elementor/widgets/woocommerce';
197
198 // Check if the folder exists before proceeding.
199 if ( is_dir( $woocommerce_dir ) ) {
200 solace_extra_register_woocommerce_widgets_recursively( $woocommerce_dir, $widgets_manager );
201 }
202
203 $widgets_manager->register( new \Solace_Extra_Nav_Menu() );
204 $widgets_manager->register( new \Solace_Extra_Purchase_Summary() );
205 // $widgets_manager->register( new \Solace_Extra_Navigation_Menu() );
206 $widgets_manager->register( new \Solace_Extra_Site_Logo() );
207 $widgets_manager->register( new \Solace_Extra_WooCommerce_Shop() );
208 $widgets_manager->register( new \Solace_Extra_WooCommerce_Cart() );
209 $widgets_manager->register( new \Solace_Extra_WooCommerce_MiniCart() );
210 $widgets_manager->register( new \Solace_Extra_WooCommerce_MyAccount() );
211 $widgets_manager->register( new \Solace_Extra_WooCommerce_Checkout() );
212 // $widgets_manager->register( new \Solace_Extra_WooCommerce_AddToCart() );
213 $widgets_manager->register( new \Solace_Extra_WooCommerce_Related_Products() );
214 $widgets_manager->register( new \Solace_Extra_WooCommerce_ProductAddToCart() );
215 $widgets_manager->register( new \Solace_Extra_WooCommerce_ProductTab() );
216 $widgets_manager->register( new \Solace_Extra_WooCommerce_Separator() );
217
218 $widgets_manager->register( new \Solace_Extra_Post_Archive() );
219 // $widgets_manager->register( new \Solace_Form_Builder() );
220 $widgets_manager->register( new \Solace_Extra_Post_Author() );
221 $widgets_manager->register( new \Solace_Extra_Post_Categories() );
222 // $widgets_manager->register( new \Solace_Extra_Post_Date() );
223 $widgets_manager->register( new \Solace_Extra_Post_Excerpt() );
224 $widgets_manager->register( new \Solace_Extra_Post_Title() );
225 $widgets_manager->register( new \Solace_Extra_Post_Featured_Image() );
226 $widgets_manager->register( new \Solace_Extra_Post_Full_Content() );
227 $widgets_manager->register( new \Solace_Extra_Post_Tags() );
228 $widgets_manager->register( new \Solace_Extra_Post_Date_Time() );
229 $widgets_manager->register( new \Solace_Extra_Post_Comments() );
230 $widgets_manager->register( new \Solace_Extra_Post_Breadcrumb() );
231 $widgets_manager->register( new \Solace_Extra_Post_Navigation() );
232 $widgets_manager->register( new \Solace_Extra_Post_RelatedPost() );
233 $widgets_manager->register( new \Solace_Social_Share_Widget() );
234 }
235 add_action( 'elementor/widgets/register', 'solace_extra_register_widget_elementor' );
236
237
238 /**
239 * Adds a new category to the Elementor widgets manager for the Solace Extra plugin.
240 *
241 * This function adds a new category named 'Solace Extra' with an icon of 'eicon-star' to the Elementor widgets manager.
242 *
243 * @param Elementor\Elements_Manager $elements_manager The Elementor widgets manager.
244 */
245 function solace_extra_add_elementor_widget_categories( $elements_manager ) {
246
247 $elements_manager->add_category(
248 'solace-extra',
249 [
250 'title' => esc_html__( 'Solace Extra', 'solace-extra' ),
251 'icon' => 'eicon-star',
252 ]
253 );
254
255 foreach ( solace_extra_widget_categories() as $id => $data ) {
256 $elements_manager->add_category(
257 $id,
258 [
259 'title' => $data['title'],
260 'icon' => $data['icon'],
261 ]
262 );
263 }
264 }
265 add_action( 'elementor/elements/categories_registered', 'solace_extra_add_elementor_widget_categories' );
266
267 }
268
269 /**
270 * Begins execution of the plugin.
271 *
272 * Since everything within the plugin is registered via hooks,
273 * then kicking off the plugin from this point in the file does
274 * not affect the page life cycle.
275 *
276 * @since 1.0.0
277 */
278 function solace_extra_run() {
279 $plugin = new Solace_Extra();
280 $plugin->run();
281
282 // Include the dynamic tags functionality file located in the 'dynamic-tags' directory.
283 // require plugin_dir_path( __FILE__ ) . 'admin/dynamic-tags/dynamic-tags.php';
284
285 }
286 solace_extra_run();
287
288 add_action('init', 'solace_extra_handle_logo_upload');
289
290 function solace_extra_handle_logo_upload() {
291 // phpcs:ignore WordPress.Security.NonceVerification.Missing
292 if (isset($_POST['action']) && $_POST['action'] === 'upload_logo_image') {
293
294 // Verify the nonce to ensure the request is legitimate
295 if (!isset($_POST['solace_conditions_nonce']) || !wp_verify_nonce(sanitize_key(wp_unslash($_POST['solace_conditions_nonce'])), 'solace_conditions_nonce_action')) {
296 wp_send_json_error('Invalid nonce.');
297 return;
298 }
299
300 // Check user capability.
301 if ( ! current_user_can( 'manage_options' ) ) {
302 wp_send_json_error( 'Unauthorized.' );
303 }
304 $method = !empty($_SERVER['REQUEST_METHOD']) ? sanitize_text_field(wp_unslash($_SERVER['REQUEST_METHOD'])) : '';
305
306 if ($method === 'POST') {
307 $image_url = ! empty( $_POST['logo_image_url'] ) ? esc_url_raw( wp_unslash( $_POST['logo_image_url'] ) ) : '';
308
309 // Use wp_remote_get() instead of file_get_contents()
310 $response = wp_remote_get($image_url);
311
312 if (is_wp_error($response)) {
313 // Handle request error
314 wp_die(esc_html('Logo download failed. Error: ' . $response->get_error_message()));
315 }
316
317 $body = wp_remote_retrieve_body($response);
318
319 // Upload the image to media library
320 $upload = wp_upload_bits(basename($image_url), null, $body);
321
322 if (!$upload['error']) {
323 // Attach the image to the media library
324 $attachment = array(
325 'post_mime_type' => wp_remote_retrieve_header($response, 'content-type'), // Use content-type from response
326 'post_title' => sanitize_file_name(basename($image_url)),
327 'post_content' => '',
328 'post_status' => 'inherit'
329 );
330
331 $attach_id = wp_insert_attachment($attachment, $upload['file']);
332
333 require_once ABSPATH . 'wp-admin/includes/image.php';
334 $attach_data = wp_generate_attachment_metadata($attach_id, $upload['file']);
335 wp_update_attachment_metadata($attach_id, $attach_data);
336
337 // Set the logo setting in Customizer
338 set_theme_mod('custom_logo', $attach_id);
339
340 // Redirect back to the page where the form was submitted
341 $referer = ! empty( $_SERVER['HTTP_REFERER'] ) ? esc_url_raw( wp_unslash( $_SERVER['HTTP_REFERER'] ) ) : '';
342 wp_safe_redirect( $referer );
343 exit();
344 } else {
345 // Handle upload error
346 wp_die(esc_html('Logo upload failed. Error: ' . $upload['error']));
347 }
348 }
349 }
350 }
351 add_action('wp_ajax_solace_extra_upload_logo', 'solace_extra_upload_logo');
352 add_action('wp_ajax_nopriv_solace_extra_upload_logo', 'solace_extra_upload_logo');
353
354 if ( ! function_exists( 'solace_is_run_in_shortcode' ) ) {
355
356 /**
357 * solace_is_run_in_shortcode - Returns true when posts run in from shortcode.
358 *
359 * @return bool
360 */
361 function solace_is_run_in_shortcode() {
362 global $solace_is_run_in_shortcode;
363
364 return $solace_is_run_in_shortcode;
365 }
366 }
367
368
369
370 // CODE FOR SITE-BUILDER IS BEGIN HERE
371
372 function solace_register_sitebuilder_post_type() {
373 $labels = array(
374 'name' => _x( 'Site Builder Parts', 'Post type general name', 'solace-extra' ),
375 'singular_name' => _x( 'Site Builder Part', 'Post type singular name', 'solace-extra' ),
376 'menu_name' => _x( 'Website Parts', 'Admin Menu text', 'solace-extra' ),
377 'name_admin_bar' => _x( 'Site Builder Part', 'Add New on Toolbar', 'solace-extra' ),
378 'add_new' => __( 'Create New', 'solace-extra' ),
379 'add_new_item' => __( 'Create New Site Builder Part', 'solace-extra' ),
380 'new_item' => __( 'New Site Builder Part', 'solace-extra' ),
381 'edit_item' => __( 'Edit Site Builder Part', 'solace-extra' ),
382 'view_item' => __( 'View Site Builder Part', 'solace-extra' ),
383 'all_items' => __( 'All Site Builder Parts', 'solace-extra' ),
384 'search_items' => __( 'Search Site Builder Parts', 'solace-extra' ),
385 'not_found' => __( 'No site builder parts found.', 'solace-extra' ),
386 'not_found_in_trash' => __( 'No site builder parts found in Trash.', 'solace-extra' ),
387 );
388
389 $args = array(
390 'labels' => $labels,
391 'public' => true,
392 // 'show_in_menu' => true,
393 'show_in_menu' => 'dashboard', // Set as submenu of Solace menu
394 'menu_position' => 25,
395 // 'rewrite' => array('slug' => 'solace-sitebuilder'),
396 'capability_type' => 'post',
397 'menu_icon' => 'dashicons-editor-code',
398 'supports' => array('title', 'editor', 'thumbnail'),
399
400 'has_archive' => false,
401 'exclude_from_search'=> true,
402 'publicly_queryable' => true,
403 );
404 solace_add_elementor_cpt_support();
405
406 register_post_type( 'solace-sitebuilder', $args );
407 flush_rewrite_rules();
408
409 }
410 add_action( 'init', 'solace_register_sitebuilder_post_type' );
411
412 function solace_add_admin_menus() {
413
414 add_submenu_page(
415 'solace',
416 __('Site Builder Parts', 'solace-extra'),
417 __('Site Builder Parts', 'solace-extra'),
418 'manage_options', // Capability
419 'edit.php?post_type=solace-sitebuilder' // URL submenu
420 );
421 }
422 // add_action('admin_menu', 'solace_add_admin_menus');
423
424 function solace_add_elementor_cpt_support() {
425
426 if ( ! is_admin() ) {
427 return;
428 }
429
430 $cpt_support = get_option( 'elementor_cpt_support' );
431
432 if ( ! $cpt_support ) {
433 update_option( 'elementor_cpt_support', array( 'post', 'page', 'solace-sitebuilder' ) );
434 } elseif ( ! in_array( 'solace-sitebuilder', $cpt_support, true ) ) {
435 $cpt_support[] = 'solace-sitebuilder';
436 update_option( 'elementor_cpt_support', $cpt_support );
437 }
438
439 }
440 // Add Elementor support for the custom post type
441 function solace_add_elementor_support_for_sitebuilder() {
442 \Elementor\Plugin::instance()->elements_manager->add_category(
443 'solace-sitebuilder',
444 array(
445 'title' => __( 'Site Builder Parts', 'solace-extra' ),
446 'icon' => 'fa fa-plug',
447 ),
448 1
449 );
450 }
451 add_action( 'elementor/elements/categories_registered', 'solace_add_elementor_support_for_sitebuilder' );
452
453 require plugin_dir_path( __FILE__ ) . 'sitebuilder/sitebuilder.php';
454
455 // add_action('wp_head', 'solace_display_custom_header');
456 function solace_check_import_status() {
457 // Check user capability.
458 if ( ! current_user_can( 'manage_options' ) ) {
459 wp_send_json_error( 'Unauthorized.' );
460 }
461
462 $status = get_option('solace_extra_import_zip_complete', false);
463 wp_send_json([
464 'completed' => (bool) $status
465 ]);
466 exit;
467 }
468 add_action('wp_ajax_check_import_status', 'solace_check_import_status');
469 add_action('wp_ajax_nopriv_check_import_status', 'solace_check_import_status');
470
471
472 function solace_disable_image_processing() {
473 if (defined('DOING_AJAX') && DOING_AJAX) {
474 // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped,WordPress.Security.NonceVerification.Recommended,WordPress.Security.NonceVerification.Missing
475 $action = isset($_GET['action']) ? sanitize_key(wp_unslash($_GET['action'])) :
476 (isset($_POST['action']) ? sanitize_key(wp_unslash($_POST['action'])) : 'tidak_terdeteksi');
477 // phpcs:enable
478 if ($action === 'wp_import_posts_process') {
479 add_filter('intermediate_image_sizes_advanced', 'solace_disable_sizes');
480 } else {
481 }
482
483 }
484 // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped,WordPress.Security.NonceVerification.Recommended
485 else if (isset($_GET['page']) && $_GET['page'] === 'dashboard-progress') {
486 add_filter('intermediate_image_sizes_advanced', 'solace_disable_sizes');
487 }
488 // phpcs:enable
489 }
490
491 function solace_disable_sizes($sizes) {
492 return [];
493 }
494
495 solace_disable_image_processing();
496
497 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- Used as cron callback, name kept for compatibility
498 function generate_all_thumbnails_for_all_images() {
499 $args = array(
500 'post_type' => 'attachment',
501 'post_mime_type' => 'image',
502 'posts_per_page' => -1,
503 'post_status' => 'any',
504 );
505
506 $query = new WP_Query( $args );
507
508 if ( $query->have_posts() ) {
509
510 while ( $query->have_posts() ) {
511 $query->the_post();
512 $image_id = get_the_ID();
513 generate_thumbnails_for_single_image( $image_id );
514 }
515
516 wp_reset_postdata();
517
518 } else {
519 }
520 }
521
522 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- Used as cron callback, name kept for compatibility
523 function generate_thumbnails_for_single_image( $image_id ) {
524 if ( ! wp_attachment_is_image( $image_id ) ) {
525 return false;
526 }
527
528 $file_path = get_attached_file( $image_id );
529 if ( ! $file_path || ! file_exists( $file_path ) ) {
530 return false;
531 }
532
533 $sizes = array(
534 'solace-single2' => array( 2000, 975 ),
535 'solace-single-default' => array( 1220, 715 ),
536 'solace-default-blog' => array( 1214, 715 ),
537 'solace-related-posts' => array( 250, 277 ),
538 'solace-wc-shop-layout3-layout4-layout6' => array( 350, 500 ),
539
540 'thumbnail' => array( (int) get_option( 'thumbnail_size_w' ), (int) get_option( 'thumbnail_size_h' ) ),
541 'medium' => array( (int) get_option( 'medium_size_w' ), (int) get_option( 'medium_size_h' ) ),
542 'medium_large' => array( (int) get_option( 'medium_large_size_w' ), (int) get_option( 'medium_large_size_h' ) ),
543 'large' => array( (int) get_option( 'large_size_w' ), (int) get_option( 'large_size_h' ) ),
544 );
545
546 $metadata = wp_get_attachment_metadata( $image_id );
547
548 if ( isset( $metadata['sizes'] ) ) {
549 foreach ( $metadata['sizes'] as $size_name => $size_data ) {
550 if ( isset( $sizes[$size_name] ) ) {
551 $file = dirname( $file_path ) . '/' . $size_data['file'];
552 if ( file_exists( $file ) ) {
553 wp_delete_file( $file );
554
555 }
556 }
557 }
558 }
559
560 foreach ( $sizes as $size_name => $dimensions ) {
561 $thumbnail = image_make_intermediate_size( $file_path, $dimensions[0], $dimensions[1], true );
562 if ( $thumbnail ) {
563 $metadata['sizes'][$size_name] = array(
564 'file' => basename( $thumbnail['file'] ),
565 'width' => $thumbnail['width'],
566 'height' => $thumbnail['height'],
567 'mime-type' => get_post_mime_type( $image_id ),
568 );
569 wp_update_attachment_metadata( $image_id, $metadata );
570 } else {
571 }
572 }
573 }
574
575
576 add_action('wp', function() {
577 // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped,WordPress.Security.NonceVerification.Recommended
578 if (isset($_GET['page']) && $_GET['page'] === 'dashboard-congratulations') {
579 if (!wp_next_scheduled('generate_thumbnails_cron')) {
580
581 wp_schedule_single_event(time() + 10, 'generate_thumbnails_cron');
582
583 }
584 }
585 // phpcs:enable
586 });
587
588 add_action('generate_thumbnails_cron', function() {
589 if (get_transient('thumbnails_cron_running')) {
590 return;
591 }
592
593 set_transient('thumbnails_cron_running', true, 0);
594 // phpcs:ignore Squiz.PHP.DiscouragedFunctions.Discouraged
595 set_time_limit(0);
596 ignore_user_abort(true);
597
598
599 $unfinished_jobs = get_transient('unfinished_thumbnails');
600
601 if (empty($unfinished_jobs)) {
602 $args = array(
603 'post_type' => 'attachment',
604 'post_mime_type' => 'image',
605 'post_status' => 'any',
606 'posts_per_page' => -1,
607 'nopaging' => true,
608 );
609
610 remove_all_filters('posts_clauses');
611 delete_transient('unfinished_thumbnails');
612
613 $query = new WP_Query($args);
614 $unfinished_jobs = [];
615
616 if ($query->have_posts()) {
617 while ($query->have_posts()) {
618 $query->the_post();
619 $unfinished_jobs[] = get_the_ID();
620 }
621 wp_reset_postdata();
622 }
623
624 set_transient('unfinished_thumbnails', $unfinished_jobs, 3600);
625 }
626
627 if (!empty($unfinished_jobs)) {
628 $image_id = array_shift($unfinished_jobs);
629 set_transient('unfinished_thumbnails', $unfinished_jobs, 3600);
630
631 generate_thumbnails_for_single_image($image_id);
632
633 if (!empty($unfinished_jobs)) {
634 wp_schedule_single_event(time() + 10, 'generate_thumbnails_cron');
635 } else {
636 delete_transient('unfinished_thumbnails');
637 }
638 }
639
640 delete_transient('thumbnails_cron_running');
641 });
642
643
644 add_action('admin_init', function() {
645 // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped,WordPress.Security.NonceVerification.Recommended
646 if (isset($_GET['page']) && $_GET['page'] === 'dashboard-progress') {
647 foreach (_get_cron_array() as $timestamp => $cron) {
648 foreach ($cron as $hook => $events) {
649 if (strpos($hook, 'generate_thumbnails_cron') !== false) {
650 wp_unschedule_event($timestamp, $hook);
651 }
652 }
653 }
654
655 delete_transient('unfinished_thumbnails');
656 delete_transient('thumbnails_cron_running');
657
658 }
659 // phpcs:enable
660 });
661
662 add_action('admin_init', function() {
663 // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped,WordPress.Security.NonceVerification.Recommended
664 if (isset($_GET['page']) && $_GET['page'] === 'dashboard-congratulations') {
665
666 $cron_url = admin_url('admin-ajax.php?action=run_generate_thumbnails_cron');
667 wp_remote_post($cron_url, array('blocking' => false));
668
669 if (!wp_next_scheduled('generate_thumbnails_cron')) {
670 wp_schedule_single_event(time(), 'generate_thumbnails_cron');
671 }
672 }
673 // phpcs:enable
674 });
675
676
677 add_action('wp_ajax_run_generate_thumbnails_cron', function() {
678 if (get_transient('thumbnails_cron_running')) {
679 wp_send_json_error('Proses sudah berjalan.');
680 return;
681 }
682
683 set_transient('thumbnails_cron_running', true, 3600);
684
685 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Plugin cron hook, name kept for compatibility
686 do_action('generate_thumbnails_cron');
687
688 wp_send_json_success('Proses generate thumbnail dimulai di background.');
689 });
690
691 add_action('wp_ajax_woocommerce_ajax_add_to_cart', 'solace_custom_ajax_add_to_cart');
692 add_action('wp_ajax_nopriv_woocommerce_ajax_add_to_cart', 'solace_custom_ajax_add_to_cart');
693
694 function solace_custom_ajax_add_to_cart() {
695 // phpcs:ignore WordPress.Security.NonceVerification.Missing
696 if (!isset($_POST['product_id'])) {
697 wp_send_json_error(['error' => true, 'message' => 'Product ID is missing.']);
698 }
699
700 // phpcs:ignore WordPress.Security.NonceVerification.Missing
701 $product_id = absint($_POST['product_id']);
702
703 // phpcs:ignore WordPress.Security.NonceVerification.Missing
704 $quantity = isset($_POST['quantity']) ? absint($_POST['quantity']) : 1;
705
706 $added = WC()->cart->add_to_cart($product_id, $quantity);
707
708 if ($added) {
709 wp_send_json_success([
710 'success' => true,
711 'product_url' => wc_get_cart_url()
712 ]);
713 } else {
714 wp_send_json_error([
715 'error' => true,
716 'product_url' => get_permalink($product_id),
717 'message' => 'Failed to add product to cart.'
718 ]);
719 }
720
721 wp_die();
722 }
723 add_action( 'admin_menu', 'solace_register_theme_submenu_dashboard_upgrade_support',999 );
724
725 function solace_register_theme_submenu_dashboard_upgrade_support() {
726 if ( ! function_exists( 'solace_pro_card' ) ) {
727 add_submenu_page(
728 'solace',
729 __( 'Upgrade', 'solace-extra' ),
730 __( 'Upgrade', 'solace-extra' ),
731 'manage_options',
732 'solace-upgrade-link',
733 '__return_null'
734 );
735 }
736
737 $saved_key = get_option( 'solace_license_key', '' );
738 $license_info = false;
739 $license_valid = false;
740
741 if ( ! empty( $saved_key ) && function_exists( 'solace_check_license' ) ) {
742 $license_info = solace_check_license( $saved_key );
743
744 if ( $license_info && isset( $license_info->license ) && $license_info->license === 'valid' ) {
745 $license_valid = true;
746 }
747 }
748
749 if ( $license_valid ) {
750 add_submenu_page(
751 'solace',
752 __( 'Support', 'solace-extra' ),
753 __( 'Support', 'solace-extra' ),
754 'manage_options',
755 'solace-support-link',
756 '__return_null'
757 );
758 }
759 }
760
761 add_action('admin_footer', function() {
762 ?>
763 <script type="text/javascript">
764 jQuery(document).ready(function($){
765 $('a[href="admin.php?page=solace-upgrade-link"]').closest('li').addClass('upgrade-menu-item');
766 $('a[href="admin.php?page=solace-upgrade-link"]')
767 .attr('href', '<?php echo esc_js( esc_url( SOLACE_UPGRADE_URL ) ); ?>')
768 .attr('target','_blank');
769 });
770 </script>
771 <script type="text/javascript">
772 jQuery(document).ready(function($){
773 $('a[href="admin.php?page=solace-support-link"]').closest('li').addClass('support-menu-item');
774 $('a[href="admin.php?page=solace-support-link"]')
775 .attr('href', '<?php echo esc_js( esc_url( SOLACE_SUPPORT_URL ) ); ?>')
776 .attr('target','_blank');
777 });
778 </script>
779 <?php
780 });
781
782 add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), 'solace_plugin_action_links' );
783
784 function solace_plugin_action_links( $links ) {
785 $saved_key = get_option( 'solace_license_key' );
786
787 $license_status = 'inactive';
788
789 if ( ! empty( $saved_key ) && function_exists( 'solace_check_license' ) ) {
790 $license_info = solace_check_license( $saved_key );
791
792 if ( $license_info && isset( $license_info->license ) ) {
793 $license_status = $license_info->license;
794 }
795 }
796
797 if ( $license_status !== 'valid' ) {
798 $upgrade_link = sprintf(
799 '<a href="%s" target="_blank"
800 style="background:#ff8f00; color:#fff; font-weight:bold; padding:4px 8px; margin-right:5px;
801 border-radius:4px; text-decoration:none;">
802 %s
803 </a>',
804 esc_url( SOLACE_UPGRADE_URL ),
805 esc_html__( 'Upgrade', 'solace-extra' )
806 );
807
808 $links[] = $upgrade_link;
809 }
810
811 return $links;
812 }