PluginProbe
Property Hive / 2.2.4
Property Hive v2.2.4
2.2.6 2.2.5 2.2.4 2.2.3 2.2.2 1.4.46 1.4.47 1.4.48 1.4.49 1.4.5 1.4.50 1.4.51 1.4.52 1.4.53 1.4.54 1.4.55 1.4.56 1.4.57 1.4.58 1.4.59 1.4.6 1.4.60 1.4.61 1.4.62 1.4.63 All 259 releases
propertyhive / propertyhive.php

propertyhive.php in Property Hive 2.2.4, at propertyhive.php

591 lines 21.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Plugin Name: Property Hive
4 * Plugin URI: https://wordpress.org/plugins/propertyhive/
5 * Description: Property Hive has everything you need to build estate agency websites
6 * Version: 2.2.4
7 * Author: PropertyHive
8 * Author URI: https://wp-property-hive.com
9 * Requires at least: 5.6
10 * Tested up to: 7.0
11 *
12 * Text Domain: propertyhive
13 * Domain Path: /i18n/languages/
14 *
15 * @package PropertyHive
16 * @category Core
17 * @author PropertyHive
18 */
19
20 if ( ! defined( 'ABSPATH' ) ) {
21 exit; // Exit if accessed directly
22 }
23
24 if ( ! class_exists( 'PropertyHive' ) )
25 {
26 /**
27 * Main PropertyHive Class
28 *
29 * @class PropertyHive
30 * @version 2.2.4
31 */
32 final class PropertyHive {
33
34 /**
35 * @var string
36 */
37 public $version = '2.2.4';
38
39 /**
40 * @var PropertyHive The single instance of the class
41 */
42 protected static $_instance = null;
43
44 /**
45 * Query instance.
46 *
47 * @var PH_Query
48 */
49 public $query = null;
50
51 /**
52 * REST API instance.
53 *
54 * @var PH_Rest_Api
55 */
56 public $rest_api = null;
57
58 /**
59 * Email instance.
60 *
61 * @var PH_Emails
62 */
63 public $email = null;
64
65 /**
66 * License instance.
67 *
68 * @var PH_Licenses
69 */
70 public $license = null;
71
72 /**
73 * Countries instance.
74 *
75 * @var PH_Countries
76 */
77 public $countries = null;
78
79 /**
80 * Main PropertyHive Instance
81 *
82 * Ensures only one instance of PropertyHive is loaded or can be loaded.
83 *
84 * @static
85 * @return PropertyHive - Main instance
86 */
87 public static function instance()
88 {
89 if ( is_null( self::$_instance ) )
90 {
91 self::$_instance = new self();
92 }
93 return self::$_instance;
94 }
95
96 /**
97 * Cloning is forbidden.
98 *
99 * @since 1.0.0
100 */
101 public function __clone() {
102 _doing_it_wrong( __FUNCTION__, __( 'Cheatin&#8217; huh?', 'propertyhive' ), '1.0.0' );
103 }
104
105 /**
106 * Unserializing instances of this class is forbidden.
107 *
108 * @since 1.0.0
109 */
110 public function __wakeup() {
111 _doing_it_wrong( __FUNCTION__, __( 'Cheatin&#8217; huh?', 'propertyhive' ), '1.0.0' );
112 }
113
114 /**
115 * PropertyHive Constructor.
116 * @access public
117 * @return PropertyHive
118 */
119 public function __construct()
120 {
121 // Auto-load classes on demand
122 if ( function_exists( "__autoload" ) ) {
123 spl_autoload_register( "__autoload" );
124 }
125
126 spl_autoload_register( array( $this, 'autoload' ) );
127
128 // Define constants
129 $this->define_constants();
130
131 // Include required files
132 $this->includes();
133
134 // Hooks
135 add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), array( $this, 'action_links' ) );
136 add_filter( 'propertyhive_departments', array( $this, 'setup_custom_departments' ) );
137 //add_action( 'widgets_init', array( $this, 'include_widgets' ) );
138 add_action( 'init', array( $this, 'init' ), 0 );
139 add_action( 'init', array( $this, 'include_template_functions' ) );
140 add_action( 'init', array( $this, 'unsubscribe_contact' ), 0 );
141 add_action( 'init', array( 'PH_Shortcodes', 'init' ) );
142 add_action( 'rest_api_init', array( $this, 'rest_api_includes' ) );
143 add_action( 'after_setup_theme', array( $this, 'setup_environment' ) );
144 add_action( 'wp', array( $this, 'set_cache_constants' ) );
145 add_action( 'wp_update_comment_count', array( $this, 'exclude_notes_from_comment_count' ) );
146
147 // Ensure Template Assistant add on is deactivated now the code is merged into core
148 add_action('plugins_loaded', function () {
149 propertyhive_deactivate_template_assistant();
150 }, 1);
151
152 // Loaded action
153 do_action( 'propertyhive_loaded' );
154 }
155
156 public function set_cache_constants()
157 {
158 $page_ids = array_filter( array( ph_get_page_id( 'my_account' ) ) );
159
160 if ( !empty($page_ids) && is_page( $page_ids ) )
161 {
162 if ( !defined('DONOTCACHEPAGE') ) { define('DONOTCACHEPAGE', TRUE); }
163 if ( !defined('DONOTCACHEOBJECT') ) { define('DONOTCACHEOBJECT', TRUE); }
164 if ( !defined('DONOTCACHEDB') ) { define('DONOTCACHEDB', TRUE); }
165 }
166 }
167
168 public function setup_custom_departments( $departments )
169 {
170 $custom_departments = ph_get_custom_departments();
171
172 foreach ( $custom_departments as $key => $custom_department )
173 {
174 $departments[$key] = __( $custom_department['name'], 'propertyhive' );
175 }
176
177 return $departments;
178 }
179
180 public function exclude_notes_from_comment_count($post_id) {
181 global $wpdb;
182 $post_id = (int)$post_id;
183 if ( !$post_id ) {
184 return false;
185 }
186 if ( !$post = get_post($post_id) ) {
187 return false;
188 }
189
190 $new = (int) $wpdb->get_var( $wpdb->prepare("SELECT COUNT(*)
191 FROM $wpdb->comments
192 WHERE comment_post_ID = %d AND comment_approved = '1' AND comment_type != 'propertyhive_note' ", $post_id) );
193 $wpdb->update( $wpdb->posts, array('comment_count' => $new), array('ID' => $post_id) );
194
195 clean_post_cache( $post );
196 }
197
198
199 /**
200 * Show action links on the plugin screen
201 *
202 * @param mixed $links
203 * @return array
204 */
205 public function action_links( $links )
206 {
207 return array_merge( array(
208 '<a href="' . admin_url( 'admin.php?page=ph-settings' ) . '">' . __( 'Settings', 'propertyhive' ) . '</a>',
209 '<a href="' . esc_url( apply_filters( 'propertyhive_features_url', admin_url( 'admin.php?page=ph-settings&tab=features' ) ) ) . '">' . __( 'Features', 'propertyhive' ) . '</a>',
210 '<a href="' . esc_url( apply_filters( 'propertyhive_url', 'https://wp-property-hive.com/', 'propertyhive' ) ) . '" target="_blank">' . __( 'Website', 'propertyhive' ) . '</a>',
211 ), $links );
212 }
213
214 /**
215 * Auto-load PH classes on demand to reduce memory consumption.
216 *
217 * @param mixed $class
218 * @return void
219 */
220 public function autoload( $class )
221 {
222 $path = null;
223 $class = strtolower( $class );
224 $file = 'class-' . str_replace( '_', '-', $class ) . '.php';
225
226 if ( strpos( $class, 'ph_shortcode_' ) === 0 ) {
227 $path = $this->plugin_path() . '/includes/shortcodes/';
228 } elseif ( strpos( $class, 'ph_meta_box' ) === 0 ) {
229 $path = $this->plugin_path() . '/includes/admin/post-types/meta-boxes/';
230 } elseif ( strpos( $class, 'ph_admin' ) === 0 ) {
231 $path = $this->plugin_path() . '/includes/admin/';
232 }
233
234 if ( $path && is_readable( $path . $file ) ) {
235 include_once( $path . $file );
236 return;
237 }
238
239 // Fallback
240 if ( strpos( $class, 'ph_' ) === 0 ) {
241 $path = $this->plugin_path() . '/includes/';
242 }
243
244 if ( $path && is_readable( $path . $file ) ) {
245 include_once( $path . $file );
246 return;
247 }
248 }
249
250 /**
251 * Define PH Constants
252 */
253 private function define_constants()
254 {
255 define( 'PH_PLUGIN_FILE', __FILE__ );
256 define( 'PH_VERSION', $this->version );
257
258 if ( ! defined( 'PH_TEMPLATE_PATH' ) ) {
259 define( 'PH_TEMPLATE_PATH', $this->template_path() );
260 }
261 }
262
263 /**
264 * Include required core files used in admin and on the frontend.
265 */
266 private function includes() {
267 include_once( 'includes/ph-core-functions.php' );
268 include_once( 'includes/ph-update-functions.php' );
269 include_once( 'includes/class-ph-install.php' );
270 include_once( 'includes/class-ph-comments.php' );
271 include_once( 'includes/class-ph-emails.php' );
272 include_once( 'includes/class-ph-licenses.php' );
273
274 if ( is_admin() ) {
275 include_once( 'includes/admin/class-ph-admin.php' );
276 include_once( 'includes/class-ph-third-party-contacts.php' );
277 }
278
279 if ( defined( 'DOING_AJAX' ) ) {
280 $this->ajax_includes();
281 }
282
283 if ( ! is_admin() || defined( 'DOING_AJAX' ) || (isset($_GET['action']) && $_GET['action'] == 'elementor') ) {
284 $this->frontend_includes();
285 }
286
287 include_once( 'includes/ph-form-functions.php' ); // Form Renderers
288 include_once( 'includes/class-ph-form-handler.php' ); // Form Handlers
289 include_once( 'includes/class-ph-shortcodes.php' ); // Shortcodes class
290
291 include( 'includes/class-ph-query.php' ); // The main query class
292
293 include_once( 'includes/class-ph-post-types.php' ); // Registers post types
294 include_once( 'includes/class-ph-countries.php' ); // Manages interaction with countries and currency
295
296 if ( get_option( 'propertyhive_address_keyword_compare', '=' ) == 'polygon' )
297 {
298 include_once( 'includes/class-ph-address-keyword-polygon.php' ); // Manages getting and caching polygons associated with search terms
299 }
300
301 include_once( 'includes/class-ph-user-contacts.php' ); // Handles keeping contacts and users in sync
302
303 include_once( 'includes/class-ph-avada.php' ); // Avada / Fusion Builder
304 include_once( 'includes/class-ph-bricks-builder.php' ); // Bricks Builder
305 include_once( 'includes/class-ph-divi.php' ); // Divi
306 include_once( 'includes/class-ph-elementor.php' ); // Elementor
307 include_once( 'includes/class-ph-salient.php' ); // Salient / WPBakery
308 include_once( 'includes/class-ph-yoast-seo.php' ); // Yoast SEO
309 include_once( 'includes/class-ph-rank-math.php' ); // Rank Math
310 include_once( 'includes/class-ph-aioseo.php' ); // All In One SEO
311 include_once( 'includes/class-ph-duplicate-post.php' ); // Duplicate Post
312
313 include_once( 'includes/class-ph-additional-fields.php' ); // Additional Fields
314 include_once( 'includes/class-ph-text-substitution.php' ); // Text Substitution
315
316 include_once( 'includes/ph-pro-feature-functions.php' ); // Pro Features
317
318 $this->query = new PH_Query();
319 $this->email = new PH_Emails();
320 $this->license = new PH_Licenses();
321 }
322
323 public function rest_api_includes()
324 {
325 include_once( 'includes/class-ph-rest-api.php' );
326 $this->rest_api = new PH_Rest_Api();
327 }
328
329 /**
330 * Include required ajax files.
331 */
332 public function ajax_includes() {
333 include_once( 'includes/class-ph-ajax.php' ); // Ajax functions for admin and the front-end
334 }
335
336 /**
337 * Include required frontend files.
338 */
339 public function frontend_includes() {
340 include_once( 'includes/ph-template-hooks.php' );
341 include_once( 'includes/class-ph-template-loader.php' ); // Template Loader
342 include_once( 'includes/class-ph-frontend-scripts.php' ); // Frontend Scripts
343 }
344
345 /**
346 * Function used to Init PropertyHive Template Functions - This makes them pluggable by plugins and themes.
347 */
348 public function include_template_functions() {
349 include_once( 'includes/ph-template-functions.php' );
350 }
351
352 /**
353 * Include core widgets
354 */
355 public function include_widgets() {
356 /*include_once( 'includes/abstracts/abstract-ph-widget.php' );
357 include_once( 'includes/widgets/class-ph-widget-properties.php' );*/
358 }
359
360 /**
361 * Unsubscribe contact if ph_unsubscribe param set in query string. Might be a better place for this
362 */
363 public function unsubscribe_contact() {
364 if ( isset($_GET['ph_unsubscribe']) && !empty($_GET['ph_unsubscribe']) )
365 {
366 $ph_unsubscribe = sanitize_text_field(base64_decode($_GET['ph_unsubscribe']));
367 if ( $ph_unsubscribe === FALSE )
368 {
369 die("Invalid token passed 1");
370 return false;
371 }
372
373 $explode_ph_unsubscribe = explode("|", $ph_unsubscribe);
374 if ( count($explode_ph_unsubscribe) != 2 )
375 {
376 die("Invalid token passed 2");
377 return false;
378 }
379
380 $contact_id = $explode_ph_unsubscribe[0];
381 if ( FALSE === get_post_status( $contact_id ) )
382 {
383 die("Invalid token passed 3");
384 return false;
385 }
386 $contact_email = get_post_meta( $contact_id, '_email_address', TRUE );
387
388 if (md5($contact_email) != $explode_ph_unsubscribe[1])
389 {
390 die("Invalid token passed 4");
391 return false;
392 }
393
394 // TODO: Make sure not already unsubscribed
395
396 // We've got this far. We received a valid token and email address
397 $forbidden_contact_methods = get_post_meta( $contact_id, '_forbidden_contact_methods', TRUE );
398 if (!is_array($forbidden_contact_methods))
399 {
400 $forbidden_contact_methods = array();
401 }
402 $forbidden_contact_methods[] = 'email';
403 update_post_meta( $contact_id, '_forbidden_contact_methods', array_unique($forbidden_contact_methods) );
404
405 // Write note to applicant
406 $comment = array(
407 'note_type' => 'unsubscribe'
408 );
409
410 $data = array(
411 'comment_post_ID' => $contact_id,
412 'comment_author' => 'Property Hive',
413 'comment_author_email' => 'propertyhive@noreply.com',
414 'comment_author_url' => '',
415 'comment_date' => date("Y-m-d H:i:s"),
416 'comment_content' => serialize($comment),
417 'comment_approved' => 1,
418 'comment_type' => 'propertyhive_note',
419 );
420 wp_insert_comment( $data );
421
422 die("You have been unsubscribed successfully. Please allow up to 24 hours for this to take effect.");
423 }
424 }
425
426 /**
427 * Init PropertyHive when WordPress Initialises.
428 */
429 public function init() {
430 // Before init action
431 do_action( 'before_propertyhive_init' );
432
433 // Set up localisation
434 $this->load_plugin_textdomain();
435
436 // Session class, handles session data for users - can be overwritten if custom handler is needed
437 //$session_class = apply_filters( 'propertyhive_session_handler', 'PH_Session_Handler' );
438
439 // Load class instances
440 //$this->product_factory = new PH_Product_Factory(); // Product Factory to create new product instances
441 $this->countries = new PH_Countries(); // Countries class
442 //$this->integrations = new PH_Integrations(); // Integrations class
443 // $this->session = new $session_class();
444
445 // Email Actions
446 /*$email_actions = array(
447 'propertyhive_low_stock',
448 'propertyhive_no_stock',
449 'propertyhive_product_on_backorder',
450 'propertyhive_order_status_pending_to_processing',
451 'propertyhive_order_status_pending_to_completed',
452 'propertyhive_order_status_pending_to_on-hold',
453 'propertyhive_order_status_failed_to_processing',
454 'propertyhive_order_status_failed_to_completed',
455 'propertyhive_order_status_completed',
456 'propertyhive_new_customer_note',
457 'propertyhive_created_customer'
458 );
459
460 foreach ( $email_actions as $action )
461 add_action( $action, array( $this, 'send_transactional_email' ), 10, 10 );*/
462
463 // Init action
464 do_action( 'propertyhive_init' );
465 }
466
467 /**
468 * Load Localisation files.
469 *
470 * Note: the first-loaded translation file overrides any following ones if the same translation is present
471 */
472 public function load_plugin_textdomain() {
473 $locale = apply_filters( 'plugin_locale', get_locale(), 'propertyhive' );
474
475 // Admin Locale
476 if ( is_admin() ) {
477 load_textdomain( 'propertyhive', WP_LANG_DIR . "/propertyhive/propertyhive-admin-$locale.mo" );
478 load_textdomain( 'propertyhive', dirname( __FILE__ ) . "/i18n/languages/propertyhive-admin-$locale.mo" );
479 }
480
481 // Global + Frontend Locale
482 load_textdomain( 'propertyhive', WP_LANG_DIR . "/propertyhive/propertyhive-$locale.mo" );
483 load_plugin_textdomain( 'propertyhive', false, plugin_basename( dirname( __FILE__ ) ) . "/i18n/languages" );
484 }
485
486 /**
487 * Ensure theme and server variable compatibility and setup image sizes..
488 */
489 public function setup_environment() {
490
491 // IIS
492 if ( ! isset($_SERVER['REQUEST_URI'] ) ) {
493 $_SERVER['REQUEST_URI'] = substr( $_SERVER['PHP_SELF'], 1 );
494 if ( isset( $_SERVER['QUERY_STRING'] ) ) {
495 $_SERVER['REQUEST_URI'].='?'.$_SERVER['QUERY_STRING'];
496 }
497 }
498
499 // NGINX Proxy
500 if ( ! isset( $_SERVER['REMOTE_ADDR'] ) && isset( $_SERVER['HTTP_REMOTE_ADDR'] ) ) {
501 $_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_REMOTE_ADDR'];
502 }
503
504 if ( ! isset( $_SERVER['HTTPS'] ) && ! empty( $_SERVER['HTTP_HTTPS'] ) ) {
505 $_SERVER['HTTPS'] = $_SERVER['HTTP_HTTPS'];
506 }
507
508 // Support for hosts which don't use HTTPS, and use HTTP_X_FORWARDED_PROTO
509 if ( ! isset( $_SERVER['HTTPS'] ) && ! empty( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https' ) {
510 $_SERVER['HTTPS'] = '1';
511 }
512 }
513
514 /** Helper functions ******************************************************/
515
516 /**
517 * Get the plugin url.
518 *
519 * @return string
520 */
521 public function plugin_url() {
522 return untrailingslashit( plugins_url( '/', __FILE__ ) );
523 }
524
525 /**
526 * Get the plugin path.
527 *
528 * @return string
529 */
530 public function plugin_path() {
531 return untrailingslashit( plugin_dir_path( __FILE__ ) );
532 }
533
534 /**
535 * Get the template path.
536 *
537 * @return string
538 */
539 public function template_path() {
540 return apply_filters( 'PH_TEMPLATE_PATH', 'propertyhive/' );
541 }
542
543 /**
544 * Get Ajax URL.
545 *
546 * @return string
547 */
548 public function ajax_url() {
549 return admin_url( 'admin-ajax.php', 'relative' );
550 }
551
552 /**
553 * Return the WC API URL for a given request
554 *
555 * @param mixed $request
556 * @param mixed $ssl (default: null)
557 * @return string
558 */
559 public function api_request_url( $request, $ssl = null ) {
560 if ( is_null( $ssl ) ) {
561 $scheme = parse_url( get_option( 'home' ), PHP_URL_SCHEME );
562 } elseif ( $ssl ) {
563 $scheme = 'https';
564 } else {
565 $scheme = 'http';
566 }
567
568 if ( get_option('permalink_structure') ) {
569 return esc_url_raw( trailingslashit( home_url( '/ph-api/' . $request, $scheme ) ) );
570 } else {
571 return esc_url_raw( add_query_arg( 'ph-api', $request, trailingslashit( home_url( '', $scheme ) ) ) );
572 }
573 }
574
575 }
576
577 }
578
579 /**
580 * Returns the main instance of PH to prevent the need to use globals.
581 *
582 * @since 1.0.0
583 * @return PropertyHive
584 */
585 function PH() {
586 return PropertyHive::instance();
587 }
588
589 // Global for backwards compatibility.
590 $GLOBALS['propertyhive'] = PH();
591