PluginProbe
WPCasa – Real Estate for WordPress / trunk
WPCasa – Real Estate for WordPress vtrunk
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 trunk, at includes/admin/class-wpsight-admin.php

1,672 lines 57.0 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 /* translators: 1: Theme name, 2: Current theme version, 3: Required theme version. */
570 __(
571 '<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.',
572 'wpcasa'
573 ),
574 esc_html( $theme_data['name'] ),
575 esc_html( $theme_data['current_version'] ),
576 esc_html( $theme_data['required_version'] )
577 )
578 );
579 echo '</p>';
580 echo '</div>';
581
582 }
583
584 /**
585 * options()
586 *
587 * Merge option tabs and
588 * return wpsight_options_listings()
589 *
590 * @uses wpsight_options_listings()
591 * @return array $options
592 *
593 * @since 1.0.0
594 * @updated 1.5.4
595 */
596 public static function options() {
597 $options = array(
598 'listings' => array(
599 '<span class="dashicons dashicons-admin-multisite"></span>' . __( 'Listings', 'wpcasa' ),
600 (array) self::options_listings(),
601 array(
602 'tabs' => array(
603 'general' => __( 'General', 'wpcasa' ),
604 'currency' => __( 'Currency', 'wpcasa' ),
605 'listing' => __( 'Listing', 'wpcasa' ),
606 'rental' => __( 'Rental', 'wpcasa' ),
607 ),
608 ),
609 ),
610 // 'search' => array(
611 // '<span class="dashicons dashicons-search"></span>' . __( 'Search', 'wpcasa' ),
612 // (array) self::options_search()
613 // ),
614 'maps' => array(
615 '<span class="dashicons dashicons-location-alt"></span>' . __( 'Maps', 'wpcasa' ),
616 (array) self::options_maps()
617 )
618 );
619
620 $options = apply_filters( 'wpsight_options', $options );
621
622 return $options;
623 }
624
625 /**
626 * licenses()
627 *
628 * Create license array
629 *
630 * @return array $licenses
631 *
632 * @since 1.0.0
633 */
634 public static function licenses() {
635
636 // initialize empty array
637 $licenses = array();
638
639 // add default license
640 $licenses['support_package'] = array(
641 'name' => __( 'Support Package', 'wpcasa' ),
642 'desc' => __( 'To receive support for a free product please enter your support package license key.', 'wpcasa' ),
643 'id' => 'support_package',
644 'section' => 'services',
645 'priority' => 1000
646 );
647
648 // filter licenses
649 $licenses = apply_filters( 'wpsight_licenses', $licenses );
650
651 // sort by priority
652 $licenses = wpsight_sort_array_by_priority( $licenses );
653
654 // return
655 return $licenses;
656
657 }
658
659 /**
660 * options_listings()
661 *
662 * Create theme options array
663 * Listings options
664 *
665 * @uses wpsight_get_option()
666 * @uses wpsight_measurements()
667 * @uses wpsight_currencies()
668 * @uses wpsight_details()
669 * @uses wpsight_rental_periods()
670 * @uses wpsight_date_formats()
671 * @return array $options_listings
672 *
673 * @since 1.0.0
674 * @updated 1.5.4
675 */
676 public static function options_listings() {
677
678 $options_listings = array();
679
680 $options_listings['pageheading_listings'] = array(
681 'name' => __( 'Listings', 'wpcasa' ),
682 'desc' => __( 'Here you can define some basic settings', 'wpcasa' ),
683 'icon' => 'dashicons dashicons-admin-multisite',
684 'link' => 'https://docs.wpcasa.com',
685 'id' => 'pageheading_listings',
686 'position' => 10,
687 'type' => 'pageheading'
688 );
689
690 $options_listings['heading_listings'] = array(
691 'name' => __( 'General Listing Settings', 'wpcasa' ),
692 'desc' => __( 'Here you can define some basic settings', 'wpcasa' ),
693 'id' => 'heading_listings',
694 'position' => 20,
695 'type' => 'heading'
696 );
697
698 $options_listings['listings_page'] = array(
699 'name' => __( 'Listings Page', 'wpcasa' ),
700 'desc' => __( 'Please select the main search results page with the <code>[wpsight_listings]</code> shortcode.', 'wpcasa' ),
701 'id' => 'listings_page',
702 'position' => 30,
703 'type' => 'pages'
704 );
705
706 $options_listings['date_format'] = array(
707 'name' => __( 'Date Format', 'wpcasa' ),
708 'desc' => __( 'Please select the date format for the listings table in the admin.', 'wpcasa' ),
709 'id' => 'date_format',
710 'position' => 40,
711 'type' => 'select',
712 'options' => array_filter( wpsight_date_formats( true ) ),
713 'default' => get_option( 'date_format' )
714 );
715
716 $options_listings['listings_css'] = array(
717 'name' => __( 'Output CSS', 'wpcasa' ),
718 'desc' => __( 'Please uncheck the box to disable the plugin from outputting CSS.', 'wpcasa' ),
719 'id' => 'listings_css',
720 'position' => 50,
721 'type' => 'checkbox',
722 'default' => '1'
723 );
724
725 // Check of old 'property_id' options was active
726 $listing_id_default = wpsight_get_option( 'property_id' ) ? wpsight_get_option( 'property_id' ) : __( 'ID-', 'wpcasa' );
727
728 $options_listings['listing_id'] = array(
729 'name' => __( 'Listing ID Prefix', 'wpcasa' ),
730 'desc' => __( 'The listing ID will be this prefix plus post ID. You can optionally set individual IDs on the listing edit screen.', 'wpcasa' ),
731 'id' => 'listing_id',
732 'position' => 60,
733 'type' => 'text',
734 'default' => $listing_id_default
735 );
736
737 $options_listings['measurement_unit'] = array(
738 'name' => __( 'Measurement Unit', 'wpcasa' ),
739 'desc' => __( 'Please select the general measurement unit. The unit for the listing details can be defined separately.', 'wpcasa' ),
740 'id' => 'measurement_unit',
741 'position' => 70,
742 'type' => 'radio',
743 'class' => 'mini',
744 'options' => array_filter( wpsight_measurements() ),
745 'default' => 'm2'
746 );
747
748 $options_listings['heading_rest_api'] = array(
749 'name' => __( 'REST API', 'wpcasa' ),
750 'id' => 'heading_rest_api',
751 'position' => 75,
752 'type' => 'heading'
753 );
754
755 $options_listings['listings_rest_api'] = array(
756 'name' => __( 'Show in REST API (and block editor)', 'wpcasa' ),
757 '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' ),
758 'id' => 'listings_rest_api',
759 'position' => 76,
760 'type' => 'checkbox',
761 'default' => '0'
762 );
763
764 $options_listings['heading_media'] = array(
765 'name' => __( 'Media Files', 'wpcasa' ),
766 'id' => 'heading_media',
767 'position' => 78,
768 'type' => 'heading'
769 );
770
771 $options_listings['listings_delete_media'] = array(
772 'name' => __( 'Delete image when the listing is deleted', 'wpcasa' ),
773 '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' ),
774 'id' => 'listings_delete_media',
775 'position' => 79,
776 'type' => 'checkbox',
777 'default' => '0'
778 );
779
780 $options_listings['heading_currency'] = array(
781 'name' => __( 'Currency', 'wpcasa' ),
782 'id' => 'heading_currency',
783 'position' => 80,
784 'type' => 'heading'
785 );
786
787 $options_listings['currency'] = array(
788 'name' => __( 'Currency', 'wpcasa' ),
789 'desc' => __( 'Please select the currency for the listing prices. If your currency is not listed, please select <code>Other</code>.', 'wpcasa' ),
790 'id' => 'currency',
791 'position' => 90,
792 'type' => 'select',
793 'class' => 'mini',
794 'options' => array_merge( array_filter( wpsight_currencies() ), array( 'other' => __( 'Other', 'wpcasa' ) ) ),
795 'default' => 'usd'
796 );
797
798 $options_listings['currency_other'] = array(
799 'name' => __( 'Other Currency', 'wpcasa' ) . ' (' . __( 'Abbreviation', 'wpcasa' ) . ')',
800 'desc' => __( 'Please insert the abbreviation of your currency (e.g. <code>EUR</code>).', 'wpcasa' ),
801 'id' => 'currency_other',
802 'position' => 100,
803 'type' => 'text',
804 'class' => 'hidden'
805 );
806
807 $options_listings['currency_other_ent'] = array(
808 'name' => __( 'Other Currency', 'wpcasa' ) . ' (' . __( 'Symbol', 'wpcasa' ) . ')',
809 'desc' => __( 'Please insert the currency symbol or HTML entity (e.g. <code>&amp;euro;</code>).', 'wpcasa' ),
810 'id' => 'currency_other_ent',
811 'position' => 110,
812 'type' => 'text',
813 'class' => 'hidden'
814 );
815
816 $options_listings['currency_symbol'] = array(
817 'name' => __( 'Currency Symbol', 'wpcasa' ),
818 'desc' => __( 'Please select the position of the currency symbol.', 'wpcasa' ),
819 'id' => 'currency_symbol',
820 'position' => 120,
821 'type' => 'radio',
822 'options' => array(
823 'before' => __( 'Before the value', 'wpcasa' ),
824 'after' => __( 'After the value', 'wpcasa' ),
825 'before_space' => __( 'Before the value (with Space)', 'wpcasa' ),
826 'after_space' => __( 'After the value (with Space)', 'wpcasa' )
827 ),
828 'default' => 'before'
829 );
830
831 $options_listings['currency_separator'] = array(
832 'name' => __( 'Thousands Separator', 'wpcasa' ),
833 'desc' => __( 'Please select the thousands separator for your listing prices.', 'wpcasa' ),
834 'id' => 'currency_separator',
835 'position' => 130,
836 'type' => 'text',
837 'default' => '.'
838 );
839
840 $options_listings['decimal_separator'] = array(
841 'name' => __( 'Decimal Separator', 'wpcasa' ),
842 'desc' => __( 'Please select the decimal separator for your listing prices.', 'wpcasa' ),
843 'id' => 'decimal_separator',
844 'position' => 131,
845 'type' => 'text',
846 'default' => ','
847 );
848
849 $options_listings['heading_details'] = array(
850 'name' => __( 'Listing Details', 'wpcasa' ),
851 'id' => 'heading_details',
852 'position' => 140,
853 'type' => 'heading'
854 );
855
856 /** Loop through standard details */
857
858 $i=1;
859 $position=150;
860
861 foreach ( wpsight_details() as $detail_id => $value ) {
862
863 $options_listings[ $detail_id ] = array(
864 'name' => __( 'Listing Detail', 'wpcasa' ) . ' #' . $i++,
865 'desc' => $value['description'] ?? '',
866 'id' => $detail_id,
867 'position' => $position++,
868 'type' => 'measurement',
869 'class' => '',
870 'default' => array(
871 'label' => $value['label'],
872 'unit' => $value['unit']
873 )
874 );
875
876 }
877
878 $options_listings['heading_rental_periods'] = array(
879 'name' => __( 'Rental Periods', 'wpcasa' ),
880 'id' => 'heading_rental_periods',
881 'position' => 300,
882 'type' => 'heading'
883 );
884
885 /** Loop through rental periods */
886
887 $i=1;
888 $position=310;
889
890 foreach ( wpsight_rental_periods() as $period => $value ) {
891
892 $options_listings[ $period ] = array(
893 'name' => __( 'Rental Period', 'wpcasa' ) . ' #' . $i++,
894 'id' => $period,
895 'position' => $position++,
896 'type' => 'text',
897 'class' => '',
898 'default' => $value
899 );
900
901 }
902
903 // Assign every core field to its Listings settings tab.
904 $listings_tab_fields = array(
905 'general' => array(
906 'heading_listings',
907 'listings_page',
908 'date_format',
909 'listings_css',
910 'listing_id',
911 'measurement_unit',
912 'heading_rest_api',
913 'listings_rest_api',
914 'heading_media',
915 'listings_delete_media',
916 ),
917 'currency' => array(
918 'heading_currency',
919 'currency',
920 'currency_other',
921 'currency_other_ent',
922 'currency_symbol',
923 'currency_separator',
924 'decimal_separator',
925 ),
926 'listing' => array_merge( array( 'heading_details' ), array_keys( wpsight_details() ) ),
927 'rental' => array_merge( array( 'heading_rental_periods' ), array_keys( wpsight_rental_periods() ) ),
928 );
929
930 foreach ( $listings_tab_fields as $tab_id => $field_ids ) {
931 foreach ( $field_ids as $field_id ) {
932 if ( isset( $options_listings[ $field_id ] ) ) {
933 $options_listings[ $field_id ]['tab'] = $tab_id;
934 }
935 }
936 }
937
938 // filter options
939 $options_listings = apply_filters( 'wpsight_options_listings', $options_listings );
940
941 // sort options by position
942 $options_listings = wpsight_sort_array_by_position( $options_listings );
943
944 return $options_listings;
945
946 }
947
948 /**
949 * options_search()
950 *
951 * Create theme options array
952 * Search options
953 *
954 * @uses wpsight_get_search_fields()
955 * @return array $options_search
956 *
957 * @since 1.1.0
958 */
959 public static function options_search() {
960
961 $options_search = array();
962
963 /** Loop through search fields */
964 $fields = wpsight_get_search_fields();
965
966 $options = array();
967
968 foreach( $fields as $field => $v ) {
969
970 $label = isset($v['label']) ? $v['label'] : '';
971
972 if( $v['type'] == 'taxonomy_select' && $v['data']['show_option_none'] )
973 $label = $v['data']['show_option_none'];
974
975 $options[$field] = $label;
976 }
977
978 $options_search['pageheading_search'] = array(
979 'name' => __( 'Search', 'wpcasa' ),
980 'desc' => __( 'Here you can define some basic settings', 'wpcasa' ),
981 'icon' => 'dashicons dashicons-search',
982 'link' => '',
983 'id' => 'pageheading_search',
984 'position' => 10,
985 'type' => 'pageheading'
986 );
987
988 $options_search['search_elements'] = array(
989 'name' => __( 'Search Form Elements', 'wpcasa' ),
990 'desc' => __( 'Choose what to display in the search form', 'wpcasa' ),
991 'id' => 'search_elements',
992 'position' => 20,
993 'type' => 'multicheck',
994 'options' => $options
995 );
996
997 // filter options
998 $options_search = apply_filters( 'wpsight_options_search', $options_search );
999
1000 // sort options by position
1001 $options_search = wpsight_sort_array_by_position( $options_search );
1002
1003 return $options_search;
1004
1005 }
1006
1007 /**
1008 * options_maps()
1009 *
1010 * Create theme options array
1011 * Maps options
1012 *
1013 * @return array $options_maps
1014 *
1015 * @since 1.1.0
1016 */
1017 public static function options_maps() {
1018
1019 $options_maps = array();
1020
1021 $options_maps['pageheading_maps'] = array(
1022 'name' => __( 'Maps', 'wpcasa' ),
1023 'desc' => __( 'Here you can define some basic settings', 'wpcasa' ),
1024 'icon' => 'dashicons dashicons-location-alt',
1025 'link' => 'https://docs.wpcasa.com/article/wpcasa-listings-map/',
1026 'id' => 'pageheading_maps',
1027 'type' => 'pageheading'
1028 );
1029
1030 $options_maps['heading_listings_map_api'] = array(
1031 'name' => __( 'Map API', 'wpcasa' ),
1032 'desc' => __( 'Here you can enter Map API', 'wpcasa' ),
1033 'id' => 'heading_listings_map_api',
1034 'type' => 'heading',
1035 'position' => '490'
1036 );
1037
1038 $options_maps['google_maps_api_key'] = array(
1039 'name' => __( 'Google Maps API', 'wpcasa' ),
1040 /* translators: %s: is the link to google maps */
1041 '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' ),
1042 'id' => 'google_maps_api_key',
1043 'type' => 'text',
1044 'position' => '500'
1045 );
1046
1047 // filter options
1048 $options_maps = apply_filters( 'wpsight_options_maps', $options_maps );
1049
1050 // sort options by position
1051 $options_maps = wpsight_sort_array_by_position( $options_maps );
1052
1053 return $options_maps;
1054
1055 }
1056
1057 /**
1058 * options_debug()
1059 *
1060 * Create theme options array
1061 * Listings options
1062 *
1063 * @uses wpsight_get_option()
1064 * @uses wpsight_measurements()
1065 * @uses wpsight_currencies()
1066 * @uses wpsight_details()
1067 * @uses wpsight_rental_periods()
1068 * @uses wpsight_date_formats()
1069 * @return array $options_listings
1070 *
1071 * @since 1.0.0
1072 */
1073 public static function options_debug() {
1074
1075 $options_debug = array();
1076
1077 if( version_compare( '1.1.0', WPSIGHT_VERSION, '>=' ) ) {
1078
1079 $options_debug['example_slider'] = array(
1080 'name' => __( 'Example Slider', 'wpcasa' ),
1081 'desc' => __( 'Example Slider Option', 'wpcasa' ),
1082 'id' => 'example_slider',
1083 'type' => 'range',
1084 'min' => 0,
1085 'max' => 1000,
1086 'step' => 50,
1087 'default' => ''
1088 );
1089
1090 $options_debug['example_number'] = array(
1091 'name' => __( 'Example Number', 'wpcasa' ),
1092 'desc' => __( 'Example Number Option', 'wpcasa' ),
1093 'id' => 'example_number',
1094 'type' => 'number',
1095 'default' => ''
1096 );
1097
1098 }
1099
1100
1101 return apply_filters( 'wpsight_options_debug', $options_debug );
1102
1103 }
1104
1105 /**
1106 * media_custom_views()
1107 *
1108 * Media library views
1109 *
1110 * @param array $views Incoming views
1111 * @uses $wpdb->prepare()
1112 * @uses $wpdb->get_col()
1113 * @uses wp_count_attachments()
1114 * @return array $views Updated views
1115 *
1116 * @since 1.0.0
1117 */
1118 public static function media_custom_views( $views ) {
1119
1120 global $wpdb, $wp_query, $pagenow;
1121
1122 if ( 'upload.php' != $pagenow )
1123 return;
1124
1125 if ( ! isset( $wp_query->query_vars['s'] ) )
1126 return $views;
1127
1128 // Search custom fields for listing ID
1129
1130 $post_ids_meta = $wpdb->get_col( $wpdb->prepare( "
1131 SELECT DISTINCT post_id FROM {$wpdb->postmeta}
1132 WHERE meta_value LIKE %s
1133 ", $wp_query->query_vars['s'] ) );
1134
1135 if ( ! empty( $post_ids_meta ) && get_search_query() !== null ) {
1136
1137 unset( $views );
1138
1139 $s = get_search_query();
1140 $_num_posts = (array) wp_count_attachments();
1141 $_total_posts = array_sum( $_num_posts ) - $_num_posts['trash'];
1142
1143 $views['all'] = '<a href="' . $pagenow . '">' . __( 'All', 'wpcasa' ) . ' <span class="count">(' . $_total_posts . ')</span></a>';
1144 $views['found'] = '<a href="' . $pagenow . '?s=' . $s . '" class="current">' . $s . ' <span class="count">(' . $wp_query->found_posts . ')</span></a>';
1145 }
1146
1147 return $views;
1148 }
1149
1150 /**
1151 * listings_custom_views()
1152 *
1153 * Listing views
1154 *
1155 * @param array $views Incoming views
1156 * @uses $wpdb->prepare()
1157 * @uses $wpdb->get_col()
1158 * @return array $views Updated views
1159 *
1160 * @since 1.0.0
1161 */
1162 public static function listings_custom_views( $views ) {
1163 global $wpdb, $wp_query, $pagenow;
1164
1165 if ( 'edit.php' != $pagenow )
1166 return;
1167
1168 // Replace 'Published' with 'Active'
1169
1170 if( isset( $views['publish'] ) )
1171 $views['publish'] = str_replace( __( 'Published', 'wpcasa' ), __( 'Active', 'wpcasa' ), $views['publish'] );
1172
1173 if ( empty( $wp_query->query_vars['s'] ) )
1174 return $views;
1175
1176 // Search custom fields for listing ID
1177
1178 $post_ids_meta = $wpdb->get_col( $wpdb->prepare( "
1179 SELECT DISTINCT post_id FROM $wpdb->postmeta
1180 WHERE meta_value LIKE %s
1181 ", $wp_query->query_vars['s'] ) );
1182
1183 if ( empty( $post_ids_meta ) )
1184 return $views;
1185
1186 }
1187
1188 /**
1189 * manage_users_columns()
1190 *
1191 * Add column for number of listings of a user.
1192 *
1193 * @param array $columns Incoming columns
1194 * @return array $columns Updated columns
1195 *
1196 * @since 1.0.0
1197 */
1198 public static function manage_users_columns( $columns ) {
1199 $columns['listings_count'] = __( 'Listings', 'wpcasa' );
1200 return $columns;
1201 }
1202
1203 /**
1204 * manage_users_custom_column()
1205 *
1206 * Show number of listings the user has
1207 *
1208 * @param string $value
1209 * @param string $column_name
1210 * @param int $user_id
1211 * @uses count_user_posts()
1212 * @uses wpsight_post_type()
1213 * @return string new value
1214 *
1215 * @since 1.0.0
1216 */
1217 public static function manage_users_custom_column( $value, $column_name, $user_id ) {
1218
1219 if ( 'listings_count' != $column_name )
1220 return $value;
1221
1222 $listings_count = count_user_posts( $user_id, wpsight_post_type() );
1223 $user_listings_links = '<a href="edit.php?author=' . $user_id . '&post_type=' . wpsight_post_type() . '">' . $listings_count . '</a>';
1224
1225 return $user_listings_links;
1226
1227 }
1228
1229
1230
1231 /**
1232 * check_license()
1233 *
1234 * Check a specific license.
1235 *
1236 * @uses get_option()
1237 * @uses urlencode()
1238 * @uses home_url()
1239 * @uses wp_remote_post()
1240 * @uses is_wp_error()
1241 * @uses wp_remote_retrieve_body()
1242 * @uses json_decode()
1243 * @uses delete_option()
1244 * @return string valid|invalid
1245 *
1246 * @since 1.0.0
1247 */
1248 // public static function check_license( $id = '', $item = '' ) {
1249 //
1250 // $licenses = get_option( 'wpsight_licenses' );
1251 //
1252 // // retrieve the license from the database
1253 // $license = isset( $licenses[ $id ] ) ? trim( $licenses[ $id ] ) : false;
1254 //
1255 // $api_params = array(
1256 // 'edd_action'=> 'check_license',
1257 // 'license' => $license,
1258 // 'item_name' => urlencode( $item ),
1259 // 'url' => home_url()
1260 // );
1261 //
1262 // // Call the custom API.
1263 // $response = wp_remote_post( WPSIGHT_SHOP_URL, array( 'timeout' => 15, 'sslverify' => false, 'body' => $api_params ) );
1264 //
1265 // if ( is_wp_error( $response ) )
1266 // return false;
1267 //
1268 // $license_data = json_decode( wp_remote_retrieve_body( $response ) );
1269 //// var_dump($license_data);
1270 // update_option( 'wpsight_' . $id . '_status', $license_data->license );
1271 //
1272 //
1273 //
1274 // return $license_data->license;
1275 //
1276 //// if( $license_data->license == 'valid' ) {
1277 //// return 'valid';
1278 //// } else {
1279 //// //delete_option( 'wpsight_' . $id . '_status' );
1280 //// return 'invalid';
1281 //// }
1282 //
1283 // }
1284
1285 /**
1286 * is_premium()
1287 *
1288 * Check if premium is active.
1289 * Premium is at least one active and valid license
1290 * which grants access to specific features and support
1291 *
1292 * @uses get_option()
1293 * @uses wpsight_licenses()
1294 * @uses in_array()
1295 * @return bool true|false
1296 *
1297 * @since 1.2.0
1298 */
1299 // public static function is_premium() {
1300 // var_dump(wpsight_licenses());
1301 // foreach( wpsight_licenses() as $id => $license )
1302 // $keys[$id] = get_transient( 'wpsight_' . $license['id'] )->license;
1303 //
1304 // if( in_array( 'valid', $keys ) )
1305 // return true;
1306 //
1307 // return false;
1308 //
1309 // }
1310
1311 /**
1312 * maybe_set_review_notice_timestamp()
1313 *
1314 * Make sure the review notice timestamp exists.
1315 * This keeps older installations compatible.
1316 *
1317 * @uses get_option()
1318 * @uses current_time()
1319 * @uses update_option()
1320 * @return void
1321 *
1322 * @since 1.5.0
1323 */
1324 public function maybe_set_review_notice_timestamp() {
1325
1326 $options = get_option( WPSIGHT_DOMAIN, array() );
1327
1328 if ( ! is_array( $options ) ) {
1329 $options = array();
1330 }
1331
1332 if ( ! empty( $options['review_notice_timestamp'] ) ) {
1333 return;
1334 }
1335
1336 $options['review_notice_timestamp'] = current_time( 'timestamp' );
1337
1338 update_option( WPSIGHT_DOMAIN, $options );
1339
1340 }
1341
1342 /**
1343 * should_show_review_notice()
1344 *
1345 * Check if the review notice should be displayed.
1346 *
1347 * @uses current_user_can()
1348 * @uses get_current_user_id()
1349 * @uses get_user_meta()
1350 * @uses wpsight_get_option()
1351 * @uses current_time()
1352 * @return bool True if the notice should be shown.
1353 *
1354 * @since 1.5.0
1355 */
1356 protected function should_show_review_notice() {
1357
1358 $timestamp = absint( wpsight_get_option( 'review_notice_timestamp', false ) );
1359
1360 if ( ! current_user_can( 'manage_options' ) ) {
1361 return false;
1362 }
1363
1364 if ( get_user_meta( get_current_user_id(), 'wpsight_review_notice_dismissed', true ) ) {
1365 return false;
1366 }
1367
1368 if ( empty( $timestamp ) ) {
1369 return false;
1370 }
1371
1372 return current_time( 'timestamp' ) >= ( $timestamp + ( 7 * DAY_IN_SECONDS ) );
1373
1374 }
1375
1376 /**
1377 * get_review_notice_recipient_name()
1378 *
1379 * Get the current user's name for the review notice.
1380 * Use first name and last name when available.
1381 * Fall back to display name when first name is empty.
1382 *
1383 * @uses wp_get_current_user()
1384 * @return string Recipient name.
1385 *
1386 * @since 1.5.0
1387 */
1388 protected function get_review_notice_recipient_name() : string {
1389
1390 $current_user = wp_get_current_user();
1391 $first_name = isset( $current_user->first_name ) ? trim( $current_user->first_name ) : '';
1392 $display_name = isset( $current_user->display_name ) ? trim( $current_user->display_name ) : '';
1393
1394 if ( empty( $first_name ) ) {
1395 return $display_name;
1396 }
1397
1398 return $first_name;
1399
1400 }
1401
1402 /**
1403 * notice_review()
1404 *
1405 * Show the review notice after the waiting period has passed.
1406 *
1407 * @uses self::should_show_review_notice()
1408 * @uses esc_url()
1409 * @uses esc_attr__()
1410 * @uses esc_html__()
1411 * @uses wp_create_nonce()
1412 * @uses wp_kses()
1413 * @return void
1414 *
1415 * @since 1.5.0
1416 */
1417 public function notice_review() {
1418
1419 if ( ! $this->should_show_review_notice() ) {
1420 return;
1421 }
1422
1423 $review_url = 'https://wordpress.org/plugins/wpcasa/#reviews';
1424 $image_url = WPSIGHT_PLUGIN_URL . '/assets/img/icon.png';
1425 $user_name = '<b>' . esc_html( $this->get_review_notice_recipient_name() ) . '</b>';
1426 $allowed_message_html = array(
1427 'a' => array(
1428 'aria-label' => array(),
1429 'class' => array(),
1430 'href' => array(),
1431 'rel' => array(),
1432 'target' => array(),
1433 ),
1434 'b' => array(),
1435 'br' => array(),
1436 );
1437 $stars_link = sprintf(
1438 '<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>',
1439 esc_url( $review_url ),
1440 esc_attr__( 'Rate WPCasa on WordPress.org', 'wpcasa' )
1441 );
1442 $wporg_link = sprintf(
1443 '<a href="%1$s" target="_blank" rel="noopener noreferrer" class="wpsight-review-notice__text-link">%2$s</a>',
1444 esc_url( $review_url ),
1445 esc_html__( 'WordPress.org', 'wpcasa' )
1446 );
1447 $message = sprintf(
1448 /* translators: 1: User name, 2: Star rating link, 3: WordPress.org review link. */
1449 __( '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' ),
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">' . wp_kses( $message, $allowed_message_html ) . '</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