# FacetWP Remote Data

**FacetWP Remote Data** is a WordPress plugin that fetches **FacetWP-filtered data** from a remote WordPress site. This allows you to query and display posts filtered by FacetWP from an external source.

## Features
- Fetch FacetWP-filtered post IDs from a remote site.
- Retrieve full post details via the WordPress REST API.
- Easily configure remote connection settings via the **WordPress Admin**.
- **Custom Templating System:** Customize the output by overriding the default template in your theme or via a filter.
- **JavaScript Enqueueing:** Load scripts dynamically for listing and property pages.
- **Neighborhood Pages:** Allow preselected FacetWP filters for specific pages.

## Installation
1. **Upload the plugin** to your WordPress site.
2. **Activate the plugin** via the **Plugins** menu in WordPress.
3. **Go to Settings → FacetWP Remote Settings** and enter:
    - **Username**
    - **Password**
    - **Remote Site URL**
4. Save changes and click on **'Sync FacetWP Settings'** to sync FacetWP settings from the main site.

### 'Enable Automatic Syncing' Checkbox
When enabled, this option ensures that whenever FacetWP settings are updated on the main site, a request is automatically sent to the subsite to sync and update its FacetWP settings accordingly.

### 'Select Pages' Checkbox
This setting allows you to specify which pages should retrieve and display FacetWP-filtered data from the remote site. When selected, the plugin will automatically apply remote FacetWP data to the chosen pages.

## Important Note
To get the **full benefit of this plugin**, we strongly recommend:
- **Disabling the native WordPress cron** (`define( 'DISABLE_WP_CRON', true );`).
- **Setting up a real system cron job** to trigger WordPress cron events reliably.

Example real cron job (every 5 minutes):

```bash
*/5 * * * * cd /path/to/your/site && flock -n ~/.wp_cron.lock /usr/local/bin/wp cron event run --due-now --quiet
```

---

## **Neighborhood Pages (Preselected Facets)**
Neighborhood Pages allow you to **preselect FacetWP filters** for a specific page. This ensures that a user **always sees filtered results** for that page without being able to change the predefined filters.

### **How It Works**
1. **Each page can have preselected FacetWP filters.**
2. **A meta box is added to the WordPress page editor** where the admin can select preselected facet values.
3. **When a neighborhood Page loads, it automatically applies the preselected facet values.**
4. **Users cannot modify or remove these preselected facets from the UI.**

### **How to Set Up a Neighborhood Page**
1. **Edit a page** in WordPress.
2. Locate the **"Preselected Facet Filters"** meta box (on the right side).
3. **Select the default values** for each facet.
4. Save the page.

Now, when users visit this page, **the selected FacetWP filters will be automatically applied**.

---

## **Caching (Transients)**
FacetWP Remote Data **caches responses from the remote site** using WordPress transients. This reduces the number of API requests and improves performance.

### **Transient Caching for Remote Site Data**
- When fetching FacetWP-filtered data or posts data, the plugin **stores the response in a transient**.
- The transient key is dynamically generated based on the **query arguments** or **post id**.
- Cached data **expires after 10 minutes**, after which a fresh request is made.

#### **Skipping Cache (Forcing a New API Request)**
You can bypass the cache and force a fresh request using the `facetwp_remote_data_skip_cache` filter:
```php
add_filter( 'facetwp_remote_data_skip_cache', '__return_true' );
```

---

## Template Customization
FacetWP Remote Data provides a flexible templating system that allows you to modify the output by copying the template file into your theme, customizing it via a filter, or both.

### **Listing Page Templating**
FacetWP Remote Data provides a template for rendering filtered listing results.

#### **How It Works**
- **Default Template Location:**
  ```
  [plugin root]/templates/facet-wp-remote-data-listing-template.php
  ```

- **Theme Override:**
  ```
  [your-theme]/facet-wp-remote-data/facet-wp-remote-data-listing-template.php
  ```

- **Filter-Based Override:**
  ```php
  add_filter( 'facet_wp_remote_data_listing_template_path', function( $template_path, $template_vars ) {
      return get_stylesheet_directory() . '/custom-templates/custom-facetwp-template.php';
  }, 10, 2 );
  ```

#### **How to Override the Listing Template**
1. **Copy the default template** from `[plugin root]/templates/facet-wp-remote-data-listing-template.php`.
2. **Paste it into your theme** under `[your-theme]/facet-wp-remote-data/`.
3. The `$properties_data` variable contains the properties data.
4. **Customize as needed.**
5. Set a per-post template:
   - In the post editor (for posts, pages, or properties), enter a template name in the `FacetWP Listing Template` meta box.
   - Example: Enter ny-page-listings, and the plugin will use /themes/[your-theme]/theme/facet-wp-remote-data/ny-page-listings.php.
   - If no custom template is set, the default logic applies.

---

### **Property Page Templating**
FacetWP Remote Data also provides a **property detail page template** that loads content dynamically based on a property ID.

#### **How It Works**
- The **property page template** is responsible for displaying individual properties.
- It loads dynamically when the URL contains `?id=<property_id>`.

- **Default Template Location:**
  ```
  [plugin root]/templates/facet-wp-remote-data-property-template.php
  ```

- **Theme Override:**
  ```
  [your-theme]/facet-wp-remote-data/facet-wp-remote-data-property-template.php
  ```

- **Filter-Based Override:**
  ```php
  add_filter( 'facet_wp_remote_data_property_template_path', function( $template_path ) {
      return get_stylesheet_directory() . '/custom-templates/custom-property-template.php';
  });
  ```

#### **How to Override the Property Template**
1. **Copy the default template** from `[plugin root]/templates/facet-wp-remote-data-property-template.php`.
2. **Paste it into your theme** under `[your-theme]/facet-wp-remote-data/`.
3. The `$property_data` variable contains the property data.
4. **Customize as needed.**

#### **Available Shortcodes**
FacetWP Remote Data provides the following shortcodes to enhance property pages:

1. `[property_google_map]` - Display Google Map with Property Location

This shortcode displays a Google Map with a **pinned property location** and the property's price.

**Example Usage:**
```php
echo do_shortcode(
    sprintf(
        '[property_google_map location="%s" price="%s"]',
        $property['address'],
        sprintf( '$%sK', floor( $property['price'] / 1000 ) )
    )
);
```
**Parameters:**
| Parameter | Description |
|-----------|-------------|
| `location` | The property address to be pinned on the map. |
| `price` | The formatted price of the property displayed on the map marker. |

---

2. `[property_payment_calculator]` - Mortgage Payment Calculator

This shortcode renders a mortgage payment calculator with **predefined values** based on property details.

**Example Usage:**
```php
echo do_shortcode(
    sprintf(
        '[property_payment_calculator price="%d" default_down_payment="%.2f" default_down_payment_percentage="%.2f" default_length_of_mortgage="%d" default_interest_rate="%.2f"]',
        (int) $property_price,
        (float) $default_down_payment,
        (float) $default_down_payment_percentage,
        (int) $default_length_of_mortgage,
        (float) $default_interest_rate
    )
);
```
**Parameters:**
| Parameter | Description |
|-----------|-------------|
| `price` | The total price of the property (integer). |
| `default_down_payment` | The default down payment amount (float). |
| `default_down_payment_percentage` | The down payment percentage (float). |
| `default_length_of_mortgage` | The mortgage length in years (integer). |
| `default_interest_rate` | The interest rate for the mortgage (float). |

---

### **Facet Labels**

FacetWP does not automatically output facet labels / headings, except in the Mobile Flyout menu.
\
\
This plugin adds facet labels alongside the facets. If you prefer to disable this functionality, you can use the following filter:

**Disable Facet Labels**

To remove facet labels, add this filter to your code:
```php
add_filter( 'sw_facetwp_show_labels', '__return_false' );
```
\
**Customize Facet Wrapper Classes**

The facet label and its corresponding facet are wrapped inside a \<div\> element. You can modify or add custom classes to this wrapper using:
```php
add_filter( 'sw_facetwp_wrapper_classes', function( $classes ) {
    return $classes . ' my-custom-class';
});
```
\
**Customize Facet Label Classes**

To style the facet label itself, you can modify its class using:
```php
add_filter( 'sw_facetwp_label_classes', function( $classes ) {
    return $classes . ' my-custom-class';
});
```

---

## **Loading Scripts into Templates**
FacetWP Remote Data provides an extendable way to enqueue JavaScript files for both **listing pages** and **property pages**.

### **How It Works**
The plugin fires **two actions** when loading templates:
- `facet_wp_property_page_load` → Fires when rendering a property page.
- `facet_wp_listing_page_load` → Fires when rendering a listing page.

Use these hooks to enqueue JavaScript files dynamically.

### **How to Enqueue Scripts**
To load custom JavaScript for **property pages**, add:
```php
add_action( 'facet_wp_property_page_load', function( $template_path, $template_vars ) {
    wp_enqueue_script(
        'facet-wp-property-script',
        get_stylesheet_directory_uri() . '/assets/js/facet-wp-property.js',
        ['jquery'],
        filemtime( get_stylesheet_directory() . '/assets/js/facet-wp-property.js' ),
        true
    );
}, 10, 2 );
```

To load JavaScript for **listing pages**, use:
```php
add_action( 'facet_wp_listing_page_load', function( $template_path, $template_vars ) {
    wp_enqueue_script(
        'facet-wp-listing-script',
        get_stylesheet_directory_uri() . '/assets/js/facet-wp-listing.js',
        ['jquery'],
        filemtime( get_stylesheet_directory() . '/assets/js/facet-wp-listing.js' ),
        true
    );
}, 10, 2 );
```

---

## Latest Listings
If you need to get the latest listings data use:
```php
Facet_Wp_Remote_Data_Handler::get_latest_listings( posts_per_page: 12, paged: 1 );
```

---

## Current Listings
If you need to get the current listings data use:
```php
Facet_Wp_Remote_Data_Handler::get_current_listings( posts_per_page: 12, paged: 1 );
```

---

## Using with the ACF Plugin

You can use the **Advanced Custom Fields (ACF)** plugin’s **Post Object** field to display property data from a remote site.

### **How to Set Up**
1. Add an **ACF Post Object** field.
2. Set the **Post Type** to `property`.
3. Set **Return Format** to `Post ID`.
3. You will now be able to select property posts from the remote site.

### **Displaying Remote Property Data**
⚠ **Do not use the standard WordPress loop** to display this field, as it fetches data from the database and will not work for remote posts.

Instead, use the following functions:

- **Get multiple property listings:**
```php
sw_get_remote_site_properties( (array) $post_ids );
```
Returns an array of property listing details for the given post IDs.

- **Get single property listing:**
```php
sw_get_remote_site_property( (int) $post_id );
```
Retrieves all details for a specific property post from the remote site.

---

## JavaScript API

The plugin exposes a global helper `SwFacetWpUser` for interacting with custom REST API endpoints.

### Available Functions

| Function | Description |
|----------|-------------|
| `SwFacetWpUser.save_favorite_property(property_id)` | Save a property ID to the user's favorites. |
| `SwFacetWpUser.get_favorite_properties()` | Retrieve all favorite property IDs for the current user. |
| `SwFacetWpUser.remove_favorite_property(property_id)` | Remove a property ID from the user's favorites. |
| `SwFacetWpUser.save_search(title, url)` | Save a search with a custom title and URL (FacetWP filters encoded in the URL). |
| `SwFacetWpUser.get_saved_searches()` | Retrieve all saved searches for the current user. |
| `SwFacetWpUser.delete_saved_search(index)` | Delete a saved search by its index (based on array position). |

Each function returns a `Promise` that resolves to an object:

```
{
  success: true | false,
  data: {...},   // if success is true
  error: {...}   // if success is false
}
```

---

### Example Usage

```js
const res = await SwFacetWpUser.save_favorite_property(123456);

if (res.success) {
    console.log('Property saved!', res.data);
} else {
    console.error('Failed to save favorite:', res.error.message);
}
```

---

## Important Note
Although this plugin uses custom templates to display results, you **must add a listing** to the page (ideally using a shortcode).

You can use the default listing template that comes with the FacetWP plugin — while this template itself won’t be used (as it gets overridden by the plugin’s custom templates), it is still necessary to ensure that **FacetWP facets are displayed**.

If no listing template is present on the page, **FacetWP will not render any facets**, even if they have been added.

---
