<?php
/**
* Internal module: Property Search.
* Loaded by onOffice Elementor Bridge.
*/
defined('ABSPATH') || exit;
final class FRESH_OnOffice_Property_Search {
const CPT = 'fresh_immobilie';
public function __construct() {
add_shortcode('oo_property_search', [$this, 'shortcode']);
add_action('pre_get_posts', [$this, 'filter_archive_query']);
}
private function get_term_options(string $taxonomy): array {
if (!taxonomy_exists($taxonomy)) return [];
$terms = get_terms([
'taxonomy' => $taxonomy,
'hide_empty' => true,
'orderby' => 'name',
'order' => 'ASC',
]);
return is_wp_error($terms) ? [] : $terms;
}
private function selected(string $key): string {
return isset($_GET[$key]) ? sanitize_text_field(wp_unslash($_GET[$key])) : '';
}
public function shortcode($atts = []): string {
$atts = shortcode_atts([
'action' => get_post_type_archive_link(self::CPT),
'class' => '',
], $atts, 'oo_property_search');
if (!$atts['action']) $atts['action'] = home_url('/immobilien/');
$marketing = $this->selected('vermarktung');
$object = $this->selected('objektart');
$location = $this->selected('ort');
$price_max = $this->selected('preis_max');
$area_min = $this->selected('flaeche_min');
$rooms_min = $this->selected('zimmer_min');
$keyword = $this->selected('suchbegriff');
$object_terms = $this->get_term_options('immo_objektart');
$location_terms = $this->get_term_options('immo_ort');
ob_start();
?>
<form class="fresh-oo-search <?php echo esc_attr($atts['class']); ?>" method="get" action="<?php echo esc_url($atts['action']); ?>">
<div class="fresh-oo-search__tabs" role="group" aria-label="Vermarktungsart">
<label class="fresh-oo-search__tab <?php echo ($marketing === '' || $marketing === 'kauf') ? 'is-active' : ''; ?>">
<input type="radio" name="vermarktung" value="kauf" <?php checked($marketing === '' || $marketing === 'kauf'); ?>>
<span>Kaufen</span>
</label>
<label class="fresh-oo-search__tab <?php echo $marketing === 'miete' ? 'is-active' : ''; ?>">
<input type="radio" name="vermarktung" value="miete" <?php checked($marketing, 'miete'); ?>>
<span>Mieten</span>
</label>
</div>
<div class="fresh-oo-search__grid">
<label class="fresh-oo-field">
<span>Objektart</span>
<select name="objektart">
<option value="">Alle Objektarten</option>
<?php foreach ($object_terms as $term): ?>
<option value="<?php echo esc_attr($term->slug); ?>" <?php selected($object, $term->slug); ?>><?php echo esc_html($term->name); ?></option>
<?php endforeach; ?>
</select>
</label>
<label class="fresh-oo-field">
<span>Ort / Stadtteil</span>
<select name="ort">
<option value="">Berlin – alle Stadtteile</option>
<?php foreach ($location_terms as $term): ?>
<option value="<?php echo esc_attr($term->slug); ?>" <?php selected($location, $term->slug); ?>><?php echo esc_html($term->name); ?></option>
<?php endforeach; ?>
</select>
</label>
<label class="fresh-oo-field">
<span>Preis bis</span>
<select name="preis_max">
<option value="">Beliebig</option>
<?php foreach ([250000,500000,750000,1000000,1500000,2000000,3000000,5000000] as $price): ?>
<option value="<?php echo esc_attr($price); ?>" <?php selected($price_max, (string)$price); ?>><?php echo esc_html(number_format_i18n($price, 0)); ?> €</option>
<?php endforeach; ?>
</select>
</label>
<label class="fresh-oo-field">
<span>Wohnfläche ab</span>
<select name="flaeche_min">
<option value="">Beliebig</option>
<?php foreach ([40,60,80,100,120,150,200] as $area): ?>
<option value="<?php echo esc_attr($area); ?>" <?php selected($area_min, (string)$area); ?>>ab <?php echo esc_html($area); ?> m²</option>
<?php endforeach; ?>
</select>
</label>
<label class="fresh-oo-field">
<span>Zimmer</span>
<select name="zimmer_min">
<option value="">Beliebig</option>
<?php foreach ([1,2,3,4,5,6] as $rooms): ?>
<option value="<?php echo esc_attr($rooms); ?>" <?php selected($rooms_min, (string)$rooms); ?>>ab <?php echo esc_html($rooms); ?></option>
<?php endforeach; ?>
</select>
</label>
<label class="fresh-oo-field fresh-oo-field--keyword">
<span>Suchbegriff</span>
<input type="search" name="suchbegriff" value="<?php echo esc_attr($keyword); ?>" placeholder="z. B. Altbau, Balkon …">
</label>
<button class="fresh-oo-search__submit" type="submit">Immobilien finden <span aria-hidden="true">→</span></button>
</div>
</form>
<style>
.fresh-oo-search{--oo-accent:#b8945d;--oo-dark:#171717;--oo-border:#ddd8cf;background:none!important;box-shadow:0 18px 55px rgba(0,0,0,.14);font-family:inherit;color:var(--oo-dark);width:100%;}
.fresh-oo-search *{box-sizing:border-box}
.fresh-oo-search__tabs{display:flex;border-bottom:1px solid var(--oo-border)}
.fresh-oo-search__tab{position:relative;margin:0;cursor:pointer}
.fresh-oo-search__tab input{position:absolute;opacity:0;pointer-events:none}
.fresh-oo-search__tab span{display:block;padding:17px 30px;background:#f2f0ec;transition:.2s ease}
.fresh-oo-search__tab.is-active span,.fresh-oo-search__tab:has(input:checked) span{background:#fff;color:#8a693c}
.fresh-oo-search__grid{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:14px;padding:20px;background:rgba(255,255,255,.96)}
.fresh-oo-field{display:flex;flex-direction:column;gap:7px;grid-column:span 2;font-size:12px;font-weight:600;letter-spacing:.01em}
.fresh-oo-field--keyword{grid-column:span 2}
.fresh-oo-field select,.fresh-oo-field input{width:100%;height:48px;border:1px solid var(--oo-border);background:#fff;padding:0 14px;border-radius:0;font:inherit;font-size:14px;color:var(--oo-dark);outline:none}
.fresh-oo-field select:focus,.fresh-oo-field input:focus{border-color:var(--oo-accent);box-shadow:0 0 0 1px var(--oo-accent)}
.fresh-oo-search__submit{grid-column:span 4!important;align-self:end;height:48px;border:0;background:var(--oo-dark);color:#fff;padding:0 22px;text-transform:uppercase;letter-spacing:.06em;font-size:12px;font-weight:700;cursor:pointer;transition:.2s ease}
.fresh-oo-search__submit:hover{background:var(--oo-accent)}
@media(max-width:1024px){.fresh-oo-field,.fresh-oo-field--keyword,.fresh-oo-search__submit{grid-column:span 4}}
@media(max-width:767px){.fresh-oo-search__tab{flex:1;text-align:center}.fresh-oo-search__tab span{padding:14px 18px}.fresh-oo-search__grid{grid-template-columns:1fr;padding:16px}.fresh-oo-field,.fresh-oo-field--keyword,.fresh-oo-search__submit{grid-column:1}.fresh-oo-search__submit{width:100%}}
</style>
<script>
document.addEventListener('change', function(e){
if(e.target.matches('.fresh-oo-search__tab input')){
e.target.closest('.fresh-oo-search__tabs').querySelectorAll('.fresh-oo-search__tab').forEach(function(tab){tab.classList.remove('is-active')});
e.target.closest('.fresh-oo-search__tab').classList.add('is-active');
}
});
</script>
<?php
return ob_get_clean();
}
public function filter_archive_query(WP_Query $query): void {
if (is_admin() || !$query->is_main_query()) return;
if (!$query->is_post_type_archive(self::CPT)) return;
$tax_query = [];
$meta_query = [];
$object = $this->selected('objektart');
$location = $this->selected('ort');
$marketing = $this->selected('vermarktung');
$price_max = absint($this->selected('preis_max'));
$area_min = (float)str_replace(',', '.', $this->selected('flaeche_min'));
$rooms_min = (float)str_replace(',', '.', $this->selected('zimmer_min'));
$keyword = $this->selected('suchbegriff');
if ($object) $tax_query[] = ['taxonomy'=>'immo_objektart','field'=>'slug','terms'=>[$object]];
if ($location) $tax_query[] = ['taxonomy'=>'immo_ort','field'=>'slug','terms'=>[$location]];
if ($marketing) {
$terms = get_terms(['taxonomy'=>'immo_vermarktungsart','hide_empty'=>false]);
if (!is_wp_error($terms)) {
$wanted = [];
foreach ($terms as $term) {
$haystack = strtolower($term->slug . ' ' . $term->name);
if ($marketing === 'kauf' && (str_contains($haystack,'kauf') || str_contains($haystack,'verkauf'))) $wanted[] = $term->term_id;
if ($marketing === 'miete' && (str_contains($haystack,'miet') || str_contains($haystack,'vermiet'))) $wanted[] = $term->term_id;
}
if ($wanted) $tax_query[] = ['taxonomy'=>'immo_vermarktungsart','field'=>'term_id','terms'=>$wanted];
}
}
if ($price_max) {
$price_keys = $marketing === 'miete' ? ['oo_kaltmiete','oo_warmmiete'] : ['oo_kaufpreis'];
$or = ['relation'=>'OR'];
foreach ($price_keys as $key) $or[] = ['key'=>$key,'value'=>$price_max,'compare'=>'<=','type'=>'NUMERIC'];
$meta_query[] = $or;
}
if ($area_min > 0) $meta_query[] = ['key'=>'oo_wohnflaeche','value'=>$area_min,'compare'=>'>=','type'=>'NUMERIC'];
if ($rooms_min > 0) $meta_query[] = ['key'=>'oo_anzahl_zimmer','value'=>$rooms_min,'compare'=>'>=','type'=>'NUMERIC'];
if ($tax_query) {
if (count($tax_query) > 1) $tax_query = array_merge(['relation'=>'AND'], $tax_query);
$query->set('tax_query', $tax_query);
}
if ($meta_query) {
if (count($meta_query) > 1) $meta_query = array_merge(['relation'=>'AND'], $meta_query);
$query->set('meta_query', $meta_query);
}
if ($keyword) $query->set('s', $keyword);
$query->set('post_status', 'publish');
}
}
new FRESH_OnOffice_Property_Search();