• Licenca agencije: 2086
    SRB / EN / RU

Napredno pretraživanje

Dodatne opcije pretraživanja
Pronašli smo 0 rezultati. Pregled rezultata

/**

  • ============= ZMAJ NEKRETNINE – GLOBAL FUNKCIJE =============
  • Shortcode napredne pretrage + binder za query + ikonice + i18n + RU-fix
    */

/* ——————————————————————
i18n helper + registracija stringova za Polylang
——————————————————————- */
// i18n helper: SR = original, EN/RU = prevod ili fallback
if (!function_exists(‘zr_t’)) {
function zr_t($text, $fallback = ”) {

// ✅ Ako je aktivni jezik srpski → vrati original
if (function_exists('pll_current_language') && pll_current_language('slug') === 'hr') {
  return $text;
}

// ✅ Ako postoji Polylang prevod → koristi ga
if (function_exists('pll__')) {
  $translated = pll__($text);
  if ($translated !== $text && $translated !== '') {
    return $translated;
  }
}

// ✅ Ako nema prevoda → koristi fallback
if ($fallback !== '') {
  return $fallback;
}

// poslednja rezerva
return $text;

}
}
// 2) Registruj tekstove za prevođenje u Polylang (Languages → String translations)
add_action(‘init’, function () {
if (!function_exists(‘pll_register_string’)) { return; }

$group = ‘ZR Advanced Search’;
$strings = [
‘Prodaja / Iznajmljivanje’,
‘Vrsta nekretnine’,
‘Lokacija’,
‘Cena’,
‘Min’,
‘Max’,
‘Pretraži’,
‘Reset’,
‘Izaberi…’, // napomena: ovo je UNICODE elipsa (…)
‘— %s (ceo grad)’,
‘Detalji’,
‘Nema rezultata.’, // <= NOVO
];

foreach ($strings as $s) {
pll_register_string($s, $s, $group);
}
});
/* ——————————————————————
Polylang pomoćni argument za get_terms
——————————————————————- */
if (!function_exists(‘zr_get_lang_arg’)) {
function zr_get_lang_arg() {
if (function_exists(‘pll_current_language’)) {
return [‘lang’ => pll_current_language(‘slug’)];
}
return [];
}
}

/* ——————————————————————
UI: select bez hijerarhije (akcija, tip)
——————————————————————- */
if (!function_exists(‘zr_render_taxonomy_select_flat’)) {
function zr_render_taxonomy_select_flat($args) {
$defaults = [
‘taxonomy’ => ”,
‘label’ => ”,
‘name’ => ”,
‘id’ => ”,
‘placeholder’ => zr_t(‘Izaberi…’, ‘Select…’),
‘allow_empty’ => true,
‘class’ => ‘zr-select’,
];
$args = wp_parse_args($args, $defaults);
if (empty($args[‘taxonomy’]) || empty($args[‘name’]) || empty($args[‘id’])) return ”;

$term_args = array_merge([
  'taxonomy'   => $args['taxonomy'],
  'hide_empty' => false,
  'orderby'    => 'name',
  'order'      => 'ASC',
], zr_get_lang_arg());

$terms   = get_terms($term_args);
$current = isset($_GET[$args['name']]) ? sanitize_text_field(wp_unslash($_GET[$args['name']])) : '';

ob_start(); ?>
<div class="zr-field zr-field-<?php echo esc_attr($args['taxonomy']); ?>">
  <?php if ($args['label']): ?>
    <label for="<?php echo esc_attr($args['id']); ?>"><?php echo esc_html($args['label']); ?></label>
  <?php endif; ?>
  <select id="<?php echo esc_attr($args['id']); ?>" name="<?php echo esc_attr($args['name']); ?>" class="<?php echo esc_attr($args['class']); ?>">
    <?php if ($args['allow_empty']): ?>
      <option value=""><?php echo esc_html($args['placeholder']); ?></option>
    <?php endif; ?>
    <?php if (!is_wp_error($terms) && $terms): foreach ($terms as $t): ?>
      <option value="<?php echo esc_attr($t->slug); ?>" <?php selected($current, $t->slug); ?>>
        <?php echo esc_html($t->name); ?>
      </option>
    <?php endforeach; endif; ?>
  </select>
</div>
<?php
return ob_get_clean();

}
}

/* ——————————————————————
UI: Lokacija (grad/opština) hijerarhijski sa optgroup
——————————————————————- */
if (!function_exists(‘zr_render_taxonomy_select_city_hier’)) {
function zr_render_taxonomy_select_city_hier($args) {
$defaults = [
‘taxonomy’ => ‘property_city’,
‘label’ => zr_t(‘Lokacija’, ‘Location’),
‘name’ => ‘property_city’,
‘id’ => ‘zr_prop_city’,
‘placeholder’ => zr_t(‘Izaberi…’, ‘Select…’),
‘allow_empty’ => true,
‘class’ => ‘zr-select’,
];
$args = wp_parse_args($args, $defaults);

$current   = isset($_GET[$args['name']]) ? sanitize_text_field(wp_unslash($_GET[$args['name']])) : '';
$lang_part = zr_get_lang_arg();

$parents = get_terms(array_merge([
  'taxonomy'   => $args['taxonomy'],
  'hide_empty' => false,
  'parent'     => 0,
  'orderby'    => 'name',
  'order'      => 'ASC',
], $lang_part));

ob_start(); ?>
<div class="zr-field zr-field-<?php echo esc_attr($args['taxonomy']); ?>">
  <?php if ($args['label']): ?>
    <label for="<?php echo esc_attr($args['id']); ?>"><?php echo esc_html($args['label']); ?></label>
  <?php endif; ?>
  <select id="<?php echo esc_attr($args['id']); ?>" name="<?php echo esc_attr($args['name']); ?>" class="<?php echo esc_attr($args['class']); ?>">
    <?php if ($args['allow_empty']): ?>
      <option value=""><?php echo esc_html($args['placeholder']); ?></option>
    <?php endif; ?>
    <?php if (!is_wp_error($parents) && $parents): foreach ($parents as $parent): ?>
      <?php
      $children = get_terms(array_merge([
        'taxonomy'   => $args['taxonomy'],
        'hide_empty' => false,
        'parent'     => $parent->term_id,
        'orderby'    => 'name',
        'order'      => 'ASC',
      ], $lang_part));
      ?>
      <?php if (empty($children)): ?>
        <option value="<?php echo esc_attr($parent->slug); ?>" <?php selected($current, $parent->slug); ?>>
          <?php echo esc_html($parent->name); ?>
        </option>
      <?php else: ?>
        <optgroup label="<?php echo esc_attr($parent->name); ?>">
          <option value="<?php echo esc_attr($parent->slug); ?>" <?php selected($current, $parent->slug); ?>>
            <?php echo esc_html( sprintf( zr_t('— %s (ceo grad)', '— %s (entire city)'), $parent->name ) ); ?>
          </option>
          <?php foreach ($children as $child): ?>
            <option value="<?php echo esc_attr($child->slug); ?>" <?php selected($current, $child->slug); ?>>
              <?php echo esc_html('— ' . $child->name); ?>
            </option>
          <?php endforeach; ?>
        </optgroup>
      <?php endif; ?>
    <?php endforeach; endif; ?>
  </select>
</div>
<?php
return ob_get_clean();

}
}

/* ——————————————————————
SHORTCODE:

— forma uvek šalje na arhivu post-tipa
——————————————————————- */
if (!function_exists(‘zr_advanced_search_shortcode’)) {
function zr_advanced_search_shortcode() {
// šaljemo uvek na arhivu gde imamo naš template
$action_url = get_post_type_archive_link(‘estate_property’);

$v_pmin = isset($_GET['price_min']) ? sanitize_text_field(wp_unslash($_GET['price_min'])) : '';
$v_pmax = isset($_GET['price_max']) ? sanitize_text_field(wp_unslash($_GET['price_max'])) : '';

ob_start(); ?>
<form class="zr-advanced-search" method="get" action="<?php echo esc_url($action_url); ?>">
  <input type="hidden" name="post_type" value="estate_property" />
  <input type="hidden" name="zr_as" value="1" />

  <?php
  // 1) Prodaja / Iznajmljivanje
  echo zr_render_taxonomy_select_flat([
    'taxonomy'    => 'property_action_category',
    'label'       => zr_t('Prodaja / Iznajmljivanje', 'Sale / Rent'),
    'name'        => 'property_action_category',
    'id'          => 'zr_prop_action',
    'placeholder' => zr_t('Izaberi…', 'Select…'),
  ]);

  // 2) Vrsta nekretnine
  echo zr_render_taxonomy_select_flat([
    'taxonomy'    => 'property_category',
    'label'       => zr_t('Vrsta nekretnine', 'Property Type'),
    'name'        => 'property_category',
    'id'          => 'zr_prop_category',
    'placeholder' => zr_t('Izaberi…', 'Select…'),
  ]);

  // 3) Lokacija — hijerarhijski
  echo zr_render_taxonomy_select_city_hier([
    'taxonomy'    => 'property_city',
    'label'       => zr_t('Lokacija', 'Location'),
    'name'        => 'property_city',
    'id'          => 'zr_prop_city',
    'placeholder' => zr_t('Izaberi…', 'Select…'),
  ]);
  ?>

  <!-- 4) Cena -->
  <div class="zr-field zr-field-price">
    <label><?php echo esc_html( zr_t('Cena', 'Price') ); ?></label>
    <div class="zr-price-wrap">
      <input type="text" inputmode="numeric" pattern="[0-9]*" name="price_min" id="zr_price_min"
             value="<?php echo esc_attr($v_pmin); ?>"
             placeholder="<?php echo esc_attr( zr_t('Min', 'Min') ); ?>" class="zr-input" />
      <span class="zr-price-sep">–</span>
      <input type="text" inputmode="numeric" pattern="[0-9]*" name="price_max" id="zr_price_max"
             value="<?php echo esc_attr($v_pmax); ?>"
             placeholder="<?php echo esc_attr( zr_t('Max', 'Max') ); ?>" class="zr-input" />
    </div>
  </div>

  <div class="zr-actions">
    <button type="submit" class="zr-btn zr-btn-primary"><?php echo esc_html( zr_t('Pretraži', 'Search') ); ?></button>
    <button type="button" class="zr-btn zr-btn-reset" id="zr_reset_btn"><?php echo esc_html( zr_t('Reset', 'Reset') ); ?></button>
  </div>
</form>

<style>
  :root{ --zr-brand:#bf9b5f; --zr-brand-fore:#fff; --zr-border:#e2e2e8; }
  .zr-advanced-search{
    display:grid; gap:12px;
    grid-template-columns: repeat(4, minmax(180px,1fr));
    align-items:end;
  }
  @media (max-width: 900px){ .zr-advanced-search{ grid-template-columns: repeat(2, minmax(160px,1fr)); } }
  @media (max-width: 640px){ .zr-advanced-search{ grid-template-columns: 1fr; } }

  .zr-field label{ display:block; font-weight:600; font-size:13px; margin-bottom:6px; color:#222; }
  .zr-select, .zr-input, .zr-btn{
    width:100%; padding:10px 12px; border-radius:10px; border:1px solid var(--zr-border); background:#fff; min-height:42px;
  }
  .zr-field-price .zr-price-wrap{ display:flex; align-items:center; gap:8px; }
  .zr-field-price .zr-price-sep{ padding:0 2px; opacity:.65; }

  .zr-actions{ grid-column: 1 / -1; display:flex; gap:10px; }
  .zr-btn{ cursor:pointer; font-weight:700; }
  .zr-btn-primary{ background:var(--zr-brand); color:var(--zr-brand-fore); border-color:var(--zr-brand); }
  .zr-btn-primary:hover{ filter:brightness(.95); }
  .zr-btn-reset{ background:#fff; color:var(--zr-brand); border-color:var(--zr-brand); }
  .zr-btn-reset:hover{ background:#fff8f0; }

  .zr-select optgroup{ font-weight:700; color:#111; }
  .zr-select optgroup option{ font-weight:400; }
</style>

<script>
  (function(){
    var btn = document.getElementById('zr_reset_btn');
    if(!btn) return;
    btn.addEventListener('click', function(){
      window.location.href = "<?php echo esc_js($action_url); ?>";
    });
  })();
</script>
<?php
return ob_get_clean();

}
add_shortcode(‘zr_advanced_search’, ‘zr_advanced_search_shortcode’);
}

/* ——————————————————————
Clean price helper
——————————————————————- */
if (!function_exists(‘zr_clean_price’)) {
function zr_clean_price($val) {
$val = str_replace([‘.’, ‘,’], ”, (string)$val);
return (” === $val) ? ” : (string)absint($val);
}
}

/* ===========================================================

  • ZR BINDER — primeni filtere na glavni upit (robustan za RU)
  • – radi sa term_id, slug ili imenom (i duplo enkodiranim RU slugovima)
  • – podržava price_min / price_max preko više meta ključeva
  • – forsira aktivni jezik (Polylang)
  • =========================================================== */
    if (!function_exists(‘zr_bind_property_filters’)) {
    function zr_bind_property_filters(\WP_Query $q) {
    if (is_admin() || !$q->is_main_query()) return; // važi samo kad smo na našoj arhivi / listingu
    $is_estate = (isset($_GET[‘post_type’]) && $_GET[‘post_type’] === ‘estate_property’) || isset($_GET[‘zr_as’]);
    if (!$is_estate) return; $q->set(‘post_type’, ‘estate_property’); // — helper: bezbedno čišćenje cene (fallback ako nema globalne funkcije) —
    $clean_price = function($val) {
    $val = (string)$val;
    $val = str_replace([‘.’, ‘,’,’ ‘], ”, $val);
    return ($val === ”) ? ” : (string)absint($val);
    }; // — helper: agresivno dekodiranje i mapiranje na term_id —
    $resolve_term_clause = function(string $taxonomy, string $raw) {
    // 1) agresivno dekodiranje (skidaj %25 → % → UTF-8 više puta)
    $val = trim($raw);
    for ($i = 0; $i < 5; $i++) {
    $dec = rawurldecode($val);
    if ($dec === $val) break;
    $val = $dec;
    }
    $val = str_replace(‘+’, ‘ ‘, $val);
    $val = trim($val); // 2) ako je broj → term_id
    if ($val !== ” && ctype_digit($val)) {
    return [
    ‘taxonomy’ => $taxonomy,
    ‘field’ => ‘term_id’,
    ‘terms’ => [ (int)$val ],
    ];
    } // 3) probaj po slug-u
    $t = get_term_by(‘slug’, $val, $taxonomy);
    if ($t && !is_wp_error($t)) {
    return [
    ‘taxonomy’ => $taxonomy,
    ‘field’ => ‘term_id’,
    ‘terms’ => [ (int)$t->term_id ],
    ];
    } // 4) probaj po imenu (tačno poklapanje)
    $t = get_term_by(‘name’, $val, $taxonomy);
    if ($t && !is_wp_error($t)) {
    return [
    ‘taxonomy’ => $taxonomy,
    ‘field’ => ‘term_id’,
    ‘terms’ => [ (int)$t->term_id ],
    ];
    } // 5) tolerantno poređenje (case-insensitive) kroz sve termine aktivnog jezika
    $terms = get_terms([
    ‘taxonomy’ => $taxonomy,
    ‘hide_empty’ => false,
    ‘lang’ => function_exists(‘pll_current_language’) ? pll_current_language(‘slug’) : ”,
    ]);
    if (!is_wp_error($terms) && $terms) {
    $needle = function_exists(‘mb_strtolower’) ? mb_strtolower($val, ‘UTF-8’) : strtolower($val);
    foreach ($terms as $cand) {
    $cand_slug = function_exists(‘mb_strtolower’) ? mb_strtolower($cand->slug, ‘UTF-8’) : strtolower($cand->slug);
    $cand_name = function_exists(‘mb_strtolower’) ? mb_strtolower($cand->name, ‘UTF-8’) : strtolower($cand->name);
    if ($cand_slug === $needle || $cand_name === $needle) {
    return [
    ‘taxonomy’ => $taxonomy,
    ‘field’ => ‘term_id’,
    ‘terms’ => [ (int)$cand->term_id ],
    ];
    }
    }
    } // 6) poslednja rezerva — ipak vrati slug (ako ga tema negde specijalno obrađuje)
    return [
    ‘taxonomy’ => $taxonomy,
    ‘field’ => ‘slug’,
    ‘terms’ => [ $val ],
    ];
    }; // — taksonomije koje pratimo iz forme —
    $tax_query = [];
    $taxes = [‘property_action_category’,’property_category’,’property_city’]; foreach ($taxes as $tax) {
    if (!empty($_GET[$tax])) {
    $raw = sanitize_text_field( wp_unslash($_GET[$tax]) );
    $tax_query[] = $resolve_term_clause($tax, $raw);
    }
    } if ($tax_query) {
    if (count($tax_query) > 1) {
    $tax_query = array_merge([‘relation’ => ‘AND’], $tax_query);
    }
    $q->set(‘tax_query’, $tax_query);
    } // — jezik (Polylang) —
    if (function_exists(‘pll_current_language’)) {
    $q->set(‘lang’, pll_current_language(‘slug’));
    } // — cena (min / max) —
    $price_min = isset($_GET[‘price_min’]) ? $clean_price($_GET[‘price_min’]) : ”;
    $price_max = isset($_GET[‘price_max’]) ? $clean_price($_GET[‘price_max’]) : ”; if ($price_min !== ” || $price_max !== ”) {
    $price_keys = apply_filters(‘zr_property_price_keys’, [‘property_price’,’price’,’estate_price’,’_price’]);
    $meta_or = [‘relation’ => ‘OR’]; foreach ($price_keys as $k) {
    $clause = [‘key’ => $k, ‘type’ => ‘NUMERIC’];
    if ($price_min !== ” && $price_max !== ”) {
    $clause[‘value’] = [ (int)$price_min, (int)$price_max ];
    $clause[‘compare’] = ‘BETWEEN’;
    } elseif ($price_min !== ”) {
    $clause[‘value’] = (int)$price_min;
    $clause[‘compare’] = ‘>=’;
    } else {
    $clause[‘value’] = (int)$price_max;
    $clause[‘compare’] = ‘<=’;
    }
    $meta_or[] = $clause;
    } $q->set(‘meta_query’, [ $meta_or ]);
    }
    }
    add_action(‘pre_get_posts’, ‘zr_bind_property_filters’);
    }

/**

  • ZR — preusmeri taxonomy property_category + property_action_category + property_city
  • na našu arhivu sa našim filterom
    */
    add_action(‘template_redirect’, function () {
    if ( is_admin() ) return; if ( is_tax([‘property_category’,’property_action_category’,’property_city’]) ) { $tax_obj = get_queried_object(); if (!$tax_obj || empty($tax_obj->taxonomy) || empty($tax_obj->slug)) return; // gradimo naš URL sa GET parametrima $url = add_query_arg([ 'post_type' => 'estate_property', 'zr_as' => '1', $tax_obj->taxonomy => $tax_obj->slug, ], get_post_type_archive_link('estate_property')); wp_safe_redirect($url, 302); exit; }
    });

/* ===========================================================

  • ZR QUERY NORMALIZER — skini dupli encoding (%25) i očisti GET
  • – radi pre bidera; popravlja RU URL-e tipa %25d0%25…
  • =========================================================== */
    add_action(‘init’, function () {
    if (is_admin()) return; $keys = [‘property_action_category’,’property_category’,’property_city’]; foreach ($keys as $k) {
    if (!isset($_GET[$k])) continue; $raw = $_GET[$k]; // 1) skini slasheve koje WP ume da doda
    if (is_string($raw)) {
    $val = wp_unslash($raw);
    } else {
    // ako bi ikad stigao array (ne bi trebalo), preskoči
    continue;
    } // 2) agresivno dekodiranje: više puta rawurldecode (skida %25 → % → utf-8)
    for ($i = 0; $i < 5; $i++) {
    $dec = rawurldecode($val);
    if ($dec === $val) break;
    $val = $dec;
    } // 3) plus → space
    $val = str_replace(‘+’, ‘ ‘, $val); // 4) trim i sanitizacija (ostavi UTF-8 slova)
    $val = trim( wp_strip_all_tags( $val ) ); // 5) upiši nazad u superglobal da binder dobije čisto
    $_GET[$k] = $val;
    }
    }, 5);

/* ——————————————————————
GLOBALNE IKONICE (bed/bath/garage/area) + layout detalja
(rooms rešavamo posebnim inline SVG blokom ispod, da ne zavisi od media library)
——————————————————————- */
add_action(‘wp_head’, function () {
$icons = [
// rooms namerno ne koristimo ovde (biće inline SVG ispod)
‘bed’ => ‘https://zmaj-nekretnine.com/wp-content/uploads/2023/05/bed-1-5c727d-1-4-2-3-1.svg’,
‘bath’ => ‘https://zmaj-nekretnine.com/wp-content/uploads/2023/05/bath2-1-5C727D-4-2-3-1.svg’,
‘garage’ => ‘https://zmaj-nekretnine.com/wp-content/uploads/2023/05/garage.svg’,
‘area’ => ‘https://zmaj-nekretnine.com/wp-content/uploads/2023/05/area-1.svg’,
];
?>
‘); ?> ‘Sobe’, ‘Комната’ => ‘Sobe’, ‘Спальни’ => ‘Spavaće sobe’, ‘Спальня’ => ‘Spavaće sobe’, ‘Ванные комнаты’ => ‘Kupatila’, ‘Ванная комната’ => ‘Kupatila’, ‘Санузлы’ => ‘Kupatila’, ‘Гаражи’ => ‘Garaže’, ‘Гараж’ => ‘Garaže’, ‘Площадь’ => ‘Površina’, ‘м²’ => ‘m²’, ]; $ru_to_en = [ ‘Комнаты’ => ‘Rooms’, ‘Комната’ => ‘Rooms’, ‘Спальни’ => ‘Bedrooms’, ‘Спальня’ => ‘Bedrooms’, ‘Ванные комнаты’ => ‘Bathrooms’, ‘Ванная комната’ => ‘Bathrooms’, ‘Санузлы’ => ‘Bathrooms’, ‘Гаражи’ => ‘Garages’, ‘Гараж’ => ‘Garages’, ‘Площадь’ => ‘Area’, ‘м²’ => ‘m²’, ]; if ($lang === ‘hr’) { $html = strtr($html, $ru_to_hr); } elseif ($lang === ‘en’) { $html = strtr($html, $ru_to_en); } return $html; } add_action(‘template_redirect’, function () { if ( is_admin() ) return; // Ako postoji prevod aktivnog oglasa na aktivnom jeziku – preusmeri na njega if ( function_exists(‘pll_current_language’) && function_exists(‘pll_get_post’) && is_singular(‘estate_property’) ) { $current_lang = pll_current_language(‘slug’); $post_id = get_queried_object_id(); if ($post_id) { $target_id = pll_get_post($post_id, $current_lang); if ( $target_id && (int)$target_id !== (int)$post_id ) { wp_safe_redirect( get_permalink($target_id), 302 ); exit; } } } // RU→HR/EN zamena u letu za single if ( is_singular(‘estate_property’) ) { ob_start(‘zr_replace_labels_in_html’); } }, 9); /* —————————————————————— (Opcionalno) Ako znaš tačan meta ključ cene: ——————————————————————- */ /* add_filter(‘zr_property_price_keys’, function($keys){ return [‘property_price’]; // prilagodi nazivu meta ključa tvoje teme }); */ // === FORCE TRANSLATE “Detalji” NA LISTING KARTICAMA (archive/tax query) === function zr_archive_replace_labels_in_html($html){ if (!function_exists(‘pll_current_language’)) return $html; $lang = pll_current_language(‘slug’); // hvata više varijanti koje tema zna da ubaci $sr_variants = [ ‘Detalji’,’DETALJI’,’Detaljnije’,’DETALJNIJE’,’Vidi detalje’,’VIDI DETALJE’ ]; if ($lang === ‘en’) { $map = array_fill_keys($sr_variants, ‘Details’); return strtr($html, $map); } if ($lang === ‘ru’) { $map = array_fill_keys($sr_variants, ‘Подробнее’); return strtr($html, $map); } return $html; } add_action(‘template_redirect’, function () { if ( is_admin() ) return; // primeni na sve listing stranice za estate_property: $is_estate_listing = is_post_type_archive(‘estate_property’) || is_tax([‘property_action_category’,’property_category’,’property_city’]) || ( isset($_GET[‘zr_as’]) && !is_singular(‘estate_property’) ); if ( $is_estate_listing ) { ob_start(‘zr_archive_replace_labels_in_html’); } }, 11); //

add_shortcode(‘zr_property_list’, function($atts){ $a = shortcode_atts([ ‘action’ => ”, // slug ILI ime termina (mi ćemo pokušati oba) ‘action_id’ => ”, ‘category’ => ”, // slug ILI ime termina ‘category_id’ => ”, ‘city’ => ”, // slug ILI ime termina (opciono) ‘city_id’ => ”, ‘per_page’ => ’12’, ‘paginate’ => ‘1’, ‘debug’ => ‘0’, ], $atts, ‘zr_property_list’); $paged = max(1, get_query_var(‘paged’) ?: get_query_var(‘page’) ?: (isset($_GET[‘pg’]) ? absint($_GET[‘pg’]) : 1)); // helper: mapiraj ID iz osnovnog jezika na aktivni (Polylang) $map_term_id = function($id){ $id = absint($id); if (!$id) return 0; if (function_exists(‘pll_get_term’) && function_exists(‘pll_current_language’)) { $mapped = pll_get_term($id, pll_current_language(‘slug’)); if ($mapped) return $mapped; } return $id; }; // helper: pronađi term po slug-u, a ako nema — probaj po imenu $find_term = function($taxonomy, $val){ if ($val === ”) return 0; $term = get_term_by(‘slug’, $val, $taxonomy); if ($term && !is_wp_error($term)) return (int)$term->term_id; // probaj po imenu (npr. “Vile”, “Prodaja”) $term = get_term_by(‘name’, $val, $taxonomy); if ($term && !is_wp_error($term)) return (int)$term->term_id; return 0; }; $tax_query = []; $debug_info = []; // Akcija if ($a[‘action_id’] !== ”) { $tid = $map_term_id($a[‘action_id’]); if ($tid) { $tax_query[] = [‘taxonomy’=>’property_action_category’,’field’=>’term_id’,’terms’=>[$tid]]; } $debug_info[‘action_id_mapped’] = $tid; } elseif ($a[‘action’] !== ”) { $tid = $find_term(‘property_action_category’, $a[‘action’]); if ($tid) { $tax_query[] = [‘taxonomy’=>’property_action_category’,’field’=>’term_id’,’terms’=>[$tid]]; } $debug_info[‘action_found’] = $tid; } // Kategorija (vrsta) if ($a[‘category_id’] !== ”) { $tid = $map_term_id($a[‘category_id’]); if ($tid) { $tax_query[] = [‘taxonomy’=>’property_category’,’field’=>’term_id’,’terms’=>[$tid]]; } $debug_info[‘category_id_mapped’] = $tid; } elseif ($a[‘category’] !== ”) { $tid = $find_term(‘property_category’, $a[‘category’]); if ($tid) { $tax_query[] = [‘taxonomy’=>’property_category’,’field’=>’term_id’,’terms’=>[$tid]]; } $debug_info[‘category_found’] = $tid; } // Grad (opciono) if ($a[‘city_id’] !== ”) { $tid = $map_term_id($a[‘city_id’]); if ($tid) { $tax_query[] = [‘taxonomy’=>’property_city’,’field’=>’term_id’,’terms’=>[$tid]]; } $debug_info[‘city_id_mapped’] = $tid; } elseif ($a[‘city’] !== ”) { $tid = $find_term(‘property_city’, $a[‘city’]); if ($tid) { $tax_query[] = [‘taxonomy’=>’property_city’,’field’=>’term_id’,’terms’=>[$tid]]; } $debug_info[‘city_found’] = $tid; } if (count($tax_query) > 1) { $tax_query = array_merge([‘relation’=>’AND’], $tax_query); } $qargs = [ ‘post_type’ => ‘estate_property’, ‘post_status’ => ‘publish’, ‘posts_per_page’ => (int)$a[‘per_page’], ‘paged’ => $paged, ‘orderby’ => ‘date’, ‘order’ => ‘DESC’, ‘tax_query’ => $tax_query ?: [], ]; if (function_exists(‘pll_current_language’)) { $qargs[‘lang’] = pll_current_language(‘slug’); } $q = new WP_Query($qargs); ob_start(); // DEBUG panel (samo admin i ako debug=”1″) if ($a[‘debug’] === ‘1’ && current_user_can(‘manage_options’)) { echo ‘

';
    echo "DEBUG zr_property_list\n\nARGS:\n"; print_r($a);
    echo "\nTerm map:\n"; print_r($debug_info);
    echo "\nWP_Query args:\n"; print_r($qargs);
    echo "\nFound posts: ".$q->found_posts."\n";
    echo "

“; } if ($q->have_posts()): ?>

have_posts()): $q->the_post(); $pid = get_the_ID(); $perma = get_permalink($pid); $price = get_post_meta($pid, ‘property_price’, true); if ($price===”) { $price = get_post_meta($pid, ‘price’, true); } $price = $price!==” ? number_format_i18n((float)$price, 0).’ €’ : ”; $get_meta = function($keys){ foreach ((array)$keys as $k) { $v = get_post_meta(get_the_ID(), $k, true); if ($v!==” && $v!==null) return $v; } return ”; }; $rooms = $get_meta([‘property_rooms’,’rooms’,’estate_rooms’,’prop_rooms’,’room_no’,’wpestate_rooms’,’property_no_of_rooms’,’_rooms’,’no_of_rooms’,’no_rooms’,’plan_rooms’]); $bedrooms = $get_meta([‘property_bedrooms’,’bedrooms’,’estate_bedrooms’,’prop_bedrooms’,’_bedrooms’]); $baths = $get_meta([‘property_bathrooms’,’bathrooms’,’estate_bathrooms’,’prop_bathrooms’,’_bathrooms’,’sanitary’]); $garages = $get_meta([‘property_garage’,’garages’,’garage’,’estate_garage’,’_garage’]); $area = $get_meta([‘property_size’,’property_area’,’estate_size’,’_area’,’_size’,’size’]); if ($area && is_numeric($area)) { $area = intval($area).’ m²’; } ?> itemscope itemtype=”https://schema.org/Place”>

‘async’,’loading’=>’lazy’]); } ?>

 

‘names’]); echo esc_html( implode(‘, ‘, $city_terms ?: []) ); ?>

 

$q->max_num_pages,’current’=>$paged]); ?>

<style>
  .zr-grid{ display:grid; gap:16px; grid-template-columns:repeat(4,minmax(0,1fr)); }
  @media (max-width:1100px){ .zr-grid{ grid-template-columns:repeat(3,minmax(0,1fr)); } }
  @media (max-width:800px){ .zr-grid{ grid-template-columns:repeat(2,minmax(0,1fr)); } }
  @media (max-width:560px){ .zr-grid{ grid-template-columns:1fr; } }
  .zr-btn.zr-btn-primary{ background:#bf9b5f; color:#fff; border:1px solid #bf9b5f; padding:10px 14px; border-radius:10px; font-weight:700; display:inline-block; }
  .zr-btn.zr-btn-primary:hover{ filter:brightness(.95); }
</style>

<?php
else:
echo ‘

‘.esc_html( zr_t(‘Nema rezultata.’,’No results.’) ).”;
endif;

wp_reset_postdata();
return ob_get_clean();
});

// Stil za ZR kartice (veća slika, elegantniji card, manje dugme)
add_action(‘wp_head’, function(){ ?>

<?php });

// ZR: “Nema rezultata.” hard patch — zameni po jeziku, bez obzira odakle tekst dolazi
add_action(‘template_redirect’, function () {
if (is_admin()) return;

// startuj output buffer i zameni u letu
ob_start(function ($html) {
if (!function_exists(‘pll_current_language’)) return $html;

$lang = pll_current_language('slug');

// šta tražimo
$needles = [
  'Nema rezultata.',
  'Nema rezultata',   // bez tačke (neke teme ovako)
];

if ($lang === 'en') {
  $repls = [
    'No results.',
    'No results',
  ];
  return str_replace($needles, $repls, $html);
}

if ($lang === 'ru') {
  $repls = [
    'Нет результатов.',
    'Нет результатов',
  ];
  return str_replace($needles, $repls, $html);
}

// ostali jezici (sr/hr) ostaju isti
return $html;

});
}, 8);

/* ===========================================================

  • ZR HARD SAFE MODE — stop redirect loops for our listing
  • – no canonical redirects whenever our filter GETs are present
  • – NO taxonomy -> archive redirects (we disable them for now)
  • =========================================================== */

/* 1) Helper: da li je ovo naš listing zahtev? */
function zr_is_zr_listing_request() {
return (
(isset($_GET[‘zr_as’]) && $_GET[‘zr_as’] == ‘1’) ||
isset($_GET[‘property_action_category’]) ||
isset($_GET[‘property_category’]) ||
isset($_GET[‘property_city’])
);
}

/* 2) Isključi canonical redirekcije čim vidimo naše GET parametre */
add_filter(‘redirect_canonical’, function ($redirect, $requested) {
if ( zr_is_zr_listing_request() ) {
return false;
}
return $redirect;
}, 1000, 2);

/* 3) Dodatno: ukloni core canonical u template_redirect za svaki slučaj + SEO canonical */
add_action(‘template_redirect’, function () {
if ( zr_is_zr_listing_request() ) {
// core canonical
remove_action(‘template_redirect’, ‘redirect_canonical’);
// Yoast
if (has_filter(‘wpseo_canonical’)) {
add_filter(‘wpseo_canonical’, ‘__return_false’, 99);
}
// RankMath
if (has_filter(‘rank_math/frontend/canonical’)) {
add_filter(‘rank_math/frontend/canonical’, ‘__return_empty_string’, 99);
}
}
}, 0);

/* 4) (Namerno) NE radimo više taxonomy -> archive preusmerenje ovde.

  • Pusti taxonomy URL-ove da budu kakvi jesu – korisnike usmeravaj iz MENIJA / LINKOVA na našu /property/ arhivu sa GET parametrima.
    */

    Usporedi nekretnine