| 1 |
<?php |
| 2 |
/** |
| 3 |
* Standalone (theme_id 990) RESO -> target routing map. |
| 4 |
* |
| 5 |
* The theme-independent analog of help_functions.php: given a RESO field name, |
| 6 |
* return where its raw value should be written. Target kinds: |
| 7 |
* column:<name> flat mlsimport_listings column |
| 8 |
* tax:<taxonomy> a term in the given taxonomy |
| 9 |
* meta:<key> post meta mlsimport_<key> |
| 10 |
* feature:<label> a term in the mlsimport_feature taxonomy |
| 11 |
* content the post body |
| 12 |
* skip never written |
| 13 |
* |
| 14 |
* Pure data + lookup. No WordPress, no DB. |
| 15 |
* |
| 16 |
* @package Mlsimport |
| 17 |
*/ |
| 18 |
|
| 19 |
if ( ! defined( 'ABSPATH' ) ) { |
| 20 |
exit; |
| 21 |
} |
| 22 |
|
| 23 |
/** |
| 24 |
* Resolves a RESO field name to its standalone-mode write targets. |
| 25 |
*/ |
| 26 |
class Mlsimport_Standalone_Reso_Map { |
| 27 |
|
| 28 |
/** |
| 29 |
* RESO field => write targets (ยง9). Fields absent here pass through to |
| 30 |
* meta:x_<Field>. Editorial taxonomies (mlsimport_label, featured) are |
| 31 |
* deliberately NOT in the map โ the writer never sets them. |
| 32 |
*/ |
| 33 |
private const MAP = array( |
| 34 |
// Identity / sync. |
| 35 |
'ListingKey' => array( 'column:listing_key', 'meta:ListingKey' ), |
| 36 |
'ListingId' => array( 'meta:ListingId' ), |
| 37 |
'ModificationTimestamp' => array( 'column:modification_timestamp', 'meta:ModificationTimestamp' ), |
| 38 |
'MlsStatus' => array( 'meta:MlsStatus' ), |
| 39 |
'InternetEntireListingDisplayYN' => array( 'meta:idx_display' ), |
| 40 |
'InternetAddressDisplayYN' => array( 'meta:show_address' ), |
| 41 |
|
| 42 |
// Price. |
| 43 |
'ListPrice' => array( 'column:price', 'meta:ListPrice' ), |
| 44 |
'OriginalListPrice' => array( 'meta:OriginalListPrice' ), |
| 45 |
'ClosePrice' => array( 'meta:ClosePrice' ), |
| 46 |
'PreviousListPrice' => array( 'meta:PreviousListPrice' ), |
| 47 |
|
| 48 |
// Beds / baths. |
| 49 |
'BedroomsTotal' => array( 'column:bedrooms', 'meta:BedroomsTotal' ), |
| 50 |
'BathroomsTotalDecimal' => array( 'column:bathrooms', 'meta:BathroomsTotalDecimal' ), |
| 51 |
'BathroomsFull' => array( 'meta:BathroomsFull' ), |
| 52 |
'BathroomsHalf' => array( 'meta:BathroomsHalf' ), |
| 53 |
|
| 54 |
// Size / structure. |
| 55 |
'LivingArea' => array( 'column:living_area', 'meta:LivingArea' ), |
| 56 |
'LivingAreaUnits' => array( 'meta:LivingAreaUnits' ), |
| 57 |
'LotSizeSquareFeet' => array( 'column:lot_size', 'meta:LotSizeSquareFeet' ), |
| 58 |
'LotSizeAcres' => array( 'meta:LotSizeAcres' ), |
| 59 |
'YearBuilt' => array( 'column:year_built', 'meta:YearBuilt' ), |
| 60 |
'GarageSpaces' => array( 'column:garage_spaces', 'meta:GarageSpaces' ), |
| 61 |
'StoriesTotal' => array( 'column:stories', 'meta:StoriesTotal' ), |
| 62 |
|
| 63 |
// Location. |
| 64 |
'City' => array( 'column:city', 'tax:mlsimport_city' ), |
| 65 |
'StateOrProvince' => array( 'column:state', 'tax:mlsimport_state' ), |
| 66 |
'CountyOrParish' => array( 'tax:mlsimport_county', 'meta:CountyOrParish' ), |
| 67 |
'PostalCode' => array( 'column:zip', 'tax:mlsimport_zip', 'meta:PostalCode' ), |
| 68 |
'CityRegion' => array( 'tax:mlsimport_area' ), |
| 69 |
'SubdivisionName' => array( 'column:subdivision', 'tax:mlsimport_area', 'meta:SubdivisionName' ), |
| 70 |
'Latitude' => array( 'column:latitude', 'meta:Latitude' ), |
| 71 |
'Longitude' => array( 'column:longitude', 'meta:Longitude' ), |
| 72 |
'UnparsedAddress' => array( 'meta:UnparsedAddress' ), |
| 73 |
'StreetNumber' => array( 'meta:StreetNumber' ), |
| 74 |
'StreetName' => array( 'meta:StreetName' ), |
| 75 |
'UnitNumber' => array( 'meta:UnitNumber' ), |
| 76 |
|
| 77 |
// Schools โ free-text district name -> its own taxonomy term (+ raw meta). |
| 78 |
'HighSchoolDistrict' => array( 'tax:mlsimport_high_school_district', 'meta:HighSchoolDistrict' ), |
| 79 |
|
| 80 |
// Type / status. |
| 81 |
'PropertySubType' => array( 'column:property_type', 'tax:mlsimport_property_type' ), |
| 82 |
'PropertyType' => array( 'column:listing_type', 'tax:mlsimport_listing_type' ), |
| 83 |
'StandardStatus' => array( 'column:status', 'tax:mlsimport_status' ), |
| 84 |
|
| 85 |
// Agent / office (display meta; writer also creates/links the agent CPT). |
| 86 |
'ListAgentFullName' => array( 'meta:ListAgentFullName' ), |
| 87 |
'ListAgentKey' => array( 'meta:ListAgentKey' ), |
| 88 |
'ListAgentMlsId' => array( 'meta:ListAgentMlsId' ), |
| 89 |
'ListAgentFirstName' => array( 'meta:ListAgentFirstName' ), |
| 90 |
'ListAgentLastName' => array( 'meta:ListAgentLastName' ), |
| 91 |
'ListAgentEmail' => array( 'meta:ListAgentEmail' ), |
| 92 |
'ListAgentPreferredPhone' => array( 'meta:ListAgentPreferredPhone' ), |
| 93 |
'ListOfficeName' => array( 'meta:ListOfficeName' ), |
| 94 |
'ListOfficeKey' => array( 'meta:ListOfficeKey' ), |
| 95 |
'ListOfficeMlsId' => array( 'meta:ListOfficeMlsId' ), |
| 96 |
'ListOfficePhone' => array( 'meta:ListOfficePhone' ), |
| 97 |
|
| 98 |
// Dates. |
| 99 |
'ListingContractDate' => array( 'column:list_date', 'meta:ListingContractDate' ), |
| 100 |
'OnMarketDate' => array( 'meta:OnMarketDate' ), |
| 101 |
'CloseDate' => array( 'meta:CloseDate' ), |
| 102 |
'DaysOnMarket' => array( 'column:days_on_market', 'meta:DaysOnMarket' ), |
| 103 |
|
| 104 |
// Media. |
| 105 |
'PhotosCount' => array( 'meta:PhotosCount' ), |
| 106 |
'VirtualTourURLUnbranded' => array( 'meta:virtual_tour' ), |
| 107 |
|
| 108 |
// HOA. |
| 109 |
'AssociationFee' => array( 'column:hoa_fee', 'meta:AssociationFee' ), |
| 110 |
'AssociationFeeFrequency' => array( 'meta:AssociationFeeFrequency' ), |
| 111 |
|
| 112 |
// Body / withheld. |
| 113 |
'PublicRemarks' => array( 'content' ), |
| 114 |
'PrivateRemarks' => array( 'skip' ), |
| 115 |
'PrivateOfficeRemarks' => array( 'skip' ), |
| 116 |
|
| 117 |
// Amenity booleans -> mlsimport_feature term (label from help_functions.php 'insert'). |
| 118 |
'PoolPrivateYN' => array( 'feature:Private Pool' ), |
| 119 |
'WaterfrontYN' => array( 'feature:Has Waterfront' ), |
| 120 |
|
| 121 |
// Amenity multi-enums -> mlsimport_feature terms (each value becomes a term). |
| 122 |
// Each writes BOTH: the term drives search/filtering, the meta keeps the |
| 123 |
// field's identity. Flattened into the taxonomy alone, "Hardwood" no longer |
| 124 |
// remembers it came from Flooring, and no section could ever place it. |
| 125 |
'Appliances' => array( 'tax:mlsimport_feature', 'meta:Appliances' ), |
| 126 |
'InteriorFeatures' => array( 'tax:mlsimport_feature', 'meta:InteriorFeatures' ), |
| 127 |
'ExteriorFeatures' => array( 'tax:mlsimport_feature', 'meta:ExteriorFeatures' ), |
| 128 |
'View' => array( 'tax:mlsimport_feature', 'meta:View' ), |
| 129 |
'Cooling' => array( 'tax:mlsimport_feature', 'meta:Cooling' ), |
| 130 |
'Heating' => array( 'tax:mlsimport_feature', 'meta:Heating' ), |
| 131 |
'Flooring' => array( 'tax:mlsimport_feature', 'meta:Flooring' ), |
| 132 |
'LaundryFeatures' => array( 'tax:mlsimport_feature', 'meta:LaundryFeatures' ), |
| 133 |
'LotFeatures' => array( 'tax:mlsimport_feature', 'meta:LotFeatures' ), |
| 134 |
'CommunityFeatures' => array( 'tax:mlsimport_feature', 'meta:CommunityFeatures' ), |
| 135 |
'ParkingFeatures' => array( 'tax:mlsimport_feature', 'meta:ParkingFeatures' ), |
| 136 |
'PoolFeatures' => array( 'tax:mlsimport_feature', 'meta:PoolFeatures' ), |
| 137 |
); |
| 138 |
|
| 139 |
/** |
| 140 |
* Write targets for a RESO field. Unmapped fields pass through to |
| 141 |
* meta:x_<Field> (opt-in is gated upstream by the field selector). |
| 142 |
* |
| 143 |
* @param string $field RESO field name (verbatim PascalCase). |
| 144 |
* @return array List of target strings. |
| 145 |
*/ |
| 146 |
public static function targets_for( string $field ): array { |
| 147 |
// Explicit mapping if the field is in the ยง9 map; else pass through to meta:x_<Field>. |
| 148 |
$targets = self::MAP[ $field ] ?? array( 'meta:x_' . $field ); |
| 149 |
|
| 150 |
// Lets an add-on map a new RESO field (or re-route one) without core edits. |
| 151 |
if ( function_exists( 'apply_filters' ) ) { |
| 152 |
/** Filter the write targets for a RESO field. @since 6.3 */ |
| 153 |
$targets = (array) apply_filters( 'mlsimport_reso_targets_for', $targets, $field ); |
| 154 |
} |
| 155 |
|
| 156 |
return $targets; |
| 157 |
} |
| 158 |
} |
| 159 |
|