PluginProbe
WPCasa – Real Estate for WordPress / 1.5.4
WPCasa – Real Estate for WordPress v1.5.4
1.5.5 1.5.4 1.5.3 1.5.2 1.5.1 1.5.1.1 trunk 1.2.0 1.2.1 1.2.10 1.2.10.1 1.2.11 1.2.12 1.2.13 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.2.9.1 1.2.9.2 1.3.0 All 31 releases
wpcasa / includes / admin / class-wpsight-admin.php

class-wpsight-admin.php in WPCasa – Real Estate for WordPress 1.5.4, at includes/admin/class-wpsight-admin.php

1,672 lines 56.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 // Exit if accessed directly
3 if ( ! defined( 'ABSPATH' ) )
4 exit;
5
6 /**
7 * WPSight_Admin class
8 */
9 class WPSight_Admin {
10
11 // Variables
12 public $cpt;
13 public $agents;
14 public $settings_page;
15 public $license_page;
16 public $color_scheme;
17 public $helpers;
18 public $translation_notice;
19
20
21 /**
22 * Constructor
23 */
24 public function __construct() {
25
26
27
28 // Include files
29 include_once WPSIGHT_PLUGIN_DIR . '/includes/admin/class-wpsight-cpt.php';
30 include_once WPSIGHT_PLUGIN_DIR . '/includes/admin/class-wpsight-agents.php';
31 include_once WPSIGHT_PLUGIN_DIR . '/includes/admin/class-wpsight-admin-page-settings.php';
32 include_once WPSIGHT_PLUGIN_DIR . '/includes/admin/class-wpsight-admin-page-licenses.php';
33 include_once WPSIGHT_PLUGIN_DIR . '/includes/admin/class-wpsight-admin-color-scheme.php';
34 include_once WPSIGHT_PLUGIN_DIR . '/includes/admin/class-wpsight-admin-helpers.php';
35 include_once WPSIGHT_PLUGIN_DIR . '/includes/admin/class-wpsight-admin-translation-notice.php';
36
37 // Load classes
38 $this->cpt = new WPSight_Admin_CPT();
39 $this->agents = new WPSight_Admin_Agents();
40 $this->settings_page = new WPSight_Admin_Settings();
41 $this->license_page = new WPSight_Admin_Licenses();
42 $this->color_scheme = new WPSight_Admin_Color_Scheme();
43 $this->helpers = new WPSight_Admin_Helpers();
44 $this->translation_notice = new WPSight_Admin_Translation_Notice(
45 array(
46 'textdomain' => 'wpcasa',
47 'project_slug' => 'wpcasa',
48 'plugin_name' => WPSIGHT_NAME,
49 'notice_id' => 'wpsight_translation_notice',
50 'logo_url' => WPSIGHT_PLUGIN_URL . '/assets/img/icon.png',
51 'minimum_percent' => 90,
52 'translation_url' => 'https://translate.wordpress.org/projects/wp-plugins/wpcasa/',
53 'screens' => array(
54 'plugins',
55 'toplevel_page_wpsight-settings',
56 'wpcasa_page_wpsight-addons',
57 'wpcasa_page_wpsight-themes',
58 'wpcasa_page_wpsight-licenses',
59 'wpcasa_page_wpsight-recommendations',
60 ),
61 )
62 );
63
64 // Actions & Filers
65
66 add_action( 'admin_menu', [ $this, 'admin_menu' ], 12 );
67 add_action( 'admin_enqueue_scripts', [ $this, 'admin_enqueue_scripts' ] );
68 add_action( 'upgrader_process_complete', array( $this, 'maybe_set_update_page_redirect' ), 10, 2 );
69 add_action( 'admin_init', array( $this, 'maybe_redirect_to_update_page' ) );
70 add_action( 'admin_init', array( $this, 'maybe_set_review_notice_timestamp' ) );
71 add_action( 'admin_footer-update.php', array( $this, 'maybe_print_update_page_redirect_script' ) );
72
73 add_action( 'admin_notices', [ $this, 'notice_setup' ] );
74 add_action( 'admin_notices', [ $this, 'notice_updater' ] );
75 add_action( 'admin_notices', array( $this, 'notice_review' ) );
76 add_action( 'admin_notices', array( $this, 'notice_theme_update_required' ) );
77 add_action( 'wp_ajax_wpsight_dismiss_review_notice', array( $this, 'dismiss_review_notice' ) );
78
79 add_filter( 'views_upload', [ $this, 'media_custom_views' ] );
80 add_filter( 'views_edit-listing', [ $this, 'listings_custom_views' ] );
81 add_filter( 'views_edit-property', [ $this, 'listings_custom_views' ] );
82 add_filter( 'plugin_row_meta', array( $this, 'plugin_row_meta' ), 10, 2 );
83 add_filter( 'manage_users_columns', [ $this, 'manage_users_columns' ] );
84 add_action( 'manage_users_custom_column', [ $this, 'manage_users_custom_column' ], 10, 3 );
85
86 add_filter( 'install_plugins_tabs', [ $this, 'add_addon_tab' ] );
87 add_action( 'install_plugins_wpcasa_addons', [ $this, 'addons_page' ] );
88 add_action( 'install_themes_wpcasa_themes', [ $this, 'themes_pag ' ] );
89 add_action( 'install_plugins_wpcasa_recommendations', [ $this, 'recommends_page' ] );
90
91 }
92
93 /**
94 * admin_enqueue_scripts()
95 *
96 * Enqueue scripts and styles used
97 * on WordPress admin pages.
98 *
99 * @access public
100 * @uses get_current_screen()
101 * @uses wp_enqueue_style()
102 * @uses wp_register_script()
103 * @uses wp_enqueue_script()
104 *
105 * @since 1.0.0
106 * @updated 1.5.4
107 */
108 public function admin_enqueue_scripts() {
109
110 global $wp_scripts;
111
112 // Script debugging?
113 $suffix = SCRIPT_DEBUG ? '' : '.min';
114
115 $screen = get_current_screen();
116 $post_type = wpsight_post_type();
117
118 // TODO: Delete it till wpcasa 1.7
119 if ( in_array( $screen->id, array( 'plugins' ), true ) ) {
120 wp_enqueue_script( 'jquery-plugins-admin', WPSIGHT_PLUGIN_URL . '/assets/js/wpsight-plugins-admin' . $suffix . '.js', array( 'jquery' ), WPSIGHT_VERSION, true );
121
122 wp_add_inline_script(
123 'jquery-plugins-admin',
124 'var wpsightPluginsAdmin = ' . wp_json_encode(
125 array(
126 'pluginFile' => plugin_basename( WPSIGHT_PLUGIN_DIR . '/wpcasa.php' ),
127 'updatePageUrl' => admin_url( 'admin.php?page=wpsight-about' ),
128 )
129 ) . ';',
130 'before'
131 );
132 }
133
134 wp_enqueue_style( 'wpsight-admin-swiper', WPSIGHT_PLUGIN_URL . '/vendor/swiper/swiper-bundle' . $suffix . '.css', array( 'cmb2-styles' ), '6.7.5' );
135 wp_enqueue_script( 'wpsight-admin-swiper', WPSIGHT_PLUGIN_URL . '/vendor/swiper/swiper-bundle' . $suffix . '.js', array( 'jquery' ), '6.7.5', true );
136
137 wp_enqueue_style( 'wpsight-admin', WPSIGHT_PLUGIN_URL . '/assets/css/wpsight-admin' . $suffix . '.css', array(), WPSIGHT_VERSION );
138
139 if ( in_array( $screen->id, array( 'edit-' . $post_type, $post_type, 'toplevel_page_wpsight-settings', 'wpcasa_page_wpsight-addons', 'wpcasa_page_wpsight-themes', 'wpcasa_page_wpsight-licenses', 'wpcasa_page_wpsight-recommendations', 'wpcasa_page_wpsight-about' ) ) || $screen->id == 'plugin-install' && isset( $_GET['tab'] ) && $_GET['tab'] == 'wpcasa_addons' ) {
140
141 wp_register_script( 'jquery-tiptip', WPSIGHT_PLUGIN_URL . '/assets/js/jquery.tipTip' . $suffix . '.js', array( 'jquery' ), '1.3', true );
142
143 wp_enqueue_style( 'wpsight-admin-ui-framework', WPSIGHT_PLUGIN_URL . '/assets/css/wpsight-admin-ui-framework' . $suffix . '.css', array( 'cmb2-styles' ), WPSIGHT_VERSION );
144 wp_enqueue_style( 'wpsight-listing-admin', WPSIGHT_PLUGIN_URL . '/assets/css/wpsight-listing-admin' . $suffix . '.css', array( 'wpsight-admin-ui-framework', 'cmb2-styles' ), WPSIGHT_VERSION );
145 if ( is_rtl() ) {
146 wp_enqueue_style( 'wpsight-listing-admin-rtl', WPSIGHT_PLUGIN_URL . '/assets/css/wpsight-admin-rtl' . $suffix . '.css', array( 'wpsight-listing-admin' ), WPSIGHT_VERSION );
147 }
148
149 wp_enqueue_style('wp-color-picker');
150
151 wp_enqueue_script( 'wpsight_admin_js', WPSIGHT_PLUGIN_URL . '/assets/js/wpsight-admin' . $suffix . '.js', array( 'jquery', 'jquery-tiptip', 'jquery-ui-datepicker', 'wp-color-picker' ), WPSIGHT_VERSION, true );
152
153 wp_add_inline_script( 'wpsight_admin_js', 'const WPCASA_SETTINGS = ' . wp_json_encode( array(
154 'name' => $this->settings_page->settings_name
155 ) ), 'before' );
156
157 // Load the optional second settings level only on the WPCasa settings screen.
158 if ( 'toplevel_page_wpsight-settings' === $screen->id ) {
159 $settings_style_dependencies = array( 'wpsight-listing-admin' );
160
161 if ( is_rtl() ) {
162 $settings_style_dependencies[] = 'wpsight-listing-admin-rtl';
163 }
164
165 wp_enqueue_style(
166 'wpsight-settings-sidebar',
167 WPSIGHT_PLUGIN_URL . '/assets/css/wpsight-settings-sidebar' . $suffix . '.css',
168 $settings_style_dependencies,
169 WPSIGHT_VERSION
170 );
171
172 wp_enqueue_style(
173 'wpsight-settings-tabs',
174 WPSIGHT_PLUGIN_URL . '/assets/css/wpsight-settings-tabs' . $suffix . '.css',
175 array( 'wpsight-settings-sidebar' ),
176 WPSIGHT_VERSION
177 );
178
179 wp_enqueue_script(
180 'wpsight-settings-sidebar',
181 WPSIGHT_PLUGIN_URL . '/assets/js/wpsight-settings-sidebar' . $suffix . '.js',
182 array( 'jquery', 'wpsight_admin_js' ),
183 WPSIGHT_VERSION,
184 true
185 );
186
187 wp_enqueue_script(
188 'wpsight-settings-tabs',
189 WPSIGHT_PLUGIN_URL . '/assets/js/wpsight-settings-tabs' . $suffix . '.js',
190 array( 'jquery', 'wpsight-settings-sidebar' ),
191 WPSIGHT_VERSION,
192 true
193 );
194 }
195 }
196
197 if ( $screen->id == 'wpcasa_page_wpsight-about' )
198 wp_enqueue_style( 'wpsight-admin-page-about', WPSIGHT_PLUGIN_URL . '/assets/css/wpsight-admin-page-about' . $suffix . '.css', null, WPSIGHT_VERSION );
199
200 if ( in_array( $screen->id, array( 'profile', 'user-edit' ) ) )
201 wp_enqueue_media();
202
203 }
204
205 /**
206 * admin_menu()
207 *
208 * Add WPSight settings main and
209 * sub pages to the admin menu.
210 *
211 * @access public
212 * @uses add_menu_page()
213 * @uses add_submenu_page()
214 * @uses apply_filters()
215 *
216 * @since 1.0.0
217 */
218 public function admin_menu() {
219
220 // WPCasa logo
221 $icon_base64 = "PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNi42NjciIGhlaWdodD0iMjYuNjY3IiB2aWV3Qm94PSIwIDAgMjAgMjAiPjxwYXRoIGQ9Ik0xNy42NCAwSC4zNkEuMzYuMzYgMCAwIDAgMCAuMzZ2MTcuMjhjMCAuMTk5LjE2MS4zNi4zNi4zNmgxNy4yOGEuMzYuMzYgMCAwIDAgLjM2LS4zNlYuMzZhLjM2LjM2IDAgMCAwLS4zNi0uMzZNMy4xMjMgMTQuMDEzdi02LjJjMC0uMjY5LjEyNS0uNTIyLjMzOC0uNjg2TDguNDc1IDMuMjlhLjg2NC44NjQgMCAwIDEgMS4wNSAwbDUuMDE0IDMuODM3YS44Ni44NiAwIDAgMSAuMzM4LjY4NnY2LjJhLjg2NC44NjQgMCAwIDEtLjg2NC44NjRIMy45ODdhLjg2NC44NjQgMCAwIDEtLjg2NC0uODY0IiBzdHlsZT0iZmlsbDojZjBmMGYxIi8+PHBhdGggZD0iTTkuNTIgOC41MjdjLTEuNjU4LS4wODYtMi4xNjIgMS45Ny0xLjYxOSAzLjIxNi40MzIgMS4xNDIgMS44NDMgMS4xMjYgMi44MzYuNzg4di41MTdjLTUuMTQgMS43MDgtNC43NjctNi43NzYuMTg4LTQuNzQ5bC0uMjM3LjUwNGMtLjM1OC0uMTYtLjc1LS4yODItMS4xNjctLjI3NiIgc3R5bGU9ImZpbGw6I2YwZjBmMSIvPjwvc3ZnPg==";
222
223 add_menu_page( WPSIGHT_NAME, WPSIGHT_NAME, 'manage_options', 'wpsight-settings', [ $this->settings_page, 'output' ], 'data:image/svg+xml;base64,' . $icon_base64 );
224
225 add_submenu_page( 'wpsight-settings', WPSIGHT_NAME . ' ' . __( 'Settings', 'wpcasa' ), __( 'Settings', 'wpcasa' ) , 'manage_options', 'wpsight-settings', [ $this->settings_page, 'output' ] );
226
227 if ( apply_filters( 'wpsight_show_addons_page', true ) )
228 add_submenu_page( 'wpsight-settings', WPSIGHT_NAME . ' ' . __( 'Add-Ons', 'wpcasa' ), __( 'Add-Ons', 'wpcasa' ) , 'manage_options', 'wpsight-addons', [ $this, 'addons_page' ] );
229
230 if ( apply_filters( 'wpsight_show_themes_page', true ) )
231 add_submenu_page( 'wpsight-settings', WPSIGHT_NAME . ' ' . __( 'Themes', 'wpcasa' ), __( 'Themes', 'wpcasa' ) , 'manage_options', 'wpsight-themes', [ $this, 'themes_page' ] );
232
233 if ( apply_filters( 'wpsight_show_licenses_page', true ) )
234 add_submenu_page( 'wpsight-settings', WPSIGHT_NAME . ' ' . __( 'Licenses', 'wpcasa' ), __( 'Licenses', 'wpcasa' ) , 'manage_options', 'wpsight-licenses', [ $this->license_page, 'output' ] );
235
236 if ( apply_filters( 'wpsight_show_about_page', true ) )
237 add_submenu_page( 'wpsight-settings', WPSIGHT_NAME . ' ' . __( 'About', 'wpcasa' ), __( 'About', 'wpcasa' ) , 'manage_options', 'wpsight-about', [ $this, 'about_page' ] );
238
239 }
240
241 /**
242 * plugin_row_meta()
243 *
244 * Add support and review links on the plugins overview page.
245 *
246 * @param array $links Existing plugin meta links.
247 * @param string $file Plugin file path.
248 * @uses plugin_basename()
249 * @uses esc_url()
250 * @uses esc_attr__()
251 * @uses esc_html__()
252 * @return array Updated plugin meta links.
253 *
254 * @since 1.5.0
255 */
256 public function plugin_row_meta( $links, $file ) {
257
258 if ( plugin_basename( WPSIGHT_PLUGIN_DIR . '/wpcasa.php' ) !== $file ) {
259 return $links;
260 }
261
262 $custom_links = array(
263 'support' => sprintf(
264 '<a href="%1$s" target="_blank" rel="noopener noreferrer" title="%2$s">%3$s</a>',
265 esc_url( 'https://wordpress.org/support/plugin/wpcasa/' ),
266 esc_attr__( 'Get support for WPCasa', 'wpcasa' ),
267 esc_html__( 'Support', 'wpcasa' )
268 ),
269 'docs' => sprintf(
270 '<a href="%1$s" target="_blank" rel="noopener noreferrer" title="%2$s">%3$s</a>',
271 esc_url( 'https://docs.wpcasa.com/' ),
272 esc_attr__( 'Documentation for WPCasa', 'wpcasa' ),
273 esc_html__( 'Docs', 'wpcasa' )
274 ),
275 'review' => sprintf(
276 '<a href="%1$s" target="_blank" rel="noopener noreferrer" title="%2$s">%3$s <span class="wpsight-plugin-row-meta-stars" aria-hidden="true">&#9733;&#9733;&#9733;&#9733;&#9733;</span></a>',
277 esc_url( 'https://wordpress.org/support/plugin/wpcasa/reviews/#new-post' ),
278 esc_attr__( 'Rate WPCasa on WordPress.org', 'wpcasa' ),
279 esc_html__( 'Rate the plugin', 'wpcasa' )
280 ),
281 );
282
283 return array_merge( $links, $custom_links );
284
285 }
286
287 /**
288 * maybe_set_update_page_redirect()
289 *
290 * Mark the current user for a one-time redirect after an individual WPCasa update.
291 *
292 * @param WP_Upgrader $upgrader Upgrader instance.
293 * @param array $hook_extra Update context data.
294 * @uses current_user_can()
295 * @uses plugin_basename()
296 * @uses update_user_meta()
297 * @uses get_current_user_id()
298 * @return void
299 *
300 * @since 1.5.3
301 */
302 public function maybe_set_update_page_redirect( $upgrader, $hook_extra ) {
303
304 if ( ! current_user_can( 'update_plugins' ) ) {
305 return;
306 }
307
308 if ( wp_doing_ajax() ) {
309 return;
310 }
311
312 if ( empty( $hook_extra['action'] ) || 'update' !== $hook_extra['action'] ) {
313 return;
314 }
315
316 if ( empty( $hook_extra['type'] ) || 'plugin' !== $hook_extra['type'] ) {
317 return;
318 }
319
320 if ( isset( $upgrader->skin->result ) && ( false === $upgrader->skin->result || is_wp_error( $upgrader->skin->result ) ) ) {
321 return;
322 }
323
324 $plugin_file = plugin_basename( WPSIGHT_PLUGIN_DIR . '/wpcasa.php' );
325
326 if ( ! $this->is_individual_wpcasa_update( $hook_extra, $plugin_file ) ) {
327 return;
328 }
329
330 update_user_meta( get_current_user_id(), '_wpsight_update_page_redirect', WPSIGHT_VERSION );
331
332 }
333
334 /**
335 * is_individual_wpcasa_update()
336 *
337 * Check if the update context contains WPCasa as the only updated plugin.
338 *
339 * @param array $hook_extra Update context data.
340 * @param string $plugin_file WPCasa plugin basename.
341 * @return bool True when WPCasa was updated individually.
342 *
343 * @since 1.5.3
344 */
345 protected function is_individual_wpcasa_update( $hook_extra, $plugin_file ) {
346
347 if ( ! empty( $hook_extra['plugin'] ) ) {
348 return $plugin_file === $hook_extra['plugin'];
349 }
350
351 if ( empty( $hook_extra['plugins'] ) || ! is_array( $hook_extra['plugins'] ) ) {
352 return false;
353 }
354
355 $plugins = array_values( array_filter( $hook_extra['plugins'] ) );
356
357 return 1 === count( $plugins ) && $plugin_file === $plugins[0];
358
359 }
360
361 /**
362 * maybe_redirect_to_update_page()
363 *
364 * Redirect the current user once to the WPCasa update information page.
365 *
366 * @uses current_user_can()
367 * @uses get_current_user_id()
368 * @uses get_user_meta()
369 * @uses delete_user_meta()
370 * @uses admin_url()
371 * @uses wp_safe_redirect()
372 * @return void
373 *
374 * @since 1.5.3
375 */
376 public function maybe_redirect_to_update_page() {
377
378 if ( wp_doing_ajax() || wp_doing_cron() || is_network_admin() ) {
379 return;
380 }
381
382 if ( ! current_user_can( 'update_plugins' ) ) {
383 return;
384 }
385
386 $user_id = get_current_user_id();
387
388 if ( ! get_user_meta( $user_id, '_wpsight_update_page_redirect', true ) ) {
389 return;
390 }
391
392 delete_user_meta( $user_id, '_wpsight_update_page_redirect' );
393
394 if ( isset( $_GET['page'] ) && 'wpsight-about' === sanitize_key( wp_unslash( $_GET['page'] ) ) ) {
395 return;
396 }
397
398 wp_safe_redirect( admin_url( 'admin.php?page=wpsight-about' ) );
399 exit;
400
401 }
402
403 /**
404 * maybe_print_update_page_redirect_script()
405 *
406 * Redirect from the classic plugin updater screen after a successful WPCasa update.
407 *
408 * @uses current_user_can()
409 * @uses get_current_user_id()
410 * @uses get_user_meta()
411 * @uses delete_user_meta()
412 * @uses admin_url()
413 * @uses wp_json_encode()
414 * @return void
415 *
416 * @since 1.5.3
417 */
418 public function maybe_print_update_page_redirect_script() {
419
420 if ( ! current_user_can( 'update_plugins' ) ) {
421 return;
422 }
423
424 $user_id = get_current_user_id();
425
426 if ( ! get_user_meta( $user_id, '_wpsight_update_page_redirect', true ) ) {
427 return;
428 }
429
430 delete_user_meta( $user_id, '_wpsight_update_page_redirect' );
431
432 ?>
433 <script type="text/javascript">
434 ( function() {
435 var updatePageUrl = <?php echo wp_json_encode( admin_url( 'admin.php?page=wpsight-about' ) ); ?>;
436
437 if ( window.parent && window.parent !== window ) {
438 window.parent.location.href = updatePageUrl;
439 return;
440 }
441
442 window.location.href = updatePageUrl;
443 }() );
444 </script>
445 <?php
446
447 }
448
449 /**
450 * Adds a new tab to the install-plugins-page.
451 *
452 * @return void
453 */
454 public function add_addon_tab( $tabs ) {
455 $tabs['wpcasa_addons'] = WPSIGHT_NAME . ' <span class="wpcasa-addons">' . __( 'Addons', 'wpcasa' ) . '</span>' ;
456 return $tabs;
457 }
458
459 /**
460 * addons_page()
461 *
462 * Add WPSight addons page to sub menu.
463 *
464 * @access public
465 *
466 * @since 1.0.0
467 */
468 public function addons_page() {
469 $addons = include WPSIGHT_PLUGIN_DIR . '/includes/admin/class-wpsight-admin-page-addons.php';
470 $addons->output();
471 }
472
473 /**
474 * themes_page()
475 *
476 * Add WPSight themes page to sub menu.
477 *
478 * @access public
479 *
480 * @since 1.0.0
481 */
482 public function themes_page() {
483 $themes = include WPSIGHT_PLUGIN_DIR . '/includes/admin/class-wpsight-admin-page-themes.php';
484 $themes->output();
485 }
486
487 /**
488 * about_page()
489 *
490 * Add WPSight about page.
491 *
492 * @access public
493 *
494 * @since 1.0.0
495 */
496 public function about_page() {
497 $about = include WPSIGHT_PLUGIN_DIR . '/includes/admin/class-wpsight-admin-page-about.php';
498 $about->output();
499 }
500
501 /**
502 * Get the outdated bundled WPCasa theme data if an update is required.
503 *
504 * @return array|false
505 */
506 protected function get_outdated_wpcasa_theme_data() {
507
508 $theme = wp_get_theme();
509 $minimum_versions = array(
510 'wpcasa-oslo' => '1.4.1',
511 'wpcasa-madrid' => '1.5.1',
512 'wpcasa-london' => '1.5.1',
513 );
514 $themes_to_check = array(
515 array(
516 'slug' => $theme->get_stylesheet(),
517 'theme' => $theme,
518 ),
519 );
520 $parent_theme = $theme->parent();
521
522 if ( $parent_theme instanceof WP_Theme ) {
523 $themes_to_check[] = array(
524 'slug' => $theme->get_template(),
525 'theme' => $parent_theme,
526 );
527 }
528
529 foreach ( $themes_to_check as $theme_data ) {
530 if ( empty( $minimum_versions[ $theme_data['slug'] ] ) ) {
531 continue;
532 }
533
534 if ( version_compare( $theme_data['theme']->get( 'Version' ), $minimum_versions[ $theme_data['slug'] ], '<' ) ) {
535 return array(
536 'name' => $theme_data['theme']->get( 'Name' ),
537 'current_version' => $theme_data['theme']->get( 'Version' ),
538 'required_version'=> $minimum_versions[ $theme_data['slug'] ],
539 );
540 }
541 }
542
543 return false;
544
545 }
546
547 /**
548 * Display a notice when an outdated bundled WPCasa theme is active.
549 *
550 * @return void
551 */
552 public function notice_theme_update_required() {
553 $theme_data = false;
554
555 if ( ! current_user_can( 'update_themes' ) ) {
556 return;
557 }
558
559 $theme_data = $this->get_outdated_wpcasa_theme_data();
560
561 if ( false === $theme_data ) {
562 return;
563 }
564
565 echo '<div class="notice notice-warning">';
566 echo '<p>';
567 echo wp_kses_post(
568 sprintf(
569 __(
570 '<strong>Theme update required:</strong> Please update %1$s from version %2$s to at least version %3$s so that the location output on the single listing page continues to work correctly.',
571 'wpcasa'
572 ),
573 esc_html( $theme_data['name'] ),
574 esc_html( $theme_data['current_version'] ),
575 esc_html( $theme_data['required_version'] )
576 )
577 );
578 echo '</p>';
579 echo '</div>';
580
581 }
582
583 /**
584 * options()
585 *
586 * Merge option tabs and
587 * return wpsight_options_listings()
588 *
589 * @uses wpsight_options_listings()
590 * @return array $options
591 *
592 * @since 1.0.0
593 * @updated 1.5.4
594 */
595 public static function options() {
596 $options = array(
597 'listings' => array(
598 '<span class="dashicons dashicons-admin-multisite"></span>' . __( 'Listings', 'wpcasa' ),
599 (array) self::options_listings(),
600 array(
601 'tabs' => array(
602 'general' => __( 'General', 'wpcasa' ),
603 'currency' => __( 'Currency', 'wpcasa' ),
604 'listing' => __( 'Listing', 'wpcasa' ),
605 'rental' => __( 'Rental', 'wpcasa' ),
606 ),
607 ),
608 ),
609 // 'search' => array(
610 // '<span class="dashicons dashicons-search"></span>' . __( 'Search', 'wpcasa' ),
611 // (array) self::options_search()
612 // ),
613 'maps' => array(
614 '<span class="dashicons dashicons-location-alt"></span>' . __( 'Maps', 'wpcasa' ),
615 (array) self::options_maps()
616 )
617 );
618
619 $options = apply_filters( 'wpsight_options', $options );
620
621 return $options;
622 }
623
624 /**
625 * licenses()
626 *
627 * Create license array
628 *
629 * @return array $licenses
630 *
631 * @since 1.0.0
632 */
633 public static function licenses() {
634
635 // initialize empty array
636 $licenses = array();
637
638 // add default license
639 $licenses['support_package'] = array(
640 'name' => __( 'Support Package', 'wpcasa' ),
641 'desc' => __( 'To receive support for a free product please enter your support package license key.', 'wpcasa' ),
642 'id' => 'support_package',
643 'section' => 'services',
644 'priority' => 1000
645 );
646
647 // filter licenses
648 $licenses = apply_filters( 'wpsight_licenses', $licenses );
649
650 // sort by priority
651 $licenses = wpsight_sort_array_by_priority( $licenses );
652
653 // return
654 return $licenses;
655
656 }
657
658 /**
659 * options_listings()
660 *
661 * Create theme options array
662 * Listings options
663 *
664 * @uses wpsight_get_option()
665 * @uses wpsight_measurements()
666 * @uses wpsight_currencies()
667 * @uses wpsight_details()
668 * @uses wpsight_rental_periods()
669 * @uses wpsight_date_formats()
670 * @return array $options_listings
671 *
672 * @since 1.0.0
673 * @updated 1.5.4
674 */
675 public static function options_listings() {
676
677 $options_listings = array();
678
679 $options_listings['pageheading_listings'] = array(
680 'name' => __( 'Listings', 'wpcasa' ),
681 'desc' => __( 'Here you can define some basic settings', 'wpcasa' ),
682 'icon' => 'dashicons dashicons-admin-multisite',
683 'link' => 'https://docs.wpcasa.com',
684 'id' => 'pageheading_listings',
685 'position' => 10,
686 'type' => 'pageheading'
687 );
688
689 $options_listings['heading_listings'] = array(
690 'name' => __( 'General Listing Settings', 'wpcasa' ),
691 'desc' => __( 'Here you can define some basic settings', 'wpcasa' ),
692 'id' => 'heading_listings',
693 'position' => 20,
694 'type' => 'heading'
695 );
696
697 $options_listings['listings_page'] = array(
698 'name' => __( 'Listings Page', 'wpcasa' ),
699 'desc' => __( 'Please select the main search results page with the <code>[wpsight_listings]</code> shortcode.', 'wpcasa' ),
700 'id' => 'listings_page',
701 'position' => 30,
702 'type' => 'pages'
703 );
704
705 $options_listings['date_format'] = array(
706 'name' => __( 'Date Format', 'wpcasa' ),
707 'desc' => __( 'Please select the date format for the listings table in the admin.', 'wpcasa' ),
708 'id' => 'date_format',
709 'position' => 40,
710 'type' => 'select',
711 'options' => array_filter( wpsight_date_formats( true ) ),
712 'default' => get_option( 'date_format' )
713 );
714
715 $options_listings['listings_css'] = array(
716 'name' => __( 'Output CSS', 'wpcasa' ),
717 'desc' => __( 'Please uncheck the box to disable the plugin from outputting CSS.', 'wpcasa' ),
718 'id' => 'listings_css',
719 'position' => 50,
720 'type' => 'checkbox',
721 'default' => '1'
722 );
723
724 // Check of old 'property_id' options was active
725 $listing_id_default = wpsight_get_option( 'property_id' ) ? wpsight_get_option( 'property_id' ) : __( 'ID-', 'wpcasa' );
726
727 $options_listings['listing_id'] = array(
728 'name' => __( 'Listing ID Prefix', 'wpcasa' ),
729 'desc' => __( 'The listing ID will be this prefix plus post ID. You can optionally set individual IDs on the listing edit screen.', 'wpcasa' ),
730 'id' => 'listing_id',
731 'position' => 60,
732 'type' => 'text',
733 'default' => $listing_id_default
734 );
735
736 $options_listings['measurement_unit'] = array(
737 'name' => __( 'Measurement Unit', 'wpcasa' ),
738 'desc' => __( 'Please select the general measurement unit. The unit for the listing details can be defined separately.', 'wpcasa' ),
739 'id' => 'measurement_unit',
740 'position' => 70,
741 'type' => 'radio',
742 'class' => 'mini',
743 'options' => array_filter( wpsight_measurements() ),
744 'default' => 'm2'
745 );
746
747 $options_listings['heading_rest_api'] = array(
748 'name' => __( 'REST API', 'wpcasa' ),
749 'id' => 'heading_rest_api',
750 'position' => 75,
751 'type' => 'heading'
752 );
753
754 $options_listings['listings_rest_api'] = array(
755 'name' => __( 'Show in REST API (and block editor)', 'wpcasa' ),
756 'desc' => __( 'Please check the box to show listings and all property taxonomies in the REST API. This is also required to show listings in the block editor.', 'wpcasa' ),
757 'id' => 'listings_rest_api',
758 'position' => 76,
759 'type' => 'checkbox',
760 'default' => '0'
761 );
762
763 $options_listings['heading_media'] = array(
764 'name' => __( 'Media Files', 'wpcasa' ),
765 'id' => 'heading_media',
766 'position' => 78,
767 'type' => 'heading'
768 );
769
770 $options_listings['listings_delete_media'] = array(
771 'name' => __( 'Delete image when the listing is deleted', 'wpcasa' ),
772 'desc' => __( 'Please check the box to delete the listings gallery images and featured image from the WordPress media library when a listing is deleted. <b><u>Please note that file deletion cannot be undone.</u></b>', 'wpcasa' ),
773 'id' => 'listings_delete_media',
774 'position' => 79,
775 'type' => 'checkbox',
776 'default' => '0'
777 );
778
779 $options_listings['heading_currency'] = array(
780 'name' => __( 'Currency', 'wpcasa' ),
781 'id' => 'heading_currency',
782 'position' => 80,
783 'type' => 'heading'
784 );
785
786 $options_listings['currency'] = array(
787 'name' => __( 'Currency', 'wpcasa' ),
788 'desc' => __( 'Please select the currency for the listing prices. If your currency is not listed, please select <code>Other</code>.', 'wpcasa' ),
789 'id' => 'currency',
790 'position' => 90,
791 'type' => 'select',
792 'class' => 'mini',
793 'options' => array_merge( array_filter( wpsight_currencies() ), array( 'other' => __( 'Other', 'wpcasa' ) ) ),
794 'default' => 'usd'
795 );
796
797 $options_listings['currency_other'] = array(
798 'name' => __( 'Other Currency', 'wpcasa' ) . ' (' . __( 'Abbreviation', 'wpcasa' ) . ')',
799 'desc' => __( 'Please insert the abbreviation of your currency (e.g. <code>EUR</code>).', 'wpcasa' ),
800 'id' => 'currency_other',
801 'position' => 100,
802 'type' => 'text',
803 'class' => 'hidden'
804 );
805
806 $options_listings['currency_other_ent'] = array(
807 'name' => __( 'Other Currency', 'wpcasa' ) . ' (' . __( 'Symbol', 'wpcasa' ) . ')',
808 'desc' => __( 'Please insert the currency symbol or HTML entity (e.g. <code>&amp;euro;</code>).', 'wpcasa' ),
809 'id' => 'currency_other_ent',
810 'position' => 110,
811 'type' => 'text',
812 'class' => 'hidden'
813 );
814
815 $options_listings['currency_symbol'] = array(
816 'name' => __( 'Currency Symbol', 'wpcasa' ),
817 'desc' => __( 'Please select the position of the currency symbol.', 'wpcasa' ),
818 'id' => 'currency_symbol',
819 'position' => 120,
820 'type' => 'radio',
821 'options' => array(
822 'before' => __( 'Before the value', 'wpcasa' ),
823 'after' => __( 'After the value', 'wpcasa' ),
824 'before_space' => __( 'Before the value (with Space)', 'wpcasa' ),
825 'after_space' => __( 'After the value (with Space)', 'wpcasa' )
826 ),
827 'default' => 'before'
828 );
829
830 $options_listings['currency_separator'] = array(
831 'name' => __( 'Thousands Separator', 'wpcasa' ),
832 'desc' => __( 'Please select the thousands separator for your listing prices.', 'wpcasa' ),
833 'id' => 'currency_separator',
834 'position' => 130,
835 'type' => 'text',
836 'default' => '.'
837 );
838
839 $options_listings['decimal_separator'] = array(
840 'name' => __( 'Decimal Separator', 'wpcasa' ),
841 'desc' => __( 'Please select the decimal separator for your listing prices.', 'wpcasa' ),
842 'id' => 'decimal_separator',
843 'position' => 131,
844 'type' => 'text',
845 'default' => ','
846 );
847
848 $options_listings['heading_details'] = array(
849 'name' => __( 'Listing Details', 'wpcasa' ),
850 'id' => 'heading_details',
851 'position' => 140,
852 'type' => 'heading'
853 );
854
855 /** Loop through standard details */
856
857 $i=1;
858 $position=150;
859
860 foreach ( wpsight_details() as $detail_id => $value ) {
861
862 $options_listings[ $detail_id ] = array(
863 'name' => __( 'Listing Detail', 'wpcasa' ) . ' #' . $i++,
864 'desc' => $value['description'] ?? '',
865 'id' => $detail_id,
866 'position' => $position++,
867 'type' => 'measurement',
868 'class' => '',
869 'default' => array(
870 'label' => $value['label'],
871 'unit' => $value['unit']
872 )
873 );
874
875 }
876
877 $options_listings['heading_rental_periods'] = array(
878 'name' => __( 'Rental Periods', 'wpcasa' ),
879 'id' => 'heading_rental_periods',
880 'position' => 300,
881 'type' => 'heading'
882 );
883
884 /** Loop through rental periods */
885
886 $i=1;
887 $position=310;
888
889 foreach ( wpsight_rental_periods() as $period => $value ) {
890
891 $options_listings[ $period ] = array(
892 'name' => __( 'Rental Period', 'wpcasa' ) . ' #' . $i++,
893 'id' => $period,
894 'position' => $position++,
895 'type' => 'text',
896 'class' => '',
897 'default' => $value
898 );
899
900 }
901
902 // Assign every core field to its Listings settings tab.
903 $listings_tab_fields = array(
904 'general' => array(
905 'heading_listings',
906 'listings_page',
907 'date_format',
908 'listings_css',
909 'listing_id',
910 'measurement_unit',
911 'heading_rest_api',
912 'listings_rest_api',
913 'heading_media',
914 'listings_delete_media',
915 ),
916 'currency' => array(
917 'heading_currency',
918 'currency',
919 'currency_other',
920 'currency_other_ent',
921 'currency_symbol',
922 'currency_separator',
923 'decimal_separator',
924 ),
925 'listing' => array_merge( array( 'heading_details' ), array_keys( wpsight_details() ) ),
926 'rental' => array_merge( array( 'heading_rental_periods' ), array_keys( wpsight_rental_periods() ) ),
927 );
928
929 foreach ( $listings_tab_fields as $tab_id => $field_ids ) {
930 foreach ( $field_ids as $field_id ) {
931 if ( isset( $options_listings[ $field_id ] ) ) {
932 $options_listings[ $field_id ]['tab'] = $tab_id;
933 }
934 }
935 }
936
937 // filter options
938 $options_listings = apply_filters( 'wpsight_options_listings', $options_listings );
939
940 // sort options by position
941 $options_listings = wpsight_sort_array_by_position( $options_listings );
942
943 return $options_listings;
944
945 }
946
947 /**
948 * options_search()
949 *
950 * Create theme options array
951 * Search options
952 *
953 * @uses wpsight_get_search_fields()
954 * @return array $options_search
955 *
956 * @since 1.1.0
957 */
958 public static function options_search() {
959
960 $options_search = array();
961
962 /** Loop through search fields */
963 $fields = wpsight_get_search_fields();
964
965 $options = array();
966
967 foreach( $fields as $field => $v ) {
968
969 $label = isset($v['label']) ? $v['label'] : '';
970
971 if( $v['type'] == 'taxonomy_select' && $v['data']['show_option_none'] )
972 $label = $v['data']['show_option_none'];
973
974 $options[$field] = $label;
975 }
976
977 $options_search['pageheading_search'] = array(
978 'name' => __( 'Search', 'wpcasa' ),
979 'desc' => __( 'Here you can define some basic settings', 'wpcasa' ),
980 'icon' => 'dashicons dashicons-search',
981 'link' => '',
982 'id' => 'pageheading_search',
983 'position' => 10,
984 'type' => 'pageheading'
985 );
986
987 $options_search['search_elements'] = array(
988 'name' => __( 'Search Form Elements', 'wpcasa' ),
989 'desc' => __( 'Choose what to display in the search form', 'wpcasa' ),
990 'id' => 'search_elements',
991 'position' => 20,
992 'type' => 'multicheck',
993 'options' => $options
994 );
995
996 // filter options
997 $options_search = apply_filters( 'wpsight_options_search', $options_search );
998
999 // sort options by position
1000 $options_search = wpsight_sort_array_by_position( $options_search );
1001
1002 return $options_search;
1003
1004 }
1005
1006 /**
1007 * options_maps()
1008 *
1009 * Create theme options array
1010 * Maps options
1011 *
1012 * @return array $options_maps
1013 *
1014 * @since 1.1.0
1015 */
1016 public static function options_maps() {
1017
1018 $options_maps = array();
1019
1020 $options_maps['pageheading_maps'] = array(
1021 'name' => __( 'Maps', 'wpcasa' ),
1022 'desc' => __( 'Here you can define some basic settings', 'wpcasa' ),
1023 'icon' => 'dashicons dashicons-location-alt',
1024 'link' => 'https://docs.wpcasa.com/article/wpcasa-listings-map/',
1025 'id' => 'pageheading_maps',
1026 'type' => 'pageheading'
1027 );
1028
1029 $options_maps['heading_listings_map_api'] = array(
1030 'name' => __( 'Map API', 'wpcasa' ),
1031 'desc' => __( 'Here you can enter Map API', 'wpcasa' ),
1032 'id' => 'heading_listings_map_api',
1033 'type' => 'heading',
1034 'position' => '490'
1035 );
1036
1037 $options_maps['google_maps_api_key'] = array(
1038 'name' => __( 'Google Maps API', 'wpcasa' ),
1039 /* translators: %s: is the link to google maps */
1040 'desc' => sprintf( __( 'If necessary, please enter your Google Maps API key (<a href="%s" target="_blank">register here</a>).', 'wpcasa' ), 'https://developers.google.com/maps/documentation/javascript/get-api-key' ),
1041 'id' => 'google_maps_api_key',
1042 'type' => 'text',
1043 'position' => '500'
1044 );
1045
1046 // filter options
1047 $options_maps = apply_filters( 'wpsight_options_maps', $options_maps );
1048
1049 // sort options by position
1050 $options_maps = wpsight_sort_array_by_position( $options_maps );
1051
1052 return $options_maps;
1053
1054 }
1055
1056 /**
1057 * options_debug()
1058 *
1059 * Create theme options array
1060 * Listings options
1061 *
1062 * @uses wpsight_get_option()
1063 * @uses wpsight_measurements()
1064 * @uses wpsight_currencies()
1065 * @uses wpsight_details()
1066 * @uses wpsight_rental_periods()
1067 * @uses wpsight_date_formats()
1068 * @return array $options_listings
1069 *
1070 * @since 1.0.0
1071 */
1072 public static function options_debug() {
1073
1074 $options_debug = array();
1075
1076 if( version_compare( '1.1.0', WPSIGHT_VERSION, '>=' ) ) {
1077
1078 $options_debug['example_slider'] = array(
1079 'name' => __( 'Example Slider', 'wpcasa' ),
1080 'desc' => __( 'Example Slider Option', 'wpcasa' ),
1081 'id' => 'example_slider',
1082 'type' => 'range',
1083 'min' => 0,
1084 'max' => 1000,
1085 'step' => 50,
1086 'default' => ''
1087 );
1088
1089 $options_debug['example_number'] = array(
1090 'name' => __( 'Example Number', 'wpcasa' ),
1091 'desc' => __( 'Example Number Option', 'wpcasa' ),
1092 'id' => 'example_number',
1093 'type' => 'number',
1094 'default' => ''
1095 );
1096
1097 }
1098
1099
1100 return apply_filters( 'wpsight_options_debug', $options_debug );
1101
1102 }
1103
1104 /**
1105 * media_custom_views()
1106 *
1107 * Media library views
1108 *
1109 * @param array $views Incoming views
1110 * @uses $wpdb->prepare()
1111 * @uses $wpdb->get_col()
1112 * @uses wp_count_attachments()
1113 * @return array $views Updated views
1114 *
1115 * @since 1.0.0
1116 */
1117 public static function media_custom_views( $views ) {
1118
1119 global $wpdb, $wp_query, $pagenow;
1120
1121 if ( 'upload.php' != $pagenow )
1122 return;
1123
1124 if ( ! isset( $wp_query->query_vars['s'] ) )
1125 return $views;
1126
1127 // Search custom fields for listing ID
1128
1129 $post_ids_meta = $wpdb->get_col( $wpdb->prepare( "
1130 SELECT DISTINCT post_id FROM {$wpdb->postmeta}
1131 WHERE meta_value LIKE %s
1132 ", $wp_query->query_vars['s'] ) );
1133
1134 if ( ! empty( $post_ids_meta ) && get_search_query() !== null ) {
1135
1136 unset( $views );
1137
1138 $s = get_search_query();
1139 $_num_posts = (array) wp_count_attachments();
1140 $_total_posts = array_sum( $_num_posts ) - $_num_posts['trash'];
1141
1142 $views['all'] = '<a href="' . $pagenow . '">' . __( 'All', 'wpcasa' ) . ' <span class="count">(' . $_total_posts . ')</span></a>';
1143 $views['found'] = '<a href="' . $pagenow . '?s=' . $s . '" class="current">' . $s . ' <span class="count">(' . $wp_query->found_posts . ')</span></a>';
1144 }
1145
1146 return $views;
1147 }
1148
1149 /**
1150 * listings_custom_views()
1151 *
1152 * Listing views
1153 *
1154 * @param array $views Incoming views
1155 * @uses $wpdb->prepare()
1156 * @uses $wpdb->get_col()
1157 * @return array $views Updated views
1158 *
1159 * @since 1.0.0
1160 */
1161 public static function listings_custom_views( $views ) {
1162 global $wpdb, $wp_query, $pagenow;
1163
1164 if ( 'edit.php' != $pagenow )
1165 return;
1166
1167 // Replace 'Published' with 'Active'
1168
1169 if( isset( $views['publish'] ) )
1170 $views['publish'] = str_replace( __( 'Published', 'wpcasa' ), __( 'Active', 'wpcasa' ), $views['publish'] );
1171
1172 if ( empty( $wp_query->query_vars['s'] ) )
1173 return $views;
1174
1175 // Search custom fields for listing ID
1176
1177 $post_ids_meta = $wpdb->get_col( $wpdb->prepare( "
1178 SELECT DISTINCT post_id FROM $wpdb->postmeta
1179 WHERE meta_value LIKE %s
1180 ", $wp_query->query_vars['s'] ) );
1181
1182 if ( empty( $post_ids_meta ) )
1183 return $views;
1184
1185 }
1186
1187 /**
1188 * manage_users_columns()
1189 *
1190 * Add column for number of listings of a user.
1191 *
1192 * @param array $columns Incoming columns
1193 * @return array $columns Updated columns
1194 *
1195 * @since 1.0.0
1196 */
1197 public static function manage_users_columns( $columns ) {
1198 $columns['listings_count'] = __( 'Listings', 'wpcasa' );
1199 return $columns;
1200 }
1201
1202 /**
1203 * manage_users_custom_column()
1204 *
1205 * Show number of listings the user has
1206 *
1207 * @param string $value
1208 * @param string $column_name
1209 * @param int $user_id
1210 * @uses count_user_posts()
1211 * @uses wpsight_post_type()
1212 * @return string new value
1213 *
1214 * @since 1.0.0
1215 */
1216 public static function manage_users_custom_column( $value, $column_name, $user_id ) {
1217
1218 if ( 'listings_count' != $column_name )
1219 return $value;
1220
1221 $listings_count = count_user_posts( $user_id, wpsight_post_type() );
1222 $user_listings_links = '<a href="edit.php?author=' . $user_id . '&post_type=' . wpsight_post_type() . '">' . $listings_count . '</a>';
1223
1224 return $user_listings_links;
1225
1226 }
1227
1228
1229
1230 /**
1231 * check_license()
1232 *
1233 * Check a specific license.
1234 *
1235 * @uses get_option()
1236 * @uses urlencode()
1237 * @uses home_url()
1238 * @uses wp_remote_post()
1239 * @uses is_wp_error()
1240 * @uses wp_remote_retrieve_body()
1241 * @uses json_decode()
1242 * @uses delete_option()
1243 * @return string valid|invalid
1244 *
1245 * @since 1.0.0
1246 */
1247 // public static function check_license( $id = '', $item = '' ) {
1248 //
1249 // $licenses = get_option( 'wpsight_licenses' );
1250 //
1251 // // retrieve the license from the database
1252 // $license = isset( $licenses[ $id ] ) ? trim( $licenses[ $id ] ) : false;
1253 //
1254 // $api_params = array(
1255 // 'edd_action'=> 'check_license',
1256 // 'license' => $license,
1257 // 'item_name' => urlencode( $item ),
1258 // 'url' => home_url()
1259 // );
1260 //
1261 // // Call the custom API.
1262 // $response = wp_remote_post( WPSIGHT_SHOP_URL, array( 'timeout' => 15, 'sslverify' => false, 'body' => $api_params ) );
1263 //
1264 // if ( is_wp_error( $response ) )
1265 // return false;
1266 //
1267 // $license_data = json_decode( wp_remote_retrieve_body( $response ) );
1268 //// var_dump($license_data);
1269 // update_option( 'wpsight_' . $id . '_status', $license_data->license );
1270 //
1271 //
1272 //
1273 // return $license_data->license;
1274 //
1275 //// if( $license_data->license == 'valid' ) {
1276 //// return 'valid';
1277 //// } else {
1278 //// //delete_option( 'wpsight_' . $id . '_status' );
1279 //// return 'invalid';
1280 //// }
1281 //
1282 // }
1283
1284 /**
1285 * is_premium()
1286 *
1287 * Check if premium is active.
1288 * Premium is at least one active and valid license
1289 * which grants access to specific features and support
1290 *
1291 * @uses get_option()
1292 * @uses wpsight_licenses()
1293 * @uses in_array()
1294 * @return bool true|false
1295 *
1296 * @since 1.2.0
1297 */
1298 // public static function is_premium() {
1299 // var_dump(wpsight_licenses());
1300 // foreach( wpsight_licenses() as $id => $license )
1301 // $keys[$id] = get_transient( 'wpsight_' . $license['id'] )->license;
1302 //
1303 // if( in_array( 'valid', $keys ) )
1304 // return true;
1305 //
1306 // return false;
1307 //
1308 // }
1309
1310 /**
1311 * maybe_set_review_notice_timestamp()
1312 *
1313 * Make sure the review notice timestamp exists.
1314 * This keeps older installations compatible.
1315 *
1316 * @uses get_option()
1317 * @uses current_time()
1318 * @uses update_option()
1319 * @return void
1320 *
1321 * @since 1.5.0
1322 */
1323 public function maybe_set_review_notice_timestamp() {
1324
1325 $options = get_option( WPSIGHT_DOMAIN, array() );
1326
1327 if ( ! is_array( $options ) ) {
1328 $options = array();
1329 }
1330
1331 if ( ! empty( $options['review_notice_timestamp'] ) ) {
1332 return;
1333 }
1334
1335 $options['review_notice_timestamp'] = current_time( 'timestamp' );
1336
1337 update_option( WPSIGHT_DOMAIN, $options );
1338
1339 }
1340
1341 /**
1342 * should_show_review_notice()
1343 *
1344 * Check if the review notice should be displayed.
1345 *
1346 * @uses current_user_can()
1347 * @uses get_current_user_id()
1348 * @uses get_user_meta()
1349 * @uses wpsight_get_option()
1350 * @uses current_time()
1351 * @return bool True if the notice should be shown.
1352 *
1353 * @since 1.5.0
1354 */
1355 protected function should_show_review_notice() {
1356
1357 $timestamp = absint( wpsight_get_option( 'review_notice_timestamp', false ) );
1358
1359 if ( ! current_user_can( 'manage_options' ) ) {
1360 return false;
1361 }
1362
1363 if ( get_user_meta( get_current_user_id(), 'wpsight_review_notice_dismissed', true ) ) {
1364 return false;
1365 }
1366
1367 if ( empty( $timestamp ) ) {
1368 return false;
1369 }
1370
1371 return current_time( 'timestamp' ) >= ( $timestamp + ( 7 * DAY_IN_SECONDS ) );
1372
1373 }
1374
1375 /**
1376 * get_review_notice_recipient_name()
1377 *
1378 * Get the current user's name for the review notice.
1379 * Use first name and last name when available.
1380 * Fall back to display name when first name is empty.
1381 *
1382 * @uses wp_get_current_user()
1383 * @return string Recipient name.
1384 *
1385 * @since 1.5.0
1386 */
1387 protected function get_review_notice_recipient_name() : string {
1388
1389 $current_user = wp_get_current_user();
1390 $first_name = isset( $current_user->first_name ) ? trim( $current_user->first_name ) : '';
1391 $display_name = isset( $current_user->display_name ) ? trim( $current_user->display_name ) : '';
1392
1393 if ( empty( $first_name ) ) {
1394 return $display_name;
1395 }
1396
1397 return $first_name;
1398
1399 }
1400
1401 /**
1402 * notice_review()
1403 *
1404 * Show the review notice after the waiting period has passed.
1405 *
1406 * @uses self::should_show_review_notice()
1407 * @uses esc_url()
1408 * @uses esc_attr__()
1409 * @uses esc_html__()
1410 * @uses wp_create_nonce()
1411 * @uses wp_kses()
1412 * @return void
1413 *
1414 * @since 1.5.0
1415 */
1416 public function notice_review() {
1417
1418 if ( ! $this->should_show_review_notice() ) {
1419 return;
1420 }
1421
1422 $review_url = 'https://wordpress.org/plugins/wpcasa/#reviews';
1423 $image_url = WPSIGHT_PLUGIN_URL . '/assets/img/icon.png';
1424 $user_name = '<b>' . esc_html__( $this->get_review_notice_recipient_name() ) . '</b>' ;
1425 $stars_link = sprintf(
1426 '<a href="%1$s" target="_blank" rel="noopener noreferrer" class="wpsight-review-notice__text-link wpsight-review-notice__stars" aria-label="%2$s">&#9733;&#9733;&#9733;&#9733;&#9733;</a>',
1427 esc_url( $review_url ),
1428 esc_attr__( 'Rate WPCasa on WordPress.org', 'wpcasa' )
1429 );
1430 $wporg_link = sprintf(
1431 '<a href="%1$s" target="_blank" rel="noopener noreferrer" class="wpsight-review-notice__text-link">%2$s</a>',
1432 esc_url( $review_url ),
1433 esc_html__( 'WordPress.org', 'wpcasa' )
1434 );
1435 $message = sprintf(
1436 wp_kses(
1437 __( 'Hi %1$s, you have used this free plugin for some time now, and we hope you like it!<br>The contributors of WPCasa have spent countless hours developing it, and it would mean a lot to us if you could rate WPCasa %2$s on %3$s to help us spread the word.<br>It costs you nothing but helps us a lot. We really appreciate your time!', 'wpcasa' ),
1438 array(
1439 'a' => array(
1440 'aria-label' => array(),
1441 'class' => array(),
1442 'href' => array(),
1443 'rel' => array(),
1444 'target' => array(),
1445 ),
1446 'b' => array(),
1447 'br' => array(),
1448 )
1449 ),
1450 $user_name,
1451 $stars_link,
1452 $wporg_link
1453 );
1454
1455 echo '<div class="notice notice-info is-dismissible wpsight-review-notice" data-nonce="' . esc_attr( wp_create_nonce( 'wpsight_dismiss_review_notice' ) ) . '">';
1456 echo '<div class="wpsight-review-notice__inner">';
1457 echo '<div class="wpsight-review-notice__media">';
1458 echo '<img src="' . esc_url( $image_url ) . '" alt="' . esc_attr__( 'WPCasa', 'wpcasa' ) . '" class="wpsight-review-notice__image" />';
1459 echo '</div>';
1460 echo '<div class="wpsight-review-notice__content">';
1461 echo '<p class="wpsight-review-notice__text">' . $message . '</p>';
1462 echo '<p class="wpsight-review-notice__actions">';
1463 echo '<a href="' . esc_url( $review_url ) . '" target="_blank" rel="noopener noreferrer" class="wpsight-review-notice__button"><span class="wpsight-review-notice__button-icon wpsight-review-notice__button-icon-star">&#9733;</span>' . esc_html__( 'Review WPCasa', 'wpcasa' ) . '</a>';
1464 echo '<button type="button" class="wpsight-review-notice__button wpsight-review-notice__button-dismiss"><span class="wpsight-review-notice__button-icon wpsight-review-notice__button-icon-close">&#x2705;</span>' . esc_html__( "I've already done it", 'wpcasa' ) . '</button>';
1465 echo '</p>';
1466 echo '</div>';
1467 echo '</div>';
1468 echo '</div>';
1469
1470 ?>
1471 <script>
1472 jQuery( function( $ ) {
1473 var $notice = $( '.wpsight-review-notice' );
1474 var dismissNotice = function() {
1475 $.post(
1476 ajaxurl,
1477 {
1478 action: 'wpsight_dismiss_review_notice',
1479 nonce: $notice.data( 'nonce' )
1480 }
1481 );
1482 };
1483
1484 if ( ! $notice.length ) {
1485 return;
1486 }
1487
1488 $notice.on( 'click', '.notice-dismiss', function() {
1489 dismissNotice();
1490 } );
1491
1492 $notice.on( 'click', '.wpsight-review-notice__button-dismiss', function() {
1493 dismissNotice();
1494 $notice.fadeOut( 180, function() {
1495 $notice.remove();
1496 } );
1497 } );
1498 } );
1499 </script>
1500 <?php
1501
1502 }
1503
1504 /**
1505 * dismiss_review_notice()
1506 *
1507 * Save the dismiss state for the current user.
1508 *
1509 * @uses current_user_can()
1510 * @uses check_ajax_referer()
1511 * @uses get_current_user_id()
1512 * @uses current_time()
1513 * @uses update_user_meta()
1514 * @uses wp_send_json_error()
1515 * @uses wp_send_json_success()
1516 * @return void
1517 *
1518 * @since 1.5.0
1519 */
1520 public function dismiss_review_notice() {
1521
1522 if ( ! current_user_can( 'manage_options' ) ) {
1523 wp_send_json_error();
1524 }
1525
1526 check_ajax_referer( 'wpsight_dismiss_review_notice', 'nonce' );
1527
1528 update_user_meta( get_current_user_id(), 'wpsight_review_notice_dismissed', current_time( 'timestamp' ) );
1529
1530 wp_send_json_success();
1531
1532 }
1533
1534 /**
1535 * notice_setup()
1536 *
1537 * Check if premium is active.
1538 * Premium is at least one active and valid license
1539 * which grants access to specific features and support
1540 *
1541 * @uses get_option()
1542 * @uses wpsight_licenses()
1543 * @uses in_array()
1544 * @return bool true|false
1545 *
1546 * @since 1.2.0
1547 */
1548 public static function notice_setup() {
1549
1550 if( empty( wpsight_get_option( 'listings_page' ) ) ) {
1551
1552 $link = admin_url() . 'admin.php?page=wpsight-settings#settings-listings';
1553
1554 echo '<div id="" class="notice notice-warning">';
1555 echo '<p>' .
1556 sprintf(
1557 wp_kses(
1558 /* translators: %s: is the link */
1559 __( '<strong>Welcome to WPCasa</strong> &#8211; You&lsquo;re almost ready. Now go ahead and <a href="%s">setup your main listings page</a> as this is required in order to properly list your properties.', 'wpcasa' ),
1560 array( 'strong' => array(), 'a' => array( 'href' => array() ) ) )
1561 , esc_url( $link ) ) .
1562 '</p>';
1563 echo '</div>';
1564
1565 }
1566
1567 }
1568
1569
1570 /**
1571 * notice_updater()
1572 *
1573 * Show a notice if updater is not available
1574 *
1575 * @uses get_option()
1576 * @uses wpsight_licenses()
1577 * @uses in_array()
1578 *
1579 * @since 1.2.0
1580 */
1581 public static function notice_updater() : void {
1582
1583 // List of WPCasa paid plugin paths relative to the plugins directory
1584 $plugins = array(
1585 'wpcasa-currency-converter/wpcasa-currency-converter.php' => 'WPCasa Currency Converter',
1586 'wpcasa-dashboard/wpcasa-dashboard.php' => 'WPCasa Dashboard',
1587 'wpcasa-energy-efficiency/wpcasa-energy-efficiency.php' => 'WPCasa Energy Efficiency',
1588 'wpcasa-expire-listings/wpcasa-expire-listings.php' => 'WPCasa Expire Listings',
1589 'wpcasa-favorites/wpcasa-favorites.php' => 'WPCasa Favorites',
1590 'wpcasa-featured-listings/wpcasa-featured-listings.php' => 'WPCasa Featured Listings',
1591 'wpcasa-listing-labels/wpcasa-listing-labels.php' => 'WPCasa Listing Labels',
1592 'wpcasa-listing-pdf/wpcasa-listing-pdf.php' => 'WPCasa Listing PDF',
1593 );
1594
1595 // Array to hold active plugins
1596 $active_plugins = array();
1597
1598 foreach ( $plugins as $plugin => $name ) {
1599 // Check if each plugin is active
1600 if ( is_plugin_active( $plugin ) ) {
1601 $active_plugins[ $plugin ] = $name;
1602 }
1603 }
1604
1605 // Output result
1606 if ( 0 < count( $active_plugins ) && ! class_exists( 'WPSight_EDD_SL_Plugin_Updater' ) ) {
1607 // At least one of the WPCasa paid plugins is active
1608
1609 $plugin_names = implode(", ", $active_plugins );
1610
1611 echo '<div id="" class="notice notice-warning">';
1612 echo '<p>' .
1613 esc_html__( 'To comply with the WordPress guidelines for plugins, we have removed the update functionality for our premium plugins from WPCasa.', 'wpcasa' ) . '<br />' .
1614 sprintf(
1615 wp_kses(
1616 /* translators: %s: is the link */
1617 _n( 'As a result, your WPCasa plugin <strong>%1$s will no longer update automatically</strong> when a new version is available. Therefore, you will need to <strong>manually download the latest version of your plugin %1$s</strong> from <a href="https://wpcasa.com/login/" target="_blank">your account on wpcasa.com</a> and upload it to your WordPress website.',
1618 'As a result, your WPCasa plugins <strong>%1$s will no longer update automatically</strong> when a new version is available. Therefore, you will need to <strong>manually download the latest version of your plugins %1$s</strong> from <a href="https://wpcasa.com/login/" target="_blank">your account on wpcasa.com</a> and upload it to your WordPress website.',
1619 count( $active_plugins ), 'wpcasa' ),
1620 array( 'strong' => array(), 'a' => array( 'href' => array() ) ) )
1621 , esc_html( $plugin_names ) ) . '<br />' .
1622 esc_html__( 'After this, automatic updates will resume as usual. Unfortunately, this action was necessary to ensure that WPCasa remains available on wordpress.org. We appreciate your understanding and continued support.', 'wpcasa' )
1623 . '</p>';
1624 echo '</div>';
1625
1626 }
1627
1628 }
1629
1630 /**
1631 *
1632 * Return array of recommendation data
1633 *
1634 * @uses apply_filters()
1635 * @return array
1636 *
1637 * @since 1.2.0
1638 */
1639 public static function recommendations() {
1640
1641 $recommendations = [
1642 'shortpixel' => [
1643 'title' => __( 'ShortPixel Image Compression', 'wpcasa' ),
1644 'description' => __( 'Here you can compress your images for free or create your personal ShortPixel account', 'wpcasa' ),
1645 'image_url' => WPSIGHT_PLUGIN_URL . '/assets/img/wpcasa-recommendation-shortpixel.jpg',
1646 'button_text' => __( 'ShortPixel', 'wpcasa' ),
1647 'button_link' => 'https://shortpixel.com/otp/af/95WCWLA889753',
1648 ]
1649
1650 ];
1651
1652 if( ! wpsight_is_premium()) {
1653
1654 $recommendations['premium'] = [
1655 'title' => __( 'Premium', 'wpcasa' ),
1656 'description' => __( 'Here you can upgrade to premium', 'wpcasa' ),
1657 'image_url' => WPSIGHT_PLUGIN_URL . '/assets/img/wpcasa-recommendation-premium.jpg',
1658 'button_text' => __( 'Premium', 'wpcasa' ),
1659 'button_link' => 'https://wpcasa.com?ref=wpcasa-admin-dashboard',
1660 ];
1661
1662 }
1663
1664 $recommendations = apply_filters( 'wpsight_recommendations', $recommendations );
1665
1666 return $recommendations;
1667
1668 }
1669
1670
1671 }
1672