Changeset 3448071
- Timestamp:
- 01/27/2026 05:03:15 PM (2 months ago)
- Location:
- houzez-property-feed/trunk
- Files:
-
- 7 edited
-
README.txt (modified) (2 diffs)
-
houzez-property-feed.php (modified) (2 diffs)
-
includes/format-functions.php (modified) (2 diffs)
-
includes/import-formats/class-houzez-property-feed-format-amplify-syndication.php (modified) (4 diffs)
-
includes/import-formats/class-houzez-property-feed-format-kyero.php (modified) (3 diffs)
-
includes/import-formats/class-houzez-property-feed-format-pixxi.php (modified) (1 diff)
-
includes/import-formats/class-houzez-property-feed-format-propctrl.php (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
houzez-property-feed/trunk/README.txt
r3442498 r3448071 4 4 Requires at least: 3.8 5 5 Tested up to: 6.9 6 Stable tag: 2.5. 397 Version: 2.5. 396 Stable tag: 2.5.40 7 Version: 2.5.40 8 8 Homepage: https://houzezpropertyfeed.com 9 9 License: GPLv3 … … 147 147 == Changelog == 148 148 149 = 2.5.40 - 2026-01-27 = 150 * Added 'Location' filter to Amplify Syndication import settings to specify only properties in a certain city/state are imported 151 * Added support for importing floorplans from Kyero XML feeds 152 * Added support for bathrooms, area, garages and more in PropCtrl imports 153 * Added support for images having no extension in Pixxi imports 154 * Updated Bridge settings so that datafeed ID is a text field instead of a fixed dropdown 155 149 156 = 2.5.39 - 2026-01-19 = 150 157 * Added support for the Amplify Syndication RESO API -
houzez-property-feed/trunk/houzez-property-feed.php
r3442498 r3448071 4 4 * Plugin Uri: https://houzezpropertyfeed.com 5 5 * Description: Automatically import properties to Houzez from estate agency CRMs and export to portals 6 * Version: 2.5. 396 * Version: 2.5.40 7 7 * Author: PropertyHive 8 8 * Author URI: https://wp-property-hive.com … … 20 20 * @var string 21 21 */ 22 public $version = '2.5. 39';22 public $version = '2.5.40'; 23 23 24 24 /** -
houzez-property-feed/trunk/includes/format-functions.php
r3442498 r3448071 371 371 'label' => __( 'Office Name(s)', 'houzezpropertyfeed' ), 372 372 'type' => 'text', 373 'tooltip' => 'Case-sensitive. Comma-delimited list of office names to import. Taken from the ListOfficeName field in the data. One or more must be entered', 373 'tooltip' => 'Case-sensitive. Comma-delimited list of office names to import. Taken from the ListOfficeName field in the data', 374 ), 375 array( 376 'id' => 'location', 377 'label' => __( 'Location(s)', 'houzezpropertyfeed' ), 378 'type' => 'text', 379 'tooltip' => 'Case-sensitive. Comma-delimited list of cities, states or provinces to import', 374 380 ), 375 381 /*array( … … 863 869 'id' => 'dataset_id', 864 870 'label' => __( 'Datafeed ID', 'houzezpropertyfeed' ), 865 'type' => 'select', 866 'options' => array( 867 'test' => 'Test Data', 868 ) 871 'type' => 'text', 869 872 ), 870 873 array( -
houzez-property-feed/trunk/includes/import-formats/class-houzez-property-feed-format-amplify-syndication.php
r3442498 r3448071 50 50 $office_names = array_filter($office_names); 51 51 52 if ( empty($office_names) ) 52 $locations = isset($import_settings['location']) ? explode(",", $import_settings['location']) : array(); 53 $locations = array_map('trim', $locations); 54 $locations = array_filter($locations); 55 56 if ( empty($office_names) && empty($locations) ) 53 57 { 54 $this->log("At least one office name must be entered into the import settings");58 $this->log("At least one office name or location must be entered into the import settings"); 55 59 return false; 56 60 } 57 61 62 if ( !empty($office_names) ) 63 { 64 $office_additional_url = ''; 65 foreach ( $office_names as $i => $office_name ) 66 { 67 if ( !empty($office_additional_url) ) { $office_additional_url .= ' or '; } 68 $office_additional_url .= ' ListOfficeName eq %27' . $office_name . '%27 '; 69 } 70 $additional_url .= ' and (' . $office_additional_url . ')'; 71 } 58 72 59 $office_additional_url = ''; 60 foreach ( $office_names as $i => $office_name ) 73 if ( !empty($locations) ) 61 74 { 62 if ( !empty($office_additional_url) ) { $office_additional_url .= ' or '; } 63 $office_additional_url .= ' ListOfficeName eq %27' . $office_name . '%27 '; 64 } 65 $additional_url .= ' and (' . $office_additional_url . ')'; 66 75 $location_additional_url = ''; 76 foreach ( $locations as $i => $location ) 77 { 78 if ( !empty($location_additional_url) ) { $location_additional_url .= ' or '; } 79 $location_additional_url .= ' City eq %27' . $location . '%27 or CityRegion eq %27' . $location . '%27 or StateOrProvince eq %27' . $location . '%27 '; 80 } 81 $additional_url .= ' and (' . $location_additional_url . ')'; 82 } 83 67 84 $limit = apply_filters( "houzez_property_feed_property_limit", 25 ); 68 85 if ( $limit !== false ) … … 147 164 return true; 148 165 } 166 } 167 168 $media_url = 'https://query.ampre.ca/odata/Media?$top=1000&$filter=ResourceRecordKey eq %27' . $property['ListingKey'] . '%27 and ResourceName eq %27Property%27'; 169 170 $media_response = wp_remote_get( 171 $media_url, 172 array( 173 'timeout' => 360, 174 'headers' => array( 175 'Content-Type' => 'application/json', 176 'Authorization' => 'Bearer ' . $import_settings['access_token'], 177 ) 178 ) 179 ); 180 181 if ( is_wp_error( $media_response ) ) 182 { 183 $this->log_error( 'Response: ' . $media_response->get_error_message() ); 184 185 return false; 186 } 187 188 if ( wp_remote_retrieve_response_code($media_response) !== 200 ) 189 { 190 $this->log_error( wp_remote_retrieve_response_code($media_response) . ' response received when requesting properties. Error message: ' . wp_remote_retrieve_response_message($response) ); 191 return false; 192 } 193 194 if ( is_array( $media_response ) ) 195 { 196 $media_contents = $media_response['body']; 197 198 $media_json = json_decode( $media_contents, TRUE ); 199 200 if ( $media_json !== FALSE && is_array($media_json) ) 201 { 202 if ( isset($media_json['error']) && !empty($media_json['error']) ) 203 { 204 $this->log_error( 'Error received from Amplify API: ' . print_r($media_json['error'], true) ); 205 return false; 206 } 207 208 $property['Media'] = isset($media_json['value']) && is_array($media_json['value']) ? $media_json['value'] : array(); 209 } 149 210 } 150 211 … … 702 763 && 703 764 isset($image['MediaCategory']) && in_array(strtolower($image['MediaCategory']), array('photo', 'image')) 765 && 766 isset($image['MediaStatus']) && strtolower($image['MediaStatus']) == 'active' 704 767 ) 705 768 { … … 772 835 && 773 836 isset($image['MediaCategory']) && in_array(strtolower($image['MediaCategory']), array('photo', 'image')) 837 && 838 isset($image['MediaStatus']) && strtolower($image['MediaStatus']) == 'active' 774 839 ) 775 840 { -
houzez-property-feed/trunk/includes/import-formats/class-houzez-property-feed-format-kyero.php
r3389596 r3448071 614 614 } 615 615 616 if ( isset($image->tags->tag) && (string)$image->tags->tag == 'floorplan' ) 617 continue; 618 616 619 $url = trim((string)$image->url); 617 620 if ( … … 684 687 } 685 688 } 689 690 if ( isset($image->tags->tag) && (string)$image->tags->tag == 'floorplan' ) 691 continue; 686 692 687 693 $url = trim((string)$image->url); … … 851 857 } 852 858 859 // Floorplans 860 $floorplans = array(); 861 862 if (isset($property->images) && !empty($property->images)) 863 { 864 foreach ($property->images as $images) 865 { 866 if (!empty($images->image)) 867 { 868 foreach ($images->image as $image) 869 { 870 if ( isset($image->tags->tag) && (string)$image->tags->tag == 'floorplan' ) 871 { 872 if ( 873 substr( strtolower((string)$image->url), 0, 2 ) == '//' || 874 substr( strtolower((string)$image->url), 0, 4 ) == 'http' 875 ) 876 { 877 $floorplans[] = array( 878 "fave_plan_title" => __( 'Floorplan', 'houzezpropertyfeed' ), 879 "fave_plan_image" => trim((string)$image->url) 880 ); 881 } 882 } 883 } 884 } 885 } 886 } 887 888 if ( !empty($floorplans) ) 889 { 890 update_post_meta( $post_id, 'floor_plans', $floorplans ); 891 update_post_meta( $post_id, 'fave_floor_plans_enable', 'enable' ); 892 } 893 else 894 { 895 update_post_meta( $post_id, 'fave_floor_plans_enable', 'disable' ); 896 } 897 898 $this->log( 'Imported ' . count($floorplans) . ' floorplans', (string)$property->propertyID, $post_id ); 899 853 900 update_post_meta( $post_id, 'fave_video_url', '' ); 854 901 update_post_meta( $post_id, 'fave_virtual_tour', '' ); -
houzez-property-feed/trunk/includes/import-formats/class-houzez-property-feed-format-pixxi.php
r3389596 r3448071 774 774 $filename = basename( $url ); 775 775 776 $extension = pathinfo($filename, PATHINFO_EXTENSION); 777 if ( $extension === '' ) 778 { 779 $filename .= '.jpg'; 780 } 781 776 782 // Check, based on the URL, whether we have previously imported this media 777 783 $imported_previously = false; -
houzez-property-feed/trunk/includes/import-formats/class-houzez-property-feed-format-propctrl.php
r3428872 r3448071 1209 1209 } 1210 1210 1211 update_post_meta( $post_id, 'fave_property_bedrooms', $bedrooms ); 1212 update_post_meta( $post_id, 'fave_property_bathrooms', '' ); 1211 $bathrooms = 0; 1212 if ( isset($property['features']) && !empty($property['features']) ) 1213 { 1214 foreach ( $property['features'] as $feature ) 1215 { 1216 if ( isset($feature['type']) && strpos(strtolower($feature['type']), 'bathroom') !== FALSE ) 1217 { 1218 ++$bathrooms; 1219 } 1220 } 1221 } 1222 1223 update_post_meta( $post_id, 'fave_property_bedrooms', !empty($bedrooms) ? $bedrooms : '' ); 1224 update_post_meta( $post_id, 'fave_property_bathrooms', !empty($bathrooms) ? $bathrooms : '' ); 1213 1225 update_post_meta( $post_id, 'fave_property_rooms', '' ); 1214 1226 1227 $size = ( isset($property['floorArea']['size']) && !empty($property['floorArea']['size']) ) ? $property['floorArea']['size'] : ''; 1228 update_post_meta( $post_id, 'fave_property_size', $size ); 1229 $unit = ''; 1230 if ( !empty($size) && isset($property['floorArea']['measurementUnit']) ) 1231 { 1232 switch ( $property['floorArea']['measurementUnit'] ) 1233 { 1234 //case "": { $unit = ''; break; } 1235 default: { $unit = 'sq m'; } 1236 } 1237 } 1238 update_post_meta( $post_id, 'fave_property_size_prefix', $unit ); 1239 1240 $size = ( isset($property['erfSize']['size']) && !empty($property['erfSize']['size']) ) ? $property['erfSize']['size'] : ''; 1241 update_post_meta( $post_id, 'fave_property_land', $size ); 1242 $unit = ''; 1243 if ( !empty($size) && isset($property['erfSize']['measurementUnit']) ) 1244 { 1245 switch ( $property['erfSize']['measurementUnit'] ) 1246 { 1247 //case "": { $unit = ''; break; } 1248 default: { $unit = 'sq m'; } 1249 } 1250 } 1251 update_post_meta( $post_id, 'fave_property_land_postfix', $unit ); 1252 1215 1253 $parking = array(); 1254 $garages = 0; 1216 1255 if ( isset($property['features']) && !empty($property['features']) ) 1217 1256 { 1218 1257 foreach ( $property['features'] as $feature ) 1219 1258 { 1220 if ( isset($feature['type']) && $feature['type'] == 'Parking' )1259 if ( isset($feature['type']) && $feature['type'] == 'Parking' && isset($feature['description']) && !empty($feature['description']) ) 1221 1260 { 1222 1261 $parking[] = $feature['description']; 1223 1262 } 1224 } 1263 if ( isset($feature['type']) && $feature['type'] == 'Garage' ) 1264 { 1265 ++$garages; 1266 } 1267 } 1268 } 1269 if ( empty($parking) && $garages > 0 ) 1270 { 1271 $parking[] = $garages . ' garages'; 1225 1272 } 1226 1273 update_post_meta( $post_id, 'fave_property_garage', implode(", ", $parking) ); … … 1743 1790 1744 1791 $file_array = array( 1745 'name' => $filename,1792 'name' => str_replace(".ashx", ".jpg", $filename), 1746 1793 'tmp_name' => $tmp 1747 1794 ); … … 1968 2015 { 1969 2016 // This is a URL 1970 $url = $ property['brochure']['url'];2017 $url = $brochure['url']; 1971 2018 $description = ( (isset($brochure['title'])) ? $brochure['title'] : '' ); 1972 2019 … … 2147 2194 do_action( "save_post", $post_id, $post, false ); 2148 2195 2149 // Send request back to PropCtrl containing post ID and URL etc 2150 $url = rtrim($import_settings['base_url'], '/') . '/listing/v1/listings/' . $property['listingId']; 2151 2152 $headers = array( 2153 'Content-Type' => 'application/json', 2154 'Authorization' => 'Basic ' . base64_encode($import_settings['api_username'] . ':' . $import_settings['api_password']), 2155 ); 2156 2157 $body = array( 2158 "listingNumber" => (string)$post_id, 2159 "status" => "Active", 2160 "listingUrl" => get_permalink($post_id) 2161 ); 2162 2163 $response = wp_remote_request( 2164 $url, 2165 array( 2166 'method' => 'PUT', 2167 'timeout' => 120, 2168 'headers' => $headers, 2169 'body' => json_encode($body), 2170 ) 2171 ); 2172 2173 if ( is_wp_error( $response ) ) 2174 { 2175 $this->log_error( 'Response when updating status in PropCtrl: ' . $response->get_error_message(), $property['listingId'], $post_id ); 2196 if ( isset($import_settings['api_version']) && $import_settings['api_version'] == 'v6' ) 2197 { 2198 // Send request back to PropCtrl containing post ID and URL etc 2199 $url = rtrim($import_settings['base_url'], '/') . '/agency-integration/v6/properties/' . $property['listingId']; 2200 2201 $headers = array( 2202 'Content-Type' => 'application/json', 2203 'Authorization' => 'Basic ' . base64_encode($import_settings['api_username'] . ':' . $import_settings['api_password']), 2204 ); 2205 2206 $body = array( 2207 "listingNumber" => (string)$post_id, 2208 "status" => "Active", 2209 "listingUrl" => get_permalink($post_id) 2210 ); 2211 2212 $response = wp_remote_request( 2213 $url, 2214 array( 2215 'method' => 'PUT', 2216 'timeout' => 120, 2217 'headers' => $headers, 2218 'body' => json_encode($body), 2219 ) 2220 ); 2221 2222 if ( is_wp_error( $response ) ) 2223 { 2224 $this->log_error( 'Response when updating status in PropCtrl: ' . $response->get_error_message(), $property['listingId'], $post_id ); 2225 } 2226 } 2227 else 2228 { 2229 // Send request back to PropCtrl containing post ID and URL etc 2230 $url = rtrim($import_settings['base_url'], '/') . '/listing/v1/listings/' . $property['listingId']; 2231 2232 $headers = array( 2233 'Content-Type' => 'application/json', 2234 'Authorization' => 'Basic ' . base64_encode($import_settings['api_username'] . ':' . $import_settings['api_password']), 2235 ); 2236 2237 $body = array( 2238 "listingNumber" => (string)$post_id, 2239 "status" => "Active", 2240 "listingUrl" => get_permalink($post_id) 2241 ); 2242 2243 $response = wp_remote_request( 2244 $url, 2245 array( 2246 'method' => 'PUT', 2247 'timeout' => 120, 2248 'headers' => $headers, 2249 'body' => json_encode($body), 2250 ) 2251 ); 2252 2253 if ( is_wp_error( $response ) ) 2254 { 2255 $this->log_error( 'Response when updating status in PropCtrl: ' . $response->get_error_message(), $property['listingId'], $post_id ); 2256 } 2176 2257 } 2177 2258
Note: See TracChangeset
for help on using the changeset viewer.