PluginProbe
Solace Extra / trunk
Solace Extra vtrunk
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 trunk, at solace-extra.php

817 lines 31.6 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.7.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.7.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 require_once( __DIR__ . '/elementor/widgets/solace-custom-css.php' );
158
159 /**
160 * Registers Elementor widgets for the Solace Extra plugin.
161 *
162 * This function registers the Elementor List Widget and oEmbed Widget for use within the Solace Extra plugin.
163 *
164 * @param Elementor\Elements_Manager $widgets_manager The Elementor widgets manager.
165 */
166 function solace_extra_register_widget_elementor( $widgets_manager ) {
167 require_once( __DIR__ . '/elementor/widgets/widget/nav-menu/nav-menu.php' );
168 require_once( __DIR__ . '/elementor/widgets/widget/purchase-summary/purchase-summary.php' );
169 require_once( __DIR__ . '/elementor/widgets/widget/site-logo/site-logo.php' );
170 require_once( __DIR__ . '/elementor/widgets/widget/shop/shop.php' );
171 require_once( __DIR__ . '/elementor/widgets/widget/shop/cart.php' );
172 require_once( __DIR__ . '/elementor/widgets/widget/shop/minicart.php' );
173 require_once( __DIR__ . '/elementor/widgets/widget/shop/checkout.php' );
174 require_once( __DIR__ . '/elementor/widgets/widget/shop/myaccount.php' );
175 require_once( __DIR__ . '/elementor/widgets/widget/shop/related-product.php' );
176 require_once( __DIR__ . '/elementor/widgets/widget/shop/product-addtocart.php' );
177 require_once( __DIR__ . '/elementor/widgets/widget/shop/producttab.php' );
178 require_once( __DIR__ . '/elementor/widgets/widget/shop/separator.php' );
179 require_once( __DIR__ . '/elementor/widgets/widget/archive-posts/archive-posts.php' );
180 // require_once( __DIR__ . '/elementor/widgets/widget/form-builder/form-builder.php' );
181 require_once( __DIR__ . '/elementor/widgets/widget/post-author/post-author.php' );
182 require_once( __DIR__ . '/elementor/widgets/widget/post-categories/post-categories.php' );
183 // require_once( __DIR__ . '/elementor/widgets/widget/post-date/post-date.php' );
184 require_once( __DIR__ . '/elementor/widgets/widget/post-excerpt/post-excerpt.php' );
185 require_once( __DIR__ . '/elementor/widgets/widget/post-title/post-title.php' );
186 require_once( __DIR__ . '/elementor/widgets/widget/post-featuredimage/featuredimage.php' );
187 require_once( __DIR__ . '/elementor/widgets/widget/post-fullcontent/fullcontent.php' );
188 require_once( __DIR__ . '/elementor/widgets/widget/post-tags/post-tags.php' );
189 require_once( __DIR__ . '/elementor/widgets/widget/post-datetime/post-datetime.php' );
190 require_once( __DIR__ . '/elementor/widgets/widget/post-comments/post-comments.php' );
191 require_once( __DIR__ . '/elementor/widgets/widget/post-breadcrumb/post-breadcrumb.php' );
192 require_once( __DIR__ . '/elementor/widgets/widget/post-navigation/post-navigation.php' );
193 require_once( __DIR__ . '/elementor/widgets/widget/social-share/social-share.php' );
194 require_once( __DIR__ . '/elementor/widgets/widget/post-relatedpost/post-relatedpost.php' );
195
196 // Define the WooCommerce widgets directory.
197 $woocommerce_dir = __DIR__ . '/elementor/widgets/woocommerce';
198
199 // Check if the folder exists before proceeding.
200 if ( is_dir( $woocommerce_dir ) ) {
201 solace_extra_register_woocommerce_widgets_recursively( $woocommerce_dir, $widgets_manager );
202 }
203
204 $widgets_manager->register( new \Solace_Extra_Nav_Menu() );
205 $widgets_manager->register( new \Solace_Extra_Purchase_Summary() );
206 // $widgets_manager->register( new \Solace_Extra_Navigation_Menu() );
207 $widgets_manager->register( new \Solace_Extra_Site_Logo() );
208 $widgets_manager->register( new \Solace_Extra_WooCommerce_Shop() );
209 $widgets_manager->register( new \Solace_Extra_WooCommerce_Cart() );
210 $widgets_manager->register( new \Solace_Extra_WooCommerce_MiniCart() );
211 $widgets_manager->register( new \Solace_Extra_WooCommerce_MyAccount() );
212 $widgets_manager->register( new \Solace_Extra_WooCommerce_Checkout() );
213 // $widgets_manager->register( new \Solace_Extra_WooCommerce_AddToCart() );
214 $widgets_manager->register( new \Solace_Extra_WooCommerce_Related_Products() );
215 $widgets_manager->register( new \Solace_Extra_WooCommerce_ProductAddToCart() );
216 $widgets_manager->register( new \Solace_Extra_WooCommerce_ProductTab() );
217 $widgets_manager->register( new \Solace_Extra_WooCommerce_Separator() );
218
219 $widgets_manager->register( new \Solace_Extra_Post_Archive() );
220 // $widgets_manager->register( new \Solace_Form_Builder() );
221 $widgets_manager->register( new \Solace_Extra_Post_Author() );
222 $widgets_manager->register( new \Solace_Extra_Post_Categories() );
223 // $widgets_manager->register( new \Solace_Extra_Post_Date() );
224 $widgets_manager->register( new \Solace_Extra_Post_Excerpt() );
225 $widgets_manager->register( new \Solace_Extra_Post_Title() );
226 $widgets_manager->register( new \Solace_Extra_Post_Featured_Image() );
227 $widgets_manager->register( new \Solace_Extra_Post_Full_Content() );
228 $widgets_manager->register( new \Solace_Extra_Post_Tags() );
229 $widgets_manager->register( new \Solace_Extra_Post_Date_Time() );
230 $widgets_manager->register( new \Solace_Extra_Post_Comments() );
231 $widgets_manager->register( new \Solace_Extra_Post_Breadcrumb() );
232 $widgets_manager->register( new \Solace_Extra_Post_Navigation() );
233 $widgets_manager->register( new \Solace_Extra_Post_RelatedPost() );
234 $widgets_manager->register( new \Solace_Social_Share_Widget() );
235 }
236 add_action( 'elementor/widgets/register', 'solace_extra_register_widget_elementor' );
237
238
239 /**
240 * Adds a new category to the Elementor widgets manager for the Solace Extra plugin.
241 *
242 * This function adds a new category named 'Solace Extra' with an icon of 'eicon-star' to the Elementor widgets manager.
243 *
244 * @param Elementor\Elements_Manager $elements_manager The Elementor widgets manager.
245 */
246 function solace_extra_add_elementor_widget_categories( $elements_manager ) {
247
248 $elements_manager->add_category(
249 'solace-extra',
250 [
251 'title' => esc_html__( 'Solace Extra', 'solace-extra' ),
252 'icon' => 'eicon-star',
253 ]
254 );
255
256 foreach ( solace_extra_widget_categories() as $id => $data ) {
257 $elements_manager->add_category(
258 $id,
259 [
260 'title' => $data['title'],
261 'icon' => $data['icon'],
262 ]
263 );
264 }
265 }
266 add_action( 'elementor/elements/categories_registered', 'solace_extra_add_elementor_widget_categories' );
267
268 }
269
270 /**
271 * Begins execution of the plugin.
272 *
273 * Since everything within the plugin is registered via hooks,
274 * then kicking off the plugin from this point in the file does
275 * not affect the page life cycle.
276 *
277 * @since 1.0.0
278 */
279 function solace_extra_run() {
280 $plugin = new Solace_Extra();
281 $plugin->run();
282
283 // Include the dynamic tags functionality file located in the 'dynamic-tags' directory.
284 // require plugin_dir_path( __FILE__ ) . 'admin/dynamic-tags/dynamic-tags.php';
285
286 }
287 solace_extra_run();
288
289 add_action('init', 'solace_extra_handle_logo_upload');
290
291 function solace_extra_handle_logo_upload() {
292 // phpcs:ignore WordPress.Security.NonceVerification.Missing
293 if (isset($_POST['action']) && $_POST['action'] === 'upload_logo_image') {
294
295 // Verify the nonce to ensure the request is legitimate
296 if (!isset($_POST['solace_conditions_nonce']) || !wp_verify_nonce(sanitize_key(wp_unslash($_POST['solace_conditions_nonce'])), 'solace_conditions_nonce_action')) {
297 wp_send_json_error('Invalid nonce.');
298 return;
299 }
300
301 // Check user capability.
302 if ( ! current_user_can( 'manage_options' ) ) {
303 wp_send_json_error( 'Unauthorized.' );
304 }
305 $method = !empty($_SERVER['REQUEST_METHOD']) ? sanitize_text_field(wp_unslash($_SERVER['REQUEST_METHOD'])) : '';
306
307 if ($method === 'POST') {
308 $image_url = ! empty( $_POST['logo_image_url'] ) ? esc_url_raw( wp_unslash( $_POST['logo_image_url'] ) ) : '';
309
310 // Use wp_remote_get() instead of file_get_contents()
311 $response = wp_remote_get($image_url);
312
313 if (is_wp_error($response)) {
314 // Handle request error
315 wp_die(esc_html('Logo download failed. Error: ' . $response->get_error_message()));
316 }
317
318 $body = wp_remote_retrieve_body($response);
319
320 // Upload the image to media library
321 $upload = wp_upload_bits(basename($image_url), null, $body);
322
323 if (!$upload['error']) {
324 // Attach the image to the media library
325 $attachment = array(
326 'post_mime_type' => wp_remote_retrieve_header($response, 'content-type'), // Use content-type from response
327 'post_title' => sanitize_file_name(basename($image_url)),
328 'post_content' => '',
329 'post_status' => 'inherit'
330 );
331
332 $attach_id = wp_insert_attachment($attachment, $upload['file']);
333
334 require_once ABSPATH . 'wp-admin/includes/image.php';
335 $attach_data = wp_generate_attachment_metadata($attach_id, $upload['file']);
336 wp_update_attachment_metadata($attach_id, $attach_data);
337
338 // Set the logo setting in Customizer
339 set_theme_mod('custom_logo', $attach_id);
340
341 // Redirect back to the page where the form was submitted
342 $referer = ! empty( $_SERVER['HTTP_REFERER'] ) ? esc_url_raw( wp_unslash( $_SERVER['HTTP_REFERER'] ) ) : '';
343 wp_safe_redirect( $referer );
344 exit();
345 } else {
346 // Handle upload error
347 wp_die(esc_html('Logo upload failed. Error: ' . $upload['error']));
348 }
349 }
350 }
351 }
352 add_action('wp_ajax_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 // Verify nonce.
458 if (!isset($_POST['nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'])), 'ajax-nonce')) {
459 wp_send_json_error('Invalid nonce.');
460 }
461
462 // Check user capability.
463 if ( ! current_user_can( 'manage_options' ) ) {
464 wp_send_json_error( 'Unauthorized.' );
465 }
466
467 $status = get_option('solace_extra_import_zip_complete', false);
468 wp_send_json([
469 'completed' => (bool) $status
470 ]);
471 exit;
472 }
473 add_action('wp_ajax_check_import_status', 'solace_check_import_status');
474
475
476 function solace_disable_image_processing() {
477 if (defined('DOING_AJAX') && DOING_AJAX) {
478 // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped,WordPress.Security.NonceVerification.Recommended,WordPress.Security.NonceVerification.Missing
479 $action = isset($_GET['action']) ? sanitize_key(wp_unslash($_GET['action'])) :
480 (isset($_POST['action']) ? sanitize_key(wp_unslash($_POST['action'])) : 'tidak_terdeteksi');
481 // phpcs:enable
482 if ($action === 'wp_import_posts_process') {
483 add_filter('intermediate_image_sizes_advanced', 'solace_disable_sizes');
484 } else {
485 }
486
487 }
488 // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped,WordPress.Security.NonceVerification.Recommended
489 else if (isset($_GET['page']) && $_GET['page'] === 'dashboard-progress') {
490 add_filter('intermediate_image_sizes_advanced', 'solace_disable_sizes');
491 }
492 // phpcs:enable
493 }
494
495 function solace_disable_sizes($sizes) {
496 return [];
497 }
498
499 solace_disable_image_processing();
500
501 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- Used as cron callback, name kept for compatibility
502 function generate_all_thumbnails_for_all_images() {
503 $args = array(
504 'post_type' => 'attachment',
505 'post_mime_type' => 'image',
506 'posts_per_page' => -1,
507 'post_status' => 'any',
508 );
509
510 $query = new WP_Query( $args );
511
512 if ( $query->have_posts() ) {
513
514 while ( $query->have_posts() ) {
515 $query->the_post();
516 $image_id = get_the_ID();
517 generate_thumbnails_for_single_image( $image_id );
518 }
519
520 wp_reset_postdata();
521
522 } else {
523 }
524 }
525
526 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- Used as cron callback, name kept for compatibility
527 function generate_thumbnails_for_single_image( $image_id ) {
528 if ( ! wp_attachment_is_image( $image_id ) ) {
529 return false;
530 }
531
532 $file_path = get_attached_file( $image_id );
533 if ( ! $file_path || ! file_exists( $file_path ) ) {
534 return false;
535 }
536
537 $sizes = array(
538 'solace-single2' => array( 2000, 975 ),
539 'solace-single-default' => array( 1220, 715 ),
540 'solace-default-blog' => array( 1214, 715 ),
541 'solace-related-posts' => array( 250, 277 ),
542 'solace-wc-shop-layout3-layout4-layout6' => array( 350, 500 ),
543
544 'thumbnail' => array( (int) get_option( 'thumbnail_size_w' ), (int) get_option( 'thumbnail_size_h' ) ),
545 'medium' => array( (int) get_option( 'medium_size_w' ), (int) get_option( 'medium_size_h' ) ),
546 'medium_large' => array( (int) get_option( 'medium_large_size_w' ), (int) get_option( 'medium_large_size_h' ) ),
547 'large' => array( (int) get_option( 'large_size_w' ), (int) get_option( 'large_size_h' ) ),
548 );
549
550 $metadata = wp_get_attachment_metadata( $image_id );
551
552 if ( isset( $metadata['sizes'] ) ) {
553 foreach ( $metadata['sizes'] as $size_name => $size_data ) {
554 if ( isset( $sizes[$size_name] ) ) {
555 $file = dirname( $file_path ) . '/' . $size_data['file'];
556 if ( file_exists( $file ) ) {
557 wp_delete_file( $file );
558
559 }
560 }
561 }
562 }
563
564 foreach ( $sizes as $size_name => $dimensions ) {
565 $thumbnail = image_make_intermediate_size( $file_path, $dimensions[0], $dimensions[1], true );
566 if ( $thumbnail ) {
567 $metadata['sizes'][$size_name] = array(
568 'file' => basename( $thumbnail['file'] ),
569 'width' => $thumbnail['width'],
570 'height' => $thumbnail['height'],
571 'mime-type' => get_post_mime_type( $image_id ),
572 );
573 wp_update_attachment_metadata( $image_id, $metadata );
574 } else {
575 }
576 }
577 }
578
579
580 add_action('wp', function() {
581 // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped,WordPress.Security.NonceVerification.Recommended
582 if (isset($_GET['page']) && $_GET['page'] === 'dashboard-congratulations') {
583 if (!wp_next_scheduled('generate_thumbnails_cron')) {
584
585 wp_schedule_single_event(time() + 10, 'generate_thumbnails_cron');
586
587 }
588 }
589 // phpcs:enable
590 });
591
592 add_action('generate_thumbnails_cron', function() {
593 if (get_transient('thumbnails_cron_running')) {
594 return;
595 }
596
597 set_transient('thumbnails_cron_running', true, 0);
598 // phpcs:ignore Squiz.PHP.DiscouragedFunctions.Discouraged
599 set_time_limit(0);
600 ignore_user_abort(true);
601
602
603 $unfinished_jobs = get_transient('unfinished_thumbnails');
604
605 if (empty($unfinished_jobs)) {
606 $args = array(
607 'post_type' => 'attachment',
608 'post_mime_type' => 'image',
609 'post_status' => 'any',
610 'posts_per_page' => -1,
611 'nopaging' => true,
612 );
613
614 remove_all_filters('posts_clauses');
615 delete_transient('unfinished_thumbnails');
616
617 $query = new WP_Query($args);
618 $unfinished_jobs = [];
619
620 if ($query->have_posts()) {
621 while ($query->have_posts()) {
622 $query->the_post();
623 $unfinished_jobs[] = get_the_ID();
624 }
625 wp_reset_postdata();
626 }
627
628 set_transient('unfinished_thumbnails', $unfinished_jobs, 3600);
629 }
630
631 if (!empty($unfinished_jobs)) {
632 $image_id = array_shift($unfinished_jobs);
633 set_transient('unfinished_thumbnails', $unfinished_jobs, 3600);
634
635 generate_thumbnails_for_single_image($image_id);
636
637 if (!empty($unfinished_jobs)) {
638 wp_schedule_single_event(time() + 10, 'generate_thumbnails_cron');
639 } else {
640 delete_transient('unfinished_thumbnails');
641 }
642 }
643
644 delete_transient('thumbnails_cron_running');
645 });
646
647
648 add_action('admin_init', function() {
649 // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped,WordPress.Security.NonceVerification.Recommended
650 if (isset($_GET['page']) && $_GET['page'] === 'dashboard-progress') {
651 foreach (_get_cron_array() as $timestamp => $cron) {
652 foreach ($cron as $hook => $events) {
653 if (strpos($hook, 'generate_thumbnails_cron') !== false) {
654 wp_unschedule_event($timestamp, $hook);
655 }
656 }
657 }
658
659 delete_transient('unfinished_thumbnails');
660 delete_transient('thumbnails_cron_running');
661
662 }
663 // phpcs:enable
664 });
665
666 add_action('admin_init', function() {
667 // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped,WordPress.Security.NonceVerification.Recommended
668 if (isset($_GET['page']) && $_GET['page'] === 'dashboard-congratulations') {
669
670 $cron_url = admin_url('admin-ajax.php?action=run_generate_thumbnails_cron');
671 wp_remote_post($cron_url, array('blocking' => false));
672
673 if (!wp_next_scheduled('generate_thumbnails_cron')) {
674 wp_schedule_single_event(time(), 'generate_thumbnails_cron');
675 }
676 }
677 // phpcs:enable
678 });
679
680
681 add_action('wp_ajax_run_generate_thumbnails_cron', function() {
682 if (get_transient('thumbnails_cron_running')) {
683 wp_send_json_error('Proses sudah berjalan.');
684 return;
685 }
686
687 set_transient('thumbnails_cron_running', true, 3600);
688
689 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Plugin cron hook, name kept for compatibility
690 do_action('generate_thumbnails_cron');
691
692 wp_send_json_success('Proses generate thumbnail dimulai di background.');
693 });
694
695 add_action('wp_ajax_woocommerce_ajax_add_to_cart', 'solace_custom_ajax_add_to_cart');
696 add_action('wp_ajax_nopriv_woocommerce_ajax_add_to_cart', 'solace_custom_ajax_add_to_cart');
697
698 function solace_custom_ajax_add_to_cart() {
699 // Verify nonce to prevent CSRF cart manipulation.
700 check_ajax_referer( 'solace_add_to_cart', 'nonce' );
701 if (!isset($_POST['product_id'])) {
702 wp_send_json_error(['error' => true, 'message' => 'Product ID is missing.']);
703 }
704
705 // phpcs:ignore WordPress.Security.NonceVerification.Missing
706 $product_id = absint($_POST['product_id']);
707
708 // phpcs:ignore WordPress.Security.NonceVerification.Missing
709 $quantity = isset($_POST['quantity']) ? absint($_POST['quantity']) : 1;
710
711 $added = WC()->cart->add_to_cart($product_id, $quantity);
712
713 if ($added) {
714 wp_send_json_success([
715 'success' => true,
716 'product_url' => wc_get_cart_url()
717 ]);
718 } else {
719 wp_send_json_error([
720 'error' => true,
721 'product_url' => get_permalink($product_id),
722 'message' => 'Failed to add product to cart.'
723 ]);
724 }
725
726 wp_die();
727 }
728 add_action( 'admin_menu', 'solace_register_theme_submenu_dashboard_upgrade_support',999 );
729
730 function solace_register_theme_submenu_dashboard_upgrade_support() {
731 if ( ! function_exists( 'solace_pro_card' ) ) {
732 add_submenu_page(
733 'solace',
734 __( 'Upgrade', 'solace-extra' ),
735 __( 'Upgrade', 'solace-extra' ),
736 'manage_options',
737 'solace-upgrade-link',
738 '__return_null'
739 );
740 }
741
742 $saved_key = get_option( 'solace_license_key', '' );
743 $license_info = false;
744 $license_valid = false;
745
746 if ( ! empty( $saved_key ) && function_exists( 'solace_check_license' ) ) {
747 $license_info = solace_check_license( $saved_key );
748
749 if ( $license_info && isset( $license_info->license ) && $license_info->license === 'valid' ) {
750 $license_valid = true;
751 }
752 }
753
754 if ( $license_valid ) {
755 add_submenu_page(
756 'solace',
757 __( 'Support', 'solace-extra' ),
758 __( 'Support', 'solace-extra' ),
759 'manage_options',
760 'solace-support-link',
761 '__return_null'
762 );
763 }
764 }
765
766 add_action('admin_footer', function() {
767 ?>
768 <script type="text/javascript">
769 jQuery(document).ready(function($){
770 $('a[href="admin.php?page=solace-upgrade-link"]').closest('li').addClass('upgrade-menu-item');
771 $('a[href="admin.php?page=solace-upgrade-link"]')
772 .attr('href', '<?php echo esc_js( esc_url( SOLACE_UPGRADE_URL ) ); ?>')
773 .attr('target','_blank');
774 });
775 </script>
776 <script type="text/javascript">
777 jQuery(document).ready(function($){
778 $('a[href="admin.php?page=solace-support-link"]').closest('li').addClass('support-menu-item');
779 $('a[href="admin.php?page=solace-support-link"]')
780 .attr('href', '<?php echo esc_js( esc_url( SOLACE_SUPPORT_URL ) ); ?>')
781 .attr('target','_blank');
782 });
783 </script>
784 <?php
785 });
786
787 add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), 'solace_plugin_action_links' );
788
789 function solace_plugin_action_links( $links ) {
790 $saved_key = get_option( 'solace_license_key' );
791
792 $license_status = 'inactive';
793
794 if ( ! empty( $saved_key ) && function_exists( 'solace_check_license' ) ) {
795 $license_info = solace_check_license( $saved_key );
796
797 if ( $license_info && isset( $license_info->license ) ) {
798 $license_status = $license_info->license;
799 }
800 }
801
802 if ( $license_status !== 'valid' ) {
803 $upgrade_link = sprintf(
804 '<a href="%s" target="_blank"
805 style="background:#ff8f00; color:#fff; font-weight:bold; padding:4px 8px; margin-right:5px;
806 border-radius:4px; text-decoration:none;">
807 %s
808 </a>',
809 esc_url( SOLACE_UPGRADE_URL ),
810 esc_html__( 'Upgrade', 'solace-extra' )
811 );
812
813 $links[] = $upgrade_link;
814 }
815
816 return $links;
817 }