WordPress RETS Import Plugin

Complete Technical Audit & Developer Handoff Guide

Comprehensive analysis of AUTO TAGGING, AUTO IMAGE RENAMING, and AUTO WP CATEGORIZATION processes

Project Overview

System Purpose

  • WordPress RETS/MLS data integration plugin
  • Automated property data import and processing
  • Real estate listing management system
  • Multi-MLS support with Bridge API integration

Core Technologies

PHP 7.4+ WordPress PHRETS Library AWS S3 MySQL JavaScript/jQuery

⚠️ Critical Analysis Focus

This audit specifically analyzes the three key automated processes that handle property data transformation and organization within the WordPress ecosystem.

AUTO TAGGING Process Analysis

Process Overview

The auto-tagging system automatically creates and assigns property_tag taxonomy terms based on RETS field values and property descriptions. This process enhances search functionality and property categorization.

Core Function Analysis

// PRIMARY TAGGING FUNCTION
function esh_set_property_tag($rets_field, $value, $property_id)
{
    if (!empty($rets_field->system_name) && !empty($value)) {
        $tags = [];
        
        switch ($rets_field->system_name) {
            // Bedroom count tagging
            case 'LM_Int1_4':
            case 'BedroomsTotal':
                $tags[] = sprintf(_n('%s Bedroom', '%s Bedrooms', $value), $value);
                break;
                
            // Bathroom count tagging  
            case 'LM_Int1_19':
            case 'BathroomsTotalInteger':
                $tags[] = sprintf(_n('%s Bath', '%s Baths', $value), $value);
                break;
                
            // Laundry features
            case 'LaundryFeatures':
                if ($value == 'In Unit') {
                    $value = 'In Suite Laundry';
                }
                $tags[] = $value;
                break;
                
            default:
                // Generic comma-separated values
                if ($value !== 'None') {
                    $value = explode(',', $value);
                    if (!empty($value)) {
                        $tags = array_merge($value, $tags);
                    }
                }
                break;
        }
        
        if (!empty($tags)) {
            wp_set_object_terms($property_id, $tags, 'property_tag', true);
        }
    }
}

Integration Points

1. Called from build_meta_array()

In class-rets-import-entity.php during field processing loop

if ($field->associate == 'property_tag') { esh_set_property_tag($field, $value, $this->_entity->getID()); }

2. Taxonomy Registration

Property tag taxonomy with custom URL rewrite

register_taxonomy('property_tag', 'property', [ 'rewrite' => [ 'slug' => 'mls/tag', 'with_front' => false, ], ]);

Field-Specific Tagging Logic

RETS Field Purpose Tag Format Example Output
LM_Int1_4, BedroomsTotal Bedroom count "{count} Bedroom(s)" "3 Bedrooms"
LM_Int1_19, BathroomsTotalInteger Bathroom count "{count} Bath(s)" "2 Baths"
LaundryFeatures Laundry amenities Transform "In Unit" → "In Suite Laundry" "In Suite Laundry"
Default (any other field) Generic features Comma-separated array ["Pool", "Garage", "Patio"]

🎯 Developer Implementation Notes

  • • Function uses WordPress wp_set_object_terms() with append=true parameter
  • • Supports internationalization with _n() for singular/plural forms
  • • Filters out "None" values to prevent empty tags
  • • Custom URL rewrite structure: /mls/tag/{tag-name}/

AUTO IMAGE RENAMING Process Analysis

Process Overview

The auto image renaming system standardizes property image filenames using address, city, MLS ID, and index before uploading to AWS S3 storage. This prevents conflicts and creates SEO-friendly, descriptive filenames.

Core Naming Logic

// Bridge API Naming (RETS 1.9+)
if ($is_bridge_api) {
    $street_number = $this->_data['StreetNumber'];
    if (!empty($this->_data['StreetDirPrefix'])) {
        $street_number = $street_number . ' ' . $this->_data['StreetDirPrefix'];
    }
    if (!empty($this->_data['UnitNumber'])) {
        $street_number = $this->_data['UnitNumber'] . ' ' . $street_number;
    }
    
    $image_name = sprintf('%s-%s-%s-%s', 
        $street_number . ' ' . $this->_data['StreetName'] . ' ' . $this->_data['StreetSuffix'], 
        $this->_data['City'], 
        $this->_data['ListingId'], 
        $key // Image index
    );
} else {
    // Legacy RETS naming
    $image_name = sprintf('%s-%s-%s-%s', 
        $this->_data['L_Address'], 
        $this->_data['L_City'], 
        $this->_data['L_DisplayId'], 
        $key
    );
}

// Sanitize for URL-safe filename
$image_name = sanitize_title($image_name);

Naming Pattern Structure

Template Format

{address}-{city}-{mls_id}-{index}

Example Output

123-main-st-toronto-n12345-0

Used as S3 object key

AWS S3 Integration

$data_array = [ 'Bucket' => 'property-mls-images', 'Key' => $image_name, 'Body' => $image_content, 'ACL' => 'public-read', ]; $result = $s3->putObject($data_array);

Field Processing Differences

API Type Address Fields City Field MLS ID Field Example
Bridge API UnitNumber + StreetNumber
+ StreetDirPrefix + StreetName
+ StreetSuffix
City ListingId 302-123-main-st-toronto-n12345-0
Legacy RETS L_Address L_City L_DisplayId 456-oak-ave-vancouver-v67890-1

🔧 Technical Features

  • • WordPress sanitize_title() for URL-safe names
  • • Rate limiting (2-second delay) prevents overload
  • • URL validation and sanitization for security
  • • Failed upload tracking for retry mechanism

⚡ Integration Points

  • • Called from import_images() in import property class
  • • Queue processing for batch operations
  • • Manual import function cu_esh_phrets_import_images_by_post_id()
  • • AWS S3 putObject() for cloud storage

AUTO WP CATEGORIZATION Process Analysis

Process Overview

The auto categorization system creates hierarchical WordPress taxonomy structures for properties based on RETS data. It generates area/subarea categories, property type categories, and SEO-friendly URL slug structures for organized property browsing.

Taxonomy Structure

Property Category Taxonomy

register_taxonomy('property_category', 'property', [ 'hierarchical' => true, 'rewrite' => [ 'slug' => 'mls', 'with_front' => false, ], ]);

URL: /mls/{category-name}/

Property Tag Taxonomy

register_taxonomy('property_tag', 'property', [ 'hierarchical' => false, 'rewrite' => [ 'slug' => 'mls/tag', 'with_front' => false, ], ]);

URL: /mls/tag/{tag-name}/

Category Hierarchy Example

Toronto (area)
├── Toronto Condos (area+type)
│ └── Toronto Downtown Condos (subarea+type)
├── Toronto Houses (area+type)
│ └── Toronto North Houses (subarea+type)
└── Toronto Townhouses (area+type)
└── Toronto East Townhouses (subarea+type)

Term Meta Fields

  • category_type: 'area', 'subarea', 'area+type', 'subarea+type'
  • breadcrumb_name: Display name for navigation
  • area: Geographic area identifier
  • type: Property type (Condos, Houses, etc.)
  • autocomplete: Enable for search suggestions

Property Type Determination Logic

// Property class determination for Bridge API
if ($property_type == 'Residential' && strpos($structure_type, 'Residential Detached') !== false) {
    $property_class = 'RD_1';
} elseif ($property_type == 'Residential' && strpos($structure_type, 'Residential Attached') !== false) {
    $property_class = 'RA_2';
} elseif ($property_type == 'Residential Income') {
    $property_class = 'MF_3';
} elseif ($property_type == 'Land') {
    $property_class = 'LD_4';
}

// Type assignment based on dwelling type
if (($property_class == 'RD_1' || $property_class == 'RA_2')) {
    if ($type_of_dwelling == 'Townhouse') {
        $type = 'Townhouses';
    } elseif ($type_of_dwelling == 'Apartment/Condo') {
        $type = 'Condos';
    } else {
        $type = 'House';
    }
}

Category Creation Process

1. Area Categories

Creates geographic area terms without property types for autocomplete search

2. Area + Type Combinations

Combines geographic areas with property types (Toronto Condos)

3. Subarea Categories

Creates child categories for subareas within main areas

4. Search Types

Assigns property_type taxonomy terms for filtering

Field Mapping by API Type

Data Component Bridge API Fields Legacy RETS Fields Usage
Area MLSAreaMajor L_Area Main geographic region
Sub Area MLSAreaMinor LM_Char10_5 Subdivision within area
Property Type PropertyType, StructureType LM_char1_36 Property classification
Dwelling Type PropertySubType LM_Char10_11 Specific property style

🏗️ Category Features

  • • Hierarchical structure with parent-child relationships
  • • SEO-friendly URL slugs (/mls/toronto-condos/)
  • • Term metadata for enhanced functionality
  • • Search autocomplete integration

🔍 Search Integration

  • • Custom keyword compilation from categories
  • • Property filtering by area and type
  • • Breadcrumb navigation support
  • • WordPress query optimization

System Architecture Overview