'text/plain'];
if ($method !== 'token') {
$token = self::getApiToken();
$headers = [
'Content-Type' => 'application/json',
'Authorization' => 'Bearer '.$token,
];
}
$args = [
'method' => $type,
'headers' => $headers,
'body' => !empty($valuesArray) ? wp_json_encode($valuesArray) : null,
'timeout' => 120,
'redirection' => 10,
'httpversion' => '1.1',
'blocking' => true,
'user-agent' => $_SERVER['HTTP_USER_AGENT'],
];
$response = $type === 'GET' ? wp_remote_get($url, $args) : wp_remote_post($url, $args);
if (is_wp_error($response)) {
return $response->get_error_message();
} else {
$body = wp_remote_retrieve_body($response);
$toReturn = json_decode($body, true);
if (json_last_error() !== JSON_ERROR_NONE) {
return 'JSON decode error: ' . json_last_error_msg();
}
return $toReturn;
}
}
/**
* Retrieve the API token
*
* @return string The API token.
*/
private static function getApiToken() {
global $mlsimport;
return $mlsimport->admin->mlsimport_saas_get_mls_api_token_from_transient();
}
/**
* Api Request to MLSimport API
*
* @param string $method The API method to call.
* @param array $valuesArray The values to pass to the API.
* @param string $type The request type (default is 'GET').
* @return array The API response data.
*/
/**
* Fire-and-forget POST to the SaaS API. Refreshes the JWT token (blocking — a
* required separate request); returns false without sending if the token is
* unavailable. Otherwise issues wp_remote_post() with blocking=false, timeout=0.01
* and returns true. The response is never inspected.
*
* @param string $method The API method/path to call.
* @param array $valuesArray The request body data.
* @return bool True if dispatched, false if token unavailable.
*/
public static function globalApiRequestSaasFireAndForget( string $method, array $valuesArray ): bool {
if ( ! self::validateAndRefreshToken() ) {
return false;
}
$token = self::getApiToken();
wp_remote_post(
MLSIMPORT_API_URL . $method,
[
'method' => 'POST',
'timeout' => 0.01,
'blocking' => false,
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Content-Type' => 'application/json',
],
'body' => wp_json_encode( $valuesArray ),
]
);
return true;
}
public static function globalApiRequestSaas($method, $valuesArray, $type = 'GET') {
global $mlsimport;
// Skip validation for token and mls requests
if ($method !== 'token' && $method !== 'mls') {
if (!self::validateAndRefreshToken()) {
return [
'success' => false,
'error_message' => 'Token validation failed'
];
}
}
$url = MLSIMPORT_API_URL . $method;
$headers = [];
if ($method !== 'token' && $method !== 'mls') {
$token = self::getApiToken();
$headers = [
'Authorization' => 'Bearer '.$token,
'Content-Type' => 'application/json',
];
}
$args = [
'method' => $type,
'timeout' => 45,
'redirection' => 5,
'httpversion' => '1.0',
'blocking' => true,
'headers' => $headers,
'cookies' => [],
'body' => !empty($valuesArray) ? wp_json_encode($valuesArray) : null,
];
$response = wp_remote_post($url, $args);
if (is_wp_error($response)) {
return [
'success' => false,
'error_code' => $response->get_error_code(),
'error_message' => esc_html($response->get_error_message())
];
}
$status_code = isset($response['response']['code']) ? intval($response['response']['code']) : 0;
$body = wp_remote_retrieve_body($response);
if (200 === $status_code) {
$receivedData = json_decode($body, true);
return $receivedData;
}
$error_message = 'Unknown error';
$error_code = $status_code;
$decoded_body = json_decode($body, true);
if (json_last_error() === JSON_ERROR_NONE && is_array($decoded_body)) {
if (isset($decoded_body['error']['message'])) {
$error_message = $decoded_body['error']['message'];
if (isset($decoded_body['error']['code'])) {
$error_code = $decoded_body['error']['code'];
}
} elseif (isset($decoded_body['message'])) {
$error_message = $decoded_body['message'];
}
}
return [
'success' => false,
'error_code' => $error_code,
'error_message' => esc_html($error_message),
];
exit();
}
/**
* Check if token is expired and refresh if needed
* Call this before any external API request
*
* @return bool True if token is valid, false if refresh failed
*/
private static function validateAndRefreshToken() {
global $mlsimport;
// Get stored expiry timestamp
$token_expiry = get_option('mlsimport_token_expiry', 0);
$current_time = time();
// Check if token is expired
if ($current_time >= $token_expiry) {
// Token expired, refresh it
$refresh_result = self::refreshToken();
if (!$refresh_result) {
return false;
}
}
return true;
}
private static function refreshToken() {
global $mlsimport;
// Get credentials for token request
$options = get_option('mlsimport_admin_options');
$username = isset($options['mlsimport_username']) ? $options['mlsimport_username'] : '';
$password = isset($options['mlsimport_password']) ? $options['mlsimport_password'] : '';
if (empty($username) || empty($password)) {
mlsimport_telemetry_bump( 'token_failures' );
return false;
}
// Prepare token request
$url = MLSIMPORT_API_URL . 'token';
$body = wp_json_encode(array(
'username' => $username,
'password' => $password
));
$args = array(
'method' => 'POST',
'headers' => array(
'Content-Type' => 'application/json'
),
'body' => $body,
'timeout' => 45
);
// Make token request
$response = wp_remote_post($url, $args);
if (is_wp_error($response)) {
mlsimport_telemetry_bump( 'token_failures' );
return false;
}
$body = wp_remote_retrieve_body($response);
$data = json_decode($body, true);
if (!isset($data['success']) || !$data['success'] || !isset($data['token']) || !isset($data['expires'])) {
mlsimport_telemetry_bump( 'token_failures' );
return false;
}
// Store new token and expiry
//$mlsimport->admin->mlsimport_saas_store_mls_api_token_transient($data['token']);
$expires_in = $data['expires'] - time();
set_transient('mlsimport_saas_token', $data['token'], $expires_in);
update_option('mlsimport_token_expiry', intval($data['expires']));
// First successful SaaS account connection (lifecycle telemetry).
mlsimport_telemetry_set_once( 'account_connected_at', time() );
return true;
}
/**
*
* @param array $readyToParseArray The array ready to be parsed.
* @param array $itemIdArray The item ID array.
* @param string $batchKey The batch key.
* @param array $mlsimportItemOptionData The item option data.
*/
public function mlsimportSaasParseSearchArrayPerItem($readyToParseArray, $itemIdArray, $batchKey, $mlsimportItemOptionData) {
// Start with aggressive memory cleanup
$this->cleanUpMemory(true);
// Log initial memory usage
$initialMemory = memory_get_usage(true);
$counterProp = 0;
$processedData = [];
if (isset($readyToParseArray['data']) && is_array($readyToParseArray['data'])) {
// Log total items to process
$totalItems = count($readyToParseArray['data']);
// Only keep essential data in memory, discard the rest
foreach ($readyToParseArray['data'] as $key => $property) {
// Save only what's needed from each property
if (isset($property['ListingKey'])) {
$processedData[$key] = $property;
}
// Remove from original array to free memory
unset($readyToParseArray['data'][$key]);
}
// Complete unset of the original array
unset($readyToParseArray);
$this->cleanUpMemory();
$mlsimportItemId = intval($itemIdArray['item_id']);
$current_prop_value = (int) get_post_meta( $mlsimportItemId, 'mlsimport_progress_properties', true );
// Process each property
foreach ($processedData as $key => $property) {
++$counterProp;
// Memory usage before processing property
$memoryBefore = memory_get_usage(true);
$memoryBeforeMB = round($memoryBefore / 1048576, 2);
$listingKey = isset($property['ListingKey']) ? $property['ListingKey'] : 'unknown';
// Clear out database caches that might be polluted
wp_cache_delete('mlsimport_force_stop_' . $itemIdArray['item_id'], 'options');
$GLOBALS['wpdb']->queries = array();
$status = get_option('mlsimport_force_stop_' . $itemIdArray['item_id']);
if ($status === 'no') {
$current_prop_value = $current_prop_value + 1;
update_post_meta( $mlsimportItemId, 'mlsimport_progress_properties', $current_prop_value );
// Process property and track memory
$this->mlsimportSaasPrepareToImportPerItem($property, $itemIdArray, 'normal', $mlsimportItemOptionData);
// Memory after processing property
$memoryAfter = memory_get_usage(true);
$memoryAfterMB = round($memoryAfter / 1048576, 2);
$memoryDiff = round(($memoryAfter - $memoryBefore) / 1048576, 2);
// Check for memory leak pattern
if ($memoryDiff > 10) {
// Force cleanup on large increases
$this->cleanUpMemory(true);
}
// Aggressively clean after each property
unset($property);
// Periodic more intensive cleanup
if ($counterProp % 3 == 0) {
$this->cleanUpMemory(true);
// Free database query cache
$GLOBALS['wpdb']->flush();
// Clear autoloaded options cache, which can grow large
wp_cache_delete('alloptions', 'options');
// Log memory after cleanup
$memoryAfterCleanup = memory_get_usage(true);
$freedMemory = round(($memoryAfter - $memoryAfterCleanup) / 1048576, 2);
}
} else {
update_post_meta($itemIdArray['item_id'], 'mlsimport_spawn_status', 'completed');
break;
}
// Clear property from processed data to free memory
unset($processedData[$key]);
}
} else {
}
// Final cleanup
unset($processedData);
$this->cleanUpMemory(true);
// Log final memory stats
$finalMemory = memory_get_usage(true);
$finalMemoryMB = round($finalMemory / 1048576, 2);
$totalMemoryDiff = round(($finalMemory - $initialMemory) / 1048576, 2);
$peakMemory = round(memory_get_peak_usage(true) / 1048576, 2);
}
/**
* Comprehensive memory cleanup function
*
* @param bool $intensive Whether to perform intensive cleanup
*/
private function cleanUpMemory($intensive = false) {
// Basic cleanup
wp_cache_flush();
gc_collect_cycles();
if ($intensive) {
// Clear WordPress object cache
global $wp_object_cache;
if (is_object($wp_object_cache) && method_exists($wp_object_cache, 'flush')) {
$wp_object_cache->flush();
}
// Clear WordPress post caches
clean_post_cache(0);
// Safe term cache clearing - avoid SQL errors
wp_cache_delete('get_terms', 'terms');
wp_cache_delete('term_meta', 'terms');
delete_option('category_children');
// Clear taxonomy-specific caches for common taxonomies
$taxonomies = array('category', 'post_tag', 'property_status', 'property_type', 'property_feature', 'property_label', 'property_area', 'property_city', 'property_state', 'property_neighborhood');
foreach ($taxonomies as $taxonomy) {
wp_cache_delete($taxonomy . '_relationships', 'terms');
}
// Clear WordPress database cache
global $wpdb;
if (is_object($wpdb)) {
$wpdb->queries = array();
if (method_exists($wpdb, 'flush')) {
$wpdb->flush();
}
}
// Multiple garbage collection passes can sometimes help
gc_collect_cycles();
gc_collect_cycles();
}
}
/**
* Write logs for import process
*
* @param string $logs The log message to write.
* @param string $type The type of log.
*/
private function writeImportLogs($logs, $type) {
mlsimport_saas_single_write_import_custom_logs($logs, $type);
}
/**
* Get memory usage
*
* @return string The memory usage in MB.
*/
public function mlsimportMemUsage() {
$memUsage = memory_get_usage(true);
$memUsageShow = round($memUsage / 1048576, 2);
return $memUsageShow . 'mb ';
}
/**
* Parse and import property data for a single MLSimport item in CRON.
* Logs memory usage for each significant operation.
*
* @param array $readyToParseArray The array with listing data (from API).
* @param array $itemIdArray The array with current MLSimport item info.
* @param string $batchKey The batch identifier for logging.
*/
public function mlsimportSaasCronParseSearchArrayPerItem($readyToParseArray, $itemIdArray, $batchKey) {
// Gather relevant meta for this MLSimport item
$mlsimportItemOptionData = [
'mlsimport_item_standardstatus' => get_post_meta($itemIdArray['item_id'], 'mlsimport_item_standardstatus', true),
'mlsimport_item_standardstatusprotect' => get_post_meta($itemIdArray['item_id'], 'mlsimport_item_standardstatusprotect', true),
'mlsimport_item_property_user' => get_post_meta($itemIdArray['item_id'], 'mlsimport_item_property_user', true),
'mlsimport_item_agent' => get_post_meta($itemIdArray['item_id'], 'mlsimport_item_agent', true),
'mlsimport_item_property_status' => get_post_meta($itemIdArray['item_id'], 'mlsimport_item_property_status', true),
];
$count = isset($readyToParseArray['data']) && is_array($readyToParseArray['data']) ? count($readyToParseArray['data']) : 0;
$log = '[Memory] Start batch ' . $batchKey . ' with ' . $count . ' listings: ' . (memory_get_usage(true) / 1024 / 1024) . ' MB';
$this->writeImportLogs($log, 'cron');
if ($count === 0) {
$this->writeImportLogs('[Memory] No data to parse in batch ' . $batchKey, 'cron');
return;
}
foreach ($readyToParseArray['data'] as $key => $property) {
// Log at the start of each property (optional, comment out if too verbose)
//$log = '[Memory] Before import property #' . $key . ': ' . (memory_get_usage(true) / 1024 / 1024) . ' MB';
//$this->writeImportLogs($log, 'cron');
$logs = 'In CRON parse search array, listing no ' . $key . ' from batch ' . $batchKey . ' with ListingKey: ' . $property['ListingKey'] . PHP_EOL;
$this->writeImportLogs($logs, 'cron');
// Main per-property import function (handles mapping/import/update)
$this->mlsimportSaasPrepareToImportPerItem($property, $itemIdArray, 'cron', $mlsimportItemOptionData);
// Clean up per-iteration memory
unset($property);
if (($key + 1) % 20 === 0) {
gc_collect_cycles();
$log = '[Memory] After importing ' . ($key + 1) . ' listings in batch ' . $batchKey . ': ' . (memory_get_usage(true) / 1024 / 1024) . ' MB';
$this->writeImportLogs($log, 'cron');
}
}
// Final memory log for this batch
$this->writeImportLogs('[Memory] End batch ' . $batchKey . ': ' . (memory_get_usage(true) / 1024 / 1024) . ' MB', 'cron');
// Housekeeping
unset($readyToParseArray, $mlsimportItemOptionData);
gc_collect_cycles();
}
/**
* Check if property already imported
*
* @param string $key The key to search for.
* @param string $postType The post type to search within (default is 'estate_property').
* @return int The post ID if found, or 0 if not found.
*/
public function mlsimportSaasRetrievePropertyById($key, $postType = 'estate_property') {
$args = [
'post_type' => $postType,
'post_status' => 'any',
'meta_query' => [
[
'key' => 'ListingKey',
'value' => $key,
'compare' => '=',
],
],
'fields' => 'ids',
];
$query = new WP_Query($args);
if ($query->have_posts()) {
$query->the_post();
$propertyId = get_the_ID();
wp_reset_postdata();
return $propertyId;
} else {
wp_reset_postdata();
return 0;
}
}
/**
* Clear taxonomy
*
* @param int $propertyId The property ID.
* @param array $taxonomies The taxonomies to clear.
*/
public function mlsimportSaasClearPropertyForTaxonomy($propertyId, $taxonomies) {
if (is_array($taxonomies)) {
foreach ($taxonomies as $taxonomy => $term) {
if (is_wp_error($taxonomy)) {
continue; // Skip this iteration
}
if (taxonomy_exists($taxonomy)) {
wp_delete_object_term_relationships($propertyId, $taxonomy);
} else {
}
}
}
}
/**
* Set taxonomy for property
*
* @param string $taxonomy The taxonomy to set.
* @param int $propertyId The property ID.
* @param mixed $fieldValues The values to set.
*/
public function mlsimportSaasUpdateTaxonomyForProperty($taxonomy, $propertyId, $fieldValues) {
global $wpdb;
// Convert comma-separated values to array if necessary
if (!is_array($fieldValues)) {
$fieldValues = strpos($fieldValues, ',') !== false ? explode(',', $fieldValues) : [$fieldValues];
}
// Trim values and remove empty ones
$fieldValues = array_filter(array_map('trim', $fieldValues));
// Start a database transaction
$wpdb->query('START TRANSACTION');
$taxLog = [];
foreach (array_chunk($fieldValues, 5) as $chunk) {
foreach ($chunk as $value) {
if (!empty($value)) {
// Check if the term already exists
$term = $wpdb->get_row($wpdb->prepare(
"SELECT t.*, tt.* FROM $wpdb->terms t
INNER JOIN $wpdb->term_taxonomy tt ON t.term_id = tt.term_id
WHERE t.name = %s AND tt.taxonomy = %s",
$value, $taxonomy
));
$taxLog[] = json_encode($term);
if (is_null($term)) {
// Insert the term if it doesn't exist
$wpdb->insert($wpdb->terms, [
'name' => $value,
'slug' => sanitize_title($value),
'term_group' => 0
]);
$termId = $wpdb->insert_id;
if ($termId) {
// Insert term taxonomy
$wpdb->insert($wpdb->term_taxonomy, [
'term_id' => $termId,
'taxonomy' => $taxonomy,
'description' => '',
'parent' => 0,
'count' => 0
]);
$termTaxonomyId = $wpdb->insert_id;
} else {
$taxLog[] = 'Error inserting term';
continue;
}
} else {
// Term exists, get term_id and term_taxonomy_id
$termId = $term->term_id;
$termTaxonomyId = $wpdb->get_var($wpdb->prepare(
"SELECT term_taxonomy_id FROM $wpdb->term_taxonomy WHERE term_id = %d AND taxonomy = %s",
$termId, $taxonomy
));
}
if (!empty($termTaxonomyId)) {
// Insert term relationship
$wpdb->replace($wpdb->term_relationships, [
'object_id' => $propertyId,
'term_taxonomy_id' => $termTaxonomyId
]);
// Location taxonomies (browse-by-city/area widgets) use a publish-aware
// recompute so the displayed count matches the publish-only archive.
// A blind +1 is not idempotent (re-imports inflate it) and ignores
// post status, so a new city could show a count while its archive is
// empty. These terms are low-cardinality (tens of listings), so the
// COUNT is cheap. High-cardinality grouping taxonomies keep the O(1)
// increment to avoid scanning thousands of rows per import.
$location_taxonomies = array('property_city', 'property_area', 'property_state', 'property_neighborhood');
if (in_array($taxonomy, $location_taxonomies, true)) {
// Mirrors WordPress' _update_post_term_count callback in SQL.
$wpdb->query($wpdb->prepare(
"UPDATE $wpdb->term_taxonomy tt
SET count = (
SELECT COUNT(*) FROM $wpdb->term_relationships tr
INNER JOIN $wpdb->posts p ON p.ID = tr.object_id
WHERE tr.term_taxonomy_id = tt.term_taxonomy_id
AND p.post_status = 'publish'
)
WHERE tt.term_taxonomy_id = %d",
$termTaxonomyId
));
} else {
$wpdb->query($wpdb->prepare(
"UPDATE $wpdb->term_taxonomy SET count = count + 1 WHERE term_taxonomy_id = %d",
$termTaxonomyId
));
}
} else {
$taxLog[] = 'Error: term_taxonomy_id is null';
}
}
}
// Flush the cache to free up memory
wp_cache_flush();
// Run garbage collection
gc_collect_cycles();
}
// Commit the transaction
$wpdb->query('COMMIT');
// Clear term cache selectively
wp_cache_delete("{$taxonomy}_terms", 'terms');
wp_cache_delete("{$taxonomy}_children", 'terms');
// Restore the term metadata filter
add_filter('get_term_metadata', [$wpdb->terms, 'cache_term_counts'], 10, 2);
// Log memory usage
// if (!empty($taxLog)) {
// $taxLogStr = implode(PHP_EOL, $taxLog);
// mlsimport_saas_single_write_import_custom_logs($taxLogStr, 'normal');
// unset($taxLogStr);
// }
}
/**
* Set Property Title
*
* @param int $propertyId The property ID.
* @param int $mlsImportPostId The MLS import post ID.
* @param array $property The property data.
* @return string The updated title format.
*/
public function mlsimportSaasUpdatePropertyTitle($propertyId, $mlsImportPostId, $property) {
global $mlsimport;
$titleFormat = esc_html(get_post_meta($mlsImportPostId, 'mlsimport_item_title_format', true));
if ('' === $titleFormat) {
$options = get_option('mlsimport_admin_mls_sync');
$titleFormat = $options['title_format'];
}
$titleArray = $this->strBetweenAll($titleFormat, '{', '}');
$propertyExtraMetaArrayLowerCase = array_change_key_case($property['extra_meta'], CASE_LOWER);
foreach ($titleArray as $key => $value) {
$replace = '';
switch ($value) {
case 'Address':
$replace = $property['adr_title'] ?? '';
break;
case 'City':
$replace = $property['adr_city'] ?? '';
break;
case 'CountyOrParish':
$replace = $property['adr_county'] ?? '';
break;
case 'PropertyType':
$replace = $property['adr_type'] ?? '';
break;
case 'Bedrooms':
$replace = $property['adr_bedrooms'] ?? '';
break;
case 'Bathrooms':
$replace = $property['adr_bathrooms'] ?? '';
break;
case 'ListingKey':
$replace = $property['ListingKey'];
break;
case 'ListingId':
$replace = $property['adr_listingid'] ?? '';
break;
case 'StateOrProvince':
$replace = $property['extra_meta']['StateOrProvince'] ?? '';
break;
case 'PostalCode':
$replace = $property['meta']['property_zip'] ?? $property['meta']['fave_property_zip'] ?? '';
$replace = is_array($replace) ? strval($replace[0]) : strval($replace);
break;
case 'StreetNumberNumeric':
$replace = $propertyExtraMetaArrayLowerCase['streetnumbernumeric'] ?? '';
break;
case 'StreetName':
$replace = $propertyExtraMetaArrayLowerCase['streetname'] ?? '';
break;
}
$titleFormat = str_replace('{' . $value . '}', $replace, $titleFormat);
}
$post = [
'ID' => $propertyId,
'post_title' => $titleFormat,
'post_name' => $titleFormat,
];
wp_update_post($post);
return $titleFormat;
}
/**
* Prepare meta data for property
*
* @param array $property The property data.
* @return array The property data with prepared meta.
*/
public function mlsimportSaasPrepareMetaForProperty($property) {
// BathroomsTotalDecimal is not provided by every MLS (e.g. BrightMLS sends only
// BathroomsTotalInteger / BathroomsFull). Fall back so the theme Overview value
// is not wiped to empty.
$bathroomsRaw = $property['extra_meta']['BathroomsTotalDecimal']
?? $property['extra_meta']['BathroomsTotalInteger']
?? $property['extra_meta']['BathroomsFull']
?? '';
$bathrooms = ( '' === $bathroomsRaw || null === $bathroomsRaw ) ? '' : floatval($bathroomsRaw);
$property['meta']['property_bathrooms'] = $bathrooms;
$property['meta']['fave_property_bathrooms'] = $bathrooms;
$property['meta']['REAL_HOMES_property_bathrooms'] = $bathrooms;
// PostalCode is commonly provided in normalized meta (property_zip) rather than extra_meta.
// Mirror it into extra_meta when missing so field mappings (postmeta/taxonomy) can process it.
if (!isset($property['extra_meta']) || !is_array($property['extra_meta'])) {
$property['extra_meta'] = array();
}
$postal_code = '';
if (isset($property['meta']) && is_array($property['meta'])) {
if (!empty($property['meta']['property_zip'])) {
$postal_code = $property['meta']['property_zip'];
} elseif (!empty($property['meta']['fave_property_zip'])) {
$postal_code = $property['meta']['fave_property_zip'];
} elseif (!empty($property['meta']['REAL_HOMES_property_zip'])) {
$postal_code = $property['meta']['REAL_HOMES_property_zip'];
}
}
if (is_array($postal_code)) {
$postal_code = reset($postal_code);
}
$postal_code = trim((string) $postal_code);
if ('' !== $postal_code && empty($property['extra_meta']['PostalCode'])) {
$property['extra_meta']['PostalCode'] = $postal_code;
}
return $property;
}
/**
* Attach media to post
*
* @param int $propertyId The property ID.
* @param array $media The media data.
* @param string $isInsert Whether the property is being inserted.
* @return string The media history log.
*/
public function mlsimportSassAttachMediaToPost($propertyId, $media, $isInsert,$media_attachments,$featuredImageKey, $shouldRefreshMedia = false) {
$mediaHistory = [];
if ($isInsert === 'no' && !$shouldRefreshMedia) {
$mediaHistory[] = 'Media - We have edit - images are not replaced';
return $media_attachments;
}
global $mlsimport;
include_once ABSPATH . 'wp-admin/includes/image.php';
$hasFeatured = false;
add_filter('intermediate_image_sizes_advanced', [$this, 'wpcUnsetImageSizes']);
if (is_array($media)) {
foreach ($media as $key=>$image) {
if (isset($image['MediaCategory']) && $image['MediaCategory'] !== 'Property Photo' && $image['MediaCategory'] !== 'Photo') {
continue;
}
if ( empty( $image['MediaURL'] ) ) {
continue;
}
if (isset($image['MediaURL'])) {
$file = $image['MediaURL'];
$attachment = [
'guid' => $file,
'post_status' => 'inherit',
'post_content' => '',
'post_parent' => $propertyId,
'post_mime_type' => $image['MimeType'] ?? 'image/jpeg',
'post_title' => $image['MediaKey'] ?? '',
];
$attachId = wp_insert_attachment($attachment, $file);
if (is_wp_error($attachId)) {
} else {
$mediaHistory[] = 'Media - Added ' . $file . ' as attachment ' . $attachId;
$media_attachments[]=$attachId;
$mlsimport->admin->env_data->enviroment_image_save($propertyId, $attachId);
update_post_meta($attachId, 'is_mlsimport', 1);
if ($key===$featuredImageKey){
set_post_thumbnail($propertyId, $attachId);
} else {
}
}
} else {
}
}
} else {
$mediaHistory[] = 'Media data is blank - there are no images';
}
remove_filter('intermediate_image_sizes_advanced', [$this, 'wpcUnsetImageSizes']);
return $media_attachments;
//return implode('', $mediaHistory);
}
/**
* Unset image sizes
*
* @param array $sizes The sizes to unset.
* @return array The modified sizes array.
*/
public function wpcUnsetImageSizes($sizes) {
return [];
}
/**
* Return user option
*
* @param int $selected The selected user ID.
* @return string The HTML option elements for users.
*/
public function mlsimportSaasThemeImportSelectUser($selected) {
$userOptions = '';
$blogusers = get_users(['blog_id' => 1, 'orderby' => 'nicename']);
foreach ($blogusers as $user) {
$userOptions .= '';
}
return $userOptions;
}
/**
* Return agent option
*
* @param int $selected The selected agent ID.
* @return string The HTML option elements for agents.
*/
public function mlsimportSaasThemeImportSelectAgent($selected) {
global $mlsimport;
$args = [
'post_type' => $mlsimport->admin->env_data->get_agent_post_type(),
'post_status' => 'publish',
'posts_per_page' => 150,
];
$agentSelection = new WP_Query($args);
$agentOptions = '';
while ($agentSelection->have_posts()) {
$agentSelection->the_post();
$agentId = get_the_ID();
$agentOptions .= '