PluginProbe
Property Hive / trunk
Property Hive vtrunk
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 trunk, at propertyhive.php

593 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.6
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.6
31 */
32 final class PropertyHive {
33
34 /**
35 * @var string
36 */
37 public $version = '2.2.6';
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-search-analytics.php' ); // Search Analytics
314
315 include_once( 'includes/class-ph-additional-fields.php' ); // Additional Fields
316 include_once( 'includes/class-ph-text-substitution.php' ); // Text Substitution
317
318 include_once( 'includes/ph-pro-feature-functions.php' ); // Pro Features
319
320 $this->query = new PH_Query();
321 $this->email = new PH_Emails();
322 $this->license = new PH_Licenses();
323 }
324
325 public function rest_api_includes()
326 {
327 include_once( 'includes/class-ph-rest-api.php' );
328 $this->rest_api = new PH_Rest_Api();
329 }
330
331 /**
332 * Include required ajax files.
333 */
334 public function ajax_includes() {
335 include_once( 'includes/class-ph-ajax.php' ); // Ajax functions for admin and the front-end
336 }
337
338 /**
339 * Include required frontend files.
340 */
341 public function frontend_includes() {
342 include_once( 'includes/ph-template-hooks.php' );
343 include_once( 'includes/class-ph-template-loader.php' ); // Template Loader
344 include_once( 'includes/class-ph-frontend-scripts.php' ); // Frontend Scripts
345 }
346
347 /**
348 * Function used to Init PropertyHive Template Functions - This makes them pluggable by plugins and themes.
349 */
350 public function include_template_functions() {
351 include_once( 'includes/ph-template-functions.php' );
352 }
353
354 /**
355 * Include core widgets
356 */
357 public function include_widgets() {
358 /*include_once( 'includes/abstracts/abstract-ph-widget.php' );
359 include_once( 'includes/widgets/class-ph-widget-properties.php' );*/
360 }
361
362 /**
363 * Unsubscribe contact if ph_unsubscribe param set in query string. Might be a better place for this
364 */
365 public function unsubscribe_contact() {
366 if ( isset($_GET['ph_unsubscribe']) && !empty($_GET['ph_unsubscribe']) )
367 {
368 $ph_unsubscribe = sanitize_text_field(base64_decode($_GET['ph_unsubscribe']));
369 if ( $ph_unsubscribe === FALSE )
370 {
371 die("Invalid token passed 1");
372 return false;
373 }
374
375 $explode_ph_unsubscribe = explode("|", $ph_unsubscribe);
376 if ( count($explode_ph_unsubscribe) != 2 )
377 {
378 die("Invalid token passed 2");
379 return false;
380 }
381
382 $contact_id = $explode_ph_unsubscribe[0];
383 if ( FALSE === get_post_status( $contact_id ) )
384 {
385 die("Invalid token passed 3");
386 return false;
387 }
388 $contact_email = get_post_meta( $contact_id, '_email_address', TRUE );
389
390 if (md5($contact_email) != $explode_ph_unsubscribe[1])
391 {
392 die("Invalid token passed 4");
393 return false;
394 }
395
396 // TODO: Make sure not already unsubscribed
397
398 // We've got this far. We received a valid token and email address
399 $forbidden_contact_methods = get_post_meta( $contact_id, '_forbidden_contact_methods', TRUE );
400 if (!is_array($forbidden_contact_methods))
401 {
402 $forbidden_contact_methods = array();
403 }
404 $forbidden_contact_methods[] = 'email';
405 update_post_meta( $contact_id, '_forbidden_contact_methods', array_unique($forbidden_contact_methods) );
406
407 // Write note to applicant
408 $comment = array(
409 'note_type' => 'unsubscribe'
410 );
411
412 $data = array(
413 'comment_post_ID' => $contact_id,
414 'comment_author' => 'Property Hive',
415 'comment_author_email' => 'propertyhive@noreply.com',
416 'comment_author_url' => '',
417 'comment_date' => date("Y-m-d H:i:s"),
418 'comment_content' => serialize($comment),
419 'comment_approved' => 1,
420 'comment_type' => 'propertyhive_note',
421 );
422 wp_insert_comment( $data );
423
424 die("You have been unsubscribed successfully. Please allow up to 24 hours for this to take effect.");
425 }
426 }
427
428 /**
429 * Init PropertyHive when WordPress Initialises.
430 */
431 public function init() {
432 // Before init action
433 do_action( 'before_propertyhive_init' );
434
435 // Set up localisation
436 $this->load_plugin_textdomain();
437
438 // Session class, handles session data for users - can be overwritten if custom handler is needed
439 //$session_class = apply_filters( 'propertyhive_session_handler', 'PH_Session_Handler' );
440
441 // Load class instances
442 //$this->product_factory = new PH_Product_Factory(); // Product Factory to create new product instances
443 $this->countries = new PH_Countries(); // Countries class
444 //$this->integrations = new PH_Integrations(); // Integrations class
445 // $this->session = new $session_class();
446
447 // Email Actions
448 /*$email_actions = array(
449 'propertyhive_low_stock',
450 'propertyhive_no_stock',
451 'propertyhive_product_on_backorder',
452 'propertyhive_order_status_pending_to_processing',
453 'propertyhive_order_status_pending_to_completed',
454 'propertyhive_order_status_pending_to_on-hold',
455 'propertyhive_order_status_failed_to_processing',
456 'propertyhive_order_status_failed_to_completed',
457 'propertyhive_order_status_completed',
458 'propertyhive_new_customer_note',
459 'propertyhive_created_customer'
460 );
461
462 foreach ( $email_actions as $action )
463 add_action( $action, array( $this, 'send_transactional_email' ), 10, 10 );*/
464
465 // Init action
466 do_action( 'propertyhive_init' );
467 }
468
469 /**
470 * Load Localisation files.
471 *
472 * Note: the first-loaded translation file overrides any following ones if the same translation is present
473 */
474 public function load_plugin_textdomain() {
475 $locale = apply_filters( 'plugin_locale', get_locale(), 'propertyhive' );
476
477 // Admin Locale
478 if ( is_admin() ) {
479 load_textdomain( 'propertyhive', WP_LANG_DIR . "/propertyhive/propertyhive-admin-$locale.mo" );
480 load_textdomain( 'propertyhive', dirname( __FILE__ ) . "/i18n/languages/propertyhive-admin-$locale.mo" );
481 }
482
483 // Global + Frontend Locale
484 load_textdomain( 'propertyhive', WP_LANG_DIR . "/propertyhive/propertyhive-$locale.mo" );
485 load_plugin_textdomain( 'propertyhive', false, plugin_basename( dirname( __FILE__ ) ) . "/i18n/languages" );
486 }
487
488 /**
489 * Ensure theme and server variable compatibility and setup image sizes..
490 */
491 public function setup_environment() {
492
493 // IIS
494 if ( ! isset($_SERVER['REQUEST_URI'] ) ) {
495 $_SERVER['REQUEST_URI'] = substr( $_SERVER['PHP_SELF'], 1 );
496 if ( isset( $_SERVER['QUERY_STRING'] ) ) {
497 $_SERVER['REQUEST_URI'].='?'.$_SERVER['QUERY_STRING'];
498 }
499 }
500
501 // NGINX Proxy
502 if ( ! isset( $_SERVER['REMOTE_ADDR'] ) && isset( $_SERVER['HTTP_REMOTE_ADDR'] ) ) {
503 $_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_REMOTE_ADDR'];
504 }
505
506 if ( ! isset( $_SERVER['HTTPS'] ) && ! empty( $_SERVER['HTTP_HTTPS'] ) ) {
507 $_SERVER['HTTPS'] = $_SERVER['HTTP_HTTPS'];
508 }
509
510 // Support for hosts which don't use HTTPS, and use HTTP_X_FORWARDED_PROTO
511 if ( ! isset( $_SERVER['HTTPS'] ) && ! empty( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https' ) {
512 $_SERVER['HTTPS'] = '1';
513 }
514 }
515
516 /** Helper functions ******************************************************/
517
518 /**
519 * Get the plugin url.
520 *
521 * @return string
522 */
523 public function plugin_url() {
524 return untrailingslashit( plugins_url( '/', __FILE__ ) );
525 }
526
527 /**
528 * Get the plugin path.
529 *
530 * @return string
531 */
532 public function plugin_path() {
533 return untrailingslashit( plugin_dir_path( __FILE__ ) );
534 }
535
536 /**
537 * Get the template path.
538 *
539 * @return string
540 */
541 public function template_path() {
542 return apply_filters( 'PH_TEMPLATE_PATH', 'propertyhive/' );
543 }
544
545 /**
546 * Get Ajax URL.
547 *
548 * @return string
549 */
550 public function ajax_url() {
551 return admin_url( 'admin-ajax.php', 'relative' );
552 }
553
554 /**
555 * Return the WC API URL for a given request
556 *
557 * @param mixed $request
558 * @param mixed $ssl (default: null)
559 * @return string
560 */
561 public function api_request_url( $request, $ssl = null ) {
562 if ( is_null( $ssl ) ) {
563 $scheme = parse_url( get_option( 'home' ), PHP_URL_SCHEME );
564 } elseif ( $ssl ) {
565 $scheme = 'https';
566 } else {
567 $scheme = 'http';
568 }
569
570 if ( get_option('permalink_structure') ) {
571 return esc_url_raw( trailingslashit( home_url( '/ph-api/' . $request, $scheme ) ) );
572 } else {
573 return esc_url_raw( add_query_arg( 'ph-api', $request, trailingslashit( home_url( '', $scheme ) ) ) );
574 }
575 }
576
577 }
578
579 }
580
581 /**
582 * Returns the main instance of PH to prevent the need to use globals.
583 *
584 * @since 1.0.0
585 * @return PropertyHive
586 */
587 function PH() {
588 return PropertyHive::instance();
589 }
590
591 // Global for backwards compatibility.
592 $GLOBALS['propertyhive'] = PH();
593