Manual property enhancements: MLS status sync, agent clone, description formatting

- Manual properties linked to MLS now inherit status (Active/Pending/Closed) and
  days_on_market from the MLS listing dynamically
- Properties not in MLS default to Closed status
- Clone feature now auto-populates listing agent by matching MLS ID to Agent CPT
- Description formatter detects embedded headers (unpunctuated text after sentences)
  and splits them into separate paragraphs

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
root
2026-01-23 21:28:44 +00:00
parent c2d5b2248d
commit 57b752f54e
60 changed files with 5323 additions and 189 deletions
@@ -464,6 +464,9 @@ class MLS_Media_Handler {
* Uses MySQL advisory lock to ensure only one request downloads
* a specific image at a time (prevents stampede on cold cache).
*
* Respects daily data budget - if approaching limit, will skip fetch
* and return null (graceful degradation).
*
* @param object $media Media record
* @return string|null Local URL on success, null on failure
*/
@@ -474,6 +477,17 @@ class MLS_Media_Handler {
return null;
}
// Check daily data budget before fetching
$rate_limiter = mls_plugin()->get_rate_limiter();
if (!$rate_limiter->can_fetch_image()) {
$this->logger->warning('Daily data budget exhausted, skipping image fetch', array(
'listing_key' => $media->listing_key,
'media_key' => $media->media_key,
'remaining_bytes' => $rate_limiter->get_daily_data_remaining(),
));
return null;
}
// Advisory lock key - unique per media record
$lock_name = 'mls_media_' . $media->id;
$lock_timeout = 35; // Slightly longer than HTTP timeout
@@ -516,9 +530,16 @@ class MLS_Media_Handler {
}
// Download the image
$response = wp_remote_get($media->media_url, array(
$request_args = array(
'timeout' => 30,
));
);
// Allow skipping SSL verification if configured (for expired certs)
if (defined('MLS_SKIP_SSL_VERIFY') && MLS_SKIP_SSL_VERIFY) {
$request_args['sslverify'] = false;
}
$response = wp_remote_get($media->media_url, $request_args);
if (is_wp_error($response)) {
$this->logger->warning('Media fetch failed', array(
@@ -545,6 +566,10 @@ class MLS_Media_Handler {
return null;
}
// Record bytes downloaded against daily data cap
$bytes_downloaded = strlen($body);
$rate_limiter->record_data_transfer($bytes_downloaded);
// Determine extension
$content_type = wp_remote_retrieve_header($response, 'content-type');
$extension = $this->get_extension_from_content_type($content_type, $media->media_url);
@@ -598,7 +623,7 @@ class MLS_Media_Handler {
$this->logger->debug('Media fetched and cached', array(
'listing_key' => $media->listing_key,
'media_key' => $media->media_key,
'original_size' => strlen($body),
'bytes_downloaded' => $bytes_downloaded,
'final_size' => $final_size,
'converted' => $conversion['converted'],
));