Snapshot: MLS sync fixes, image refresh, plugin/theme updates

MLS plugin fixes from this session:
- Fix silent insert failures: location column NOT NULL was rejecting wpdb->insert calls,
  causing ~18k new properties since Dec 2025 to be lost. Inserts now build raw SQL
  with ST_PointFromText so the spatial column is populated atomically.
- Auto-refresh expired media URLs in MLS_Media_Handler::fetch_and_cache(), guarded by
  a property-level GET_LOCK so concurrent fetches share one API refresh.
- Normalize WP_Error to null in mls_get_property_image() so callers can rely on the
  documented string|null contract.
- Support comma-separated property_type filters in MLS_Query and MLS_Cluster so the
  homepage "View All Commercial" link (?property_type=Commercial+Sale,Land,Farm)
  actually filters correctly.
- Incremental sync now looks back 10 minutes past the latest modification timestamp
  as a safety margin against missed records.
- Smart sync exits silently (info-level, not warning) when a full sync is in progress.

Operational:
- New cron: weekly full sync Sundays at 3 AM (/usr/local/bin/mls-full-sync).
- New cron: hourly 2GB cap on mls-thumbnails/ and cache/transformed-images/
  (/usr/local/bin/mls-image-cache-cap).
- Logrotate config for wp-content/debug.log (2-day retention, daily rotation,
  delaycompress).

Repo policy:
- CLAUDE.md updated with explicit "commit everything except build artifacts" policy.
- .gitignore: untrack runtime image caches and debug.log rotations.

Other modifications in this snapshot are pre-existing in-flight theme/plugin/db_content_updates work.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
root
2026-04-29 15:32:23 +00:00
parent 57b752f54e
commit b6df4dbb92
5385 changed files with 838580 additions and 2416 deletions
View File
View File
View File
View File
@@ -0,0 +1,138 @@
# Property Inquiry Form Field Reorder
**Date:** 2026-01-12
**Purpose:** Reorder Contact Form 7 "Property Inquiry Form" fields so Additional Comments appears after Name/Email/Phone
**Status:** Applied to dev on 2026-01-12
## Background
The property inquiry form should have this field order:
1. Your Inquiry (readonly display message)
2. Your Name
3. Email / Phone (side by side)
4. Additional Comments
5. Submit button
Previously, Additional Comments was above the contact fields.
## Changes Required
### Via WP Admin (Recommended)
1. Go to WP Admin > Contact > Forms
2. Edit "Property Inquiry Form"
3. Reorder the form fields as shown below
4. Save the form
### New Form Structure
```
<div class="form-group">
<label>Your Inquiry</label>
<div class="readonly-message-display readonly-message"></div>
</div>
[hidden listing-key]
[hidden listing-id]
[hidden property-address]
[hidden property-price]
[hidden property-url]
[hidden default-message]
[hidden agent-email]
[hidden agent-name]
<div class="form-row">
<div class="form-group">
<label>Your Name <span class="required">*</span></label>
[text* your-name]
</div>
</div>
<div class="form-row form-row-2col">
<div class="form-group">
<label>Email <span class="required">*</span></label>
[email* your-email]
</div>
<div class="form-group">
<label>Phone <span class="required">*</span></label>
[tel* your-phone]
</div>
</div>
<div class="form-group">
<label>Additional Comments</label>
[textarea comments placeholder "Any specific questions or information you'd like to know..."]
</div>
[submit class:btn class:btn-primary class:btn-lg "Send Inquiry"]
```
### Via SQL (Alternative)
**Important:** CF7 stores the form structure in `wp_postmeta._form`, not `wp_posts.post_content`.
First, find the form ID:
```sql
SELECT ID, post_title FROM wp_posts
WHERE post_type = 'wpcf7_contact_form'
AND post_title = 'Property Inquiry Form';
-- Result: ID = 156 (in dev)
```
Then update the `_form` meta with the new form structure:
```sql
UPDATE wp_postmeta
SET meta_value = '<div class="form-group">
<label>Your Inquiry</label>
<div class="readonly-message-display readonly-message"></div>
</div>
[hidden listing-key]
[hidden listing-id]
[hidden property-address]
[hidden property-price]
[hidden property-url]
[hidden default-message]
[hidden agent-email]
[hidden agent-name]
<div class="form-row">
<div class="form-group">
<label>Your Name <span class="required">*</span></label>
[text* your-name]
</div>
</div>
<div class="form-row form-row-2col">
<div class="form-group">
<label>Email <span class="required">*</span></label>
[email* your-email]
</div>
<div class="form-group">
<label>Phone <span class="required">*</span></label>
[tel* your-phone]
</div>
</div>
<div class="form-group">
<label>Additional Comments</label>
[textarea comments placeholder "Any specific questions or information you would like to know..."]
</div>
[submit class:btn class:btn-primary class:btn-lg "Send Inquiry"]'
WHERE post_id = (SELECT ID FROM wp_posts WHERE post_type = 'wpcf7_contact_form' AND post_title = 'Property Inquiry Form')
AND meta_key = '_form';
```
## Related Code Changes
The following theme files were also updated to support this change:
- `page-property-inquiry.php` - Updated fallback form field order, added agent lookup, split display vs submission messages
- `inc/wpcf7-hooks.php` - Updated HomeProz listing detection to use office name
- `template-parts/property/property-agent.php` - Updated to use listing key for inquiry URL
## Why
- Better UX: Users should enter their contact info before typing additional comments
- The display message shown to users no longer includes MLS# (cleaner)
- The submitted message includes MLS#, property URL, and user comments for agent reference
+35
View File
@@ -0,0 +1,35 @@
# Agent MLS ID Assignments
**Date:** 2026-01-12
**Purpose:** Assign HomeProz agent MLS IDs to agent profiles
## Changes Made
Updated `agent_mls_id` ACF field for agents to match MLS Grid listing agent IDs.
## SQL Commands
```sql
-- Assign NST503517070 to Davy Villarreal (ID 129) and Jordan Mullenbach (ID 130)
UPDATE wp_postmeta
SET meta_value = 'NST503517070'
WHERE post_id IN (129, 130)
AND meta_key = 'agent_mls_id';
```
## Final State
| Agent ID | Agent Name | MLS ID |
|----------|------------|--------|
| 128 | Anna Rahn | NST503517068 |
| 129 | Davy Villarreal | NST503517070 |
| 130 | Jordan Mullenbach | NST503517070 |
| 131 | Lily Dulitz | NST503517068 |
## Why
HomeProz has 2 listing agent MLS IDs in the MLS Grid data:
- NST503517068 (2 properties)
- NST503517070 (2 properties)
These were assigned to agents so property cards can display the correct agent information.
@@ -0,0 +1,65 @@
# Remove Legacy Property Posts
**Date**: 2026-01-20
**Type**: Content Deletion
**Priority**: Required before or after code deployment
## Summary
The legacy manual property entry system has been deprecated. All properties now come exclusively from the MLS sync. This requires deleting the manually-created property posts and their associated data.
## What Changed
The following legacy system components were removed from the codebase:
- `property` custom post type registration
- `single-property.php` template
- `property-card.php` template part
- ACF "Property Details" field group
- Agent listings section from `single-agent.php`
## Database Changes Required on Production
### 1. Delete Legacy Property Posts
Run this WP-CLI command to delete the legacy property posts:
```bash
wp --allow-root post delete 24 35 60 85 125 --force
```
These were the legacy posts:
- ID 24: "Geneva, MN - Double Lot with Shop"
- ID 35: "115 N Newton Ave, Albert Lea, MN"
- ID 60: "411 Court St, Albert Lea, MN"
- ID 85: "1224 Saint Joseph Ave, Albert Lea, MN"
- ID 125: "15131 800th Ave, Glenville, MN"
### 2. Clean Up Orphaned Post Meta
After deleting the posts, clean up any orphaned meta data:
```bash
wp --allow-root db query "DELETE pm FROM wp_postmeta pm LEFT JOIN wp_posts p ON pm.post_id = p.ID WHERE p.ID IS NULL"
```
### 3. Flush Rewrite Rules
After code deployment, flush rewrite rules to remove the property slug:
```bash
wp --allow-root rewrite flush
```
## Verification
After completing these steps, verify:
1. The `/properties/` archive page still works (MLS-based)
2. Agent profile pages no longer show a "Current Listings" section (expected - removed)
3. No 404 errors from old property URLs (will naturally 404 since posts deleted)
## Notes
- The `/properties/` URL now exclusively serves MLS data via `archive-property.php`
- Individual property URLs use the `?listing=XXXXX` query parameter for MLS listings
- Agent pages no longer display properties; this was intentional as the legacy linking system is deprecated
@@ -0,0 +1,130 @@
# Split About and Team Pages + Blog Menu
**Date**: 2026-01-21
**Type**: Page Template Split + New Page Creation + Menu Updates
**Status**: IMPLEMENTED IN DEV
## Summary
The About page has been split into two separate pages:
- **About Page** - Company story, additional WYSIWYG content area, and CTA
- **Team Page** - Agent grid, broker info, and CTA
Additionally:
- **Blog** added to navigation menu
- Blog templates updated to use consistent archive-hero styling
## Code Changes
- Created `page-team.php` - New Team Page template
- Modified `page-about.php` - Removed team/broker sections, added WYSIWYG content section
- Created `template-parts/content/content-team.scss` - Team page styles
- Updated `template-parts/content/content-about.scss` - Added styles for additional content section
- Updated `inc/template-functions.php` - Added Team_Page body class
- Updated `src/main.scss` - Added team SCSS import
- Updated `home.php` - Blog index uses archive-hero for consistency
- Updated `archive.php` - Category/tag archives use archive-hero for consistency
- Created `page-results.php` - Results Page template for sold properties
- Created `template-parts/content/content-results.scss` - Results page styles
## Database Changes (Already Applied in Dev)
The following changes were made directly to the dev database and need to be replicated in production:
### 1. Team Page Created
**Page ID**: 256
**Title**: Our Team
**Slug**: team
**Template**: page-team.php
```sql
-- Create page
INSERT INTO wp_posts (post_author, post_date, post_date_gmt, post_content, post_title, post_excerpt, post_status, comment_status, ping_status, post_name, post_type, post_modified, post_modified_gmt, to_ping, pinged, post_content_filtered)
VALUES (1, NOW(), UTC_TIMESTAMP(), '', 'Our Team', '', 'publish', 'closed', 'closed', 'team', 'page', NOW(), UTC_TIMESTAMP(), '', '', '');
-- Set page template (use the actual page ID from above)
INSERT INTO wp_postmeta (post_id, meta_key, meta_value) VALUES (LAST_INSERT_ID(), '_wp_page_template', 'page-team.php');
```
### 2. Menu Item Added to Primary Menu
Team added after About in the Primary Menu:
**Menu Order**:
1. Properties (0)
2. About (3)
3. Team (4) - NEW
4. Results (5) - NEW
5. Resources (6)
6. Blog (7) - NEW
7. Contact (8)
```sql
-- Shift existing items down (adjust IDs for production)
-- Resources menu item: update menu_order from 4 to 5
-- Contact menu item: update menu_order from 5 to 6
-- Create nav_menu_item for Team (adjust page ID for production)
INSERT INTO wp_posts (post_author, post_date, post_date_gmt, post_content, post_title, post_excerpt, post_status, comment_status, ping_status, post_name, post_type, menu_order, post_modified, post_modified_gmt, to_ping, pinged, post_content_filtered)
VALUES (1, NOW(), UTC_TIMESTAMP(), '', 'Team', '', 'publish', 'closed', 'closed', 'team-menu', 'nav_menu_item', 4, NOW(), UTC_TIMESTAMP(), '', '', '');
-- Add to Primary Menu term relationship
-- Add required meta: _menu_item_type, _menu_item_object_id, _menu_item_object, etc.
```
### 3. Blog Menu Item Added
Blog page (ID 9, already exists) added to Primary Menu.
### 4. Results Page Created
**Page ID**: 259
**Title**: Our Results
**Slug**: results
**Template**: page-results.php
Displays sold/closed properties from MLS sync and manual entries, sorted by close date (most recent first).
## Production Deployment Steps
1. Deploy code changes (theme files)
2. Run `npm run build` in theme directory
3. Either:
- **Option A**: Manually create Team page in WordPress admin, assign template, add to menu
- **Option B**: Run SQL statements above with adjusted IDs
### Manual Steps (Option A - Recommended)
1. Go to **Pages > Add New**
2. Title: `Our Team`
3. Slug: `team`
4. Template: **Team Page**
5. Publish
6. Go to **Appearance > Menus**
7. Select Primary Menu
8. Add "Our Team" page (set custom label to "Team")
9. Add "Blog" page
10. Order: Properties, About, Team, Resources, Blog, Contact
11. Save Menu
## Optional ACF Fields for Team Page
| Field | Default Value |
|-------|---------------|
| `hero_title` | "Our Team" |
| `hero_subtitle` | "A dedicated group of real estate professionals committed to your success." |
| `hero_background` | (none) |
| `broker_title` | "Broker Information" |
| `broker_text` | HomeProz broker details |
| `cta_title` | "Ready to Work With Us?" |
| `cta_text` | "Contact our team today..." |
| `cta_button_text` | "Get in Touch" |
| `cta_button_url` | /contact/ |
## Notes
- Agent ordering on Team page respects the `menu_order` field (drag-drop sortable in admin)
- Disabled agents are automatically excluded
- The About page retains its existing ACF fields
+67
View File
@@ -0,0 +1,67 @@
# Blog Enhancements
**Date**: 2026-01-21
**Type**: Template Updates + ACF Field Addition
**Status**: IMPLEMENTED IN DEV
## Summary
Enhanced single blog post pages with additional sections and added Agent author capability.
## Code Changes
### Templates
- `single.php` - Added three new sections below post content:
1. Enhanced Next/Prev navigation with thumbnails
2. Related Posts section (always shows, falls back to recent posts)
3. Featured Properties section (3 active MLS listings)
- `template-parts/content/content-single.php` - Added agent author display in post meta
- `template-parts/content/content-single.scss` - Added styles for:
- Post navigation with thumbnails
- Featured properties grid
- Author meta styling
### ACF Fields
- Added "Post Author" field group for blog posts:
- Field: `post_agent_author` (post_object linking to Agent CPT)
- Location: Sidebar of post edit screen
- Only shows active (non-disabled) agents in dropdown
### Functions
- Added `homeproz_filter_agent_post_object()` filter to exclude disabled agents from author dropdown
- Removed comments functionality site-wide
## Features
### Agent Author on Blog Posts
- In post editor sidebar, select an agent as the post author
- Author name displays in post meta with link to agent profile
- If agent is later disabled, name still shows but link is removed
- Only active agents appear in the dropdown selector
### Enhanced Post Navigation
- Shows Previous/Next post with thumbnail images
- Falls back to placeholder icon if no featured image
- Responsive grid layout
### Related Posts
- Shows 3 posts from same category
- Falls back to 3 recent posts if no category matches
- Always displays something (unless only 1 post exists)
### Featured Properties
- Shows 3 active MLS listings below blog content
- "View All Properties" button links to /properties/
- Helps drive traffic from blog to listings
## Agent Disabled Flag Behavior
The existing `agent_disabled` ACF field controls:
1. **Team Page**: Disabled agents hidden from grid
2. **Agent Archive**: Disabled agents excluded
3. **Agent Profile**: Returns 404 for disabled agents
4. **Property Cards**: Shows office contact instead of disabled agent
5. **Blog Author Dropdown**: Only active agents shown (NEW)
6. **Blog Author Display**: Disabled agent names show without link (NEW)
+77
View File
@@ -0,0 +1,77 @@
# Manual Property Entry System
**Date**: 2026-01-21
**Type**: Schema Change + New Feature
## Summary
Added the ability to manually enter properties that integrate seamlessly with MLS-synced listings. Manual properties can override MLS listings (same MLS ID), support cloning from existing MLS data, and include geocoding for addresses.
## Schema Changes
New table `wp_mls_properties_manual` created automatically by the MLS plugin on activation/upgrade.
The table will be created automatically when the plugin runs - no manual SQL needed.
## New Custom Post Type
**CPT**: `manual_property`
**Menu**: "Manual Properties" in WordPress admin
## ACF Field Group
ACF fields are registered programmatically (no JSON import needed). Fields will appear automatically on the Manual Property edit screen.
## How to Use
### Add a Manual Property
1. Go to **Manual Properties > Add Property** in WordPress admin
2. Fill in property details across the tabs:
- Basic Info: Status, Price, Type, HomeProz checkbox, Featured toggle
- Location: Address (geocoded automatically), City, State, ZIP
- Details: Beds, Baths, Square Feet, etc.
- Description: Public remarks
- Media: Upload property photos
- Agent: Select from Agent CPT
- Dates: List date, close date, etc.
3. Publish the property
### Clone from MLS
1. Go to **Manual Properties > Add Property**
2. Enter an MLS # in the "Clone from MLS Listing" box
3. Click "Clone Listing"
4. Images will be downloaded and fields pre-populated
5. Review and modify as needed, then publish
### Override an MLS Listing
1. Create a manual property
2. Set the MLS # field to the MLS ID you want to override
3. Publish
4. The manual version will appear in search results instead of the MLS-synced version
## Dependencies
- ACF Pro (already installed)
- MLS by HansonXyz plugin (updated in this release)
## Files Changed
Plugin files (MLS plugin):
- `mls-by-hansonxyz.php` - Added table constant, class includes
- `includes/class-mls-db.php` - Added manual properties table schema
- `includes/class-mls-query.php` - Modified to include manual properties in queries
- `includes/class-mls-image-endpoint.php` - Handle manual property images
- `includes/class-mls-manual-property.php` - NEW: CPT, ACF fields, sync logic
- `includes/class-mls-geocoder.php` - NEW: Address geocoding via Nominatim
- `admin/js/manual-property.js` - NEW: Clone from MLS functionality
- `admin/css/manual-property.css` - NEW: Admin styles
## Notes
- Manual properties use WordPress Media Library for images (not MLS media cache)
- Geocoding uses free Nominatim API (rate limited, cached for 30 days)
- Manual property listing keys follow format: `MANUAL-{post_id}`
- Properties with `listing_id` set will override MLS listings with matching ID
@@ -0,0 +1,37 @@
# About Page ACF Fields Update
**Date:** 2026-01-23
**Author:** Claude Code
## Summary
Added a new ACF WYSIWYG field to the About page to separate the second content section from the main page body. Previously, the page body content was appearing in both sections (duplicate content).
## Changes
### Content Structure (After)
- **Top Story Section** (next to image): Uses standard WordPress page body content (`the_content()`)
- **Additional Content Section** (below): Uses new ACF field `about_additional_content`
### ACF Field Added
**Additional Content** - `about_additional_content`
- WYSIWYG field
- Displayed in a separate section below the story section
- For extended company information
## Production Sync Instructions
1. Deploy the updated files:
- `wp-content/themes/homeproz/inc/acf-fields.php`
- `wp-content/themes/homeproz/page-about.php`
2. In WordPress Admin, edit the About page:
- Keep the main story content in the standard WordPress page body editor
- Add any additional content to the new "Additional Content" ACF field below
## Files Modified
- `wp-content/themes/homeproz/inc/acf-fields.php` - Added `about_additional_content` field
- `wp-content/themes/homeproz/page-about.php` - Top section now uses `the_content()`, bottom section uses ACF field
Regular → Executable
View File