PluginProbe
MLSImport: IDX Plugin & MLS Plugin for Real Estate Listings / 6.0.5
MLSImport: IDX Plugin & MLS Plugin for Real Estate Listings v6.0.5
7.2 7.1.2 7.1.1 7.1 7.0.4 7.0.6 7.0.7 6.3.8 6.3.7 6.3.6 6.3.5 6.3.4 6.3.3 6.3.1 trunk 5.7.3 5.7.5 5.8.1 5.8.2 5.8.3 5.8.4 5.8.6 6.0.4 6.0.5 6.0.7 All 35 releases
mlsimport / admin / class-mlsimport-admin.php

class-mlsimport-admin.php in MLSImport: IDX Plugin & MLS Plugin for Real Estate Listings 6.0.5, at admin/class-mlsimport-admin.php

2,824 lines 92.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if ( ! defined( 'ABSPATH' ) ) {
3 exit; // Exit if accessed directly
4 }
5
6
7 /**
8 * The admin-specific functionality of the plugin.
9 *
10 * @link http://mlsimport.com/
11 * @since 1.0.0
12 *
13 * @package Mlsimport
14 * @subpackage Mlsimport/admin
15 */
16
17
18 /**
19 * The admin-specific functionality of the plugin.
20 *
21 * Defines the plugin name, version, and two examples hooks for how to
22 * enqueue the admin-specific stylesheet and JavaScript.
23 *
24 * @package Mlsimport
25 * @subpackage Mlsimport/admin
26 * @author MlsImport <office@mlsimport.com>
27 */
28 class Mlsimport_Admin {
29
30 /**
31 * The ID of this plugin.
32 *
33 * @since 1.0.0
34 * @access private
35 * @var string $plugin_name The ID of this plugin.
36 */
37 private $plugin_name;
38
39 /**
40 * The version of this plugin.
41 *
42 * @since 1.0.0
43 * @access private
44 * @var string $version The current version of this plugin.
45 */
46 private $version;
47 public $main;
48 public $theme_importer;
49 public $env_data;
50 public $mls_env_data;
51 protected $process_all;
52 public $field_import;
53 public $themes;
54 /**
55 * Initialize the class and set its properties.
56 *
57 * @since 1.0.0
58 * @param string $plugin_name The name of this plugin.
59 * @param string $version The version of this plugin.
60 */
61 public function __construct( $plugin_name, $version ) {
62
63 $this->plugin_name = $plugin_name;
64 $this->version = $version;
65
66 $this->field_import = array(
67 'City',
68 'CountyOrParish',
69 'MlsStatus',
70 'PropertySubType',
71 'PropertyType',
72 'StandardStatus',
73 'InternetEntireListingDisplayYN',
74 'InternetAddressDisplayYN',
75 );
76
77 $this->themes = array(
78 991 => 'WpResidence',
79 992 => 'Houzez',
80 993 => 'RealHomes',
81 994 => 'Wpestate',
82 );
83 }
84 /**
85 *
86 *
87 *
88 * Admin Setup
89 *
90 * @since 1.0.0
91 */
92 public function admin_setup( $plugin_name, $mls_enviroment, $theme_enviroment ) {
93
94 $options = get_option( $this->plugin_name . '_admin_options' );
95 $theme_id = 0;
96 if ( isset( $options['mlsimport_theme_used'] ) ) {
97 $theme_id = intval( $options['mlsimport_theme_used'] );
98 }
99 $themes = $this->themes;
100
101 $theme_enviroment = '';
102 if ( isset( $themes[ $theme_id ] ) ) {
103 $theme_enviroment = $themes[ $theme_id ];
104 }
105
106 $this->theme_importer = new ThemeImport( $plugin_name );
107
108 $options_api = get_option( $this->plugin_name . '_admin_options' );
109
110 if ( '' !== $theme_enviroment ) {
111 $classname = str_replace('Wp','',$theme_enviroment ). 'Class';
112 $this->env_data = new $classname();
113 } else {
114 $this->env_data = new stdClass();
115 }
116
117 if ( '' !== $mls_enviroment ) {
118 $mls_classname = $mls_enviroment . 'Class';
119
120 $this->mls_env_data = new $mls_classname( $this->theme_importer );
121 } else {
122 $this->mls_env_data = new stdClass();
123 }
124 }
125
126 /**
127 *
128 *
129 *
130 * Register the stylesheets for the admin area.
131 *
132 * @since 1.0.0
133 */
134 public function enqueue_styles() {
135 wp_enqueue_style( $this->plugin_name, plugin_dir_url( __FILE__ ) . 'css/mlsimport-admin.css', array(), MLSIMPORT_VERSION, 'all' );
136 wp_enqueue_style( 'mlsimport-onboarding', plugin_dir_url( __FILE__ ) . 'css/mlsimport-onboarding.css', array(), MLSIMPORT_VERSION, 'all' );
137 wp_enqueue_style( 'mlsimport-field-selector', plugin_dir_url( __FILE__ ) . 'css/mlsimport-field-selector.css', array(), MLSIMPORT_VERSION, 'all' );
138 }
139
140
141
142
143 /**
144 *
145 *
146 *
147 * Register the JavaScript for the admin area.
148 *
149 * @since 1.0.0
150 */
151 public function enqueue_scripts($hook_suffix) {
152 wp_enqueue_script( 'jquery-ui-autocomplete' );
153 $mls_import_list = mlsimport_saas_request_list();
154 wp_enqueue_script( 'mlsimport-admin', plugin_dir_url( __FILE__ ) . 'js/mlsimport-admin.js', array( 'jquery' ), $this->version, true );
155 wp_localize_script(
156 'mlsimport-admin',
157 'mlsimport_vars',
158 array(
159 'ajax_url' => admin_url( 'admin-ajax.php' )
160 )
161 );
162
163 wp_enqueue_script( 'mlsimport-field-selector', plugin_dir_url( ( __FILE__ ) ) . 'js/mlsimport-field-selector.js', array( 'jquery', 'jquery-ui-sortable', 'jquery-ui-tooltip' ), '1.0.0', true );
164
165 // Pass AJAX parameters to script
166 wp_localize_script( 'mlsimport-field-selector', 'mlsimport_params', array(
167 'ajax_url' => admin_url( 'admin-ajax.php' ),
168 'nonce' => wp_create_nonce( 'mlsimport_field_selector_nonce' )
169 ));
170
171
172 wp_enqueue_script( 'mlsimport-progressive-save', plugin_dir_url( ( __FILE__ ) ) . 'js/progressive-save.js', array('mlsimport-field-selector' ), '1.0.0', true );
173
174
175
176 if ('toplevel_page_mlsimport_plugin_options' === $hook_suffix &&
177 isset($_GET['page']) && $_GET['page'] === 'mlsimport_plugin_options' &&
178 isset($_GET['tab']) && $_GET['tab'] === 'field_options') {
179 $mlsimport_mls_metadata_populated = get_option( 'mlsimport_mls_metadata_populated', '' );
180 if ( 'yes' !== $mlsimport_mls_metadata_populated ) {
181 $inline_script = 'jQuery(document).ready(function($){ mlsimport_saas_get_metadata(); });';
182 wp_add_inline_script('mlsimport-admin', $inline_script);
183 }
184 }
185
186 if (
187 'admin_page_mlsimport-onboarding' === $hook_suffix &&
188 isset($_GET['page']) && $_GET['page'] === 'mlsimport-onboarding'
189 ) {
190 $mlsimport_mls_metadata_populated = get_option('mlsimport_mls_metadata_populated', '');
191 if ('yes' !== $mlsimport_mls_metadata_populated) {
192 $inline_script = 'jQuery(document).ready(function($){ mlsimport_saas_get_metadata(); });';
193 wp_add_inline_script('mlsimport-admin', $inline_script);
194 }
195 }
196
197
198
199
200 if ('toplevel_page_mlsimport_plugin_options' === $hook_suffix &&
201 ( isset($_GET['page']) && $_GET['page'] === 'mlsimport_plugin_options' && isset($_GET['tab']) && $_GET['tab'] === 'display_options') ||
202 (isset($_GET['page']) && $_GET['page'] === 'mlsimport_plugin_options' && !isset($_GET['tab']) ) ) {
203
204 $mls_import_list = mlsimport_saas_request_list();
205 if(!is_array($mls_import_list)){
206 $inline_script = 'jQuery(document).ready(function($){ var autofill='.wp_kses_post($mls_import_list).';mlsimport_autocomplte_mls_selection(autofill); });';
207 wp_add_inline_script('mlsimport-admin', $inline_script);
208 }
209 }
210
211 }
212
213
214
215
216
217 /**
218 *
219 *
220 *
221 * Register the administration menu for this plugin into the WordPress Dashboard menu.
222 *
223 * @since 1.0.0
224 */
225 public function add_plugin_admin_menu() {
226 add_menu_page(
227 esc_html__( 'MLS Import Settings', 'mlsimport'),
228 esc_html__( 'MLS Import Settings', 'mlsimport' ),
229 'administrator',
230 'mlsimport_plugin_options',
231 array( $this, 'display_plugin_setup_page' ),
232 MLSIMPORT_PLUGIN_URL . '/img/mlsimport_menu.png',
233 22
234 );
235 }
236
237
238
239
240
241
242
243
244 /**
245 *
246 *
247 *
248 * Add settings action link to the plugins page.
249 *
250 * @since 1.0.0
251 */
252 public function add_action_links( $links ) {
253 $settings_link = array(
254 '<a href="' . admin_url( 'admin.php?page=mlsimport_plugin_options' ) . '">' . esc_html__( 'Settings', 'mlsimport') . '</a>',
255 );
256 return array_merge( $settings_link, $links );
257 }
258
259
260
261
262
263
264
265
266 /**
267 *
268 *
269 * Render the settings page for this plugin.
270 *
271 * @since 1.0.0
272 */
273 public function display_plugin_setup_page() {
274 include_once 'partials/' . $this->plugin_name . '-admin-display.php';
275 }
276
277
278
279
280
281
282 /**
283 *
284 *
285 * Validate plugin options fields
286 *
287 * @since 1.0.0
288 */
289 public function validate_admin_options( $input ) {
290
291 $valid = array();
292 $settings_list = array(
293 'auth_username' => array(
294 'name' => esc_html__( 'Api auth_username ', 'mlsimport' ),
295 'details' => 'to be added',
296 ),
297 'auth_password' => array(
298 'name' => esc_html__( 'Api auth_password', 'mlsimport' ),
299 'details' => 'to be added',
300 ),
301 'client_id' => array(
302 'name' => esc_html__( 'Api client_id', 'mlsimport' ),
303 'details' => 'to be added',
304 ),
305 'client_secret' => array(
306 'name' => esc_html__( 'client_secret', 'mlsimport' ),
307 'details' => 'to be added',
308 ),
309 'redirect_uri' => array(
310 'name' => esc_html__( 'redirect_uri', 'mlsimport' ),
311 'details' => 'to be added',
312 ),
313 'title_format' => array(
314 'name' => esc_html__( 'title_format', 'mlsimport' ),
315 'details' => 'to be added',
316 ),
317 'force_rand' => array(
318 'name' => esc_html__( 'title_format', 'mlsimport' ),
319 'details' => 'to be added',
320 ),
321 'mlsimport_username' => array(
322 'name' => esc_html__( 'MLSImport.com Username (not your email)', 'mlsimport' ),
323 'details' => 'to be added',
324 ),
325 'mlsimport_password' => array(
326 'name' => esc_html__( 'MLSImport.com Password', 'mlsimport' ),
327 'details' => 'to be added',
328 ),
329 'mlsimport_mls_name' => array(
330 'name' => esc_html__( 'MLSImport Name', 'mlsimport' ),
331 'details' => 'to be added',
332 ),
333 'mlsimport_mls_token' => array(
334 'name' => esc_html__( 'MLSImport Token', 'mlsimport' ),
335 'details' => 'to be added',
336 ),
337
338 'mlsimport_tresle_client_id' => array(
339 'name' => esc_html__( 'MLSImport Tresle Client id', 'mlsimport' ),
340 'details' => 'to be added',
341 ),
342
343 'mlsimport_tresle_client_secret' => array(
344 'name' => esc_html__( 'MLSImport Client Secret', 'mlsimport' ),
345 'details' => 'to be added',
346 ),
347
348 'mlsimport_rapattoni_client_id' => array(
349 'name' => esc_html__( 'MLSImport Rapattoni Client id','mlsimport'),
350 'details' => 'to be added',
351 ),
352
353 'mlsimport_rapattoni_client_secret' => array(
354 'name' => esc_html__( 'MLSImport Rapattoni Secret', 'mlsimport' ),
355 'details' => 'to be added',
356 ),
357
358 'mlsimport_rapattoni_username' => array(
359 'name' => esc_html__( 'MLSImport Rapattoni Username', 'mlsimport' ),
360 'details' => 'to be added',
361 ),
362
363 'mlsimport_rapattoni_password' => array(
364 'name' => esc_html__( 'MLSImport Rapattoni Password', 'mlsimport' ),
365 'details' => 'to be added',
366 ),
367
368 'mlsimport_paragon_client_id' => array(
369 'name' => esc_html__( 'MLSImport Paragon Client id','mlsimport' ),
370 'details' => 'to be added',
371 ),
372
373 'mlsimport_paragon_client_secret' => array(
374 'name' => esc_html__( 'MLSImport Paragon Secret', 'mlsimport' ),
375 'details' => 'to be added',
376 ),
377 'mlsimport_realtorca_client_id' => array(
378 'name' => esc_html__( 'MLSImport Realtor.ca Client id','mlsimport' ),
379 'details' => 'to be added',
380 ),
381
382 'mlsimport_realtorca_client_secret' => array(
383 'name' => esc_html__( 'MLSImport Realtor.ca Secret', 'mlsimport' ),
384 'details' => 'to be added',
385 ),
386
387 'mlsimport_theme_used' => array(
388 'name' => esc_html__( 'Your Wordpress Theme', 'mlsimport' ),
389 'details' => 'to be added',
390 ),
391 'mlsimport_mls_name_front' => array(
392 'name' => '',
393 'details' => 'to be added',
394 ),
395 'mlsimport-disable-logs' => array(
396 'name' => '',
397 'details' => 'to be added',
398 ),
399 );
400
401 foreach ( $settings_list as $key => $setting ) {
402 $valid[ $key ] = ( isset( $input[ $key ] ) && ! empty( $input[ $key ] ) ) ? esc_attr( $input[ $key ] ) : '';
403 }
404
405 delete_option( 'mlsimport_connection_test' );
406 delete_option( 'mlsimport_mls_metadata_populated' );
407
408 update_option( 'mlsimport_encoding_array', '' );
409 delete_transient( 'mlsimport_token_request' );
410 delete_transient( 'mlsimport_schema' );
411 delete_transient( 'mlsimport_plugin_data_schema' );
412
413 delete_transient( 'mlsimport_saas_token' );
414 return $valid;
415 }
416
417
418
419
420
421 /**
422 *
423 *
424 * Validate admin fields
425 *
426 * @since 1.0.0
427 */
428 public function validate_admin_fields_select( $input ) {
429 $valid = array();
430
431 $mlsimport_mls_metadata_mls_data = get_option( 'mlsimport_mls_metadata_mls_data', '' );
432 $metadata_api_call = json_decode( $mlsimport_mls_metadata_mls_data, true );
433
434 foreach ( $metadata_api_call as $key => $value ) {
435 if ( isset( $input['mls-fields'][ $key ] ) ) {
436 $valid['mls-fields'][ $key ] = esc_attr( $input['mls-fields'][ $key ] );
437 }
438
439 if ( isset( $input['mls-fields-admin'][ $key ] ) ) {
440 $valid['mls-fields-admin'][ $key ] = esc_attr( $input['mls-fields-admin'][ $key ] );
441 $valid['mls-fields-label'][ $key ] = esc_attr( $input['mls-fields-label'][ $key ] );
442 $valid['mls-fields-map-postmeta'][ $key ] = esc_attr( $input['mls-fields-map-postmeta'][ $key ] );
443 $valid['mls-fields-map-taxonomy'][ $key ] = esc_attr( $input['mls-fields-map-taxonomy'][ $key ] );
444 $valid['field_order'][ $key ] = esc_attr( $input['field_order'][ $key ] );
445 }
446 }
447 //$valid['mls-fields-admin']['force_rand'] = esc_attr( $input['mls-fields-admin']['force_rand'] );
448 return $valid;
449 }
450
451 /**
452 *
453 *
454 * Validate Mls Sync fields
455 *
456 * @since 1.0.0
457 */
458 public function validate_admin_mls_sync( $input ) {
459 $valid = array();
460
461 $field_import = array( 'force_rand', 'min_price', 'max_price', 'title_format', 'property_agent', 'property_user', 'City', 'City_check', 'CountyOrParish', 'CountyOrParish_check', 'MlsStatus', 'MlsStatus_check', 'PropertySubType', 'PropertySubType_check', 'PropertyType', 'PropertyType_check',
462 'StandardStatus_delete', 'StandardStatus_delete_check', 'InternetEntireListingDisplayYN', 'InternetAddressDisplayYN' );
463 foreach ( $field_import as $key ) {
464 $valid[ $key ] = $input[ $key ];
465 }
466
467 return $valid;
468 }
469
470
471 /**
472 *
473 *
474 * Validate Administrative options
475 *
476 * @since 1.0.0
477 */
478 public function validate_administrative_options( $input ) {
479
480 $valid = array();
481
482 $field_import = array( 'import' );
483 foreach ( $field_import as $key ) {
484 $valid[ $key ] = $input[ $key ];
485 }
486
487 return $valid;
488 }
489
490 /**
491 *
492 *
493 *
494 * Validate Import Options fields
495 *
496 * @since 1.0.0
497 */
498 public function validate_admin_import_options( $input ) {
499 $valid = array();
500
501 $field_import = array( 'import_number' );
502 foreach ( $field_import as $key ) {
503 $valid[ $key ] = intval( $input[ $key ] );
504 }
505
506 if ( isset( $input['import'] ) && '' !== $input['import'] ) {
507 $decode = json_decode( $input['import'] );
508 update_option( 'mlsimport_admin_fields_select', $decode['mlsimport_admin_fields_select'] );
509 update_option( 'mlsimport_admin_mls_sync', $decode['mlsimport_admin_mls_sync'] );
510 update_option( 'mlsimport_admin_import_options', $decode['mlsimport_admin_import_options'] );
511 update_option( 'mlsimport_admin_use_transients', $decode['mlsimport_admin_use_transients'] );
512 }
513
514 return $valid;
515 }
516
517
518
519
520
521
522 /**
523 *
524 *
525 * plugin options update
526 */
527 public function options_update() {
528 register_setting( $this->plugin_name . '_admin_options', $this->plugin_name . '_admin_options', array( $this, 'validate_admin_options' ) );
529 register_setting( $this->plugin_name . '_admin_fields_select', $this->plugin_name . '_admin_fields_select', array( $this, 'validate_admin_fields_select' ) );
530 register_setting( $this->plugin_name . '_admin_mls_sync', $this->plugin_name . '_admin_mls_sync', array( $this, 'validate_admin_mls_sync' ) );
531 register_setting( $this->plugin_name . '_admin_import_options', $this->plugin_name . '_admin_import_options', array( $this, 'validate_admin_import_options' ) );
532 register_setting( $this->plugin_name . '_administrative_options', $this->plugin_name . '_administrative_options', array( $this, 'validate_administrative_options' ) );
533 }
534
535
536
537 /**
538 *
539 *
540 *
541 *
542 *
543 *
544 *
545 */
546 public function update_option_mlsimport_administrative_options() {
547 $import = get_option( 'mlsimport_administrative_options' );
548 if ( '' !== $import ) {
549 $decode = json_decode( $import['import'], true );
550 update_option( 'mlsimport_admin_fields_select', $decode['mlsimport_admin_fields_select'] );
551 update_option( 'mlsimport_admin_mls_sync', $decode['mlsimport_admin_mls_sync'] );
552 update_option( 'mlsimport_admin_import_options', $decode['mlsimport_admin_import_options'] );
553 }
554 }
555
556 /**
557 *
558 *
559 * plugin options update
560 */
561 public function update_option_mlsimport_admin_fields_select() {
562
563 $this->env_data->enviroment_custom_fields( $this->plugin_name );
564 }
565
566
567 /**
568 *
569 *
570 * plugin options update
571 */
572 public function mlsimport_meta_options() {
573 if ( method_exists( $this->env_data, 'get_property_post_type' ) ) {
574 add_meta_box( 'mlsimport_hidden_fields', esc_html__( 'Mls Import Hidden Fields', 'mlsimport' ), array( $this, 'mlsimport_hidden_fields' ), $this->env_data->get_property_post_type(), 'normal', 'low' );
575 }
576 }
577
578 /**
579 *
580 *
581 * plugin options update
582 */
583 public function mlsimport_hidden_fields() {
584 global $post;
585
586 $options = get_option( $this->plugin_name . '_admin_fields_select' );
587
588 $MLSimport_item_inserted = get_post_meta( $post->ID, 'MLSimport_item_inserted', true );
589 $MLSimport_item_updated = get_post_meta( $post->ID, 'MLSimport_item_updated', true );
590 $listing_key = get_post_meta( $post->ID, 'ListingKey', true );
591 $mlsImportItemStatusDelete = get_post_meta($post->ID, 'mlsImportItemStatusDelete', true);
592
593
594
595 // Check if the ListingKey exists
596 if ( !empty( $listing_key ) ) {
597 echo 'ListingKey: ' . $listing_key . '<br>';
598 }
599
600 // Check if MLSimport_item_inserted exists
601 if ( !empty( $MLSimport_item_inserted ) ) {
602 echo 'Added via MLS item id: ' . $MLSimport_item_inserted . ' - ' . get_the_title( $MLSimport_item_inserted ) . '<br>';
603 }
604
605 // Check if MLSimport_item_updated exists
606 if ( !empty( $MLSimport_item_updated ) ) {
607 echo 'Updated via MLS item id: ' . $MLSimport_item_updated . ' - ' . get_the_title( $MLSimport_item_updated ) . '<br>';
608 }
609
610
611 if(!empty($mlsImportItemStatusDelete)) {
612 if(is_array($mlsImportItemStatusDelete)) {
613
614 echo 'Do not delete if status: ' . implode(',' ,$mlsImportItemStatusDelete) . '<br>';
615 } else {
616
617 echo 'Do not delete if status: ' . esc_html($mlsImportItemStatusDelete) . '<br>';
618
619 }
620
621 }
622
623 foreach ( $options['mls-fields-admin'] as $key => $value ) {
624 if ( 1 === intval($options['mls-fields-admin'][ $key ] ) ) {
625 if ( isset( $options['mls-fields-label'][ $key ] ) && '' !== $options['mls-fields-label'][ $key ] ) {
626 $key = $options['mls-fields-label'][ $key ];
627 }
628
629 if ( 'ListingKey' !== $key ) {
630 $meta_key = strtolower( $key );
631 } else {
632 $meta_key = $key;
633 }
634 ?>
635
636 <strong><?php echo esc_html($key);?>:</strong>
637 <?php echo esc_html( get_post_meta( $post->ID, $meta_key, true ) ); ?> </br>
638 <?php
639 }
640 }
641 ?>
642
643 <h2 style="font-weight:bold;padding-left:0px;">Mls Import History</h2>
644 <?php
645 $meta = get_post_meta( $post->ID, 'mlsimport_property_history', true );
646 if ( '' === trim( $meta ) ) { ?>
647 <strong>Property history is blank - you can enable it in Settings/ Tools page </strong>
648 <?php
649 } else {
650 print wp_kses_post($meta);
651 }
652 }
653
654
655
656
657 /**
658 * delete cache
659 */
660 function mlsimport_delete_cache() {
661
662 check_ajax_referer( 'mlsimport_tool_actions', 'security' );
663
664 delete_transient( 'mlsimport_token_request' );
665 delete_transient( 'mlsimport_metadata_api_call_data_service_property' );
666 delete_transient( 'mls_import_meta_enums' );
667 delete_transient( 'mls_import_meta' );
668 delete_transient( 'mlsimport_plugin_data_schema' );
669 delete_transient( 'mlsimport_ready_to_go_mlsimport_data' );
670 delete_transient( 'mlsimport_saas_token' );
671
672 delete_option( 'mlsimport_mls_metadata_populated' );
673
674 die( 'deleted' );
675 }
676
677 /**
678 * clear fields data
679 */
680 function mlsimport_clear_fields_data() {
681
682 check_ajax_referer( 'mlsimport_tool_actions', 'security' );
683
684 delete_option( 'mlsimport_mls_metadata_populated' );
685 delete_option( 'mlsimport_admin_fields_select' );
686
687 die( 'deleted' );
688 }
689
690 /**
691 *
692 *
693 *
694 *
695 * delete properties
696 */
697 function mlsimport_delete_properties() {
698 $error = false;
699 global $mlsimport;
700
701 check_ajax_referer( 'mlsimport_tool_actions', 'security' );
702
703
704 if ( current_user_can( 'administrator' ) ) :
705 $mlsimport_delete_category = sanitize_text_field( wp_unslash( $_POST['mlsimport_delete_category'] ) ) ;
706 $mlsimport_delete_category_term = sanitize_title( sanitize_text_field( wp_unslash( $_POST['mlsimport_delete_category_term']) ) );
707 $mlsimport_delete_timeout = intval( $_POST['mlsimport_delete_timeout'] );
708
709 if ( '' === $mlsimport_delete_category ) {
710 $error_message = esc_html__('Category cannot be blank','mlsimport');
711 $error = true;
712 }
713
714 if ( '' === $mlsimport_delete_category_term ) {
715 $error_message = esc_html__('Category Term cannot be blank','mlsimport');
716 $error = true;
717 }
718
719 $category = get_term_by( 'slug', $mlsimport_delete_category_term, $mlsimport_delete_category );
720
721 if ( $error ) {
722 print wp_json_encode(
723 array(
724 'message' => esc_html($error_message),
725 )
726 );
727 } else {
728 $mlsimport_delete_category_term_array = array();
729
730 $mlsimport_delete_category_term_array[] = $mlsimport_delete_category_term;
731 $tax_array = array(
732 'taxonomy' => $mlsimport_delete_category,
733 'field' => 'slug',
734 'terms' => $mlsimport_delete_category_term_array,
735 );
736
737 $args = array(
738 'post_type' => array( 'estate_property', 'property' ),
739 'post_status' => 'any',
740 'paged' => 1,
741 'posts_per_page' => -1,
742 'tax_query' => array(
743 $tax_array,
744 ),
745 'fields' => 'ids',
746 );
747
748 $prop_selection = new WP_Query( $args );
749
750 foreach ( $prop_selection->posts as $key => $delete_get_id ) {
751 if ( 0 !== $mlsimport_delete_timeout ) {
752 set_timeout( $mlsimport_delete_timeout );
753 }
754
755 $mlsimport->admin->theme_importer->mlsimportSaasDeletePropertyViaMysql( $delete_get_id, ' delete from tools ' );
756 }
757
758
759
760
761
762
763
764 wp_update_term_count_now( array( $category->term_id ), $mlsimport_delete_category );
765
766 print wp_json_encode(
767 array(
768 '$category' => $category->term_id,
769 'arguments' => $args,
770 'posts' => $prop_selection->posts,
771 'found' => $prop_selection->found_posts,
772 'message' => 'Done...',
773 )
774 );
775 }
776 endif;
777 die();
778 }
779
780
781
782
783
784
785
786
787 /**
788 *
789 *
790 * Testing enviroment variables
791 */
792 public function mlsimport_saas_setting_up() {
793 // Do not output warnings during AJAX requests
794 if ( ( function_exists( 'wp_doing_ajax' ) && wp_doing_ajax() ) ||
795 ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ) {
796 return;
797 }
798
799 $is_onboarding = isset( $_GET['page'] ) && 'mlsimport-onboarding' === $_GET['page'];
800 if ( ! $is_onboarding && intval( WP_MEMORY_LIMIT ) < 256 ) :
801 if (intval(WP_MEMORY_LIMIT) < 256){ ?>
802 <div class="mlsimport_warning long_warning">
803 <strong>WordPress Memory Limit</strong> is set to <strong><?php echo esc_html(WP_MEMORY_LIMIT); ?></strong>. Allocated Memory should be at least <strong>256MB</strong>. Please refer to: <a href="https://wordpress.org/support/article/editing-wp-config-php/#increasing-memory-allocated-to-php" target="_blank">Increasing memory allocated to PHP</a>
804 </div>
805 <?php
806 }
807
808 $max_time = ini_get('max_execution_time');
809 if ($max_time < 600 && 0 !== $max_time){
810 ?>
811 <div class="mlsimport_warning long_warning">Your <strong>max_execution_time</strong> setting in php is set to <strong><?php echo esc_html($max_time); ?></strong>. Importing hundreds of listings requires extra time. Please set max_execution_time to <strong>0 (unlimited)</strong>. If that is not possible, set it to a minimum of <strong>600 (10 minutes)</strong>.</div>
812
813 <?php
814 }
815
816
817 endif; // emd pn boardingin check
818
819 }
820
821 /**
822 * Check if token validates with MLS
823 *
824 * @since 4.0.1
825 * returns token fron mlsimport
826 */
827 public function mlsimport_saas_check_mls_connection() {
828
829 $values = array();
830 $options = get_option( $this->plugin_name . '_admin_options' );
831
832 $mls_id = '';
833 if ( isset( $options['mlsimport_mls_name'] ) ) {
834 $mls_id = sanitize_text_field( trim( $options['mlsimport_mls_name'] ) );
835 }
836
837 $mls_token = '';
838 if ( isset( $options['mlsimport_mls_name'] ) ) {
839 $mls_token = sanitize_text_field( trim( $options['mlsimport_mls_token'] ) );
840 }
841
842 $mlsimport_tresle_client_id = '';
843 if ( isset( $options['mlsimport_tresle_client_id'] ) ) {
844 $mlsimport_tresle_client_id = sanitize_text_field( trim( $options['mlsimport_tresle_client_id'] ) );
845 }
846
847 $mlsimport_tresle_client_secret = '';
848 if ( isset( $options['mlsimport_tresle_client_secret'] ) ) {
849 $mlsimport_tresle_client_secret = sanitize_text_field( trim( $options['mlsimport_tresle_client_secret'] ) );
850 }
851
852 // rapattoni data
853 $mlsimport_rapattoni_client_id = '';
854 if ( isset( $options['mlsimport_rapattoni_client_id'] ) ) {
855 $mlsimport_rapattoni_client_id = sanitize_text_field( trim( $options['mlsimport_rapattoni_client_id'] ) );
856 }
857 $mlsimport_rapattoni_client_secret = '';
858 if ( isset( $options['mlsimport_rapattoni_client_secret'] ) ) {
859 $mlsimport_rapattoni_client_secret = sanitize_text_field( trim( $options['mlsimport_rapattoni_client_secret'] ) );
860 }
861
862 $mlsimport_rapattoni_username = '';
863 if ( isset( $options['mlsimport_rapattoni_username'] ) ) {
864 $mlsimport_rapattoni_username = sanitize_text_field( trim( $options['mlsimport_rapattoni_username'] ) );
865 }
866
867 $mlsimport_rapattoni_password = '';
868 if ( isset( $options['mlsimport_rapattoni_password'] ) ) {
869 $mlsimport_rapattoni_password = sanitize_text_field( trim( $options['mlsimport_rapattoni_password'] ) );
870 }
871
872 // paragon data
873 $mlsimport_paragon_client_id = '';
874 if ( isset( $options['mlsimport_paragon_client_id'] ) ) {
875 $mlsimport_paragon_client_id = sanitize_text_field( trim( $options['mlsimport_paragon_client_id'] ) );
876 }
877 $mlsimport_paragon_client_secret = '';
878 if ( isset( $options['mlsimport_paragon_client_secret'] ) ) {
879 $mlsimport_paragon_client_secret = sanitize_text_field( trim( $options['mlsimport_paragon_client_secret'] ) );
880 }
881
882 // realtor.ca data
883 $mlsimport_realtorca_client_id = '';
884 if ( isset( $options['mlsimport_realtorca_client_id'] ) ) {
885 $mlsimport_realtorca_client_id = sanitize_text_field( trim( $options['mlsimport_realtorca_client_id'] ) );
886 }
887 $mlsimport_realtorca_client_secret = '';
888 if ( isset( $options['mlsimport_realtorca_client_secret'] ) ) {
889 $mlsimport_realtorca_client_secret = sanitize_text_field( trim( $options['mlsimport_realtorca_client_secret'] ) );
890 }
891
892
893
894
895
896
897
898 if ( trim( $mls_token ) === '' ) {
899 if ( intval( $mls_id ) > 900 && intval( $mls_id ) < 3000 ) {
900 if ( trim( $mlsimport_tresle_client_id ) === '' || trim( $mlsimport_tresle_client_secret ) === '' ) {
901 return;
902 }
903 } elseif ( intval( $mls_id ) >= 5000 && intval( $mls_id ) < 6000 ) {
904 if (
905 trim( $mlsimport_rapattoni_client_id ) === '' ||
906 trim( $mlsimport_rapattoni_client_secret ) === '' ||
907 trim( $mlsimport_rapattoni_username ) === '' ||
908 trim( $mlsimport_rapattoni_password ) === ''
909 ) {
910 return;
911 }
912 } elseif ( intval( $mls_id ) >= 6000 && intval( $mls_id ) < 7000 ) {
913 if (
914 trim( $mlsimport_paragon_client_id ) === '' ||
915 trim( $mlsimport_paragon_client_secret ) === ''
916 ) {
917 return;
918 }
919 } elseif ( intval( $mls_id ) >= 7000 ) {
920 if (
921 trim( $mlsimport_realtorca_client_id ) === '' ||
922 trim( $mlsimport_realtorca_client_secret ) === ''
923 ) {
924 return;
925 }
926 }
927 }
928
929 $values['mls_token'] = $mls_token;
930 $values['mls_id'] = $mls_id;
931 $values['mlsimport_tresle_client_id'] = $mlsimport_tresle_client_id;
932 $values['mlsimport_tresle_client_secret'] = $mlsimport_tresle_client_secret;
933
934 $values['mlsimport_rapattoni_client_id'] = $mlsimport_rapattoni_client_id;
935 $values['mlsimport_rapattoni_client_secret'] = $mlsimport_rapattoni_client_secret;
936 $values['mlsimport_rapattoni_username'] = $mlsimport_rapattoni_username;
937 $values['mlsimport_rapattoni_password'] = $mlsimport_rapattoni_password;
938
939 $values['mlsimport_paragon_client_id'] = $mlsimport_paragon_client_id;
940 $values['mlsimport_paragon_client_secret'] = $mlsimport_paragon_client_secret;
941
942
943 $values['mlsimport_realtorca_client_id'] = $mlsimport_realtorca_client_id;
944 $values['mlsimport_realtorca_client_secret'] = $mlsimport_realtorca_client_secret;
945
946
947
948
949
950
951
952 $answer = $this->theme_importer->globalApiRequestSaas( 'clients', $values, 'PATCH' );
953
954
955
956
957 if ( isset( $answer['success'] ) && true === $answer['success'] ) {
958 if ( isset( $answer['tested'] ) && true === $answer['tested'] ) {
959 update_option( 'mlsimport_connection_test', 'yes' );
960 } else {
961 delete_option( 'mlsimport_connection_test' );
962 delete_option( 'mlsimport_mls_metadata_populated' );
963 }
964 } else {
965 delete_option( 'mlsimport_connection_test' );
966 delete_option( 'mlsimport_mls_metadata_populated' );
967 }
968
969 return $answer;
970 }
971
972
973
974
975
976
977 /**
978 * Request auth token from mlsimport.net
979 *
980 * @since 4.0.1
981 * returns token fron mlsimport
982 */
983 public function mlsimport_saas_get_mls_api_token_from_transient() {
984
985 $token = get_transient( 'mlsimport_saas_token' );
986
987 if ( false === $token || '' === $token ) {
988 $token_json_answer = $this->mlsimport_saas_get_mls_api_token();
989
990 if ( isset( $token_json_answer['success'] ) && true === $token_json_answer['success'] ) {
991 $token = $token_json_answer['token'];
992
993 set_transient( 'mlsimport_saas_token', $token, 3500 );
994 }
995 }
996
997 return $token;
998 }
999
1000
1001 /**
1002 * call for token
1003 *
1004 * @since 4.0.1
1005 * returns token fron mlsimport
1006 */
1007 protected function mlsimport_saas_get_mls_api_token() {
1008 $values = array();
1009 $options = get_option( $this->plugin_name . '_admin_options' );
1010
1011 // Check if the MLS provider has changed since the last run
1012 $prev_mls = get_option( 'mlsimport_prev_mls_name', '' );
1013
1014
1015 $username = '';
1016 if ( isset( $options['mlsimport_username'] ) ) {
1017 $username = sanitize_text_field( trim( $options['mlsimport_username'] ) );
1018 }
1019
1020 $password = '';
1021 if ( isset( $options['mlsimport_password'] ) ) {
1022 $password = sanitize_text_field( trim( $options['mlsimport_password'] ) );
1023 }
1024 $mls_name = '';
1025 if ( isset( $options['mlsimport_mls_name'] ) ) {
1026 $mls_name = sanitize_text_field( trim( $options['mlsimport_mls_name'] ) );
1027 }
1028
1029 $mls_token = '';
1030 if ( isset( $options['mlsimport_mls_token'] ) ) {
1031 $mls_token = sanitize_text_field( trim( $options['mlsimport_mls_token'] ) );
1032 }
1033
1034 if ( $prev_mls !== '' && $prev_mls !== $mls_name ) {
1035 delete_transient( 'mlsimport_token_request' );
1036 delete_transient( 'mlsimport_metadata_api_call_data_service_property' );
1037 delete_transient( 'mls_import_meta_enums' );
1038 delete_transient( 'mls_import_meta' );
1039 delete_transient( 'mlsimport_plugin_data_schema' );
1040 delete_transient( 'mlsimport_ready_to_go_mlsimport_data' );
1041 delete_transient( 'mlsimport_saas_token' );
1042
1043 delete_option( 'mlsimport_mls_metadata_populated' );
1044 //error_log('deleting '.$prev_mls.' - '.$mls_name);
1045
1046 delete_option( 'mlsimport_admin_fields_select' );
1047 }
1048
1049 update_option( 'mlsimport_prev_mls_name', $mls_name );
1050
1051
1052
1053 $values['username'] = $username;
1054 $values['password'] = $password;
1055
1056 if ( '' === $username || '' === $password ) {
1057 return '';
1058 }
1059
1060 $theme_Start = new ThemeImport();
1061 $answer = $theme_Start::globalApiRequestSaas( 'token', $values, 'POST' );
1062
1063
1064
1065 return $answer;
1066 }
1067
1068
1069
1070
1071
1072
1073 /**
1074 * save meta options
1075 *
1076 * @since 3.0.1
1077 */
1078 public function mlsimport_item_product_metaboxes() {
1079 add_meta_box( 'mlsimport_item_metaboxes-sectionid', __( 'Set Import data', 'mlsimport' ), array( $this, 'mlsimport_saas_display_meta_options' ), 'mlsimport_item', 'normal', 'default' );
1080 }
1081
1082
1083
1084 /**
1085 *
1086 *
1087 *
1088 * save meta options
1089 *
1090 * @since 3.0.1
1091 */
1092 public function mlsimport_item_product_save_metaboxes( $post_id, $post ) {
1093
1094 if ( ! is_object( $post ) || ! isset( $post->post_type ) ) {
1095 return;
1096 }
1097
1098 if ( 'mlsimport_item' !== $post->post_type ) {
1099 return;
1100 }
1101
1102 $allowed_keys = array(
1103 'mlsimport_item_how_many',
1104 'mlsimport_item_title_format',
1105 'mlsimport_item_agent',
1106 'mlsimport_item_property_status',
1107 'mlsimport_item_property_user',
1108 'mlsimport_item_min_price',
1109 'mlsimport_item_max_price',
1110 'mlsimport_item_city_check',
1111 'mlsimport_item_city',
1112 'mlsimport_item_city[]',
1113 'mlsimport_item_countyorparish_check',
1114 'mlsimport_item_countyorparish',
1115 'mlsimport_item_mlsstatus_check',
1116 'mlsimport_item_mlsstatus',
1117 'mlsimport_item_propertysubtype_check',
1118 'mlsimport_item_propertysubtype',
1119 'mlsimport_item_propertytype_check',
1120 'mlsimport_item_propertytype',
1121 'mlsimport_item_standardstatus_check',
1122 'mlsimport_item_standardstatus',
1123 'mlsimport_item_standardstatusdelete_check',
1124 'mlsimport_item_standardstatusdelete',
1125
1126 'mlsimport_item_internetentirelistingdisplayyn',
1127 'mlsimport_item_internetaddressdisplayyn',
1128 'mlsimport_item_stat_cron',
1129 'mlsimport_item_listagentkey',
1130 'mlsimport_item_listagentmlsid',
1131 'mlsimport_item_listofficekey',
1132 'mlsimport_item_postalcode',
1133 'mlsimport_item_listofficemlsid',
1134 'mlsimport_item_listingid',
1135 'mlsimport_item_extracity',
1136 'mlsimport_item_extracounty',
1137 'mlsimport_item_exclude_listofficemlsid',
1138 'mlsimport_item_exclude_listofficekey',
1139 'mlsimport_item_exclude_listagentmlsid',
1140 'mlsimport_item_exclude_listagentkey',
1141 'mlsimport_item_mlsareamajor',
1142 'mlsimport_item_subdivisionname',
1143 );
1144
1145
1146
1147
1148 foreach ( $allowed_keys as $key => $key_value ) {
1149 if( isset($_POST[$key_value]) ){
1150 $postmeta = mlsimport_sanitize_multi_dimensional_array ( $_POST[$key_value] ) ;
1151 update_post_meta( $post_id, sanitize_key( $key_value ), $postmeta );
1152 }
1153
1154 }
1155
1156 $blank_keys = array(
1157 'mlsimport_item_standardstatus',
1158 'mlsimport_item_city',
1159 'mlsimport_item_countyorparish',
1160 'mlsimport_item_propertysubtype',
1161 'mlsimport_item_propertytype',
1162 'mlsimport_item_standardstatus',
1163 'mlsimport_item_listingid',
1164 'mlsimport_item_mlsareamajor',
1165 'mlsimport_item_subdivisionname',
1166
1167 );
1168
1169 foreach ( $blank_keys as $key ) {
1170 if ( ! isset( $_POST[ $key ] ) ) {
1171 update_post_meta( $post_id, $key, '' );
1172 }
1173 }
1174
1175
1176 }
1177
1178
1179 /**
1180 * Display Meta Options
1181 *
1182 * @param WP_Post $post The post object.
1183 */
1184 public function mlsimport_saas_display_meta_options($post) {
1185 wp_nonce_field(plugin_basename(__FILE__), 'estate_agent_noncename');
1186 global $mlsimport;
1187
1188 $postId = $post->ID;
1189 $token = $mlsimport->admin->mlsimport_saas_get_mls_api_token_from_transient();
1190
1191 $mlsimportItemHowMany = esc_html(get_post_meta($postId, 'mlsimport_item_how_many', true));
1192 $mlsimportItemStatCron = esc_html(get_post_meta($postId, 'mlsimport_item_stat_cron', true));
1193 $lastDate = get_post_meta($postId, 'mlsimport_last_date', true);
1194 $status = get_option('mlsimport_force_stop_' . $postId);
1195 $fieldImport = $this->mlsimport_saas_return_mls_fields();
1196 $options = get_option('mlsimport_admin_options');
1197 $mlsimportMlsId = isset($options['mlsimport_mls_name']) && $options['mlsimport_mls_name'] !== ''
1198 ? intval($options['mlsimport_mls_name'])
1199 : 0;
1200
1201 $mlsRequest = $this->mlsimport_make_listing_requests($postId);
1202 //print_r($mlsRequest);
1203
1204 if (isset($mlsRequest['success']) && !$mlsRequest['success']) {
1205 echo '<div class="mlsimport_warning">' . esc_html($mlsRequest['message']) . '</div>';
1206 }
1207
1208 $foundItems = isset($mlsRequest['results']) ? intval($mlsRequest['results']) : 'none';
1209 if ($foundItems === 'none') {
1210 $mlsimport->admin->mlsimport_saas_check_mls_connection();
1211 esc_html_e('Your Token was expired. Please refresh the page to renew it wait while we renew it.', 'mlsimport');
1212 }
1213
1214 echo $this->generateMetaOptionsHtml($postId, $foundItems, $lastDate, $mlsimportItemHowMany, $mlsimportItemStatCron, $mlsimportMlsId, $fieldImport);
1215 }
1216
1217
1218
1219
1220 /**
1221 * Generate Meta Options HTML
1222 *
1223 * @param int $postId The post ID.
1224 * @param int $foundItems The number of found items.
1225 * @param string $lastDate The last date checked.
1226 * @param string $mlsimportItemHowMany How many items to import.
1227 * @param string $mlsimportItemStatCron The status of the cron job.
1228 * @param int $mlsimportMlsId The MLS import ID.
1229 * @param array $fieldImport The fields to import.
1230 * @return string The generated HTML.
1231 */
1232 private function generateMetaOptionsHtml($postId, $foundItems, $lastDate, $mlsimportItemHowMany, $mlsimportItemStatCron, $mlsimportMlsId, $fieldImport) {
1233
1234 ob_start();
1235
1236 ?>
1237 <div class="mlsimport_item_search_url" style="display:none;"><?php echo esc_html__('Last date/time we check :', 'mlsimport') . ' ' . esc_html($lastDate); ?></div>
1238 <ul>
1239 <li>1. Set the import parameters.</li>
1240 <li>2. Hit Publish or Update, otherwise import will not work correctly.</li>
1241 <li>3. Click the Start Import button. Most MLS limit the import number to 1000. If you need to import more create additional import items.</li>
1242 <li>4. Press the Update button after you make any change in the import settings.</li>
1243 </ul>
1244
1245 <?php if (is_numeric($foundItems) && $foundItems >= 500): ?>
1246 <div class="mlsimport_notification">
1247 <?php esc_html_e('You found a large number of listings. While MlsImport import can handle such a large number, you need to make sure that your server can do this operation. This import will take some time. Make sure your server has the capacity, there are no time limits for a long-running process and consider splitting the import between multiple MLS Import items.', 'mlsimport'); ?>
1248 </div>
1249 <?php endif; ?>
1250
1251 <div class="mlsimport_import_no">
1252 <?php esc_html_e('We found', 'mlsimport'); ?>
1253 <strong><?php echo esc_html($foundItems); ?></strong> listings. If you decide to import all of them make sure your server database can handle the load. Please do a database backup before initial import.
1254 </div>
1255
1256 <fieldset class="mlsimport-fieldset">
1257 <label class="mlsimport-label" for="mlsimport_item_how_many">
1258 <?php esc_html_e('How Many to import. Use 0 if you want to import all listings found.', 'mlsimport'); ?>
1259 </label>
1260 <input type="text" id="mlsimport_item_how_many" name="mlsimport_item_how_many"
1261 class="mlsimport-input mlsimport-2025-input " value="<?php echo esc_attr($mlsimportItemHowMany); ?>"/>
1262 </fieldset>
1263
1264 <fieldset class="mlsimport-fieldset mlsimport_auto_switch">
1265 <?php esc_html_e('Enable Auto Update every hour?', 'mlsimport'); ?>
1266 <label class="mlsimport_switch">
1267 <input type="hidden" value="0" name="mlsimport_item_stat_cron">
1268 <input type="checkbox" class="mlsimport-import-checkbox" value="1" name="mlsimport_item_stat_cron"<?php if (intval($mlsimportItemStatCron) !== 0) echo esc_html(' checked'); ?>>
1269 <span class="slider round"></span>
1270 </label>
1271 </fieldset>
1272
1273 <?php if ($mlsimportItemStatCron !== ''): ?>
1274 <div id="mlsimport_item_status"></div>
1275 <div id="mlsimport_item_progress" class="mlsimport-progress-bar">
1276 <div class="mlsimport-progress-bar-inner" style="width:0%;"></div>
1277 </div>
1278 <input class="button mlsimport_button save_data " type="button" id="mlsimport-start_item"
1279 data-post-number="<?php echo intval($foundItems); ?>"
1280 data-post_id="<?php echo intval($postId); ?>" value="Start Import">
1281 <input class="button mlsimport_button error_action" type="button" id="mlsimport_stop_item"
1282 data-post-number="<?php echo intval($foundItems); ?>"
1283 data-post_id="<?php echo intval($postId); ?>" value="Stop Import">
1284 <?php endif; ?>
1285
1286 <input type="hidden" id="mlsimport_item_actions" value="<?php echo esc_attr(wp_create_nonce("mlsimport_item_actions")); ?>"/>
1287 <div class="mlsimport_param_wrapper"><h2><?php esc_html_e('Import Parameters', 'mlsimport'); ?></h2>
1288
1289 <?php
1290 $mlsimportItemTitleFormat = esc_html(get_post_meta($postId, 'mlsimport_item_title_format', true));
1291 ?>
1292
1293 <fieldset class="mlsimport-fieldset">
1294 <label class="mlsimport-label" for="mlsimport_item_title_format">
1295 <?php esc_html_e('Title Format', 'mlsimport'); ?>
1296 </label>
1297
1298 <p class="mlsimport-exp"><?php esc_html_e('You can use {Address}, {City}, {CountyOrParish}, {StateOrProvince}, {PostalCode}, {PropertyType}, {Bedrooms}, {Bathrooms}, {ListingKey}, {ListingId},{StreetNumberNumeric} or {StreetName}', 'mlsimport'); ?></p>
1299 <input type="text" id="mlsimport_item_title_format" name="mlsimport_item_title_format"
1300 class="mlsimport-input mlsimport-2025-input"
1301 value="<?php echo '' !== $mlsimportItemTitleFormat ? trim(esc_html($mlsimportItemTitleFormat)) : esc_html('{Address},{City},{CountyOrParish},{PropertyType}'); ?>"/>
1302 </fieldset>
1303
1304 <?php
1305 $mlsimportItemAgent = esc_html(get_post_meta($postId, 'mlsimport_item_agent', true));
1306 ?>
1307
1308 <fieldset class="mlsimport-fieldset">
1309 <label class="mlsimport-label" for="mlsimport_item_agent">
1310 <?php esc_html_e('Select Agent', 'mlsimport'); ?>
1311 </label>
1312 <select class="mlsimport-select mlsimport-2025-select" name="mlsimport_item_agent" id="mlsimport_item_agent">
1313 <?php
1314 $permitedTags = mlsimport_allowed_html_tags_content();
1315 $selectAgent =$this->theme_importer->mlsimportSaasThemeImportSelectAgent($mlsimportItemAgent);
1316 print wp_kses($selectAgent, $permitedTags);
1317 ?>
1318 </select>
1319 </fieldset>
1320
1321 <?php
1322 $mlsimportItemPropertyStatus = esc_html(get_post_meta($postId, 'mlsimport_item_property_status', true));
1323 if ('' === $mlsimportItemPropertyStatus) {
1324 $mlsimportItemPropertyStatus = 'publish';
1325 }
1326 $statusArray = array('publish', 'draft');
1327 ?>
1328 <fieldset class="mlsimport-fieldset">
1329 <label class="mlsimport-label" for="mlsimport_item_property_status">
1330 <?php esc_html_e('Select Property Status on import', 'mlsimport'); ?>
1331 </label>
1332 <select class="mlsimport-select mlsimport-2025-select" name="mlsimport_item_property_status" id="mlsimport_item_property_status">
1333 <?php foreach ($statusArray as $value): ?>
1334 <option value="<?php echo esc_attr($value); ?>" <?php if ($value === $mlsimportItemPropertyStatus) echo esc_html('selected'); ?>>
1335 <?php echo esc_html($value); ?>
1336 </option>
1337 <?php endforeach; ?>
1338 </select>
1339 </fieldset>
1340
1341 <?php
1342 $mlsimportItemPropertyUser = esc_html(get_post_meta($postId, 'mlsimport_item_property_user', true));
1343 ?>
1344 <fieldset class="mlsimport-fieldset">
1345 <label class="mlsimport-label" for="mlsimport_item_property_user">
1346 <?php esc_html_e('User', 'mlsimport'); ?>
1347 </label>
1348 <select class="mlsimport-select mlsimport-2025-select" id="mlsimport_item_property_user" name="mlsimport_item_property_user">
1349 <?php
1350 $selectUser = $this->theme_importer->mlsimportSaasThemeImportSelectUser($mlsimportItemPropertyUser);
1351 print wp_kses($selectUser, $permitedTags);
1352 ?>
1353 </select>
1354 </fieldset>
1355
1356 <?php
1357 $mlsimportItemMinPrice = floatval(get_post_meta($postId, 'mlsimport_item_min_price', true));
1358 $mlsimportItemMaxPrice = floatval(get_post_meta($postId, 'mlsimport_item_max_price', true));
1359 if (0 === intval($mlsimportItemMaxPrice)) {
1360 $mlsimportItemMaxPrice = 10000000;
1361 }
1362 ?>
1363 <fieldset class="mlsimport-fieldset">
1364 <label class="mlsimport-label">
1365 <?php esc_html_e('Price Between', 'mlsimport'); ?>
1366 </label>
1367 <input type="text" class="mlsimport-select mlsimport-input mlsimport-2025-input " id="mlsimport_item_min_price" name="mlsimport_item_min_price" value="<?php echo esc_attr($mlsimportItemMinPrice); ?>"> and
1368 <input type="text" class="mlsimport-select mlsimport-input mlsimport-2025-input " id="mlsimport_item_max_price" name="mlsimport_item_max_price" value="<?php echo esc_attr($mlsimportItemMaxPrice); ?>">
1369 </fieldset>
1370
1371 <?php
1372 $options = get_option($this->plugin_name . '_admin_options');
1373
1374 $mlsId = '';
1375 if (isset($options['mlsimport_mls_name'])) {
1376 $mlsId = sanitize_text_field(trim($options['mlsimport_mls_name']));
1377 }
1378
1379 if ($mlsId > 5000) {
1380 $fieldImport['PropertyType']['multiple'] = 'no';
1381 }
1382
1383
1384 if ($mlsId >= 7000) {
1385 // there is no such thing for realtor.ca
1386 unset($fieldImport['PropertyType']);
1387 }
1388
1389 foreach ($fieldImport as $key => $field):
1390 $nameCheck = strtolower('mlsimport_item_' . $key . '_check');
1391 $name = strtolower('mlsimport_item_' . $key);
1392
1393 $value = get_post_meta($postId, $name, true);
1394 $valueCheck = get_post_meta($postId, $nameCheck, true);
1395 $extraClass = '';
1396 if ('extraCity' === $key || 'extraCounty' === $key) {
1397 $extraClass = ' mlsimport_hidden_field_button button mlsimport_button';
1398 }
1399 ?>
1400 <fieldset class="mlsimport-fieldset">
1401 <label class="mlsimport-label <?php echo esc_attr($extraClass); ?>" for="<?php echo esc_attr($name); ?>">
1402 <?php echo esc_html($field['label']); ?>
1403 </label>
1404 <?php if ('extraCity' === $key || 'extraCounty' === $key): ?>
1405 <div class="mlsimport-input-wrapper" style="display:none">
1406 <?php endif; ?>
1407 <p class="mlsimport-exp"><?php echo wp_kses_post($this->mlsimport_notes_for_mls($mlsimportMlsId, $name, $field['description'])); ?>
1408 <?php
1409 $isCheckboxAdmin = 0;
1410 if (1 === intval($valueCheck)) {
1411 $isCheckboxAdmin = 1;
1412 }
1413
1414 $selectAllNone = [
1415 'InternetAddressDisplayYN',
1416 'InternetEntireListingDisplayYN',
1417 'PostalCode',
1418 'ListAgentKey',
1419 'ListAgentMlsId',
1420 'ListOfficeKey',
1421 'ListOfficeMlsId',
1422 'StandardStatus',
1423 'StandardStatusDelete',
1424 'ListingId',
1425 'extraCity',
1426 'extraCounty',
1427 'Exclude_ListOfficeKey',
1428 'Exclude_ListOfficeMlsId',
1429 'Exclude_ListAgentKey',
1430 'Exclude_ListAgentMlsId',
1431 'MLSAreaMajor',
1432 'SubdivisionName',
1433 ];
1434
1435 if ($mlsId > 5000) {
1436 $selectAllNone[] = 'PropertyType';
1437 }
1438
1439 if (!in_array($key, $selectAllNone)): ?>
1440 <?php
1441 esc_html_e('- Or Select All ', 'mlsimport');
1442
1443 ?>
1444 <input type="hidden" name="<?php echo esc_attr($nameCheck); ?>" value="0"/>
1445 <input type="checkbox" class="mlsimport-import-checkbox" name="<?php echo esc_attr($nameCheck); ?>" value="1" <?php print esc_attr(checked($isCheckboxAdmin, 1, 0)); ?>/>
1446 <?php endif; ?>
1447 </p>
1448
1449 <?php
1450 $permittedStatus = ['active', 'active under contract', 'coming soon', 'activeundercontract', 'comingsoon', 'pending'];
1451
1452 if ($field['type'] === 'select'): ?>
1453 <?php
1454 $multiple = '';
1455 if ('yes' === $field['multiple']) {
1456 $multiple = 'multiple';
1457 $name .= '[]';
1458 }
1459
1460 if ('StandardStatus' === $key && '' === $value) {
1461 $value = ['Active'];
1462 }
1463
1464
1465
1466 // Additional conditions can be placed here.
1467 ?>
1468 <select class="mlsimport-select mlsimport-2025-select" id="<?php echo esc_attr($name); ?>" name="<?php echo esc_attr($name); ?>" <?php echo esc_attr($multiple); ?>>
1469 <?php foreach ($field['values'] as $selectKey): ?>
1470
1471 <?php if ('' !== $selectKey): ?>
1472 <option value="<?php echo esc_attr($selectKey); ?>"
1473 <?php
1474 if ($key === "StandardStatusDelete" && $value==null ) {
1475
1476 print 'selected';
1477 }
1478 ?>
1479 <?php if (is_array($value) ? in_array($selectKey, $value) : $selectKey === $value) echo 'selected'; ?>>
1480 <?php echo esc_html($selectKey); ?>
1481 </option>
1482 <?php endif; ?>
1483
1484 <?php endforeach; ?>
1485 </select>
1486
1487 <?php elseif ($field['type'] === 'input'): ?>
1488 <input type="text" class="mlsimport-select mlsimport-input mlsimport-2025-input" id="<?php echo esc_attr($name); ?>" name="<?php echo esc_attr($name); ?>" value="<?php echo esc_attr($value); ?>">
1489 <?php endif; ?>
1490 <?php if ('extraCity' === $key || 'extraCounty' === $key): ?>
1491 </div>
1492 <?php endif; ?>
1493 </fieldset>
1494 <?php endforeach; ?>
1495
1496 </div>
1497 <?php
1498 return ob_get_clean();
1499 }
1500
1501
1502
1503
1504
1505
1506 public function mlsimport_add_extra_fields() {
1507 }
1508
1509 /**
1510 *
1511 *
1512 *
1513 *
1514 *
1515 *
1516 */
1517 function mlsimport_notes_for_mls( $mlsimport_mls_id, $name, $description ) {
1518 // 111 - Rae Edmonton
1519
1520 if ( 111 === intval($mlsimport_mls_id) && 'mlsimport_item_standardstatus' === $name ) {
1521 return esc_html__( 'Your MLS does not use this field - all listings are considered Active.', 'mlsimport' );
1522 } else {
1523 return $description;
1524 }
1525 }
1526
1527
1528 /**
1529 *
1530 *
1531 * Get Last date
1532 */
1533 public function mlsimport_saas_get_last_date( $item_id ) {
1534 $last_date = get_post_meta( $item_id, 'mlsimport_last_date', true );
1535
1536 if ( '' === $last_date ) {
1537 $last_date = $this->mlsimport_saas_update_last_date( $item_id );
1538 }
1539 return $last_date;
1540 }
1541
1542
1543 /**
1544 *
1545 *
1546 * Save Last date
1547 */
1548 public function mlsimport_saas_update_last_date( $item_id ) {
1549
1550 $unix_time = current_time( 'timestamp', 0 ) - ( 2 * 60 * 60 );
1551 print $last_date_to_save = date( 'Y-m-d\TH:i', $unix_time );
1552 update_post_meta( $item_id, 'mlsimport_last_date', $last_date_to_save );
1553
1554 return $last_date_to_save;
1555 }
1556
1557
1558
1559
1560
1561 /**
1562 * Check and process MLSimport item for modified listings in the last 2 hours.
1563 * Optimized for memory: logs memory, unsets large arrays, and triggers garbage collection.
1564 *
1565 * @param int $item_id
1566 * @return void
1567 */
1568 public function mlsimport_saas_start_cron_links_per_item( $item_id ) {
1569 // Log memory before start
1570 //error_log("[MLSimport] Start $item_id, memory: " . (memory_get_usage(true) / 1024 / 1024) . " MB");
1571
1572 $last_date = $this->mlsimport_saas_get_last_date( $item_id );
1573 print 'MLSitem id: ' . $item_id . ' - ';
1574 esc_html_e('date to consider: ','mlsimport');
1575 print esc_html($last_date) . '. ';
1576
1577 // Make request to MLS API
1578 $mlsrequest = $this->mlsimport_make_listing_requests( $item_id, $last_date );
1579 //error_log("[MLSimport] After mlsimport_make_listing_requests, memory: " . (memory_get_usage(true) / 1024 / 1024) . " MB");
1580
1581 $found_items = 0;
1582 if ( isset( $mlsrequest['results'] ) ) {
1583 $found_items = intval( $mlsrequest['results'] );
1584 } else {
1585 delete_transient( 'mlsimport_saas_token' );
1586 }
1587 print esc_html__('We found ','mlsimport') . esc_html( $found_items ) . ' listings.</br>' . PHP_EOL;
1588
1589 // Only process if items found
1590 if ( $found_items > 0 ) {
1591
1592 $item_id_array = array(
1593 'item_id' => $item_id,
1594 'how_many' => 0,
1595 'max_number' => $found_items,
1596 'batch_counter' => 1,
1597 );
1598
1599 // Potentially large array, log memory before/after
1600 $attachments_to_move = (array) $this->mlsimport_saas_generate_import_requests_per_item( $item_id_array, $last_date );
1601 //error_log("[MLSimport] After generate_import_requests_per_item, memory: " . (memory_get_usage(true) / 1024 / 1024) . " MB");
1602
1603 // Store in post meta (beware if array is huge)
1604 update_post_meta( $item_id, 'mlsimport_spawn_status_cron_job', 'started' );
1605 update_post_meta( $item_id, 'mlsimport_cron_attach_to_move_' . $item_id, $attachments_to_move );
1606
1607 // Save last date for next run
1608 $this->mlsimport_saas_update_last_date( $item_id );
1609
1610 // Prepare and pass only necessary arguments to background process
1611 $attachments_to_send = array(
1612 'args' => array(
1613 'attachments_to_move' => $item_id,
1614 'item_id_array' => $item_id_array,
1615 ),
1616 );
1617
1618 $this->mlsimport_background_process_per_item_cron_function( $attachments_to_send['args'] );
1619
1620 // Unset large arrays/objects after use
1621 unset($attachments_to_move, $attachments_to_send, $mlsrequest, $item_id_array);
1622 gc_collect_cycles();
1623 //error_log("[MLSimport] End processing $item_id, memory: " . (memory_get_usage(true) / 1024 / 1024) . " MB");
1624 }
1625 }
1626
1627
1628
1629
1630
1631
1632 /**
1633 * Reconciliation log (optimized, batched, memory logged)
1634 */
1635 public function mlsimport_saas_start_doing_reconciliation() {
1636 global $mlsimport, $wpdb;
1637
1638
1639 // Get all MLS keys in memory (we assume this is necessary for lookup)
1640 $mls_data = $this->mlsimport_saas_get_mls_reconciliation_data();
1641 $listingKey_in_MLS = $mls_data['all_data'] ?? [];
1642
1643 unset($mls_data);
1644 gc_collect_cycles();
1645
1646 if (empty($listingKey_in_MLS)) {
1647 return;
1648 }
1649 // Flip for fast lookup
1650 $listingKey_in_MLS = array_flip($listingKey_in_MLS);
1651
1652 // Batch fetch local listings
1653 $batch = 1000;
1654 $offset = 0;
1655 $to_delete = 0;
1656 $counter = 0;
1657
1658 $mlsimport_preload_all_mls_item_status_meta = $this->mlsimport_preload_all_mls_item_status_meta();
1659 //print_r($mlsimport_preload_all_mls_item_status_meta);
1660
1661 do {
1662 $local = $wpdb->get_results(
1663 $wpdb->prepare(
1664 "SELECT
1665 p.ID,
1666 listingkey_meta.meta_value AS listingkey,
1667 inserted_meta.meta_value AS mlsimport_item_inserted
1668 FROM {$wpdb->posts} p
1669 INNER JOIN {$wpdb->postmeta} listingkey_meta
1670 ON p.ID = listingkey_meta.post_id
1671 AND listingkey_meta.meta_key = %s
1672 LEFT JOIN {$wpdb->postmeta} inserted_meta
1673 ON p.ID = inserted_meta.post_id
1674 AND inserted_meta.meta_key = %s
1675 WHERE p.post_status NOT IN ('draft', 'trash')
1676 LIMIT %d OFFSET %d",
1677 'ListingKey',
1678 'MLSimport_item_inserted',
1679 $batch,
1680 $offset
1681 ),
1682 ARRAY_A
1683 );
1684
1685 $count = count($local);
1686
1687
1688 foreach ($local as $item) {
1689 $listingkey = $item['listingkey']; // not 'meta_value' anymore
1690 $property_id = $item['ID'];
1691 $mlsimportItemId = $item['mlsimport_item_inserted'];
1692 ++$counter;
1693 // IN MLS
1694 if (isset($listingKey_in_MLS[$listingkey])) {
1695
1696 if (!empty($mlsimportItemId) && isset($mlsimport_preload_all_mls_item_status_meta[$mlsimportItemId])) {
1697 $mlsimport_item_standardstatus = $mlsimport_preload_all_mls_item_status_meta[$mlsimportItemId]['mlsimport_item_standardstatus'] ?? null;
1698 } else {
1699 $mlsimport_item_standardstatus = null;
1700 }
1701
1702 $keep_when_in_mls = $mlsimport->admin->theme_importer->check_if_delete_when_status_when_in_mls($property_id,$mlsimport_item_standardstatus);
1703 if (!$keep_when_in_mls) {
1704 ++$to_delete;
1705 $mlsimport->admin->theme_importer->mlsimportSaasDeletePropertyViaMysql($property_id, $listingkey);
1706 }
1707 } else {
1708 // NOT IN MLS
1709
1710 if (!empty($mlsimportItemId) && isset($mlsimport_preload_all_mls_item_status_meta[$mlsimportItemId])) {
1711 $mlsimport_item_standardstatus = $mlsimport_preload_all_mls_item_status_meta[$mlsimportItemId]['mlsimport_item_standardstatus'] ?? null;
1712 $mlsimport_item_standardstatusdelete = $mlsimport_preload_all_mls_item_status_meta[$mlsimportItemId]['mlsimport_item_standardstatusdelete'] ?? null;
1713 } else {
1714 $mlsimport_item_standardstatus = null;
1715 $mlsimport_item_standardstatusdelete = null;
1716 }
1717 $keep = $mlsimport->admin->theme_importer->check_if_delete_when_status($property_id, $mlsimport_item_standardstatus, $mlsimport_item_standardstatusdelete);
1718 if (!$keep) {
1719 ++$to_delete;
1720 $mlsimport->admin->theme_importer->mlsimportSaasDeletePropertyViaMysql($property_id, $listingkey);
1721 }
1722 }
1723
1724 // Memory housekeeping
1725 unset($listingkey, $property_id, $mlsimportItemId, $mlsImportItemStatus, $mlsImportItemStatusDelete, $keep_when_in_mls, $keep);
1726 if ($counter % 250 == 0) {
1727 gc_collect_cycles();
1728 }
1729 }
1730
1731 unset($local);
1732 gc_collect_cycles();
1733
1734 $offset += $batch;
1735 } while ($count === $batch);
1736
1737
1738 print esc_html(' to delete:' . $to_delete);
1739
1740 // Final cleanup
1741 unset($listingKey_in_MLS);
1742 gc_collect_cycles();
1743
1744
1745 return;
1746 }
1747
1748
1749
1750 /**
1751 * Preload all status meta for ALL mlsimport_item posts in ONE QUERY.
1752 * Returns: [mlsimport_item_id => ['mlsimport_item_standardstatus' => ..., 'mlsimport_item_standardstatusdelete' => ...], ...]
1753 */
1754 function mlsimport_preload_all_mls_item_status_meta() {
1755 global $wpdb;
1756
1757 // Only 1 query: join posts and postmeta, grab both metas
1758 $sql = "
1759 SELECT p.ID as post_id, pm.meta_key, pm.meta_value
1760 FROM {$wpdb->posts} p
1761 LEFT JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id
1762 WHERE p.post_type = 'mlsimport_item'
1763 AND pm.meta_key IN ('mlsimport_item_standardstatus', 'mlsimport_item_standardstatusdelete')
1764 ";
1765
1766 $rows = $wpdb->get_results($sql);
1767
1768 $meta = [];
1769 foreach ($rows as $row) {
1770 if (!isset($meta[$row->post_id])) {
1771 $meta[$row->post_id] = [
1772 'mlsimport_item_standardstatus' => null,
1773 'mlsimport_item_standardstatusdelete' => null
1774 ];
1775 }
1776 $meta[$row->post_id][$row->meta_key] = maybe_unserialize($row->meta_value);
1777 }
1778 return $meta;
1779 }
1780
1781
1782
1783 /**
1784 *
1785 *
1786 * Requestq Reconciliation log
1787 */
1788 public function mlsimport_saas_get_mls_reconciliation_data() {
1789
1790 $arguments = array();
1791 $answer = $this->theme_importer->globalApiRequestCurlSaas( 'reconciliation', $arguments, 'GET' );
1792 return $answer;
1793 }
1794
1795 /**
1796 *
1797 *
1798 * Reconciliation get local data
1799 */
1800 public function mlsimport_saas_get_all_meta_values($key) {
1801 global $wpdb;
1802 $result = $wpdb->get_results(
1803 $wpdb->prepare(
1804 "
1805 SELECT pm.meta_value, p.ID
1806 FROM {$wpdb->postmeta} pm
1807 INNER JOIN {$wpdb->posts} p ON p.ID = pm.post_id
1808 WHERE pm.meta_key = %s
1809 AND p.post_status = 'publish'
1810 ",
1811 $key
1812 ),
1813 ARRAY_A // Lighter than OBJECT, unless you need objects
1814 );
1815 return $result;
1816 }
1817
1818
1819
1820 /*
1821 * Do api Listing Requests
1822 *
1823 *
1824 *
1825 *
1826 * */
1827 public function mlsimport_make_listing_requests( $item_id, $last_date = '', $skip = '', $top = '' ) {
1828 $options = get_option( $this->plugin_name . '_admin_options' );
1829 $mls_id = '';
1830 if ( isset( $options['mlsimport_mls_name'] ) ) {
1831 $mls_id = sanitize_text_field( trim( $options['mlsimport_mls_name'] ) );
1832 }
1833
1834 $arguments = $this->mlsimport_saas_make_listing_requests_arguments( $item_id, $last_date, $skip, $top );
1835
1836
1837 if (
1838 $mls_id > 5000 && $mls_id < 6000 &&
1839 ( ! isset( $arguments['property_type'] ) or
1840 ( isset( $arguments['property_type'] ) && '' === $arguments['property_type'] ) or
1841 ( isset( $arguments['property_type'][0] ) && '' === $arguments['property_type'][0] )
1842 )
1843 ) {
1844 return array(
1845 'success' => false,
1846 'type' => 'rapattoni',
1847 'message' => esc_html__( 'This MLS requires to have one item selected from "Property Action Category" dropdown', 'mlsimport' ),
1848 );
1849 }
1850
1851 $potential_leght = strlen( wp_json_encode( $arguments ) );
1852 if ( $potential_leght > 1750 ) {
1853 return array(
1854 'success' => false,
1855 'potential_leght' => $potential_leght,
1856 'message' => esc_html__( 'You have too many parameters selected. Split the import beween multiple MLS Import items: For ex : Import per County instead of selecting 10 cities or import listing between certain price range.', 'mlsimport' ),
1857 );
1858 }
1859
1860 //print_r($arguments);
1861 //print '----------------------------'.PHP_EOL;
1862 $answer = $this->theme_importer->globalApiRequestCurlSaas( 'listings', $arguments, 'POST' );
1863 $answer['potential_leght'] = $potential_leght;
1864 return ( $answer );
1865 }
1866
1867
1868
1869
1870
1871
1872 /*
1873 * Create Api query arguments
1874 *
1875 *
1876 *
1877 *
1878 *
1879 * */
1880
1881 public function mlsimport_saas_make_listing_requests_arguments( $item_id, $last_date = '', $skip = '', $top = '' ) {
1882
1883 $options = get_option( $this->plugin_name . '_admin_options' );
1884 if ( isset( $options['mlsimport_mls_name'] ) ) {
1885 $mls_id = intval( $options['mlsimport_mls_name'] );
1886 } else {
1887 return '';
1888 }
1889
1890 if ( isset( $options['mlsimport_theme_used'] ) ) {
1891 $theme_id = intval( $options['mlsimport_theme_used'] );
1892 } else {
1893 return '';
1894 }
1895
1896 $values = array();
1897 $values['mls_id'] = $mls_id;
1898 $values['theme_id'] = $theme_id;
1899
1900 if ( '' !== $top ) {
1901 $values['top'] = $top;
1902 $values['skip'] = intval( $skip );
1903 }
1904
1905 // // add price
1906 $mlsimport_item_min_price = get_post_meta( $item_id, 'mlsimport_item_min_price', true );
1907 $mlsimport_item_max_price = get_post_meta( $item_id, 'mlsimport_item_max_price', true );
1908 if ( '' !== $mlsimport_item_min_price && '' !== $mlsimport_item_max_price ) {
1909 $values['list_price_min'] = floatval( $mlsimport_item_min_price );
1910 $values['list_price_max'] = floatval( $mlsimport_item_max_price );
1911 }
1912
1913 // add city
1914 $values = $this->mls_import_return_multiple_param_value( 'city', $item_id, 'city', $values );
1915
1916 // add county
1917 $values = $this->mls_import_return_multiple_param_value( 'countyorparish', $item_id, 'county_or_parish', $values );
1918
1919 // add MLSAreaMajor
1920 $values = $this->mls_import_saas_add_to_parms_input( 'MLSAreaMajor', $item_id, 'mls_area_major', $values );
1921
1922 // add SubdivisionName
1923 $values = $this->mls_import_saas_add_to_parms_input( 'SubdivisionName', $item_id, 'subdivision_name', $values );
1924
1925 // add postal code
1926 $values = $this->mls_import_saas_add_to_parms_input( 'PostalCode', $item_id, 'postal_code', $values );
1927
1928 // add status
1929
1930 if ( 111 !== $mls_id ) { // edmonton check
1931 $values = $this->mls_import_return_multiple_param_value( 'StandardStatus', $item_id, 'status', $values );
1932 }
1933
1934 // add property_subtype
1935 $values = $this->mls_import_return_multiple_param_value( 'PropertySubType', $item_id, 'property_subtype', $values );
1936
1937 // add property_type
1938 $values = $this->mls_import_return_multiple_param_value( 'PropertyType', $item_id, 'property_type', $values );
1939
1940 // rapattoni exception
1941 if ( $mls_id > 5000 &&
1942 ( isset($values['property_type']) && $values['property_type'] !='' ) ) {
1943
1944 $values = $this->mls_import_saas_add_to_parms_input( 'PropertyType', $item_id, 'property_type', $values );
1945 $temp = $values['property_type'];
1946 $temp = str_replace( ' ', '', $temp );
1947 $values['property_type'] = array();
1948 $values['property_type'][] = $temp;
1949 }
1950
1951 // add internet_entirelisting_displayyn
1952 $values = $this->mls_import_saas_add_to_parms_input( 'InternetEntireListingDisplayYN', $item_id, 'internet_entirelisting_displayyn', $values );
1953
1954 // add internet_address_displayyn
1955 $values = $this->mls_import_saas_add_to_parms_input( 'InternetAddressDisplayYN', $item_id, 'internet_address_displayyn', $values );
1956
1957 // add ListAgentKey
1958 $values = $this->mls_import_saas_add_to_parms_input( 'ListAgentKey', $item_id, 'list_agentkey', $values );
1959 // add ListAgentKey
1960 $values = $this->mls_import_saas_add_to_parms_input( 'ListAgentMlsId', $item_id, 'list_agentmlsid', $values );
1961 // add ListOfficeKey
1962 $values = $this->mls_import_saas_add_to_parms_input( 'ListOfficeKey', $item_id, 'list_officekey', $values );
1963 // add ListOfficeMlsId
1964 $values = $this->mls_import_saas_add_to_parms_input( 'ListOfficeMlsId', $item_id, 'list_officemlsid', $values );
1965
1966 // add ListingId
1967 $values = $this->mls_import_saas_add_to_parms_input( 'ListingId', $item_id, 'listingid', $values );
1968
1969 //add Exclude_ListOfficeKey
1970 $values = $this->mls_import_saas_add_to_parms_input( 'Exclude_ListOfficeKey', $item_id, 'exclude_list_officekey', $values );
1971 // add Exclude_ListOfficeMlsId
1972 $values = $this->mls_import_saas_add_to_parms_input( 'Exclude_ListOfficeMlsId', $item_id, 'exclude_list_officemlsid', $values );
1973
1974
1975
1976 //add Exclude_ListAgentKey
1977 $values = $this->mls_import_saas_add_to_parms_input( 'Exclude_ListAgentKey', $item_id, 'exclude_list_agentkey', $values );
1978 // add Exclude_ListAgentMlsId
1979 $values = $this->mls_import_saas_add_to_parms_input( 'Exclude_ListAgentMlsId', $item_id, 'exclude_list_agentmlsid', $values );
1980
1981
1982 // if we have realtorca
1983 if ($mls_id >= 7000 && $last_date!=='') {
1984 $dateTime_realtorca = new DateTime($last_date, new DateTimeZone('UTC'));
1985 // Format with seconds and UTC timezone marker
1986 $last_date = $dateTime_realtorca->format('Y-m-d\TH:i:s.000\Z');
1987 }
1988
1989 if ( '' !== $last_date ) {
1990 $values['modification_time'] = $last_date;
1991 }
1992
1993 return( $values );
1994 }
1995
1996
1997
1998 /*
1999 *
2000 * add input items to parameters array
2001 *
2002 */
2003
2004 public function mls_import_saas_add_to_parms_input( $key, $post_id, $new_name, $all_values ) {
2005 $name = strtolower( 'mlsimport_item_' . $key );
2006 $value = get_post_meta( $post_id, $name, true );
2007 if ( '' !== $value ) {
2008 $all_values[ $new_name ] = $value;
2009 }
2010
2011 return $all_values;
2012 }
2013
2014
2015 /*
2016 *
2017 * add list items to parameters array
2018 *
2019 */
2020
2021 public function mls_import_return_multiple_param_value( $key, $post_id, $new_name, $all_values ) {
2022 $name_check = strtolower( 'mlsimport_item_' . $key . '_check' );
2023 $name = strtolower( 'mlsimport_item_' . $key );
2024
2025 $value = get_post_meta( $post_id, $name, true );
2026
2027 // add extra county - should be moved into function if pass tests
2028 if ( 'countyorparish' === $key ) {
2029 $extracounty_values = get_post_meta( $post_id, 'mlsimport_item_extracounty', true );
2030
2031 if ( '' !== $extracounty_values ) {
2032 $extracounty_array = explode( ',', $extracounty_values );
2033
2034 if ( ! is_array( $value ) ) {
2035 if ( '' === $value ) {
2036 $value = array();
2037 } else {
2038 $value = array( $value );
2039 }
2040 }
2041
2042 foreach ( $extracounty_array as $extra ) {
2043 $value[] = $extra;
2044 }
2045 }
2046 }
2047
2048 // add extra city - should be moved into function if pass tests
2049 if ( 'city' === $key ) {
2050 $extracity_values = get_post_meta( $post_id, 'mlsimport_item_extracity', true );
2051 if ( '' !== $extracity_values ) {
2052 $extracity_array = explode( ',', $extracity_values );
2053
2054 if ( ! is_array( $value ) ) {
2055 if ('' === $value ) {
2056 $value = array();
2057 } else {
2058 $value = array( $value );
2059 }
2060 }
2061
2062 foreach ( $extracity_array as $extra ) {
2063 $value[] = $extra;
2064 }
2065 }
2066 }
2067
2068 $value_check = get_post_meta( $post_id, $name_check, true );
2069
2070 if ( 0 === intval($value_check) && '' !== $value ) {
2071 $all_values[ $new_name ] = $value;
2072 }
2073
2074 // status exception
2075 if ( 'status' === $new_name ) {
2076 $all_values[ $new_name ] = $value;
2077 }
2078
2079 return $all_values;
2080 }
2081
2082
2083
2084 /*
2085 *
2086 * All Enums fiels to be used on MLS import Item
2087 *
2088 *
2089 *
2090 *
2091 *
2092 *
2093 * */
2094
2095 public function mlsimport_saas_return_mls_fields() {
2096
2097 $mlsimport_mls_metadata_mls_enums = get_option( 'mlsimport_mls_metadata_mls_enums', '' );
2098
2099 if ( '' === $mlsimport_mls_metadata_mls_enums ) {
2100 ?>
2101 <div class="mlsimport_warning long_warning">Please select the import fields(from MLS Import Settings) before starting a MLS import process.</div>
2102 <?php
2103 }
2104
2105 $metadata_api_call_full = json_decode( $mlsimport_mls_metadata_mls_enums, true );
2106
2107 if ( isset( $metadata_api_call_full['global_array'] ) ) {
2108 $metadata_api_call = $metadata_api_call_full['global_array'];
2109 }
2110
2111 $city_array = array();
2112 if ( isset( $metadata_api_call['PropertyEnums']['City'] ) && is_array( $metadata_api_call['PropertyEnums']['City'] ) ) {
2113 $city_array = array_keys( $metadata_api_call['PropertyEnums']['City'] );
2114 }
2115
2116 $county_array = array();
2117 if ( isset( $metadata_api_call['PropertyEnums']['CountyOrParish'] ) && is_array( $metadata_api_call['PropertyEnums']['CountyOrParish'] ) ) {
2118 $county_array = array_keys( $metadata_api_call['PropertyEnums']['CountyOrParish'] );
2119 }
2120
2121 $mlsstatus_array = array();
2122 if ( isset( $metadata_api_call['PropertyEnums']['MlsStatus'] ) && is_array( $metadata_api_call['PropertyEnums']['MlsStatus'] ) ) {
2123 $mlsstatus_array = array_keys( $metadata_api_call['PropertyEnums']['MlsStatus'] );
2124 }
2125
2126 $propertysubtype_array = array();
2127 if ( isset( $metadata_api_call['PropertyEnums']['PropertySubType'] ) && is_array( $metadata_api_call['PropertyEnums']['PropertySubType'] ) ) {
2128 $propertysubtype_array = array_keys( $metadata_api_call['PropertyEnums']['PropertySubType'] );
2129 }
2130
2131 $propertytype_array = array();
2132 if ( isset( $metadata_api_call['PropertyEnums']['PropertyType'] ) && is_array( $metadata_api_call['PropertyEnums']['PropertyType'] ) ) {
2133 $propertytype_array = array_keys( $metadata_api_call['PropertyEnums']['PropertyType'] );
2134 }
2135
2136
2137 $standardstatus_array = array();
2138 $standardstatus_delete_array=array();
2139 if ( isset( $metadata_api_call['PropertyEnums']['StandardStatus'] ) && is_array( $metadata_api_call['PropertyEnums']['StandardStatus'] ) ) {
2140 $standardstatus_array = array_keys( $metadata_api_call['PropertyEnums']['StandardStatus'] );
2141 $standardstatus_delete_array= array_keys( $metadata_api_call['PropertyEnums']['StandardStatus'] );
2142 }
2143
2144 // if we do not have standart status
2145 if ( empty( $standardstatus_array ) ) {
2146 $standardstatus_array = $mlsstatus_array;
2147 $standardstatus_delete_array = $mlsstatus_array;
2148
2149 }
2150
2151
2152 $permited_status=array('active','active under contract','coming soon','activeundercontract','comingsoon','pending');
2153 $permited_status_lower = array_map('strtolower', $permited_status);
2154
2155 // Filter out permitted statuses from array1 values
2156 // $standardstatus_delete_array = array_filter($standardstatus_delete_array, function ($value) use ($permited_status_lower) {
2157 // return !in_array(strtolower($value), $permited_status_lower);
2158 // });
2159
2160
2161
2162
2163 $extracounty_values = '';
2164 $extracity_values = '';
2165
2166 $field_import = array(
2167 'City' => array(
2168 'label' => esc_html__( 'Select cities', 'mlsimport' ),
2169 'description' => esc_html__( 'Select the cities from where we will import data.', 'mlsimport' ),
2170 'type' => 'select',
2171 'multiple' => 'yes',
2172 'values' => $city_array,
2173 ),
2174
2175 'extraCity' => array(
2176 'label' => esc_html__( 'Add extra Cities', 'mlsimport' ),
2177 'description' => esc_html__( 'Add extra cities, separated by comma. They need to be written exactly like they are stored in MLS (for example all caps)', 'mlsimport' ),
2178 'type' => 'input',
2179 'multiple' => 'no',
2180 'values' => $extracity_values,
2181 ),
2182
2183 'CountyOrParish' => array(
2184 'label' => esc_html__( 'Select Counties', 'mlsimport' ),
2185 'description' => esc_html__( 'Select the counties from where we will import data.', 'mlsimport' ),
2186 'type' => 'select',
2187 'multiple' => 'yes',
2188 'values' => $county_array,
2189 'show_extra_field' => true,
2190 ),
2191
2192 'extraCounty' => array(
2193 'label' => esc_html__( 'Add extra Counties', 'mlsimport' ),
2194 'description' => esc_html__( 'Add extra counties, separated by comma. They need to be written exactly like they are stored in MLS (for example all caps)', 'mlsimport' ),
2195 'type' => 'input',
2196 'multiple' => 'no',
2197 'values' => $extracounty_values,
2198 ),
2199
2200 'MLSAreaMajor' => array(
2201 'label' => esc_html__( 'MLS Area Major', 'mlsimport' ),
2202 'description' => esc_html__( 'Filter listings by MLSAreaMajor.', 'mlsimport' ),
2203 'type' => 'input',
2204 'multiple' => 'no',
2205 ),
2206
2207 'SubdivisionName' => array(
2208 'label' => esc_html__( 'Subdivision Name', 'mlsimport' ),
2209 'description' => esc_html__( 'Filter listings by SubDivisionName.', 'mlsimport' ),
2210 'type' => 'input',
2211 'multiple' => 'no',
2212 ),
2213
2214 'PostalCode' => array(
2215 'label' => esc_html__( 'Select Postal Code', 'mlsimport' ),
2216 'description' => esc_html__( 'Select the PostalCode from where to import listings. Works with only one PostalCode.', 'mlsimport' ),
2217 'type' => 'input',
2218 'multiple' => 'no',
2219 ),
2220
2221 'PropertySubType' => array(
2222 'label' => esc_html__( 'Select Property Category', 'mlsimport' ),
2223 'description' => esc_html__( 'Property Category', 'mlsimport' ),
2224 'type' => 'select',
2225 'multiple' => 'yes',
2226 'values' => $propertysubtype_array,
2227 ),
2228 'PropertyType' => array(
2229 'label' => esc_html__( 'Select Property Action Category', 'mlsimport' ),
2230 'description' => esc_html__( 'Property Action Category', 'mlsimport' ),
2231 'type' => 'select',
2232 'multiple' => 'yes',
2233 'values' => $propertytype_array,
2234 ),
2235 'StandardStatus' => array(
2236 'label' => esc_html__( 'Select Status', 'mlsimport' ),
2237 'description' => __( 'The list is auto-populated with MLS available statuses. To select multiple statuses, use Ctrl (Windows) or Command (Mac).', 'mlsimport' ),
2238 'type' => 'select',
2239 'multiple' => 'yes',
2240 'values' => $standardstatus_array,
2241 ),
2242 'StandardStatusDelete' => array(
2243 'label' => esc_html__( 'Delete Statuses', 'mlsimport' ),
2244 'description' => __( 'Properties with these statuses will be deleted from your website after they are removed from MLS database. If you edit the field after importing, the changes will NOT apply to listings that have already been imported.', 'mlsimport' ),
2245 'type' => 'select',
2246 'multiple' => 'yes',
2247 'values' => $standardstatus_delete_array,
2248 ),
2249
2250 'InternetEntireListingDisplayYN' => array(
2251 'label' => esc_html__( 'Internet Entire Listing Display ', 'mlsimport'),
2252 'description' => esc_html__( 'A yes/no field that states the seller has allowed the listing to be displayed on Internet sites.', 'mlsimport' ),
2253 'type' => 'select',
2254 'multiple' => 'no',
2255 'values' => array(
2256 'yes',
2257 'no',
2258 ),
2259 ),
2260 'InternetAddressDisplayYN' => array(
2261 'label' => esc_html__( 'Internet Address display', 'mlsimport' ),
2262 'description' => esc_html__( 'A yes/no field that states the seller has allowed the listing address to be displayed on Internet sites.', 'mlsimport' ),
2263 'type' => 'select',
2264 'multiple' => 'no',
2265 'values' => array(
2266 'yes',
2267 'no',
2268 ),
2269 ),
2270 'ListAgentKey' => array(
2271 'label' => esc_html__( 'ListAgentKey', 'mlsimport' ),
2272 'description' => esc_html__( 'Import listings from a specific Agent (contact your MLS for this information)', 'mlsimport' ),
2273 'type' => 'input',
2274 'multiple' => 'no',
2275 ),
2276 'ListAgentMlsId' => array(
2277 'label' => esc_html__( 'ListAgentMlsId', 'mlsimport' ),
2278 'description' => esc_html__( 'Import listings from a specific Agent (contact your MLS for this information)', 'mlsimport' ),
2279 'type' => 'input',
2280 'multiple' => 'no',
2281 ),
2282 'ListOfficeKey' => array(
2283 'label' => esc_html__( 'ListOfficeKey', 'mlsimport' ),
2284 'description' => esc_html__( 'Import listings from a specific Office (contact your MLS for this information)', 'mlsimport'),
2285 'type' => 'input',
2286 'multiple' => 'no',
2287 ),
2288 'ListOfficeMlsId' => array(
2289 'label' => esc_html__( 'ListOfficeMlsId', 'mlsimport' ),
2290 'description' => esc_html__( 'Import listings from a specific Office (contact your MLS for this information)', 'mlsimport' ),
2291 'type' => 'input',
2292 'multiple' => 'no',
2293 ),
2294 'ListingId' => array(
2295 'label' => esc_html__( 'ListingId', 'mlsimport' ),
2296 'description' => esc_html__( 'Import One Property Only via parameter ListingID. If this does not work for you, please contact us to check if the field exists in your MLS.', 'mlsimport'),
2297 'type' => 'input',
2298 'multiple' => 'no',
2299 ),
2300 'Exclude_ListOfficeMlsId' => array(
2301 'label' => esc_html__( 'Exclude listings with ListOfficeMlsId', 'mlsimport' ),
2302 'description' => esc_html__( 'Exclude listings that belong to one or more ListOfficeMlsId.', 'mlsimport' ),
2303 'type' => 'input',
2304 'multiple' => 'no',
2305 ),
2306 'Exclude_ListOfficeKey' => array(
2307 'label' => esc_html__( 'Exclude listings with ListOfficeKey', 'mlsimport' ),
2308 'description' => esc_html__( 'Exclude listings that belong to one or more ListOfficeKey', 'mlsimport'),
2309 'type' => 'input',
2310 'multiple' => 'no',
2311 ),
2312
2313
2314 'Exclude_ListAgentMlsId' => array(
2315 'label' => esc_html__( 'Exclude listings with ListAgentMlsId', 'mlsimport' ),
2316 'description' => esc_html__( 'Exclude listings that belong to one or more ListAgentMlsId.', 'mlsimport' ),
2317 'type' => 'input',
2318 'multiple' => 'no',
2319 ),
2320 'Exclude_ListAgentKey' => array(
2321 'label' => esc_html__( 'Exclude listings with ListAgentKey ', 'mlsimport' ),
2322 'description' => esc_html__( 'Exclude listings that belong to one or more ListAgentKey ', 'mlsimport'),
2323 'type' => 'input',
2324 'multiple' => 'no',
2325 ),
2326
2327
2328 );
2329 return $field_import;
2330 }
2331
2332
2333
2334
2335
2336
2337
2338 /**
2339 *
2340 *
2341 * AYsnc Test
2342 */
2343 public function mlsimport_move_files_per_item() {
2344 check_ajax_referer( 'mlsimport_item_actions', 'security' );
2345 $post_id = 0;
2346 $how_many = 0;
2347 $max_number = 0;
2348 if(isset( $_POST['post_id'] )){
2349 $post_id = intval( $_POST['post_id'] );
2350 }
2351 if(isset( $_POST['how_many'] )){
2352 $how_many = intval( $_POST['how_many'] );
2353 }
2354 if(isset( $_POST['post_number'] )){
2355 $max_number = intval( $_POST['post_number'] );
2356 }
2357
2358
2359 $is_onboard=intval($_POST['is_onboard']);
2360
2361
2362 update_option( 'mlsimport_force_stop_' . $post_id, 'no', false );
2363
2364 $item_id_array = array(
2365 'item_id' => $post_id,
2366 'how_many' => $how_many,
2367 'max_number' => $max_number,
2368 'batch_counter' => 1,
2369 );
2370
2371 //error_log(json_encode($item_id_array));
2372 //error_log("starting post id ".$post_id);
2373
2374 update_post_meta( $post_id, 'mlsimport_attach_to_move_' . $post_id, '' );
2375
2376 $attachments_to_move = (array) $this->mlsimport_saas_generate_import_requests_per_item( $item_id_array );
2377
2378 update_post_meta( $post_id, 'mlsimport_attach_to_move_' . $post_id, $attachments_to_move );
2379
2380 // net stat data
2381 update_post_meta( $post_id, 'mlsimport_progress_properties', 0 );
2382 update_post_meta( $post_id, 'mlsimport_progress_batches', 0 );
2383 update_post_meta( $post_id, 'mlsimport_progress_memory', 0 );
2384
2385
2386
2387 $attachments_to_send = array(
2388 'args' => array(
2389 'attachments_to_move' => $post_id,
2390 'item_id_array' => $item_id_array,
2391 'is_onboard' =>$is_onboard,
2392 ),
2393 );
2394
2395 mlsimport_saas_single_write_import_custom_logs( 'Preparing the import. Please hold on.' . PHP_EOL );
2396 mlsimport_debuglogs_per_plugin( 'Preparing the import. Please hold on.' . PHP_EOL );
2397
2398 update_post_meta( $post_id, 'mlsimport_spawn_status', 'started' );
2399
2400 // old
2401 as_enqueue_async_action( 'mlsimport_background_process_per_item', $attachments_to_send );
2402
2403 // Remove any pending async jobs for this item and enqueue a unique one
2404 //bad ideea
2405 // as_unschedule_all_actions( 'mlsimport_background_process_per_item', $attachments_to_send );
2406 //as_enqueue_async_action( 'mlsimport_background_process_per_item', $attachments_to_send, '', true );
2407
2408
2409 spawn_cron();
2410
2411 unset( $attachments_to_send ); print'before die';
2412 die();
2413 }
2414
2415 /**
2416 * Process MLS Import attachments via background cron.
2417 * Memory-optimized with detailed memory usage logging.
2418 *
2419 * @param array $input_arg
2420 * @return void
2421 */
2422 public function mlsimport_background_process_per_item_cron_function( $input_arg ) {
2423 global $mlsimport;
2424
2425 $log = 'In cron processing function ->' . wp_json_encode( $input_arg['item_id_array'] ) . PHP_EOL;
2426 mlsimport_saas_single_write_import_custom_logs( $log, 'cron' );
2427 mlsimport_saas_single_write_import_custom_logs( '[Memory] Start: ' . (memory_get_usage(true) / 1024 / 1024) . ' MB', 'cron' );
2428
2429 // Load attachments to move from post meta
2430 $attachments_to_move = get_post_meta(
2431 $input_arg['item_id_array']['item_id'],
2432 'mlsimport_cron_attach_to_move_' . $input_arg['item_id_array']['item_id'],
2433 true
2434 );
2435 $log = '[Memory] After loading attachments: ' . (memory_get_usage(true) / 1024 / 1024) . ' MB' . PHP_EOL;
2436 mlsimport_saas_single_write_import_custom_logs( $log, 'cron' );
2437
2438 if (!empty($attachments_to_move) && is_array($attachments_to_move)) {
2439 foreach ($attachments_to_move as $key => $import_arguments) {
2440 // Optionally clear any cache for this batch
2441 if ( isset($GLOBALS['wp_object_cache']) ) {
2442 $GLOBALS['wp_object_cache']->delete('mlsimport_force_stop_' . $input_arg['item_id_array']['item_id'], 'options');
2443 }
2444
2445 $log = '[Memory] Before API batch ' . $key . ': ' . (memory_get_usage(true) / 1024 / 1024) . ' MB' . PHP_EOL;
2446 mlsimport_saas_single_write_import_custom_logs( $log, 'cron' );
2447
2448 // API call
2449 $api_call_array = $this->theme_importer->globalApiRequestCurlSaas('listings', $import_arguments, 'POST');
2450
2451 $log = '[Memory] After API batch ' . $key . ': ' . (memory_get_usage(true) / 1024 / 1024) . ' MB' . PHP_EOL;
2452 mlsimport_saas_single_write_import_custom_logs( $log, 'cron' );
2453
2454 // Parse/process response
2455 $mlsimport->admin->theme_importer->mlsimportSaasCronParseSearchArrayPerItem(
2456 $api_call_array, $input_arg['item_id_array'], $key
2457 );
2458
2459 // Free per-iteration memory
2460 unset($api_call_array, $import_arguments);
2461 gc_collect_cycles();
2462
2463 $log = '[Memory] After cleanup batch ' . $key . ': ' . (memory_get_usage(true) / 1024 / 1024) . ' MB' . PHP_EOL;
2464 mlsimport_saas_single_write_import_custom_logs( $log, 'cron' );
2465 }
2466 }
2467
2468 mlsimport_saas_single_write_import_custom_logs('[Memory] End: ' . (memory_get_usage(true) / 1024 / 1024) . ' MB', 'cron' );
2469 mlsimport_saas_single_write_import_custom_logs('CRON JOB Import Completed ' . PHP_EOL, 'cron');
2470 mlsimport_debuglogs_per_plugin('CRON JOB Import Completed ' . PHP_EOL);
2471 update_post_meta($input_arg['item_id_array']['item_id'], 'mlsimport_spawn_status', 'completed');
2472
2473 unset($attachments_to_move, $input_arg, $log);
2474 gc_collect_cycles();
2475 }
2476
2477
2478
2479
2480 /**
2481 *
2482 *
2483 * Generate import Requests per item
2484 */
2485 public function mlsimport_saas_generate_import_requests_per_item( $item_id_array, $last_date = '' ) {
2486 $import_step = 25;
2487
2488 $prop_id = $item_id_array['item_id'];
2489 $max_found = $item_id_array['max_number'];
2490 $how_many = $item_id_array['how_many'];
2491 if ( 0=== intval($how_many) ) {
2492 $how_many = $max_found;
2493 }
2494 if ( $how_many > $max_found ) {
2495 $how_many = $max_found;
2496 }
2497
2498 $search_url_step = '';
2499 $urls_array = array();
2500
2501 $skip = 0;
2502 if ( $how_many > 10000 ) {
2503 $how_many = 10000;
2504 }
2505 //error_log('updating for '.$prop_id.' with'. $how_many);
2506 update_post_meta($prop_id,'mlsimport_task_to_import', intval($how_many) );
2507
2508 if ( $how_many < $import_step ) {
2509 $import_step = $how_many;
2510 }
2511
2512 while ( $skip < $how_many ) {
2513
2514 //$batch_step = min( $import_step, $how_many - $skip );
2515
2516 //$search_url_step = $this->mlsimport_saas_make_listing_requests_arguments( $prop_id, $last_date, $skip, $import_step );
2517 //$skip = $skip + $import_step;
2518 //$urls_array[] = $search_url_step;
2519
2520 // Determine how many items to request for this batch.
2521 $batch_step = min( $import_step, $how_many - $skip );
2522
2523 // Build the request arguments using the remaining count.
2524 $search_url_step = $this->mlsimport_saas_make_listing_requests_arguments( $prop_id, $last_date, $skip, $batch_step );
2525
2526 $skip += $batch_step;
2527 $urls_array[] = $search_url_step;
2528
2529
2530 }
2531 return $urls_array;
2532 }
2533
2534
2535
2536
2537
2538
2539
2540 /**
2541 * Process Async function
2542 */
2543 public function mlsimport_background_process_per_item_function( $input_arg ) {
2544
2545 $mlsimportItemId = $input_arg['item_id_array']['item_id'];
2546 $log_prefix = 'In processing function - Item ID: ' . $mlsimportItemId . ' -> ';
2547 mlsimport_saas_single_write_import_custom_logs( $log_prefix . wp_json_encode( $input_arg['item_id_array'] ) . PHP_EOL );
2548
2549
2550 // Get from MLS Import the big argument array only once
2551 $attachments_to_move = get_post_meta( $mlsimportItemId, 'mlsimport_attach_to_move_' . $mlsimportItemId, true );
2552
2553 // Retrieve all meta data in one go to reduce database queries
2554 $mlsimport_item_option_data = array(
2555 'mlsimport_item_standardstatus' => get_post_meta( $mlsimportItemId, 'mlsimport_item_standardstatus', true ),
2556 'mlsimport_item_standardstatusdelete' => get_post_meta( $mlsimportItemId, 'mlsimport_item_standardstatusdelete', true ),
2557 'mlsimport_item_property_user' => get_post_meta( $mlsimportItemId, 'mlsimport_item_property_user', true ),
2558 'mlsimport_item_agent' => get_post_meta( $mlsimportItemId, 'mlsimport_item_agent', true ),
2559 'mlsimport_item_property_status' => get_post_meta( $mlsimportItemId, 'mlsimport_item_property_status', true ),
2560 );
2561
2562 $total_batches = count( $attachments_to_move );
2563
2564 //error_log('$total_batches '. json_encode($total_batches) );
2565
2566
2567
2568 // removed because $this
2569 global $mlsimport;
2570
2571 $log = 'In processing function $attachments_to_move ->' . wp_json_encode( $attachments_to_move ) . PHP_EOL;
2572 mlsimport_saas_single_write_import_custom_logs( $log );
2573
2574
2575 foreach ( $attachments_to_move as $key => $import_arguments ) {
2576 // reconsider use
2577 // $GLOBALS['wp_object_cache']->delete('mlsimport_force_stop_' . $input_arg['item_id_array']['item_id'], 'options');
2578 $status = get_option( 'mlsimport_force_stop_' . $mlsimportItemId );
2579 if ( 'no' === $status ) {
2580 // Clear memory before processing each batch
2581 wp_cache_flush();
2582 gc_collect_cycles();
2583
2584 // wp_cache_flush();
2585 $mem_usage = memory_get_usage( true );
2586 $mem_usage_show = round( $mem_usage / 1048576, 2 );
2587
2588 update_post_meta( $mlsimportItemId, 'mlsimport_progress_batches', $key + 1 );
2589 update_post_meta( $mlsimportItemId, 'mlsimport_progress_memory', $mem_usage_show );
2590
2591
2592
2593 mlsimport_saas_single_write_import_custom_logs( $log );
2594 $log = 'Parsing import batch: ' . ( $key + 1 ) . ' of ' . $total_batches . '. Memory used: ' . $mem_usage_show . ' MB.' . PHP_EOL;
2595 //error_log($log);
2596
2597
2598 // Combine logs and reduce function calls
2599 mlsimport_saas_single_write_import_custom_logs( $log );
2600 mlsimport_debuglogs_per_plugin( $log );
2601 print esc_html($log);
2602
2603 $api_call_array = $this->theme_importer->globalApiRequestCurlSaas( 'listings', $import_arguments, 'POST' );
2604
2605 $mlsimport->admin->theme_importer->mlsimportSaasParseSearchArrayPerItem( $api_call_array, $input_arg['item_id_array'], $key, $mlsimport_item_option_data );
2606
2607
2608
2609 // Explicitly unset large variables after each batch
2610 unset($api_call_array);
2611
2612 // Force garbage collection again after processing
2613 wp_cache_flush();
2614 gc_collect_cycles();
2615
2616
2617 // Add a small delay to allow memory to be freed
2618 if (($key + 1) < $total_batches) {
2619 usleep(100000); // 100ms pause between batches
2620 }
2621
2622 } else {
2623
2624 $final_mem_usage = memory_get_usage( true );
2625 $final_mem_usage_show = round( $final_mem_usage / 1048576, 2 );
2626
2627
2628 update_post_meta( $mlsimportItemId, 'mlsimport_spawn_status', 'completed' );
2629 delete_post_meta( $mlsimportItemId, 'mlsimport_attach_to_move_' . $mlsimportItemId );
2630
2631 //new stats
2632 update_post_meta( $mlsimportItemId, 'mlsimport_progress_batches', $total_batches );
2633 update_post_meta( $mlsimportItemId, 'mlsimport_progress_memory', $final_mem_usage_show );
2634
2635
2636 mlsimport_saas_single_write_import_custom_logs( PHP_EOL . 'Parsing importing link FORCE STOP : ' );
2637 mlsimport_debuglogs_per_plugin( 'Parsing importing link FORCE STOP : ' );
2638 break; // Exit the loop if forced to stop
2639 }
2640 }
2641
2642 mlsimport_saas_single_write_import_custom_logs( 'Import Completed ' . PHP_EOL );
2643 mlsimport_debuglogs_per_plugin( 'Import Completed ' . PHP_EOL );
2644
2645 update_post_meta( $mlsimportItemId, 'mlsimport_spawn_status', 'completed' );
2646 delete_post_meta( $mlsimportItemId, 'mlsimport_attach_to_move_' . $mlsimportItemId );
2647
2648 // Final cleanup
2649 unset($attachments_to_move);
2650 unset($mlsimport_item_option_data);
2651 unset($input_arg);
2652 unset($log);
2653
2654 // One final garbage collection
2655 wp_cache_flush();
2656 gc_collect_cycles();
2657 }
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667 /**
2668 *
2669 *
2670 *
2671 * update log function
2672 */
2673 public function mlsimport_logger_per_item() {
2674 //check_ajax_referer( 'mlsimport_item_actions', 'security' );
2675 $post_id=0;
2676 if(isset($_POST['post_id'] )){
2677 $post_id = intval( $_POST['post_id'] );
2678 }
2679
2680 $status = get_post_meta( $post_id, 'mlsimport_spawn_status', true );
2681 $path = WP_PLUGIN_DIR . '/mlsimport/logs/status_logs.log';
2682 $logs = file_get_contents( $path );
2683
2684 //get neww status data
2685 $current = intval( get_post_meta( $post_id, 'mlsimport_progress_properties', true ) );
2686 $total = intval( get_post_meta( $post_id, 'mlsimport_progress_batches', true ) );
2687 $memory = get_post_meta( $post_id, 'mlsimport_progress_memory', true );
2688 $mlsimport_task_to_import = intval( get_post_meta($post_id, 'mlsimport_task_to_import',true));
2689
2690
2691
2692 $force_status = intval( get_post_meta( $post_id, 'mlsimport_force_stop', true ) );
2693 $force_status = get_option( 'mlsimport_force_stop_' . $post_id );
2694
2695 if ( 'no' !== $force_status ) {
2696 echo wp_json_encode(
2697 array(
2698 'is_done' => 'done',
2699 'status' => $status,
2700 'logs' => $logs,
2701 )
2702 );
2703 die();
2704 }
2705
2706 if ( '' === $status || 'completed' === $status ) {
2707 echo wp_json_encode(
2708 array(
2709 'is_done' => 'done',
2710 'status' => $status,
2711 'logs' => $logs,
2712 )
2713 );
2714 } else {
2715 // return from log
2716 echo wp_json_encode(
2717 array(
2718 'is_done' => 'wip',
2719 'status' => $status,
2720 'logs' => $logs,
2721 'mlsimport_progress_properties' => $current,
2722 'mlsimport_progress_batches' => $total,
2723 'memory' => $memory,
2724 'mlsimport_task_to_import'=>$mlsimport_task_to_import,
2725 'post_id'=>$post_id
2726
2727 )
2728 );
2729 }
2730 die();
2731 }
2732
2733
2734
2735
2736
2737
2738 /**
2739 *
2740 *
2741 *
2742 *
2743 * Force Stop Import
2744 */
2745 public function mlsimport_stop_import_per_item() {
2746
2747
2748 check_ajax_referer( 'mlsimport_item_actions', 'security' );
2749 $post_id=0;
2750 if(isset($_POST['post_id'] )){
2751 $post_id = intval( $_POST['post_id'] );
2752 }
2753 update_option( 'mlsimport_force_stop_' . $post_id, 'yes', false );
2754 // ensure caches are cleared so running processes see the update immediately
2755 if ( function_exists( 'wp_cache_delete' ) ) {
2756 wp_cache_delete( 'mlsimport_force_stop_' . $post_id, 'options' );
2757 }
2758 mlsimport_saas_single_write_import_custom_logs( 'Stopped for ' . $post_id . PHP_EOL );
2759 mlsimport_debuglogs_per_plugin( 'Stopped for ' . $post_id . PHP_EOL );
2760 wp_send_json_success();
2761 }
2762
2763
2764
2765 /*
2766 *
2767 * Get MLS Metadata
2768 *
2769 *
2770 *
2771 *
2772 **/
2773
2774 public function mlsimport_saas_get_metadata_function() {
2775 check_ajax_referer( 'mlsimport_saas_get_metadata', 'security' );
2776 $theme_Start = new ThemeImport();
2777
2778 $values = array();
2779 $options = get_option( $this->plugin_name . '_admin_options' );
2780 $url = 'clients?theme_id=' . intval( $options['mlsimport_theme_used'] );
2781
2782 $answer = $theme_Start::globalApiRequestSaas( $url, $values, 'GET' );
2783
2784 update_option( 'mlsimport_mls_metadata_populated', 'yes' );
2785
2786 update_option( 'mlsimport_mls_metadata_theme_schema', $answer['theme_schema'] );
2787 update_option( 'mlsimport_mls_metadata_mls_data', $answer['mls_data']['mls_meta_data'] );
2788 update_option( 'mlsimport_mls_metadata_mls_enums', $answer['mls_data']['mls_meta_enums'] );
2789 }
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802 /**
2803 *
2804 *
2805 * write debug logs
2806 */
2807 public function mlsimport_debuglog_cron( $message ) {
2808 if ( is_array( $message ) ) {
2809 $message = wp_json_encode( $message );
2810 }
2811 $message = date( 'F j, Y, g:i a' ) . ' -> ' . $message;
2812 global $wp_filesystem;
2813 if ( empty( $wp_filesystem ) ) {
2814 require_once ABSPATH . '/wp-admin/includes/file.php';
2815 WP_Filesystem();
2816 }
2817
2818 $path = WP_PLUGIN_DIR . '/mlsimport/logs/cron_logs.log';
2819
2820 file_put_contents( $path, $message, FILE_APPEND | LOCK_EX );
2821 }
2822
2823 }
2824