AlkantarClanX12
| Current Path : /www/capitalgmcbuickregina_830/public/wp-content/themes/lbx-egypt/app/ |
| Current File : /www/capitalgmcbuickregina_830/public/wp-content/themes/lbx-egypt/app/helpers.php |
<?php
use Illuminate\Support\Facades\Log;
/**
* Theme helpers.
* Theme helpers are in the global namespace for blade usage
*/
// namespace App;
// add_filter('acorn/throw_error_exception', function ($e) {
// dd($e);
// }, 1, 999);
// Since we're using namespaces, the natual function names
// are no longer sufficient. Instead we need to use "App\\function_name".
// Since this is a pain, we'll use wrapper functions.
//
// These functions are called over the native functions, while in our namespace.
// To call a base function, you can override with \function_name.
//
// e.g. \add_action('init', 'App\function_name')
// function add_action($name, $callable, $priority = 10, $args = 1) {
// return is_string($callable) && 0 !== strpos($callable, __NAMESPACE__)
// ? \add_action($name, __NAMESPACE__."\\$callable", $priority, $args)
// : \add_action($name, $callable, $priority, $args);
// }
if (!function_exists('add_actions')) {
function add_actions($names, $callable, $priority = 10, $args = 1)
{
collect($names)->each(function ($name) use ($callable, $priority, $args) {
add_action($name, $callable, $priority, $args);
});
}
}
if (!function_exists('add_filters')) {
function add_filters($names, $callable, $priority = 10, $args = 1)
{
collect($names)->each(function ($name) use ($callable, $priority, $args) {
add_filter($name, $callable, $priority, $args);
});
}
}
if (!function_exists('config')) {
function config($string)
{
return \Roots\config($string);
}
}
if (!function_exists('env')) {
function env($string)
{
return \Roots\env($string);
}
}
//THEME LOCALIZATION
load_theme_textdomain('leadbox', get_template_directory() . '/languages');
// Adding Leadbox Patterns
//Removing default patterns
remove_theme_support('core-block-patterns');
$lbSettings = get_leadbox_settings();
$showroom_page = get_page_by_title(ucfirst($lbSettings['manufacturer']) . " Showroom");
if ($showroom_page === null && $lbSettings['manufacturer']) {
$sr_post = array(
'post_title' => wp_strip_all_tags(ucfirst($lbSettings['manufacturer']) . " Showroom"),
'post_content' => "<!-- wp:sage/showroom /-->",
'post_status' => 'draft',
'post_author' => 1,
'post_category' => array(1),
'post_type' => 'page'
);
// Insert the Showroom page into the database
wp_insert_post($sr_post);
// Create the Showroom Model page
$sr_model_post = array(
'post_title' => wp_strip_all_tags("Model"),
'post_content' => "",
'post_status' => 'publish',
'post_author' => 1,
'post_category' => array(1),
'post_type' => 'page'
);
// Insert the Showroom Model page into the database
wp_insert_post($sr_model_post);
$showroom_model_page = get_page_by_title("Model");
update_post_meta($showroom_model_page->ID, '_wp_page_template', 'template-showroom-model.blade.php');
}
//Including our patterns
//Adding Patterns Categories
add_action('current_screen', function ($screen) {
if ( ! is_admin() || ! $screen ) return;
$is_block_editor = method_exists($screen, 'is_block_editor') ? $screen->is_block_editor() : false;
if ( ! $is_block_editor ) return;
// Rutas locales en el TEMA PADRE
$parent_dir = trailingslashit(get_template_directory());
$cat_path = $parent_dir . 'assets/patterns/categories-egypt.json';
$pat_path = $parent_dir . 'assets/patterns/patterns-egypt.json';
// ----- Categorías
$cats = get_transient('lb_patterns_categories_egypt');
if ($cats === false) {
if (function_exists('wp_json_file_decode') && file_exists($cat_path)) {
$cats = wp_json_file_decode($cat_path, ['associative' => false]) ?: [];
} else {
$json_cat = @file_get_contents($cat_path);
$cats = $json_cat ? json_decode($json_cat) : [];
}
set_transient('lb_patterns_categories_egypt', $cats, HOUR_IN_SECONDS * 12);
}
if (!empty($cats)) {
foreach ($cats as $category) {
if (!empty($category->name) && !empty($category->label)) {
register_block_pattern_category(
$category->name,
['label' => _x($category->label, 'Block pattern category', 'textdomain')]
);
}
}
}
// ----- Patrones
$patterns = get_transient('lb_patterns_list_egypt');
if ($patterns === false) {
if (function_exists('wp_json_file_decode') && file_exists($pat_path)) {
$patterns = wp_json_file_decode($pat_path, ['associative' => false]) ?: [];
} else {
$json_pat = @file_get_contents($pat_path);
$patterns = $json_pat ? json_decode($json_pat) : [];
}
set_transient('lb_patterns_list_egypt', $patterns, HOUR_IN_SECONDS * 12);
}
if (!empty($patterns)) {
foreach ($patterns as $pattern) {
if (empty($pattern->name) || empty($pattern->title) || empty($pattern->content) || empty($pattern->category)) {
continue;
}
register_block_pattern(
$pattern->name,
[
'title' => __($pattern->title, 'textdomain'),
'description' => _x($pattern->description ?? '', '', 'textdomain'),
'content' => str_replace("'", '"', $pattern->content),
'categories' => [$pattern->category],
]
);
}
}
});
/* END PATTERNS */
// Global variable of the VDP data for Yoast and SEO functions
global $vdp_vehicle_data;
if (preg_match('[view|vue|form|forme]', $_SERVER["REQUEST_URI"])) {
$vdp_url = explode("-", $_SERVER["REQUEST_URI"]);
if (isset($_SERVER["QUERY_STRING"]) && strlen($_SERVER["QUERY_STRING"]) > 0) {
$vdp_url[count($vdp_url) - 1] = str_replace("?" . $_SERVER["QUERY_STRING"], "", $vdp_url[count($vdp_url) - 1]);
}
$vdp_vehicle_data = get_vehicle_by_id(str_replace("/", "", $vdp_url[count($vdp_url) - 1]));
}
function get_dealer_hours_additional()
{
return get_option('dealer-settings-hours-options');
}
function get_custom_finance_array()
{
return get_option('dealer-settings-used-finance-custom-options');
}
function get_dealer_hours()
{
$hours = get_option('dealer-settings-hours-options');
$days = collect(['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday']);
$types = collect(['sale', 'service', 'parts', 'additionalone', 'additionaltwo', 'additionalthree']);
if (isset($hours) && ($hours != false)) {
return collect($hours)->groupBy(function ($_, $key) use ($types) {
return $types->first(function ($v) use ($key) {
return strpos($key, $v) === 0;
});
}, $preserve_keys = true)->map(function ($hours, $type) use ($days) {
return $days->mapWithKeys(function ($day) use ($hours, $type) {
$string = $hours->get("{$type}_hours_{$day}_closed", $default = false)
? 'Closed'
: sprintf(
"%s - %s",
$hours->get("{$type}_hours_{$day}_start", ''),
$hours->get("{$type}_hours_{$day}_end", '')
);
return [ucfirst($day) => $string];
});
});
} else {
$result["sale"] = array();
$result["service"] = array();
$result["parts"] = array();
return $result;
}
}
function get_dealer_contact()
{
return get_option('dealer-settings-contact-options');
}
/**
* Normaliza una coordenada (latitud/longitud) a un string decimal limpio, con
* un máximo de 6 decimales y sin ceros sobrantes. Evita el artefacto de punto
* flotante (p. ej. 45.33 -> 45.329999999999998) que aparece al castear a float
* y serializar. Devuelve siempre string para que el JSON-LD sea estable en
* cualquier configuración de `serialize_precision`.
*
* @param mixed $value
* @return string Coordenada normalizada, o '' si no es numérica.
*/
function lbx_normalize_coordinate($value)
{
$value = trim((string) $value);
if ($value === '' || !is_numeric($value)) {
return '';
}
// number_format redondea de forma decimal (no binaria) a 6 decimales.
$formatted = number_format((float) $value, 6, '.', '');
$formatted = rtrim($formatted, '0'); // quita ceros finales: 45.330000 -> 45.33
$formatted = rtrim($formatted, '.'); // por si queda un punto suelto: 45. -> 45
return $formatted;
}
/**
* Serializa un array a JSON para un bloque <script type="application/ld+json">.
* Fuerza serialize_precision=-1 durante la serialización para que los números
* decimales (p. ej. coordenadas) usen su representación más corta y exacta, sin
* el artefacto de punto flotante, sea cual sea la configuración del servidor.
*
* @param mixed $data
* @return string|false
*/
function lbx_json_ld($data)
{
$previous = @ini_set('serialize_precision', '-1');
$json = wp_json_encode(
$data,
JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_PRETTY_PRINT
);
if ($previous !== false) {
@ini_set('serialize_precision', $previous);
}
return $json;
}
/**
* Elimina recursivamente las propiedades vacías ('' o null) de un schema y
* descarta los sub-objetos que quedan sin datos reales (solo con claves de
* metadata como @type o unitText).
*
* @param array $node
* @return array
*/
function lbx_schema_prune(array $node)
{
$meta = ['@context', '@type', 'unitText', 'priceCurrency'];
foreach ($node as $key => $value) {
if (is_array($value)) {
$value = lbx_schema_prune($value);
// Si solo sobreviven claves de metadata, el sub-objeto no aporta nada.
if (empty(array_diff(array_keys($value), $meta))) {
unset($node[$key]);
continue;
}
$node[$key] = $value;
continue;
}
if ($value === null || $value === '') {
unset($node[$key]);
}
}
return $node;
}
/**
* Convierte los horarios de un departamento (día => "start - end" | "Closed")
* en una lista de OpeningHoursSpecification. Los días cerrados o con rangos
* no parseables se OMITEN: un día ausente se interpreta como cerrado y evita
* la ambigüedad de un 00:00-00:00.
*
* @param iterable|mixed $dayRanges Formato de get_dealer_hours()['sale'|'service'|'parts'].
* @return array
*/
function lbx_opening_hours_schema($dayRanges)
{
$specs = [];
if (!is_iterable($dayRanges)) {
return $specs;
}
foreach ($dayRanges as $day => $range) {
$range = trim((string) $range);
if ($range === '' || strtolower($range) === 'closed') {
continue;
}
$parts = explode(' - ', $range);
if (count($parts) !== 2) {
continue;
}
$opens = strtotime(trim($parts[0]));
$closes = strtotime(trim($parts[1]));
if ($opens === false || $closes === false) {
continue;
}
$specs[] = [
'@type' => 'OpeningHoursSpecification',
'dayOfWeek' => $day,
'opens' => date('H:i', $opens),
'closes' => date('H:i', $closes),
];
}
return $specs;
}
/**
* Decide si el schema AutoDealer se emite en la página actual según el setting
* "Schema Scope" (Dealer Settings → Contact → Schema):
* - '' | 'all' (default): todas las páginas — variante SD "Suggested" y
* comportamiento histórico del theme.
* - 'required': solo homepage + las páginas listadas en schema_required_pages
* (slugs separados por comas; vacío = about-us y service) — el mínimo que
* exige SD como "Required".
*
* @return bool
*/
function lbx_autodealer_schema_in_scope()
{
$contact = get_dealer_contact();
$contact = is_array($contact) ? $contact : [];
if (trim((string) ($contact['schema_scope'] ?? '')) !== 'required') {
return true;
}
if (is_front_page()) {
return true;
}
$slugs = array_values(array_filter(array_map(
'trim',
explode(',', (string) ($contact['schema_required_pages'] ?? ''))
)));
if (empty($slugs)) {
$slugs = ['about-us', 'service'];
}
return is_page($slugs);
}
/**
* Construye el structured data AutoDealer + LocalBusiness del dealer para el
* <head> global (LBT-1510, Shift Digital AI-Readiness A6).
*
* Autocontenido: lee Dealer Settings / Leadbox Settings directamente, sin
* depender de variables inyectadas por composers a la vista. Devuelve el
* array ya podado (sin propiedades vacías); si el site no tiene ni el nombre
* del dealer configurado — o la página actual está fuera del Schema Scope
* configurado — devuelve [] y no se emite nada.
*
* @return array
*/
function lbx_autodealer_schema()
{
if (!lbx_autodealer_schema_in_scope()) {
return [];
}
$contact = get_dealer_contact();
$contact = is_array($contact) ? $contact : [];
$branding = get_dealer_branding();
$branding = is_array($branding) ? $branding : [];
$dealerName = trim((string) ($contact['dealer_name'] ?? ''));
$dealerUrl = trim((string) ($contact['dealer_url'] ?? ''));
// @id estable por entidad: el mismo IRI identifica al dealer en todas las
// páginas del site (y permite referenciarlo desde otros schemas).
$idBase = $dealerUrl !== '' ? $dealerUrl : home_url('/');
if (!preg_match('#^https?://#i', $idBase)) {
$idBase = 'https://' . ltrim($idBase, '/');
}
// Teléfonos por departamento: alimentan telephone (plano, para lectores
// legacy) y contactPoint (con contactType, para entity matching).
$phones = [
'sales' => trim((string) ($contact['sale_phone'] ?? '')),
'service' => trim((string) ($contact['service_phone'] ?? '')),
'parts' => trim((string) ($contact['parts_phone'] ?? '')),
];
$contactPoints = [];
foreach ($phones as $department => $phone) {
if ($phone === '') {
continue;
}
$contactPoints[] = [
'@type' => 'ContactPoint',
'contactType' => $department,
'telephone' => $phone,
];
}
// Marcas que vende el dealer: manufacturer principal + all_brands (lista
// separada por comas). Ambos son texto libre en Leadbox Settings, así que
// los valores todo-minúsculas se normalizan (acrónimos conocidos incluidos);
// los que ya traen mayúsculas se respetan tal cual.
$lbSettings = get_leadbox_settings();
$lbSettings = is_array($lbSettings) ? $lbSettings : [];
$acronyms = ['bmw' => 'BMW', 'gmc' => 'GMC', 'mini' => 'MINI', 'fiat' => 'FIAT', 'ram' => 'RAM'];
$brands = [];
$seenBrands = [];
$brandNames = array_merge(
[(string) ($lbSettings['manufacturer'] ?? '')],
explode(',', (string) ($lbSettings['all_brands'] ?? ''))
);
foreach ($brandNames as $brandName) {
$brandName = trim($brandName);
$brandKey = mb_strtolower($brandName);
if ($brandName === '' || isset($seenBrands[$brandKey])) {
continue;
}
$seenBrands[$brandKey] = true;
if ($brandName === $brandKey) {
$brandName = $acronyms[$brandKey] ?? ucwords($brandName);
}
$brands[] = [
'@type' => 'Brand',
'name' => $brandName,
];
}
// sameAs: perfiles sociales de Dealer Settings → Social Media.
$social = get_option('dealer-settings-socialmedia-options');
$social = is_array($social) ? $social : [];
$sameAs = [];
foreach ($social as $key => $socialUrl) {
if (substr((string) $key, -12) !== '_socialmedia') {
continue;
}
$socialUrl = trim((string) $socialUrl);
if ($socialUrl === '') {
continue;
}
if (!preg_match('#^https?://#i', $socialUrl)) {
$socialUrl = 'https://' . ltrim($socialUrl, '/');
}
// Descarta valores que no son URLs reales (p. ej. "FB" o "n/a"): el host
// debe tener al menos un punto.
$socialHost = parse_url($socialUrl, PHP_URL_HOST);
if (!is_string($socialHost) || strpos($socialHost, '.') === false) {
continue;
}
$sameAs[] = $socialUrl;
}
$sameAs = array_values(array_unique($sameAs));
$hours = get_dealer_hours();
$saleHours = lbx_opening_hours_schema($hours['sale'] ?? []);
$serviceHours = lbx_opening_hours_schema($hours['service'] ?? []);
$partsHours = lbx_opening_hours_schema($hours['parts'] ?? []);
// Departamentos como LocalBusiness anidados; solo se emiten si tienen
// alguna señal real (teléfono u horarios propios).
$departments = [];
if ($phones['service'] !== '' || !empty($serviceHours)) {
$departments[] = [
'@type' => 'AutoRepair',
'name' => trim($dealerName . ' Service'),
'telephone' => $phones['service'],
'openingHoursSpecification' => $serviceHours,
];
}
if ($phones['parts'] !== '' || !empty($partsHours)) {
$departments[] = [
'@type' => 'AutoPartsStore',
'name' => trim($dealerName . ' Parts'),
'telephone' => $phones['parts'],
'openingHoursSpecification' => $partsHours,
];
}
$schema = [
'@context' => 'http://schema.org',
'@type' => ['AutoDealer', 'LocalBusiness'],
'@id' => rtrim($idBase, '/') . '/#dealer',
'name' => $dealerName,
'url' => $dealerUrl,
'logo' => $branding['logo_image'] ?? '',
'image' => $branding['logo_image'] ?? '',
'telephone' => array_values(array_unique(array_filter($phones))),
'contactPoint' => $contactPoints,
'brand' => $brands,
'sameAs' => $sameAs,
'currenciesAccepted' => ['CAD'],
'openingHoursSpecification' => $saleHours,
'department' => $departments,
'address' => [
'@type' => 'PostalAddress',
'addressLocality' => $contact['address_city'] ?? '',
'addressRegion' => $contact['address_province'] ?? '',
'postalCode' => $contact['address_postal_code'] ?? '',
'streetAddress' => $contact['address_line_1'] ?? '',
],
];
// Geo: solo si latitude y longitude son numéricas (Dealer Settings →
// Contact → Address). Coordenadas malas son peores que no tener geo.
$lat = isset($contact['latitude']) ? trim((string) $contact['latitude']) : '';
$lng = isset($contact['longitude']) ? trim((string) $contact['longitude']) : '';
if (is_numeric($lat) && is_numeric($lng)) {
$schema['geo'] = [
'@type' => 'GeoCoordinates',
'latitude' => (float) lbx_normalize_coordinate($lat),
'longitude' => (float) lbx_normalize_coordinate($lng),
];
}
$schema = lbx_schema_prune($schema);
// Sin nombre no hay entidad que declarar: mejor no emitir nada.
if (!isset($schema['name'])) {
return [];
}
return $schema;
}
/**
* Mapea un drivetrain de inventario (AWD, 4WD, FWD…) a su valor canónico de
* DriveWheelConfigurationValue; si no matchea ninguno devuelve el texto tal
* cual (schema.org acepta texto libre).
*
* @param mixed $drivetrain
* @return string
*/
function lbx_drivewheel_configuration($drivetrain)
{
$drivetrain = trim((string) $drivetrain);
$driveMap = [
'AWD' => 'https://schema.org/AllWheelDriveConfiguration',
'4WD' => 'https://schema.org/FourWheelDriveConfiguration',
'4X4' => 'https://schema.org/FourWheelDriveConfiguration',
'FWD' => 'https://schema.org/FrontWheelDriveConfiguration',
'RWD' => 'https://schema.org/RearWheelDriveConfiguration',
];
$driveKey = strtoupper(preg_replace('/[^A-Za-z0-9]/', '', $drivetrain));
return $driveMap[$driveKey] ?? $drivetrain;
}
/**
* URL absoluta del VDP de un vehículo, replicando el slug que construye la
* vehicle card (spa-vehicle-card.vue.js → viewSlug):
* /view/{condition}-{year}-{make}-{model}[-{vin}]-{id}/ (/vue/ en francés).
* El flag use-slug-vin sale del genius config, igual que en la card.
*
* @param array $vehicle Item del array `vehicles` de inventory.json.
* @return string
*/
function lbx_vehicle_vdp_url(array $vehicle)
{
$slugify = static function ($value) {
return str_replace(' ', '-', strtolower(trim((string) $value)));
};
// El JS solo elimina la PRIMERA '/' del modelo (String.replace sin flag global).
$model = $slugify($vehicle['model'] ?? '');
$slashPos = strpos($model, '/');
if ($slashPos !== false) {
$model = substr_replace($model, '', $slashPos, 1);
}
$parts = [
$slugify($vehicle['condition'] ?? ''),
$slugify($vehicle['year'] ?? ''),
$slugify($vehicle['make'] ?? ''),
$model,
];
$useVin = (defined('GENIUS') && isset(GENIUS['vehicle-card']['data']['use-slug-vin']))
? GENIUS['vehicle-card']['data']['use-slug-vin']
: false;
if ($useVin && !empty($vehicle['vin'])) {
$parts[] = (string) $vehicle['vin'];
}
$parts[] = (string) ($vehicle['id'] ?? '');
$base = (function_exists('isFrench') && isFrench()) ? '/vue/' : '/view/';
return home_url($base . implode('-', $parts) . '/');
}
/**
* Construye el ItemList de Car (schema.org) de una vista de inventario
* (SRP/VLP) a partir de los vehículos YA filtrados/ordenados/paginados que la
* vista renderiza (LBT-1508, Shift Digital AI-Readiness A4).
*
* Solo emite en vistas de inventario reales: los bloques con `filter` activo.
* Los carousels (home, etc.) usan el mismo bloque con filter=false y se
* omiten. La lista se acota a la primera "página" visible del SRP
* (vehiclePerPage o loadMoreBtnItemsPerPage del genius config, fallback 24)
* para que el JSON-LD refleje lo que el usuario ve sin inflar el HTML.
*
* @param array $vehicles Vehículos de la vista (post filter/sort/paginate).
* @param array $options Opciones del bloque inventory-block.
* @return array
*/
function lbx_srp_itemlist_schema(array $vehicles, array $options = [])
{
if (!filter_var($options['filter'] ?? false, FILTER_VALIDATE_BOOLEAN)) {
return [];
}
if (empty($vehicles)) {
return [];
}
$cap = 24;
if (defined('GENIUS') && isset(GENIUS['srp-layout']['data']) && is_array(GENIUS['srp-layout']['data'])) {
$layoutData = GENIUS['srp-layout']['data'];
if (!empty($layoutData['vehiclePerPage'])) {
$cap = (int) $layoutData['vehiclePerPage'];
} elseif (!empty($layoutData['loadMoreBtnItemsPerPage'])) {
$cap = (int) $layoutData['loadMoreBtnItemsPerPage'];
}
}
$vehicles = array_slice(array_values($vehicles), 0, max(1, $cap));
$items = [];
foreach ($vehicles as $vehicle) {
if (!is_array($vehicle)) {
continue;
}
$condition = trim((string) ($vehicle['condition'] ?? ''));
$isNew = strtolower($condition) === 'new';
$url = lbx_vehicle_vdp_url($vehicle);
$offer = [
'@type' => 'Offer',
'availability' => !empty($vehicle['incoming']) ? 'https://schema.org/OutOfStock' : 'https://schema.org/InStock',
'priceCurrency' => 'CAD',
'url' => $url,
];
$price = $vehicle['price'] ?? null;
if (is_numeric($price) && (float) $price > 0) {
$offer['price'] = (string) $price;
}
$car = [
'@type' => 'Car',
'name' => trim(preg_replace('/\s+/', ' ', sprintf(
'%s %s %s %s %s',
$condition,
$vehicle['year'] ?? '',
$vehicle['make'] ?? '',
$vehicle['model'] ?? '',
$vehicle['trim'] ?? ''
))),
'url' => $url,
'image' => (string) ($vehicle['picture'] ?? ''),
'brand' => [
'@type' => 'Brand',
'name' => (string) ($vehicle['make'] ?? ''),
],
'model' => (string) ($vehicle['model'] ?? ''),
'vehicleModelDate' => (string) ($vehicle['year'] ?? ''),
'itemCondition' => $isNew
? 'https://schema.org/NewCondition'
: 'https://schema.org/UsedCondition',
'driveWheelConfiguration' => lbx_drivewheel_configuration($vehicle['drivetrain'] ?? ''),
'vehicleIdentificationNumber' => (string) ($vehicle['vin'] ?? ''),
'sku' => (string) ($vehicle['stocknumber'] ?? ''),
'offers' => $offer,
];
// Kilometraje: en usados y demos (mismo criterio que las cards).
if ((!$isNew || !empty($vehicle['demo'])) && is_numeric($vehicle['mileage'] ?? null)) {
$car['mileageFromOdometer'] = [
'@type' => 'QuantitativeValue',
'value' => (string) $vehicle['mileage'],
'unitText' => 'KM',
];
}
$items[] = [
'@type' => 'ListItem',
'position' => count($items) + 1,
'item' => $car,
];
}
if (empty($items)) {
return [];
}
$schema = [
'@context' => 'http://schema.org',
'@type' => 'ItemList',
'name' => wp_strip_all_tags((string) get_the_title()),
'numberOfItems' => count($items),
'itemListElement' => $items,
];
return lbx_schema_prune($schema);
}
/**
* Renderiza el <script> JSON-LD del ItemList del SRP, o '' si la vista no
* aplica (bloque sin filtro activo o sin vehículos). Pensado para llamarse
* desde layouts/srp-layout/* justo después de paginar.
*
* @param mixed $vehicles Vehículos ya filtrados/paginados de la vista.
* @param mixed $options Opciones del bloque inventory-block.
* @return string
*/
function lbx_render_srp_itemlist_schema($vehicles, $options = [])
{
if (!is_array($vehicles)) {
return '';
}
$schema = lbx_srp_itemlist_schema($vehicles, is_array($options) ? $options : []);
if (empty($schema)) {
return '';
}
return "\n<script type=\"application/ld+json\">\n" . lbx_json_ld($schema) . "\n</script>\n";
}
/**
* Construye el structured data Car (schema.org) de un vehículo para las
* plantillas VDP/product/form y lo devuelve ya serializado como JSON-LD.
*
* Reemplaza los bloques JSON armados a mano en los blades: al construir el
* schema como array PHP y serializarlo con lbx_json_ld(), la salida es JSON
* válido por construcción, incluso con descripciones multi-párrafo (saltos de
* línea, comillas, HTML). La descripción se emite como texto plano y las
* propiedades opcionales sin valor se omiten en vez de emitirse como cadenas
* vacías (p. ej. nunca se emite "price": "" en vehículos sin precio).
*
* @param array $data JSON per-vehicle (uploads/data/<id>.json).
* @param array|null $contact Datos de contacto del dealer.
* @param array|null $branding Branding del dealer (logo).
* @param array $args Overrides por plantilla: name, image, url, mileage.
* @return string|false
*/
function lbx_vehicle_car_schema($data, $contact = null, $branding = null, $args = [])
{
$data = is_array($data) ? $data : [];
$contact = is_array($contact) ? $contact : [];
$branding = is_array($branding) ? $branding : [];
// Descripción: texto plano, sin HTML, sin saltos de línea y acotada.
$description = (string) ($data['description'] ?? '');
if ($description !== '') {
$description = wp_strip_all_tags($description);
$description = html_entity_decode($description, ENT_QUOTES | ENT_HTML5, 'UTF-8');
$description = str_replace("\xC2\xA0", ' ', $description); // nbsp
$description = trim(preg_replace('/\s+/u', ' ', $description));
if (mb_strlen($description) > 5000) {
$description = mb_substr($description, 0, 5000);
$cut = mb_strrpos($description, ' ');
if ($cut !== false && $cut > 4000) {
$description = mb_substr($description, 0, $cut);
}
$description .= '…';
}
}
// drivetrain -> valor canónico de DriveWheelConfigurationValue (o el texto
// tal cual si no matchea ninguno).
$driveWheelConfiguration = lbx_drivewheel_configuration($data['drivetrain'] ?? '');
$offer = [
'@type' => 'Offer',
'availability' => !empty($data['incoming']) ? 'https://schema.org/OutOfStock' : 'https://schema.org/InStock',
'priceCurrency' => 'CAD',
'url' => (string) ($args['url'] ?? ''),
'seller' => [
'@type' => 'AutoDealer',
'name' => (string) ($contact['dealer_name'] ?? ''),
'telephone' => (string) ($contact['sale_phone'] ?? ''),
'image' => (string) ($branding['logo_image'] ?? ''),
'address' => [
'@type' => 'PostalAddress',
'addressLocality' => (string) ($contact['address_city'] ?? ''),
'addressRegion' => (string) ($contact['address_province'] ?? ''),
'postalCode' => (string) ($contact['address_postal_code'] ?? ''),
'streetAddress' => (string) ($contact['address_line_1'] ?? ''),
],
],
];
$price = $data['price'] ?? null;
if (is_numeric($price) && (float) $price > 0) {
$offer['price'] = (string) $price;
}
// seats/doors en 0 son data ausente, no un valor real: se omiten.
$seats = $data['seats'] ?? null;
$seats = (is_numeric($seats) && (int) $seats > 0) ? (string) $seats : '';
$doors = $data['doors'] ?? null;
$doors = (is_numeric($doors) && (int) $doors > 0) ? (string) $doors : '';
$schema = [
'@context' => 'http://schema.org',
'@type' => 'Car',
'name' => (string) ($args['name'] ?? ''),
'image' => (string) ($args['image'] ?? ''),
'itemCondition' => strtolower((string) ($data['condition'] ?? '')) == 'new'
? 'http://schema.org/NewCondition'
: 'http://schema.org/UsedCondition',
'manufacturer' => (string) ($data['make'] ?? ''),
'vehicleIdentificationNumber' => (string) ($data['vin'] ?? ''),
'vehicleModelDate' => (string) ($data['year'] ?? ''),
'brand' => (string) ($data['make'] ?? ''),
'model' => (string) ($data['model'] ?? ''),
'description' => $description,
'vehicleInteriorColor' => (string) ($data['interiorcolor'] ?? ''),
'bodyType' => (string) ($data['bodystyle'] ?? ''),
'vehicleSeatingCapacity' => $seats,
'mileageFromOdometer' => [
'@type' => 'QuantitativeValue',
'value' => (string) ($args['mileage'] ?? ($data['mileage'] ?? '')),
'unitText' => 'KM',
],
'numberOfDoors' => $doors,
'vehicleEngine' => [
'@type' => 'EngineSpecification',
'name' => (string) ($data['engine'] ?? ''),
'fuelType' => (string) ($data['fueltype'] ?? ''),
],
'driveWheelConfiguration' => $driveWheelConfiguration,
'vehicleTransmission' => (string) ($data['transmission'] ?? ''),
'color' => (string) ($data['exteriorcolor'] ?? ''),
'sku' => (string) ($data['stocknumber'] ?? ''),
'offers' => $offer,
];
return lbx_json_ld(lbx_schema_prune($schema));
}
/**
* ¿La página que se está mostrando es una página de Preguntas Frecuentes?
*
* Se considera FAQ si usa la plantilla template-faq.blade.php o si su slug
* contiene "faq" (cubre rutas como /faq/ o /finance/credit-faq/ aunque no
* usen la plantilla dedicada).
*
* @return bool
*/
function lbx_is_faq_page()
{
if (!function_exists('is_page') || !is_page()) {
return false;
}
if (get_page_template_slug() === 'template-faq.blade.php') {
return true;
}
$queried = get_queried_object();
return ($queried instanceof WP_Post)
&& stripos((string) $queried->post_name, 'faq') !== false;
}
/**
* Imprime el structured data FAQPage (schema.org) en el <head> de las páginas
* de Preguntas Frecuentes.
*
* Lee el contenido ya publicado de la página y deriva los pares pregunta/
* respuesta con lbx_build_faq_entities(). Solo emite el bloque JSON-LD si se
* detectan al menos dos pares, de modo que nunca se imprime un schema vacío o
* incompleto. Reutiliza lbx_json_ld() para la serialización.
*
* Si un plugin SEO (p. ej. Yoast) ya genera el FAQPage desde su propio bloque
* de FAQ, se aborta para no duplicar el structured data.
*
* @return void
*/
function lbx_render_faqpage_schema()
{
if (!lbx_is_faq_page()) {
return;
}
$post = get_queried_object();
if (!($post instanceof WP_Post) || trim((string) $post->post_content) === '') {
return;
}
$html = apply_filters('the_content', $post->post_content);
// Si un plugin SEO (p. ej. Yoast) ya genera el FAQPage desde su propio bloque
// de FAQ, no duplicamos el structured data.
if (
stripos($html, 'schema-faq-question') !== false
|| stripos($html, 'wp-block-yoast-faq-block') !== false
) {
return;
}
$entities = lbx_build_faq_entities($html);
if (count($entities) < 2) {
return;
}
$schema = [
'@context' => 'https://schema.org',
'@type' => 'FAQPage',
'mainEntity' => $entities,
];
echo "\n <script type=\"application/ld+json\">\n"
. lbx_json_ld($schema)
. "\n </script>\n";
}
/**
* Extrae los pares pregunta/respuesta de un fragmento HTML para construir el
* mainEntity de un FAQPage schema.
*
* La heurística es tolerante a los distintos formatos que usan los sitios:
* - Pregunta: un encabezado <h2>–<h6>, o un <p> cuyo contenido sea íntegramente
* negrita (<strong>/<b>), siempre que el texto termine en "?".
* - Respuesta: el texto de los párrafos siguientes hasta la próxima pregunta.
* - Un encabezado que no termina en "?" se trata como título de sección y cierra
* la respuesta en curso.
* - Se elimina el prefijo "Q:" / "A:" que anteponen algunos sitios.
*
* Las respuestas se guardan como texto plano (válido para schema.org), por lo que
* no se conserva el HTML interno (listas, enlaces) de la respuesta.
*
* @param string $html
* @return array Lista de nodos Question; vacío si no se detecta ninguno.
*/
function lbx_build_faq_entities($html)
{
$html = trim((string) $html);
if ($html === '' || !class_exists('DOMDocument')) {
return [];
}
$dom = new DOMDocument();
$previous = libxml_use_internal_errors(true);
$dom->loadHTML('<?xml encoding="utf-8" ?><div id="lbx-faq-root">' . $html . '</div>');
libxml_clear_errors();
libxml_use_internal_errors($previous);
$xpath = new DOMXPath($dom);
$root = $xpath->query('//div[@id="lbx-faq-root"]')->item(0);
if (!$root) {
return [];
}
// Encabezados y párrafos en orden de documento (atravesando los contenedores
// que generan los bloques de Gutenberg).
$nodes = $xpath->query('.//h2|.//h3|.//h4|.//h5|.//h6|.//p', $root);
$entities = [];
$current = null;
foreach ($nodes as $node) {
$question = lbx_faq_extract_question($node);
if ($question !== null) {
$entities[] = [
'@type' => 'Question',
'name' => $question,
'acceptedAnswer' => ['@type' => 'Answer', 'text' => ''],
];
$current = count($entities) - 1;
continue;
}
// Encabezado que no es pregunta: separador de sección.
if (strtolower($node->nodeName)[0] === 'h') {
$current = null;
continue;
}
if ($current !== null) {
$text = lbx_faq_clean_text($node->textContent, true);
if ($text !== '') {
$existing = $entities[$current]['acceptedAnswer']['text'];
$entities[$current]['acceptedAnswer']['text'] =
$existing === '' ? $text : $existing . ' ' . $text;
}
}
}
// Descarta preguntas que se quedaron sin respuesta.
return array_values(array_filter($entities, function ($q) {
return $q['acceptedAnswer']['text'] !== '';
}));
}
/**
* Devuelve el texto de la pregunta si $node es un nodo pregunta, o null si no.
*
* Es pregunta un encabezado <h2>–<h6> o un <p> cuyo contenido sea íntegramente
* negrita, siempre que el texto (ya sin el prefijo "Q:") termine en "?".
*
* @param DOMElement $node
* @return string|null
*/
function lbx_faq_extract_question(DOMElement $node)
{
$tag = strtolower($node->nodeName);
$text = lbx_faq_clean_text($node->textContent, false);
if ($text === '' || substr($text, -1) !== '?') {
return null;
}
if (in_array($tag, ['h2', 'h3', 'h4', 'h5', 'h6'], true)) {
return $text;
}
if ($tag !== 'p') {
return null;
}
// <p> que solo contiene negrita (y, a lo sumo, saltos de línea) => pregunta.
$hasBold = false;
foreach ($node->childNodes as $child) {
if ($child->nodeType === XML_TEXT_NODE) {
if (trim($child->textContent) !== '') {
return null;
}
} elseif ($child->nodeType === XML_ELEMENT_NODE) {
$childTag = strtolower($child->nodeName);
if (in_array($childTag, ['strong', 'b'], true)) {
$hasBold = true;
} elseif ($childTag !== 'br') {
return null;
}
}
}
return $hasBold ? $text : null;
}
/**
* Normaliza el texto de un nodo: colapsa los espacios en blanco, decodifica las
* entidades y elimina el prefijo "Q:" o "A:" que anteponen algunos sitios.
*
* @param string $raw
* @param bool $isAnswer Si es respuesta quita el prefijo "A:"; si no, "Q:".
* @return string
*/
function lbx_faq_clean_text($raw, $isAnswer = false)
{
$text = html_entity_decode((string) $raw, ENT_QUOTES | ENT_HTML5, 'UTF-8');
$text = preg_replace('/\s+/u', ' ', $text);
$text = trim($text);
$prefix = $isAnswer ? 'A' : 'Q';
$text = preg_replace('/^' . $prefix . '\s*:\s*/u', '', $text);
return trim($text);
}
function get_iboost_option()
{
$option = "disabled";
$lbSettings = get_leadbox_settings();
if (
isset($lbSettings) && !empty($lbSettings) && isset($lbSettings["iboost"])
&& !empty($lbSettings["iboost"]) && (strlen($lbSettings["iboost"]) > 0)
) {
$option = strtolower($lbSettings["iboost"]);
}
return $option;
}
function get_dealer_iboost()
{
$dealer_input = null;
$lbSettings = get_leadbox_settings();
if (
isset($lbSettings) && !empty($lbSettings) && isset($lbSettings["iboost_token"])
&& !empty($lbSettings["iboost_token"]) && (strlen($lbSettings["iboost_token"]) > 0)
) {
$dealer_input = $lbSettings["iboost_token"];
}
return $dealer_input;
}
function get_dealer_policies()
{
return get_option('dealer-settings-policies-options');
}
function get_dealer_labels()
{
return get_option('dealer-settings-labels-options');
}
function get_dealer_listings()
{
return get_option('dealer-settings-listing-options');
}
function get_dealer_branding()
{
return get_option('dealer-settings-branding-options');
}
function get_dealer_disclaimer()
{
return get_option('dealer-settings-disclaimer-options');
}
function get_dealer_filter()
{
return get_option('dealer-settings-filter-options');
}
function get_newsletter_status()
{
return get_option('dealer-settings-branding-options')['newsletter_enabled_option'];
}
function is_my_garage_active()
{
$options = get_option('dealer-settings-my-garage-options', []);
$my_garage_status = is_array($options) && isset($options['my_garage_status'])
? $options['my_garage_status']
: '';
$my_garage_is_active = LBX_is_plugin_activated('Leadbox Saved Vehicles');
return (strtolower($my_garage_status) === 'enabled' && $my_garage_is_active);
}
function format_phone($data)
{
if (preg_match('/^\+\d(\d{3})(\d{3})(\d{4})$/', $data, $matches)) {
$result = $matches[1] . '-' . $matches[2] . '-' . $matches[3];
return $result;
}
}
function format_phone_v2($data)
{
if (preg_match('/^\+\d(\d{3})(\d{3})(\d{4})$/', $data, $matches)) {
$result = '(' . $matches[1] . ') ' . $matches[2] . '-' . $matches[3];
return $result;
}
}
function change_image($image)
{
$vdp_str = get_query_var('vdp_string');
$vdp_arr = explode('-', $vdp_str);
$id = array_pop($vdp_arr);
$data = $GLOBALS['vdp_vehicle_data'];
$id_feature_image = get_queried_object_id();
$branding = get_dealer_branding();
if (isset($data['pictures'])) {
$file = $data['pictures'][0];
}
if (has_post_thumbnail($id_feature_image)) {
return wp_get_attachment_image_src(get_post_thumbnail_id($id_feature_image), 'full')[0];
} else {
if (isset($id) && $id > 0) {
if (isset($data['pictures']) && url_exists($file)) {
$image = $data['pictures'][0];
if (strpos($image, '?ts=') !== false) {
$expStr = explode("?ts=", $image);
if (count($expStr) > 0) {
if (str_contains($expStr[0], "http")) {
if (str_contains($expStr[0], "-XXL"))
$image = str_replace("-XXL", "-large.jpg", $expStr[0]);
else
$image = $expStr[0] . '-large.jpg';
} else {
if (str_contains($expStr[0], "-XXL"))
$image = 'https:' . str_replace("-XXL", "-large.jpg", $expStr[0]);
else
$image = 'https:' . $expStr[0] . '-large.jpg';
}
}
return str_replace("http:", "https:", $image);
} else {
if (str_contains($image, "-XXL"))
return str_replace("-XXL", "-large.jpg", str_replace("http:", "https:", $image));
else
return str_replace("http:", "https:", $image) . '-large.jpg';
}
} else {
return $branding['logo_image'];
}
} else {
return $branding['logo_image'];
}
}
}
function getFilesInFolder($folder, $extension)
{
$target = realpath(get_template_directory() . $folder);
dd($folder, $target);
if (!$target) {
return array();
} else {
$files = scandir($target);
return array_filter($files, function ($file) use ($extension) {
if (in_array($file, ['.', '..'])) {
return array();
}
return ends_with($file, $extension);
});
}
}
function getFormLocale_text()
{
$idiom = get_locale();
$view = 'forme';
if (strpos($idiom, 'en') !== false) {
$view = 'form';
}
return $view;
}
function getDetailLocale_text()
{
$idiom = get_locale();
$view = 'vue';
if (strpos($idiom, 'en') !== false) {
$view = 'view';
}
return $view;
}
function verifyRebateToTranslate($rebate)
{
$idiom = get_locale();
if (strpos($idiom, 'en') !== false) {
return $rebate;
}
if (strpos(strtolower($rebate), 'delivery allowance') !== false) {
return 'Rabais à la livraison';
}
if (strpos(strtolower($rebate), 'ev rebate retail') !== false) {
return 'Rabais gouvernement VE';
}
return $rebate;
}
function getInventoryLocale_text()
{
$idiom = get_locale();
$view = 'inventaire-neufs';
if (strpos($idiom, 'en') !== false) {
$view = 'new-inventory';
}
return $view;
}
function getFormPageLocale($form)
{
$textForm = getFormLocale_name($form);
return '/' . getFormLocale_text() . '/' . $textForm;
}
function modelTotal($regex, $trim = false, $model = '')
{
$inventory = get_search_inventory();
$total = 0;
$matches = [];
if(strtolower($model) == 'escapeplug-inhybrid'){
foreach ($inventory as $vehicle) {
if (isset($vehicle) && isset($vehicle["condition"]) && strtolower($vehicle["condition"]) == 'new') {
if (strtolower("escape") == strtolower($vehicle['model']) && (strtolower($vehicle['trim']) == 'plug-in hybrid' || strtolower($vehicle['trim']) == 'phev')){
$regex = '/(plug-inhybrid|phev)/';
preg_match($regex, strtolower($vehicle['trim']), $matches);
if (isset($matches) && count($matches) > 0) {
$total++;
}
}
}
}
}
else {
if ($trim) {
foreach ($inventory as $vehicle) {
if (isset($vehicle) && isset($vehicle["condition"]) && strtolower($vehicle["condition"]) == 'new') {
if (strtolower($model) == strtolower($vehicle['model'])) {
preg_match($regex, strtolower($vehicle['trim']), $matches);
if (isset($matches) && count($matches) > 0) {
$total++;
}
}
}
}
} else {
if(strtolower($model) == 'transit'){
$regex = '/transit (cargo van|cutaway)[a-zA-Z ]*/';
}
else if(strtolower($model) == 'superduty'){
$regex = '/super duty [a-zA-Z ]*/';
}
foreach ($inventory as $vehicle) {
if (isset($vehicle) && isset($vehicle["condition"]) && strtolower($vehicle["condition"]) == 'new') {
preg_match($regex, strtolower($vehicle['model']), $matches);
if (isset($matches) && count($matches) > 0) {
$total++;
}
}
}
}
}
return $total;
}
function modelPrice($regex, $istrim = false)
{
$inventory = get_search_inventory();
$price = 0;
$matches = [];
foreach ($inventory as $vehicle) {
if (($vehicle["price"] > 0 && $vehicle["price"] < $price) || $price == 0) {
if (isset($vehicle) && isset($vehicle["condition"]) && strtolower($vehicle["condition"]) == 'new') {
if (!$istrim) {
preg_match($regex, strtolower(str_replace(' ', '-', $vehicle['model'])), $matches);
if (isset($matches) && count($matches) > 0) {
$price = $vehicle["price"];
}
} else {
preg_match($regex, strtolower(str_replace(' ', '-', $vehicle['model'])) . '' . strtolower(str_replace(' ', '-', $vehicle['trim'])), $matches);
if (isset($matches) && count($matches) > 0) {
$price = $vehicle["price"];
}
}
}
}
}
return currency_format($price);
}
function currency_format_decimals($n,$d)
{
$lang = get_locale();
if ($lang == 'fr_CA')
return (number_format(floatval($n), $d, ',', ' ')) . ' $';
else
return "$" . (number_format(floatval($n), $d));
}
function getFormLocale_name($name)
{
$idiom = get_locale();
switch ($name) {
case 'contact-us':
if (strpos($idiom, 'en') !== false) {
return $name;
} else {
return 'contactez-nous';
}
break;
case 'request-more-information':
if (strpos($idiom, 'en') !== false) {
return $name;
} else {
return 'demande-d-informations';
}
break;
case 'book-a-test-drive':
if (strpos($idiom, 'en') !== false) {
return $name;
} else {
return 'reservez-un-essai-routier';
}
break;
case 'trade-in-appraisal':
if (strpos($idiom, 'en') !== false) {
return $name;
} else {
return 'evaluation-du-vehicule-dechange';
}
break;
case 'confirm-availability':
if (strpos($idiom, 'en') !== false) {
return $name;
} else {
return 'confirmez-la-disponibilite';
}
break;
case 'book-a-service-appointment':
if (strpos($idiom, 'en') !== false) {
return $name;
} else {
return 'prenez-rendez-vous';
}
break;
case 'schedule-viewing':
if (strpos($idiom, 'en') !== false) {
return $name;
} else {
return 'planifier-un-rendez-vous';
}
break;
case 'model-test-drive':
if (strpos($idiom, 'en') !== false) {
return $name;
} else {
return 'essai-de-modele';
}
break;
case 'model-trade-in':
if (strpos($idiom, 'en') !== false) {
return $name;
} else {
return 'modele-reprise';
}
break;
case 'model-reserve-now':
if (strpos($idiom, 'en') !== false) {
return $name;
} else {
return 'modele-reservez-maintenant';
}
break;
case 'model-confirm-availability':
if (strpos($idiom, 'en') !== false) {
return $name;
} else {
return 'modele-confirmer-la-disponibilite';
}
break;
case 'get-offer-information':
if (strpos($idiom, 'en') !== false) {
return $name;
} else {
return 'obtenir-des-informations-sur-l-offre';
}
break;
default:
return $name;
break;
}
}
function isFrench()
{
return false !== strpos(get_locale(), 'fr');
}
function outerLabelOmnisearch($outerLabel)
{
if (isset($outerLabel)) {
echo ($outerLabel);
} else {
_e('Search', 'leadbox');
}
}
function innerLabelOmnisearch($innerLabel)
{
if (isset($innerLabel)) {
echo ($innerLabel);
} else {
_e('Search by Type, Year, Make, Model or Stock #', 'leadbox');
}
}
function getVehiclesYearUsed($yearVehicle)
{
$year = date('Y');
$totalYear = $year - $yearVehicle;
return $totalYear;
}
function get_leadbox_settings()
{
return get_option('leadbox-settings');
}
function get_leadbox_finance_settings()
{
return get_option('dealer-settings-branding-options');
}
function get_leadbox_used_finance_settings()
{
return get_option('dealer-settings-used-finance-options');
}
function has_dealer_listings() {
if (function_exists('get_dealer_listings')) {
if (
(!empty(get_listing_image_new())) ||
(!empty(get_listing_image_new_fr())) ||
(!empty(get_listing_image_used())) ||
(!empty(get_listing_image_used_fr()))
) {
return true;
}
}
return false;
}
function get_listing_image_new()
{
$dealer_input = "";
$listingSettings = get_dealer_listings();
if (
isset($listingSettings) && !empty($listingSettings) && isset($listingSettings["image_new"])
&& !empty($listingSettings["image_new"]) && (strlen($listingSettings["image_new"]) > 0)
) {
$dealer_input = $listingSettings["image_new"];
}
return $dealer_input;
}
//get listing link new
function get_listing_link_new()
{
$dealer_input = "";
$listingSettings = get_dealer_listings();
if (
isset($listingSettings) && !empty($listingSettings) && isset($listingSettings["link_new"])
&& !empty($listingSettings["link_new"]) && (strlen($listingSettings["link_new"]) > 0)
) {
$dealer_input = $listingSettings["link_new"];
}
return $dealer_input;
}
//get linsting image new fr
function get_listing_image_new_fr()
{
$dealer_input = "";
$listingSettings = get_dealer_listings();
if (
isset($listingSettings) && !empty($listingSettings) && isset($listingSettings["image_new_fr"])
&& !empty($listingSettings["image_new_fr"]) && (strlen($listingSettings["image_new_fr"]) > 0)
) {
$dealer_input = $listingSettings["image_new_fr"];
}
return $dealer_input;
}
//get listing link new fr
function get_listing_link_new_fr()
{
$dealer_input = "";
$listingSettings = get_dealer_listings();
if (
isset($listingSettings) && !empty($listingSettings) && isset($listingSettings["link_new_fr"])
&& !empty($listingSettings["link_new_fr"]) && (strlen($listingSettings["link_new_fr"]) > 0)
) {
$dealer_input = $listingSettings["link_new_fr"];
}
return $dealer_input;
}
//get insert after new
function get_insert_after_new()
{
$dealer_input = 0;
$listingSettings = get_dealer_listings();
if (
isset($listingSettings) && !empty($listingSettings) && isset($listingSettings["insert_after_new"])
&& !empty($listingSettings["insert_after_new"]) && (strlen($listingSettings["insert_after_new"]) > 0)
) {
$dealer_input = $listingSettings["insert_after_new"];
}
return $dealer_input;
}
//get limit date new
function get_limit_date_new()
{
$dealer_input = "";
$listingSettings = get_dealer_listings();
if (
isset($listingSettings) && !empty($listingSettings) && isset($listingSettings["limit_date_new"])
&& !empty($listingSettings["limit_date_new"]) && (strlen($listingSettings["limit_date_new"]) > 0)
) {
$dealer_input = $listingSettings["limit_date_new"];
}
return $dealer_input;
}
//get limit date used
function get_limit_date_used()
{
$dealer_input = "";
$listingSettings = get_dealer_listings();
if (
isset($listingSettings) && !empty($listingSettings) && isset($listingSettings["limit_date_used"])
&& !empty($listingSettings["limit_date_used"]) && (strlen($listingSettings["limit_date_used"]) > 0)
) {
$dealer_input = $listingSettings["limit_date_used"];
}
return $dealer_input;
}
//get activate limit date
function get_activate_limit_date()
{
$dealer_input = "";
$listingSettings = get_dealer_listings();
if (
isset($listingSettings) && !empty($listingSettings) && isset($listingSettings["activate_limit_date"])
&& !empty($listingSettings["activate_limit_date"]) && (strlen($listingSettings["activate_limit_date"]) > 0)
) {
$dealer_input = $listingSettings["activate_limit_date"];
}
return $dealer_input;
}
//get activate limit date used
function get_activate_limit_date_used()
{
$dealer_input = "";
$listingSettings = get_dealer_listings();
if (
isset($listingSettings) && !empty($listingSettings) && isset($listingSettings["activate_limit_date_used"])
&& !empty($listingSettings["activate_limit_date_used"]) && (strlen($listingSettings["activate_limit_date_used"]) > 0)
) {
$dealer_input = $listingSettings["activate_limit_date_used"];
}
return $dealer_input;
}
function has_passed_limit_date() {
$limit_date = function_exists('get_limit_date_new') ? get_limit_date_new() : null;
$current_date = date('Y-m-d');
$activate_limit_date = function_exists('get_activate_limit_date') ? get_activate_limit_date() : 'Disabled';
// Verificar si la fecha límite es válida
if (!$limit_date) {
return false;
}
// Convertir fechas a objetos DateTime
$limit_date_obj = DateTime::createFromFormat('Y-m-d', $limit_date);
$current_date_obj = DateTime::createFromFormat('Y-m-d', $current_date);
if (!$limit_date_obj) {
return false; // Si la fecha límite no se pudo convertir, retornamos false
}
return ($activate_limit_date === 'Enabled' && $limit_date_obj < $current_date_obj);
}
function has_passed_limit_date_used() {
$limit_date = function_exists('get_limit_date_used') ? get_limit_date_used() : null;
$current_date = date('Y-m-d');
$activate_limit_date = function_exists('get_activate_limit_date_used') ? get_activate_limit_date_used() : 'Disabled';
// Verificar si la fecha límite es válida
if (!$limit_date) {
return false;
}
// Convertir fechas a objetos DateTime
$limit_date_obj = DateTime::createFromFormat('Y-m-d', $limit_date);
$current_date_obj = DateTime::createFromFormat('Y-m-d', $current_date);
if (!$limit_date_obj) {
return false; // Si la fecha límite no es válida, retorna false
}
return ($activate_limit_date === 'Enabled' && $limit_date_obj < $current_date_obj);
}
//get listing image used
function get_listing_image_used()
{
$dealer_input = "";
$listingSettings = get_dealer_listings();
if (
isset($listingSettings) && !empty($listingSettings) && isset($listingSettings["image_used"])
&& !empty($listingSettings["image_used"]) && (strlen($listingSettings["image_used"]) > 0)
) {
$dealer_input = $listingSettings["image_used"];
}
return $dealer_input;
}
//get listing link used
function get_listing_link_used()
{
$dealer_input = "";
$listingSettings = get_dealer_listings();
if (
isset($listingSettings) && !empty($listingSettings) && isset($listingSettings["link_used"])
&& !empty($listingSettings["link_used"]) && (strlen($listingSettings["link_used"]) > 0)
) {
$dealer_input = $listingSettings["link_used"];
}
return $dealer_input;
}
//get listing image used fr
function get_listing_image_used_fr()
{
$dealer_input = "";
$listingSettings = get_dealer_listings();
if (
isset($listingSettings) && !empty($listingSettings) && isset($listingSettings["image_used_fr"])
&& !empty($listingSettings["image_used_fr"]) && (strlen($listingSettings["image_used_fr"]) > 0)
) {
$dealer_input = $listingSettings["image_used_fr"];
}
return $dealer_input;
}
//get listing link used fr
function get_listing_link_used_fr()
{
$dealer_input = "";
$listingSettings = get_dealer_listings();
if (
isset($listingSettings) && !empty($listingSettings) && isset($listingSettings["link_used_fr"])
&& !empty($listingSettings["link_used_fr"]) && (strlen($listingSettings["link_used_fr"]) > 0)
) {
$dealer_input = $listingSettings["link_used_fr"];
}
return $dealer_input;
}
/* -------------------------------------------------------------------------
* LBT-1462 — Multiple inventory-insert images (repeatable list)
*
* The legacy feature stored a single image per (new|used) x (en|fr) slot in
* the flat option `dealer-settings-listing-options`. This adds a repeatable
* list stored in `dealer-settings-listing-images-options` (an array of
* entries). `get_listing_images()` is the single source of truth for the SRP
* render: when the repeater is empty it transparently migrates the legacy
* flat keys into equivalent entries, so existing single-image configs keep
* working without a data write.
* ---------------------------------------------------------------------- */
//raw repeater option (array of entries) or empty array
function get_dealer_listing_images()
{
$entries = get_option('dealer-settings-listing-images-options');
return is_array($entries) ? $entries : array();
}
/**
* Global config for how the listing-insert images are placed:
* mode 'grouped' (default) | 'individual'
* offset cards between insertions (grouped mode)
* repeat number of full cycles (grouped mode); 0 = repeat until inventory ends
*
* Stored in the companion option `dealer-settings-listing-images-config`.
* Defaults to grouped with the legacy interval as offset so existing
* single-image configs keep inserting exactly as before.
*/
function get_listing_images_config()
{
$cfg = get_option('dealer-settings-listing-images-config');
$cfg = is_array($cfg) ? $cfg : array();
$mode = isset($cfg['mode']) ? strtolower(trim($cfg['mode'])) : 'grouped';
if (!in_array($mode, array('grouped', 'individual'), true)) {
$mode = 'grouped';
}
$legacyInterval = function_exists('get_insert_after_new') ? (int) get_insert_after_new() : 0;
$offset = isset($cfg['offset']) && $cfg['offset'] !== '' ? max(0, (int) $cfg['offset']) : $legacyInterval;
$repeat = isset($cfg['repeat']) ? max(0, (int) $cfg['repeat']) : 0;
return array(
'mode' => $mode,
'offset' => $offset,
'repeat' => $repeat,
);
}
//fill defaults + cast a single entry to a stable shape
function normalize_listing_image_entry($entry)
{
$entry = is_array($entry) ? $entry : array();
$condition = isset($entry['condition']) ? strtolower(trim($entry['condition'])) : 'both';
if (!in_array($condition, array('new', 'used', 'both'), true)) {
$condition = 'both';
}
$language = isset($entry['language']) ? strtolower(trim($entry['language'])) : 'both';
if (!in_array($language, array('en', 'fr', 'both'), true)) {
$language = 'both';
}
$target = isset($entry['target']) ? trim($entry['target']) : '_self';
if (!in_array($target, array('_self', '_blank'), true)) {
$target = '_self';
}
$activate = isset($entry['activate_limit_date']) ? trim($entry['activate_limit_date']) : 'Disabled';
$activate = ($activate === 'Enabled') ? 'Enabled' : 'Disabled';
// How the image sits in its card: 'contain' letterboxes (no crop, default),
// 'cover' fills and crops. Default 'contain' to never lose promo content.
$fit = isset($entry['fit']) ? strtolower(trim($entry['fit'])) : 'contain';
if (!in_array($fit, array('cover', 'contain'), true)) {
$fit = 'contain';
}
return array(
'image' => isset($entry['image']) ? trim($entry['image']) : '',
'link' => isset($entry['link']) ? trim($entry['link']) : '',
'target' => $target,
'insert_after' => isset($entry['insert_after']) ? max(0, (int) $entry['insert_after']) : 0,
'repeat_every' => isset($entry['repeat_every']) ? max(0, (int) $entry['repeat_every']) : 0,
'condition' => $condition,
'language' => $language,
'fit' => $fit,
'limit_date' => isset($entry['limit_date']) ? trim($entry['limit_date']) : '',
'activate_limit_date' => $activate,
'alt' => isset($entry['alt']) ? trim($entry['alt']) : '',
);
}
//build entries from the legacy flat keys (backwards-compat migration on read)
function migrate_legacy_listing_images()
{
// Legacy behaviour REPEATS each image every `insert_after_new` cards (a single
// global interval drove both New and Used). Preserve that by migrating to a
// repeating entry (repeat_every = interval), not a one-time insert.
$interval = function_exists('get_insert_after_new') ? (int) get_insert_after_new() : 0;
$legacy = array(
// image getter, link getter, condition, language, limit_date getter, activate getter
array('get_listing_image_new', 'get_listing_link_new', 'new', 'en', 'get_limit_date_new', 'get_activate_limit_date'),
array('get_listing_image_new_fr', 'get_listing_link_new_fr', 'new', 'fr', 'get_limit_date_new', 'get_activate_limit_date'),
array('get_listing_image_used', 'get_listing_link_used', 'used', 'en', 'get_limit_date_used', 'get_activate_limit_date_used'),
array('get_listing_image_used_fr', 'get_listing_link_used_fr', 'used', 'fr', 'get_limit_date_used', 'get_activate_limit_date_used'),
);
$entries = array();
foreach ($legacy as $row) {
list($imageFn, $linkFn, $condition, $language, $limitFn, $activateFn) = $row;
$image = function_exists($imageFn) ? $imageFn() : '';
if (empty($image)) {
continue; // only migrate configured slots
}
$entries[] = normalize_listing_image_entry(array(
'image' => $image,
'link' => function_exists($linkFn) ? $linkFn() : '',
'target' => '_self',
'insert_after' => 0,
'repeat_every' => $interval, // reproduce the legacy "repeat every N" behaviour
'condition' => $condition,
'language' => $language,
'fit' => 'contain', // preserve the legacy natural (no-crop) look
'limit_date' => function_exists($limitFn) ? $limitFn() : '',
'activate_limit_date' => function_exists($activateFn) ? $activateFn() : 'Disabled',
'alt' => '',
));
}
return $entries;
}
//single source of truth for the SRP render: normalized list, migrated when empty
function get_listing_images()
{
$entries = get_dealer_listing_images();
if (!empty($entries)) {
return array_values(array_filter(array_map('normalize_listing_image_entry', $entries), function ($e) {
return !empty($e['image']);
}));
}
return migrate_legacy_listing_images();
}
//whether any listing-insert image is configured (new + legacy)
function has_dealer_listing_images()
{
$images = get_listing_images();
return !empty($images);
}
//per-entry expiration (mirrors has_passed_limit_date but scoped to one entry)
function listing_image_entry_expired($entry)
{
$entry = normalize_listing_image_entry($entry);
if ($entry['activate_limit_date'] !== 'Enabled') {
return false;
}
if (empty($entry['limit_date'])) {
return false;
}
$limit_date_obj = DateTime::createFromFormat('Y-m-d', $entry['limit_date']);
if (!$limit_date_obj) {
return false;
}
$current_date_obj = DateTime::createFromFormat('Y-m-d', date('Y-m-d'));
return ($limit_date_obj < $current_date_obj);
}
/**
* LBT-1462 Round 3: resolve a reusable listing-image group (created in the plugin,
* option `lbx_listing_image_groups`) into the same shape the SRP render pipeline
* already consumes — entries[] (normalized) + config{ mode, start, offset, repeat }.
*
* Returns null when the group is missing, disabled, or its group-level expiration
* date has passed (which hides the whole group). Per-image language + expiration are
* NOT applied here — the blade's existing entry filter handles those uniformly for
* both the group and the legacy/global source.
*
* @param string $group_id Group id chosen in the Inventory block ('' = none).
* @return array|null ['config' => [...], 'entries' => [...]] or null.
*/
function get_listing_image_group($group_id)
{
if (empty($group_id)) {
return null;
}
$groups = get_option('lbx_listing_image_groups', array());
if (!is_array($groups) || !isset($groups[$group_id]) || !is_array($groups[$group_id])) {
return null;
}
$group = $groups[$group_id];
// Inactive groups render nothing.
if (empty($group['active'])) {
return null;
}
// Group-level expiration hides the entire group once the date has passed.
if (!empty($group['date_enabled']) && !empty($group['limit_date'])) {
$limit = DateTime::createFromFormat('Y-m-d', $group['limit_date']);
$today = DateTime::createFromFormat('Y-m-d', date('Y-m-d'));
if ($limit && $today && $limit < $today) {
return null;
}
}
$offset = isset($group['offset']) ? max(1, (int) $group['offset']) : 1;
$images = (isset($group['images']) && is_array($group['images'])) ? $group['images'] : array();
$entries = array();
foreach ($images as $img) {
if (!is_array($img)) {
continue;
}
// Only active images render (manual on/off). Missing key = active (defensive).
if (array_key_exists('active', $img) && empty($img['active'])) {
continue;
}
// Map the group image shape to the render entry shape. Position lives on the
// group (offset), so per-entry insert_after/repeat_every are 0. Condition and
// language are forced to 'both': a group image shows regardless of the vehicle's
// new/used status or the page language. The per-image date toggle maps to
// activate_limit_date so the shared listing_image_entry_expired() filter in the
// blade drops expired images.
$entries[] = normalize_listing_image_entry(array(
'image' => isset($img['image']) ? $img['image'] : '',
'link' => isset($img['link']) ? $img['link'] : '',
'target' => isset($img['target']) ? $img['target'] : '_self',
'insert_after' => 0,
'repeat_every' => 0,
'condition' => 'both',
'language' => 'both',
'fit' => isset($img['fit']) ? $img['fit'] : 'contain',
'limit_date' => isset($img['limit_date']) ? $img['limit_date'] : '',
'activate_limit_date' => !empty($img['date_enabled']) ? 'Enabled' : 'Disabled',
'alt' => isset($img['alt']) ? $img['alt'] : '',
));
}
return array(
// Groups always cycle (grouped mode). No `start` — the first image lands on card
// `offset` (spa-inventory falls back to start=offset when start is absent).
// `repeat` = 0 means "until the end of the SRP" (images repeat indefinitely).
'config' => array('mode' => 'grouped', 'offset' => $offset, 'repeat' => 0),
'entries' => $entries,
);
}
function get_calculated_msrp_label()
{
if (get_locale() == 'fr_CA') {
return get_calculated_msrp_fr_label();
} else {
return get_calculated_msrp_en_label();
}
}
function get_calculated_msrp_en_label()
{
$dealer_input = "Basic MSRP";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["calculated_msrp"])
&& !empty($labelSettings["calculated_msrp"]) && (strlen($labelSettings["calculated_msrp"]) > 0)
) {
$dealer_input = $labelSettings["calculated_msrp"];
}
return $dealer_input;
}
function get_calculated_msrp_fr_label()
{
$dealer_input = "PDSF de base";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["calculated_msrp_fr"])
&& !empty($labelSettings["calculated_msrp_fr"]) && (strlen($labelSettings["calculated_msrp_fr"]) > 0)
) {
$dealer_input = $labelSettings["calculated_msrp_fr"];
}
return $dealer_input;
}
function get_vehicle_price_label($condition = null)
{
if(!$condition)
$condition = "new";
if($condition == "new"){
return get_new_vehicle_price_label();
}
else {
return get_used_vehicle_price_label();
}
}
function get_new_vehicle_price_label()
{
if (get_locale() == 'fr_CA') {
return get_new_vehicle_price_fr_label();
} else {
return get_new_vehicle_price_en_label();
}
}
function get_new_vehicle_price_en_label()
{
$dealer_input = "MSRP";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["new_vehicle_price"])
&& !empty($labelSettings["new_vehicle_price"]) && (strlen($labelSettings["new_vehicle_price"]) > 0)
) {
$dealer_input = $labelSettings["new_vehicle_price"];
}
return $dealer_input;
}
function get_new_vehicle_price_fr_label()
{
$dealer_input = "PDSF";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["new_vehicle_price_fr"])
&& !empty($labelSettings["new_vehicle_price_fr"]) && (strlen($labelSettings["new_vehicle_price_fr"]) > 0)
) {
$dealer_input = $labelSettings["new_vehicle_price_fr"];
}
return $dealer_input;
}
function get_after_discount_price_label($condition = null)
{
if(!$condition)
$condition = "new";
if($condition == "new"){
if (get_locale() == 'fr_CA') {
return get_after_discount_price_fr_label();
} else {
return get_after_discount_price_en_label();
}
}
else {
if (get_locale() == 'fr_CA') {
return get_used_after_discount_price_fr_label();
} else {
return get_used_after_discount_price_en_label();
}
}
}
function get_after_discount_price_en_label()
{
$dealer_input = "";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["after_discount_price"])
&& !empty($labelSettings["after_discount_price"]) && (strlen($labelSettings["after_discount_price"]) > 0)
) {
$dealer_input = $labelSettings["after_discount_price"];
}
return $dealer_input;
}
function get_after_discount_price_fr_label()
{
$dealer_input = "";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["after_discount_price_fr"])
&& !empty($labelSettings["after_discount_price_fr"]) && (strlen($labelSettings["after_discount_price_fr"]) > 0)
) {
$dealer_input = $labelSettings["after_discount_price_fr"];
}
return $dealer_input;
}
function get_used_after_discount_price_en_label()
{
$dealer_input = "";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["used_after_discount_price"])
&& !empty($labelSettings["used_after_discount_price"]) && (strlen($labelSettings["used_after_discount_price"]) > 0)
) {
$dealer_input = $labelSettings["used_after_discount_price"];
}
else if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["after_discount_price"])
&& !empty($labelSettings["after_discount_price"]) && (strlen($labelSettings["after_discount_price"]) > 0)
) {
$dealer_input = $labelSettings["after_discount_price"];
}
return $dealer_input;
}
function get_used_after_discount_price_fr_label()
{
$dealer_input = "";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["used_after_discount_price_fr"])
&& !empty($labelSettings["used_after_discount_price_fr"]) && (strlen($labelSettings["used_after_discount_price_fr"]) > 0)
) {
$dealer_input = $labelSettings["used_after_discount_price_fr"];
}
else if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["after_discount_price_fr"])
&& !empty($labelSettings["after_discount_price_fr"]) && (strlen($labelSettings["after_discount_price_fr"]) > 0)
) {
$dealer_input = $labelSettings["after_discount_price_fr"];
}
return $dealer_input;
}
function get_special_price_label()
{
if (get_locale() == 'fr_CA') {
return get_special_price_fr_label();
} else {
return get_special_price_en_label();
}
}
function get_special_price_en_label()
{
$dealer_input = "Special Price";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["special_price"])
&& !empty($labelSettings["special_price"]) && (strlen($labelSettings["special_price"]) > 0)
) {
$dealer_input = $labelSettings["special_price"];
}
return $dealer_input;
}
function get_special_price_fr_label()
{
$dealer_input = "Prix spéciale";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["special_price_fr"])
&& !empty($labelSettings["special_price_fr"]) && (strlen($labelSettings["special_price_fr"]) > 0)
) {
$dealer_input = $labelSettings["special_price_fr"];
}
return $dealer_input;
}
function get_special_discount_label()
{
if (get_locale() == 'fr_CA') {
return get_special_discount_fr_label();
} else {
return get_special_discount_en_label();
}
}
function get_special_discount_en_label()
{
$dealer_input = "Special Discount";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["special_discount_price"])
&& !empty($labelSettings["special_discount_price"]) && (strlen($labelSettings["special_discount_price"]) > 0)
) {
$dealer_input = $labelSettings["special_discount_price"];
}
return $dealer_input;
}
function get_special_discount_fr_label()
{
$dealer_input = "Remise spéciale";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["special_discount_price_fr"])
&& !empty($labelSettings["special_discount_price_fr"]) && (strlen($labelSettings["special_discount_price_fr"]) > 0)
) {
$dealer_input = $labelSettings["special_discount_price_fr"];
}
return $dealer_input;
}
//! Helper tag custom funcion
function getTagStyles($colorLabel, $limitLabel, $version) {
$backgroundColor = $colorLabel != '#000000' ? "background-color: $colorLabel !important;" : '';
$adjustedLimitLabel = $version === 1 ? $limitLabel + 1 : $limitLabel; // Sumar 2 al valor original
$characterTrunk = $limitLabel > 0 ? "width: {$adjustedLimitLabel}ch; display:inline-block;" : 'display: inline-block; white-space: nowrap;';
return [
'backgroundColor' => $backgroundColor,
'characterTrunk' => $characterTrunk
];
}
//! Sale pending tags
function get_salepending_tag_label()
{
if (get_locale() == 'fr_CA') {
return get_salepending_tag_fr_label();
} else {
return get_salepending_tag_en_label();
}
}
function get_salepending_tag_en_label()
{
$dealer_input = "Sale Pending";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["salepending_tag_label"])
&& !empty($labelSettings["salepending_tag_label"]) && (strlen($labelSettings["salepending_tag_label"]) > 0)
) {
$dealer_input = $labelSettings["salepending_tag_label"];
}
return $dealer_input;
}
function get_salepending_tag_fr_label()
{
$dealer_input = "Vente en cours";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["salepending_tag_label_fr"])
&& !empty($labelSettings["salepending_tag_label_fr"]) && (strlen($labelSettings["salepending_tag_label_fr"]) > 0)
) {
$dealer_input = $labelSettings["salepending_tag_label_fr"];
}
return $dealer_input;
}
// color tag salepending
function get_salepending_tag_color_label()
{
$dealer_input = "bg-primary";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["salepending_tag_label_color"])
&& !empty($labelSettings["salepending_tag_label_color"]) && (strlen($labelSettings["salepending_tag_label_color"]) != "#000000")
) {
$dealer_input = $labelSettings["salepending_tag_label_color"];
}
return $dealer_input;
}
// limit tag salepending
function get_salepending_tag_limit_label()
{
$dealer_input = 0;
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["salepending_tag_label_limit"])
&& !empty($labelSettings["salepending_tag_label_limit"]) && ($labelSettings["salepending_tag_label_limit"] > 0)
) {
$dealer_input = $labelSettings["salepending_tag_label_limit"];
}
return $dealer_input;
}
//! special tag
function get_special_tag_label()
{
if (get_locale() == 'fr_CA') {
return get_special_tag_fr_label();
} else {
return get_special_tag_en_label();
}
}
function get_special_tag_en_label()
{
$dealer_input = "Special";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["special_tag_label"])
&& !empty($labelSettings["special_tag_label"]) && (strlen($labelSettings["special_tag_label"]) > 0)
) {
$dealer_input = $labelSettings["special_tag_label"];
}
return $dealer_input;
}
function get_special_tag_fr_label()
{
$dealer_input = "Spéciaux";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["special_tag_label_fr"])
&& !empty($labelSettings["special_tag_label_fr"]) && (strlen($labelSettings["special_tag_label_fr"]) > 0)
) {
$dealer_input = $labelSettings["special_tag_label_fr"];
}
return $dealer_input;
}
// color tag special
function get_special_tag_color_label()
{
$dealer_input = "bg-primary";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["special_tag_label_color"])
&& !empty($labelSettings["special_tag_label_color"]) && (strlen($labelSettings["special_tag_label_color"]) != "#000000")
) {
$dealer_input = $labelSettings["special_tag_label_color"];
}
return $dealer_input;
}
// limit tag special
function get_special_tag_limit_label()
{
$dealer_input = 0;
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["special_tag_label_limit"])
&& !empty($labelSettings["special_tag_label_limit"]) && ($labelSettings["special_tag_label_limit"] > 0)
) {
$dealer_input = $labelSettings["special_tag_label_limit"];
}
return $dealer_input;
}
//! certified tag
function get_certified_tag_label()
{
if (get_locale() == 'fr_CA') {
return get_certified_tag_fr_label();
} else {
return get_certified_tag_en_label();
}
}
function get_certified_tag_en_label()
{
$dealer_input = "Certified";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["certified_tag_label"])
&& !empty($labelSettings["certified_tag_label"]) && (strlen($labelSettings["certified_tag_label"]) > 0)
) {
$dealer_input = $labelSettings["certified_tag_label"];
}
return $dealer_input;
}
function get_certified_tag_fr_label()
{
$dealer_input = "Certifié";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["certified_tag_label_fr"])
&& !empty($labelSettings["certified_tag_label_fr"]) && (strlen($labelSettings["certified_tag_label_fr"]) > 0)
) {
$dealer_input = $labelSettings["certified_tag_label_fr"];
}
return $dealer_input;
}
// color tag certified
function get_certified_tag_color_label()
{
$dealer_input = "bg-primary";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["certified_tag_label_color"])
&& !empty($labelSettings["certified_tag_label_color"]) && (strlen($labelSettings["certified_tag_label_color"]) != "#000000")
) {
$dealer_input = $labelSettings["certified_tag_label_color"];
}
return $dealer_input;
}
// limit tag certified
function get_certified_tag_limit_label()
{
$dealer_input = 0;
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["certified_tag_label_limit"])
&& !empty($labelSettings["certified_tag_label_limit"]) && ($labelSettings["certified_tag_label_limit"] > 0)
) {
$dealer_input = $labelSettings["certified_tag_label_limit"];
}
return $dealer_input;
}
//! asis tag
function get_asis_tag_label()
{
if (get_locale() == 'fr_CA') {
return get_asis_tag_fr_label();
} else {
return get_asis_tag_en_label();
}
}
function get_asis_tag_en_label()
{
$dealer_input = "As Is";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["asis_tag_label"])
&& !empty($labelSettings["asis_tag_label"]) && (strlen($labelSettings["asis_tag_label"]) > 0)
) {
$dealer_input = $labelSettings["asis_tag_label"];
}
return $dealer_input;
}
function get_asis_tag_fr_label()
{
$dealer_input = "Comme si";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["asis_tag_label_fr"])
&& !empty($labelSettings["asis_tag_label_fr"]) && (strlen($labelSettings["asis_tag_label_fr"]) > 0)
) {
$dealer_input = $labelSettings["asis_tag_label_fr"];
}
return $dealer_input;
}
// color tag asis
function get_asis_tag_color_label()
{
$dealer_input = "bg-primary";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["asis_tag_label_color"])
&& !empty($labelSettings["asis_tag_label_color"]) && (strlen($labelSettings["asis_tag_label_color"]) != "#000000")
) {
$dealer_input = $labelSettings["asis_tag_label_color"];
}
return $dealer_input;
}
// limit tag asis
function get_asis_tag_limit_label()
{
$dealer_input = 0;
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["asis_tag_label_limit"])
&& !empty($labelSettings["asis_tag_label_limit"]) && ($labelSettings["asis_tag_label_limit"] > 0)
) {
$dealer_input = $labelSettings["asis_tag_label_limit"];
}
return $dealer_input;
}
//! incoming tag
function get_incoming_tag_label()
{
if (get_locale() == 'fr_CA') {
return get_incoming_tag_fr_label();
} else {
return get_incoming_tag_en_label();
}
}
function get_incoming_tag_en_label()
{
$dealer_input = "Incoming";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["incoming_tag_label"])
&& !empty($labelSettings["incoming_tag_label"]) && (strlen($labelSettings["incoming_tag_label"]) > 0)
) {
$dealer_input = $labelSettings["incoming_tag_label"];
}
return $dealer_input;
}
function get_incoming_tag_fr_label()
{
$dealer_input = "En transit";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["incoming_tag_label_fr"])
&& !empty($labelSettings["incoming_tag_label_fr"]) && (strlen($labelSettings["incoming_tag_label_fr"]) > 0)
) {
$dealer_input = $labelSettings["incoming_tag_label_fr"];
}
return $dealer_input;
}
// color tag incoming
function get_incoming_tag_color_label()
{
$dealer_input = "bg-primary";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["incoming_tag_label_color"])
&& !empty($labelSettings["incoming_tag_label_color"]) && (strlen($labelSettings["incoming_tag_label_color"]) != "#000000")
) {
$dealer_input = $labelSettings["incoming_tag_label_color"];
}
return $dealer_input;
}
// limit tag incoming
function get_incoming_tag_limit_label()
{
$dealer_input = 0;
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["incoming_tag_label_limit"])
&& !empty($labelSettings["incoming_tag_label_limit"]) && ($labelSettings["incoming_tag_label_limit"] > 0)
) {
$dealer_input = $labelSettings["incoming_tag_label_limit"];
}
return $dealer_input;
}
//! Demo Tags
function get_demo_tag_label()
{
if (get_locale() == 'fr_CA') {
return get_demo_tag_fr_label();
} else {
return get_demo_tag_en_label();
}
}
function get_demo_tag_en_label()
{
$dealer_input = "Demo";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["demo_tag_label"])
&& !empty($labelSettings["demo_tag_label"]) && (strlen(trim($labelSettings["demo_tag_label"])) > 0)
) {
$dealer_input = $labelSettings["demo_tag_label"];
}
return $dealer_input;
}
function get_demo_tag_fr_label()
{
$dealer_input = "Démo";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["demo_tag_label_fr"])
&& !empty($labelSettings["demo_tag_label_fr"]) && (strlen(trim($labelSettings["demo_tag_label_fr"])) > 0)
) {
$dealer_input = $labelSettings["demo_tag_label_fr"];
}
return $dealer_input;
}
// color tag demo
function get_demo_tag_color_label()
{
$dealer_input = "bg-primary";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["demo_tag_label_color"])
&& !empty($labelSettings["demo_tag_label_color"]) && (strlen($labelSettings["demo_tag_label_color"]) != "#000000")
) {
$dealer_input = $labelSettings["demo_tag_label_color"];
}
return $dealer_input;
}
// limit tag demo
function get_demo_tag_limit_label()
{
$dealer_input = 0;
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["demo_tag_label_limit"])
&& !empty($labelSettings["demo_tag_label_limit"]) && ($labelSettings["demo_tag_label_limit"] > 0)
) {
$dealer_input = $labelSettings["demo_tag_label_limit"];
}
return $dealer_input;
}
function get_tax_and_lic_label($condition = "NEW", $include_tax = false)
{
if (get_locale() == 'fr_CA') {
return get_tax_and_lic_fr_label($condition, $include_tax);
} else {
return get_tax_and_lic_en_label($condition, $include_tax);
}
}
function get_tax_and_lic_label_asterix($condition = "NEW", $include_tax = false)
{
if (get_locale() == 'fr_CA') {
return get_tax_and_lic_fr_label($condition, $include_tax) . " *";
} else {
return get_tax_and_lic_en_label($condition, $include_tax) . " *";
}
}
function get_tax_and_lic_en_label($condition = "NEW", $include_tax = false)
{
$dealer_input = $include_tax ? "+ Lic" : "+ Tax & Lic";
$labelSettings = get_dealer_labels();
if (strtoupper($condition) === "USED") {
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["used_tax_and_lic_label"])
&& !empty($labelSettings["used_tax_and_lic_label"]) && (strlen($labelSettings["used_tax_and_lic_label"]) > 0)
) {
$dealer_input = $include_tax ? "" : $labelSettings["used_tax_and_lic_label"];
} elseif (
isset($labelSettings) && !empty($labelSettings)
&& isset($labelSettings["used_tax_label"]) && !empty($labelSettings["used_tax_label"]) && (strlen($labelSettings["used_tax_label"]) > 0)
&& isset($labelSettings["used_lic_label"]) && !empty($labelSettings["used_lic_label"]) && (strlen($labelSettings["used_lic_label"]) > 0)
) {
$dealer_input = $include_tax ? "+ " . $labelSettings["used_lic_label"] : "+ " . $labelSettings["used_tax_label"] . " & " . $labelSettings["used_lic_label"];
}
} else {
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["tax_and_lic_label"])
&& !empty($labelSettings["tax_and_lic_label"]) && (strlen($labelSettings["tax_and_lic_label"]) > 0)
) {
$dealer_input = $include_tax ? "" : $labelSettings["tax_and_lic_label"];
} elseif (
isset($labelSettings) && !empty($labelSettings)
&& isset($labelSettings["new_tax_label"]) && !empty($labelSettings["new_tax_label"]) && (strlen($labelSettings["new_tax_label"]) > 0)
&& isset($labelSettings["new_lic_label"]) && !empty($labelSettings["new_lic_label"]) && (strlen($labelSettings["new_lic_label"]) > 0)
) {
$dealer_input = $include_tax ? "+ " . $labelSettings["new_lic_label"] : "+ " . $labelSettings["new_tax_label"] . " & " . $labelSettings["new_lic_label"];
}
}
return $dealer_input;
}
function get_tax_and_lic_fr_label($condition = "NEW", $include_tax = false)
{
$dealer_input = $include_tax ? "+ Imm." : "+ Taxes et Imm";
$labelSettings = get_dealer_labels();
if (strtoupper($condition) === "USED") {
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["used_tax_and_lic_label_fr"])
&& !empty($labelSettings["used_tax_and_lic_label_fr"]) && (strlen($labelSettings["used_tax_and_lic_label_fr"]) > 0)
) {
$dealer_input = $include_tax ? "" : $labelSettings["used_tax_and_lic_label_fr"];
} elseif (
isset($labelSettings) && !empty($labelSettings)
&& isset($labelSettings["used_tax_label_fr"]) && !empty($labelSettings["used_tax_label_fr"]) && (strlen($labelSettings["used_tax_label_fr"]) > 0)
&& isset($labelSettings["used_lic_label_fr"]) && !empty($labelSettings["used_lic_label_fr"]) && (strlen($labelSettings["used_lic_label_fr"]) > 0)
) {
$dealer_input = $include_tax ? "+ " . $labelSettings["used_lic_label_fr"] : "+ " . $labelSettings["used_tax_label_fr"] . " et " . $labelSettings["used_lic_label_fr"];
}
} else {
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["tax_and_lic_label_fr"])
&& !empty($labelSettings["tax_and_lic_label_fr"]) && (strlen($labelSettings["tax_and_lic_label_fr"]) > 0)
) {
$dealer_input = $include_tax ? "" : $labelSettings["tax_and_lic_label_fr"];
} elseif (
isset($labelSettings) && !empty($labelSettings)
&& isset($labelSettings["new_tax_label_fr"]) && !empty($labelSettings["new_tax_label_fr"]) && (strlen($labelSettings["new_tax_label_fr"]) > 0)
&& isset($labelSettings["new_lic_label_fr"]) && !empty($labelSettings["new_lic_label_fr"]) && (strlen($labelSettings["new_lic_label_fr"]) > 0)
) {
$dealer_input = $include_tax ? "+ " . $labelSettings["new_lic_label_fr"] : "+ " . $labelSettings["new_tax_label_fr"] . " et " . $labelSettings["new_lic_label_fr"];
}
}
return $dealer_input;
}
function get_tax_and_lic_en_label_asterix()
{
$dealer_input = "+ Tax & Lic *";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["tax_and_lic_label"])
&& !empty($labelSettings["tax_and_lic_label"]) && (strlen($labelSettings["tax_and_lic_label"]) > 0)
) {
$dealer_input = "+ Tax & Lic *";
}
return $dealer_input;
}
function get_tax_and_lic_fr_label_asterix()
{
$dealer_input = "+ taxes et imm.";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["tax_and_lic_label_fr"])
&& !empty($labelSettings["tax_and_lic_label_fr"]) && (strlen($labelSettings["tax_and_lic_label_fr"]) > 0)
) {
$dealer_input = "+ taxes et imm. *";
}
return $dealer_input;
}
function get_rebates_label()
{
if (get_locale() == 'fr_CA') {
return get_rebates_fr_label();
} else {
return get_rebates_en_label();
}
}
function get_rebates_en_label()
{
$dealer_input = "Discounts and Rebates";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["rebates_label"])
&& !empty($labelSettings["rebates_label"]) && (strlen($labelSettings["rebates_label"]) > 0)
) {
$dealer_input = $labelSettings["rebates_label"];
}
return $dealer_input;
}
function get_rebates_fr_label()
{
$dealer_input = "Réductions et rabais";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["rebates_label_fr"])
&& !empty($labelSettings["rebates_label_fr"]) && (strlen($labelSettings["rebates_label_fr"]) > 0)
) {
$dealer_input = $labelSettings["rebates_label_fr"];
}
return $dealer_input;
}
function get_additional_rebates_label()
{
if (get_locale() == 'fr_CA') {
return get_additional_rebates_fr_label();
} else {
return get_additional_rebates_en_label();
}
}
function get_additional_rebates_en_label()
{
$dealer_input = "Additional Rebate";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["additional_rebates_label"])
&& !empty($labelSettings["additional_rebates_label"]) && (strlen($labelSettings["additional_rebates_label"]) > 0)
) {
$dealer_input = $labelSettings["additional_rebates_label"];
}
return $dealer_input;
}
function get_additional_rebates_fr_label()
{
$dealer_input = "Rabais supplémentaires";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["additional_rebates_label_fr"])
&& !empty($labelSettings["additional_rebates_label_fr"]) && (strlen($labelSettings["additional_rebates_label_fr"]) > 0)
) {
$dealer_input = $labelSettings["additional_rebates_label_fr"];
}
return $dealer_input;
}
function get_used_vehicle_price_label()
{
if (get_locale() == 'fr_CA') {
return get_used_vehicle_price_fr_label();
} else {
return get_used_vehicle_price_en_label();
}
}
function get_used_vehicle_price_en_label()
{
$dealer_input = "Vehicle Price";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["used_vehicle_price"])
&& !empty($labelSettings["used_vehicle_price"]) && (strlen($labelSettings["used_vehicle_price"]) > 0)
) {
$dealer_input = $labelSettings["used_vehicle_price"];
}
return $dealer_input;
}
function get_used_vehicle_price_fr_label()
{
$dealer_input = "Prix du véhicule";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["used_vehicle_price_fr"])
&& !empty($labelSettings["used_vehicle_price_fr"]) && (strlen($labelSettings["used_vehicle_price_fr"]) > 0)
) {
$dealer_input = $labelSettings["used_vehicle_price_fr"];
}
return $dealer_input;
}
function get_phone_sales_label()
{
if (get_locale() == 'fr_CA') {
return get_phone_sales_fr_label();
} else {
return get_phone_sales_en_label();
}
}
function get_phone_sales_en_label()
{
$dealer_input = "Sales";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["phone_sales_label"])
&& !empty($labelSettings["phone_sales_label"]) && (strlen($labelSettings["phone_sales_label"]) > 0)
) {
$dealer_input = $labelSettings["phone_sales_label"];
}
return $dealer_input;
}
function get_phone_sales_fr_label()
{
$dealer_input = "Ventes";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["phone_sales_label_fr"])
&& !empty($labelSettings["phone_sales_label_fr"]) && (strlen($labelSettings["phone_sales_label_fr"]) > 0)
) {
$dealer_input = $labelSettings["phone_sales_label_fr"];
}
return $dealer_input;
}
function get_phone_parts_label()
{
if (get_locale() == 'fr_CA') {
return get_phone_parts_fr_label();
} else {
return get_phone_parts_en_label();
}
}
function get_phone_parts_en_label()
{
$dealer_input = "Parts";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["phone_parts_label"])
&& !empty($labelSettings["phone_parts_label"]) && (strlen($labelSettings["phone_parts_label"]) > 0)
) {
$dealer_input = $labelSettings["phone_parts_label"];
}
return $dealer_input;
}
function get_phone_parts_fr_label()
{
$dealer_input = "Pièces";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["phone_parts_label_fr"])
&& !empty($labelSettings["phone_parts_label_fr"]) && (strlen($labelSettings["phone_parts_label_fr"]) > 0)
) {
$dealer_input = $labelSettings["phone_parts_label_fr"];
}
return $dealer_input;
}
function get_phone_service_label()
{
if (get_locale() == 'fr_CA') {
return get_phone_service_fr_label();
} else {
return get_phone_service_en_label();
}
}
function get_phone_service_en_label()
{
$dealer_input = "Service";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["phone_service_label"])
&& !empty($labelSettings["phone_service_label"]) && (strlen($labelSettings["phone_service_label"]) > 0)
) {
$dealer_input = $labelSettings["phone_service_label"];
}
return $dealer_input;
}
function get_phone_service_fr_label()
{
$dealer_input = "Service";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["phone_service_label_fr"])
&& !empty($labelSettings["phone_service_label_fr"]) && (strlen($labelSettings["phone_service_label_fr"]) > 0)
) {
$dealer_input = $labelSettings["phone_service_label_fr"];
}
return $dealer_input;
}
function get_phone_fax_label()
{
return isFrench()
? get_phone_fax_fr_label()
: get_phone_fax_en_label();
}
function get_phone_fax_en_label()
{
$dealer_input = "Fax";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["phone_fax_label"])
&& !empty($labelSettings["phone_fax_label"]) && (strlen($labelSettings["phone_fax_label"]) > 0)
) {
$dealer_input = $labelSettings["phone_fax_label"];
}
return $dealer_input;
}
function get_phone_fax_fr_label()
{
$dealer_input = "Fax";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["phone_fax_label_fr"])
&& !empty($labelSettings["phone_fax_label_fr"]) && (strlen($labelSettings["phone_fax_label_fr"]) > 0)
) {
$dealer_input = $labelSettings["phone_fax_label_fr"];
}
return $dealer_input;
}
function get_phone_body_shop_label()
{
return isFrench()
? get_phone_body_shop_fr_label()
: get_phone_body_shop_en_label();
}
function get_phone_body_shop_en_label()
{
$dealer_input = "Body Shop";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["phone_body_shop_label"])
&& !empty($labelSettings["phone_body_shop_label"]) && (strlen($labelSettings["phone_body_shop_label"]) > 0)
) {
$dealer_input = $labelSettings["phone_body_shop_label"];
}
return $dealer_input;
}
function get_phone_body_shop_fr_label()
{
$dealer_input = "Atelier de carrosserie";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["phone_body_shop_label_fr"])
&& !empty($labelSettings["phone_body_shop_label_fr"]) && (strlen($labelSettings["phone_body_shop_label_fr"]) > 0)
) {
$dealer_input = $labelSettings["phone_body_shop_label_fr"];
}
return $dealer_input;
}
function get_phone_sms_label()
{
return isFrench()
? get_phone_sms_fr_label()
: get_phone_sms_en_label();
}
function get_phone_sms_en_label()
{
$dealer_input = "SMS";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["phone_sms_label"])
&& !empty($labelSettings["phone_sms_label"]) && (strlen($labelSettings["phone_sms_label"]) > 0)
) {
$dealer_input = $labelSettings["phone_sms_label"];
}
return $dealer_input;
}
function get_phone_sms_fr_label()
{
$dealer_input = "SMS";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["phone_sms_label_fr"])
&& !empty($labelSettings["phone_sms_label_fr"]) && (strlen($labelSettings["phone_sms_label_fr"]) > 0)
) {
$dealer_input = $labelSettings["phone_sms_label_fr"];
}
return $dealer_input;
}
function get_phone_collision_label()
{
return isFrench()
? get_phone_collision_fr_label()
: get_phone_collision_en_label();
}
function get_phone_collision_en_label()
{
$dealer_input = "Collision";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["phone_collision_label"])
&& !empty($labelSettings["phone_collision_label"]) && (strlen($labelSettings["phone_collision_label"]) > 0)
) {
$dealer_input = $labelSettings["phone_collision_label"];
}
return $dealer_input;
}
function get_phone_collision_fr_label()
{
$dealer_input = "Collision";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["phone_collision_label_fr"])
&& !empty($labelSettings["phone_collision_label_fr"]) && (strlen($labelSettings["phone_collision_label_fr"]) > 0)
) {
$dealer_input = $labelSettings["phone_collision_label_fr"];
}
return $dealer_input;
}
function get_phone_accessories_label()
{
return isFrench()
? get_phone_accessories_fr_label()
: get_phone_accessories_en_label();
}
function get_phone_accessories_en_label()
{
$dealer_input = "Accessories";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["phone_accessories_label"])
&& !empty($labelSettings["phone_accessories_label"]) && (strlen($labelSettings["phone_accessories_label"]) > 0)
) {
$dealer_input = $labelSettings["phone_accessories_label"];
}
return $dealer_input;
}
function get_phone_accessories_fr_label()
{
$dealer_input = "Accessoires";
$labelSettings = get_dealer_labels();
if (
isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["phone_accessories_label_fr"])
&& !empty($labelSettings["phone_accessories_label_fr"]) && (strlen($labelSettings["phone_accessories_label_fr"]) > 0)
) {
$dealer_input = $labelSettings["phone_accessories_label_fr"];
}
return $dealer_input;
}
/* Hooks tester */
function test_hook()
{
echo ('This hook works!');
}
function get_lbx_image_path($route)
{
$fr_path = isFrench() ? 'fr/' : '';
$childRoute = get_stylesheet_directory() . '/assets/images/' . $fr_path;
$childRouteUri = get_stylesheet_directory_uri() . '/assets/images/' . $fr_path;
$parentRouteUri = get_template_directory_uri() . '/resources/images/' . $fr_path;
return file_exists($childRoute . $route)
? $childRouteUri . $route
: $parentRouteUri . $route;
}
function url_exists($file)
{
// $file_headers = @get_headers($file);
// foreach($file_headers as $key => $value){
// if ($value == 'HTTP/1.1 404 Not Found'){
// return false;
// }
// }
return true;
}
//Exclude pages from WordPress Search
function french_time_format($str_time)
{
$exploded_str_time = explode(':', $str_time);
$hours = (strpos($str_time, 'pm') && $exploded_str_time[0] != 12) ?
$exploded_str_time[0] + 12 :
$exploded_str_time[0];
$minutes = preg_replace(['/am/', '/pm/'], ['', ''], $exploded_str_time[1]);
return $hours . 'h' . $minutes;
}
function get_dealer_french_hours($hours)
{
foreach ($hours["sale"] as $key => $value)
if ($value != 'Closed') {
$exploded_time = explode('-', str_replace(' ', '', $value));
$since_time = french_time_format($exploded_time[0]);
$to_time = french_time_format($exploded_time[1]);
$hours["sale"] = $since_time . " - " . $to_time;
}
foreach ($hours["service"] as $key => $value)
if ($value != 'Closed') {
$exploded_time = explode('-', str_replace(' ', '', $value));
$since_time = french_time_format($exploded_time[0]);
$to_time = french_time_format($exploded_time[1]);
$hours["service"] = $since_time . " - " . $to_time;
}
foreach ($hours["parts"] as $key => $value)
if ($value != 'Closed') {
$exploded_time = explode('-', str_replace(' ', '', $value));
$since_time = french_time_format($exploded_time[0]);
$to_time = french_time_format($exploded_time[1]);
$hours["parts"] = $since_time . " - " . $to_time;
}
return $hours;
}
function get_min_open_today($day)
{
$hours = get_dealer_hours();
$hours_additional_settings = get_dealer_hours_additional();
$sale_hours = $hours["sale"];
$service_hours = $hours["service"];
$parts_hours = $hours["parts"];
$exploded_time = explode('-', str_replace(' ', '', $sale_hours[ucfirst($day)]));
$exploded_time_service = explode('-', str_replace(' ', '', $service_hours[ucfirst($day)]));
$exploded_time_parts = explode('-', str_replace(' ', '', $parts_hours[ucfirst($day)]));
$hours_array = [];
if ($exploded_time[0] != 'Closed') {
array_push($hours_array, date("H:i", strtotime($exploded_time[0])));
}
if ($exploded_time_service[0] != 'Closed' && $hours_additional_settings['servicehourstatus'] == 'Enabled') {
array_push($hours_array, date("H:i", strtotime($exploded_time_service[0])));
}
if ($exploded_time_parts[0] != 'Closed' && $hours_additional_settings['parthourstatus'] == 'Enabled') {
array_push($hours_array, date("H:i", strtotime($exploded_time_parts[0])));
}
if (count($hours_array) == 0)
return 'Closed';
sort($hours_array);
if (!isFrench()) {
return date('g:ia', strtotime($hours_array[0]));
} else {
return french_time_format(date('h:ia', strtotime($hours_array[0])));
}
}
function get_max_open_today($day)
{
$hours = get_dealer_hours();
$hours_additional_settings = get_dealer_hours_additional();
$sale_hours = $hours["sale"];
$service_hours = $hours["service"];
$parts_hours = $hours["parts"];
$exploded_time = explode('-', str_replace(' ', '', $sale_hours[ucfirst($day)]));
$exploded_time_service = explode('-', str_replace(' ', '', $service_hours[ucfirst($day)]));
$exploded_time_parts = explode('-', str_replace(' ', '', $parts_hours[ucfirst($day)]));
$hours_array = [];
if ($exploded_time[0] != 'Closed') {
array_push($hours_array, date("H:i", strtotime($exploded_time[1])));
}
if ($exploded_time_service[0] != 'Closed' && $hours_additional_settings['servicehourstatus'] == 'Enabled') {
array_push($hours_array, date("H:i", strtotime($exploded_time_service[1])));
}
if ($exploded_time_parts[0] != 'Closed' && $hours_additional_settings['parthourstatus'] == 'Enabled') {
array_push($hours_array, date("H:i", strtotime($exploded_time_parts[1])));
}
if (count($hours_array) == 0)
return 'Closed';
rsort($hours_array);
if (!isFrench()) {
return date('g:ia', strtotime($hours_array[0]));
} else {
return french_time_format(date('h:ia', strtotime($hours_array[0])));
}
}
/* GET FORD ADOBE TAGGING */
function show_ford_adobe_tagging()
{
$show = false;
$lbSettings = get_leadbox_settings();
if (
isset($lbSettings) && !empty($lbSettings) && isset($lbSettings["ford_adobe_option"])
&& !empty($lbSettings["ford_adobe_option"]) && (strtolower($lbSettings["ford_adobe_option"]) == "enabled")
) {
$show = true;
}
return $show;
}
/* SHOW MODEL E PRICE */
function show_model_e_setting()
{
$show = false;
$lbSettings = get_leadbox_settings();
if (
isset($lbSettings) && !empty($lbSettings) && isset($lbSettings["model_e_setting"])
&& !empty($lbSettings["model_e_setting"]) && (strtolower($lbSettings["model_e_setting"]) == "enabled")
) {
$show = true;
}
return $show;
}
/* GET FORD DEALER CODE */
function get_ford_dealer_code()
{
$dealer_code = null;
$lbSettings = get_leadbox_settings();
if (
isset($lbSettings) && !empty($lbSettings) && isset($lbSettings["ford_dealer_code"])
&& !empty($lbSettings["ford_dealer_code"]) && (strlen($lbSettings["ford_dealer_code"]) > 0)
) {
$dealer_code = $lbSettings["ford_dealer_code"];
}
return $dealer_code;
}
function get_graphql_url()
{
$graphql_url = null;
$lbSettings = get_leadbox_settings();
if (
isset($lbSettings) && !empty($lbSettings) && isset($lbSettings["graphql_url"])
&& !empty($lbSettings["graphql_url"]) && (strlen($lbSettings["graphql_url"]) > 0)
) {
$graphql_url = $lbSettings["graphql_url"];
}
return $graphql_url;
}
function get_live_agent_option()
{
$dealer_code = null;
$lbSettings = get_leadbox_settings();
if (
isset($lbSettings) && !empty($lbSettings) && isset($lbSettings["live_agent"])
&& !empty($lbSettings["live_agent"]) && (strlen($lbSettings["live_agent"]) > 0)
) {
$dealer_code = $lbSettings["live_agent"];
}
return $dealer_code;
}
function get_live_agent_code()
{
$dealer_code = null;
$lbSettings = get_leadbox_settings();
if (
isset($lbSettings) && !empty($lbSettings) && isset($lbSettings["live_agent_code"])
&& !empty($lbSettings["live_agent_code"]) && (strlen($lbSettings["live_agent_code"]) > 0)
) {
$dealer_code = $lbSettings["live_agent_code"];
}
return $dealer_code;
}
function get_moto_insight_option()
{
$option = "disabled";
$lbSettings = get_leadbox_settings();
if (
isset($lbSettings) && !empty($lbSettings) && isset($lbSettings["moto_insight"])
&& !empty($lbSettings["moto_insight"]) && (strlen($lbSettings["moto_insight"]) > 0)
) {
$option = strtolower($lbSettings["moto_insight"]);
}
return $option;
}
function get_moto_insight_url()
{
$dealer_input = null;
$lbSettings = get_leadbox_settings();
if (
isset($lbSettings) && !empty($lbSettings) && isset($lbSettings["moto_insight_url"])
&& !empty($lbSettings["moto_insight_url"]) && (strlen($lbSettings["moto_insight_url"]) > 0)
) {
$dealer_input = $lbSettings["moto_insight_url"];
}
return $dealer_input;
}
function show_moto_insight_button()
{
if (get_moto_insight_option() == 'enabled' && get_moto_insight_url() != '') {
return true;
} else {
return false;
}
}
function get_moto_insight_label()
{
$dealer_input = "BUILD YOUR DEAL";
$lbSettings = get_leadbox_settings();
if (
isset($lbSettings) && !empty($lbSettings) && isset($lbSettings["moto_insight_label"])
&& !empty($lbSettings["moto_insight_label"]) && (strlen($lbSettings["moto_insight_label"]) > 0)
) {
$dealer_input = $lbSettings["moto_insight_label"];
}
return $dealer_input;
}
function get_moto_insight_label_fr()
{
$dealer_input = "CONSTRUISEZ VOTRE OFFRE";
$lbSettings = get_leadbox_settings();
if (
isset($lbSettings) && !empty($lbSettings) && isset($lbSettings["moto_insight_label_fr"])
&& !empty($lbSettings["moto_insight_label_fr"]) && (strlen($lbSettings["moto_insight_label_fr"]) > 0)
) {
$dealer_input = $lbSettings["moto_insight_label_fr"];
}
return $dealer_input;
}
function get_carfax_option()
{
$option = "disabled";
$lbSettings = get_leadbox_settings();
if (
isset($lbSettings) && !empty($lbSettings) && isset($lbSettings["carfax"])
&& !empty($lbSettings["carfax"]) && (strlen($lbSettings["carfax"]) > 0)
) {
$option = strtolower($lbSettings["carfax"]);
}
return $option;
}
function get_cartender_option()
{
$option = "disabled";
$lbSettings = get_leadbox_settings();
if (
isset($lbSettings) && !empty($lbSettings) && isset($lbSettings["cartender"])
&& !empty($lbSettings["cartender"]) && (strlen($lbSettings["cartender"]) > 0)
) {
$option = strtolower($lbSettings["cartender"]);
}
return $option;
}
function get_cartender_url()
{
$dealer_input = null;
$lbSettings = get_leadbox_settings();
if (
isset($lbSettings) && !empty($lbSettings) && isset($lbSettings["cartender_url"])
&& !empty($lbSettings["cartender_url"]) && (strlen($lbSettings["cartender_url"]) > 0)
) {
$dealer_input = $lbSettings["cartender_url"];
}
return $dealer_input;
}
function show_cartender_button()
{
if (get_cartender_option() == 'enabled' && get_cartender_url() != '') {
return true;
} else {
return false;
}
}
function get_cartender_label()
{
$dealer_input = "VIDEO OVERVIEW";
$lbSettings = get_leadbox_settings();
if (
isset($lbSettings) && !empty($lbSettings) && isset($lbSettings["cartender_label"])
&& !empty($lbSettings["cartender_label"]) && (strlen($lbSettings["cartender_label"]) > 0)
) {
$dealer_input = $lbSettings["cartender_label"];
}
return $dealer_input;
}
function get_cartender_label_fr()
{
$dealer_input = "VIDEO OVERVIEW";
$lbSettings = get_leadbox_settings();
if (
isset($lbSettings) && !empty($lbSettings) && isset($lbSettings["cartender_label_fr"])
&& !empty($lbSettings["cartender_label_fr"]) && (strlen($lbSettings["cartender_label_fr"]) > 0)
) {
$dealer_input = $lbSettings["cartender_label_fr"];
}
return $dealer_input;
}
const LBX_ADOBE_JSON = <<<'JSON'
[
{
"nonvehicle": [
{
"pagename": "dc:specials:offers:contact us:thank you",
"channel": "specials",
"hier": "specials",
"pagenamenovehicle": "dc:specials:offers:contact us:thank you",
"slugs": "contact-us-specials-offers,contact-specials-offers,specials-offers",
"tool": "default form",
"tooldescriptor": "offers:contact",
"leadtype": "offers:contact",
"variantname": "form-submit",
"action": "lead submitted|tool"
},
{
"pagename": "dc:specials:new specials:contact us:thank you",
"channel": "specials",
"hier": "specials",
"pagenamenovehicle": "dc:specials:new specials:contact us:thank you",
"slugs": "contact-us-new-specials,contact-new-specials,new-specials",
"tool": "default form",
"tooldescriptor": "new specials:contact",
"leadtype": "new specials:contact",
"variantname": "form-submit",
"action": "lead submitted|tool"
},
{
"pagename": "dc:specials:used specials:contact us:thank you",
"channel": "specials",
"hier": "specials",
"pagenamenovehicle": "dc:specials:used specials:contact us:thank you",
"slugs": "contact-us-used-specials,contact-used-specials,used-specials",
"tool": "default form",
"tooldescriptor": "used specials:contact",
"leadtype": "used specials:contact",
"variantname": "form-submit",
"action": "lead submitted|tool"
},
{
"pagename": "dc:specials:finance:contact us:thank you",
"channel": "specials",
"hier": "specials",
"pagenamenovehicle": "dc:specials:finance:contact us:thank you",
"slugs": "contact-us-finance,contact-finance,finance",
"tool": "default form",
"tooldescriptor": "finance:contact",
"leadtype": "finance:contact",
"variantname": "form-submit",
"action": "lead submitted|tool"
},
{
"pagename": "dc:specials:service:contact us:thank you",
"channel": "specials",
"hier": "specials",
"pagenamenovehicle": "dc:specials:service:contact us:thank you",
"slugs": "contact-us-specials-service,contact-us-service-specials,contact-specials-service,specials-service",
"tool": "default form",
"tooldescriptor": "service:contact",
"leadtype": "service:contact",
"variantname": "form-submit",
"action": "lead submitted|tool"
},
{
"pagename": "dc:specials:parts:contact us:thank you",
"channel": "specials",
"hier": "specials",
"pagenamenovehicle": "dc:specials:parts:contact us:thank you",
"slugs": "contact-us-specials-parts,contact-us-parts-specials,contact-specials-parts,specials-parts",
"tool": "default form",
"tooldescriptor": "parts:contact",
"leadtype": "parts:contact",
"variantname": "form-submit",
"action": "lead submitted|tool"
},
{
"pagename": "dc:service:request appointment:thank you",
"channel": "service and parts",
"hier": "service and parts:request appointment",
"pagenamenovehicle": "dc:service:request appointment:thank you",
"slugs": "book-an-appointment,book-appointment,service,request-appointment,schedule-service,book-a-service-appointment,service-appointment",
"tool": "default form",
"tooldescriptor": "request appointment",
"leadtype": "request appointment",
"variantname": "form-submit",
"action": "lead submitted|tool"
},
{
"pagename": "dc:service:order parts:contact us:thank you",
"channel": "service and parts",
"hier": "service and parts:order parts",
"pagenamenovehicle": "dc:service:order parts:contact us:thank you",
"slugs": "parts,contact-us-service-order-parts,order-parts",
"tool": "default form",
"tooldescriptor": "order parts:contact",
"leadtype": "order parts:contact",
"variantname": "form-submit",
"action": "lead submitted|tool"
},
{
"pagename": "dc:service:accessories:contact us:thank you",
"channel": "service and parts",
"hier": "service and parts:accessories",
"pagenamenovehicle": "dc:service:accessories:contact us:thank you",
"slugs": "accessories,contact-us-service-accessories,service-accessories,order-accessories",
"tool": "default form",
"tooldescriptor": "accessories:contact",
"leadtype": "accessories:contact",
"variantname": "form-submit",
"action": "lead submitted|tool"
},
{
"pagename": "dc:ev lifestyle:test drive:thank you",
"channel": "ev landing page",
"hier": "shopping tools:ev lifestyle:test drive",
"pagenamenovehicle": "dc:ev lifestyle:test drive:thank you",
"slugs": "ev-lifestyle-test-drive-thank-you",
"tool": "event:lead submitted",
"tooldescriptor": "ev lifestyle:test drive",
"leadtype": "ev ownership:test drive:thank you",
"variantname": "test-drive-submit",
"action": "lead submitted|test drive|tool"
},
{
"pagename": "dc:ev ownership:contact us:thank you",
"channel": "ev ownership",
"hier": "ev ownership",
"pagenamenovehicle": "dc:ev ownership:contact us:thank you",
"slugs": "ev-ownership-contact-us-thank-you",
"tool": "ev ownership:contact us",
"tooldescriptor": "ev ownership:contact us",
"leadtype": "ev ownership:contact us",
"variantname": "form-submit",
"action": "lead submitted|tool"
},
{
"pagename": "dc:ev lifestyle:contact us:thank you",
"channel": "ev landing page",
"hier": "ev lifestyle",
"pagenamenovehicle": "dc:ev lifestyle:contact us:thank you",
"slugs": "ev-lifestyle-contact-us-thank-you",
"tool": "ev lifestyle:contact us",
"tooldescriptor": "ev lifestyle:contact us",
"leadtype": "ev lifestyle:contact us",
"variantname": "form-submit",
"action": "lead submitted|tool"
},
{
"pagename": "dc:ev vhp:contact us:thank you",
"channel": "ev vhp",
"hier": "shopping tools:ev vhp:contact us",
"pagenamenovehicle": "dc:ev vhp:contact us:thank you",
"slugs": "ev-vhp-contact-us-thank-you",
"tool": "ev vhp:contact us",
"tooldescriptor": "ev vhp:contact",
"leadtype": "ev vhp:contact",
"variantname": "form-submit",
"action": "lead submitted|tool"
},
{
"pagename": "dc:about us:thank you",
"channel": "about us",
"hier": "about us",
"pagenamenovehicle": "dc:about us:thank you",
"slugs": "about-us,contact-about-us,contact-us-about-us",
"tool": "default form",
"tooldescriptor": "about us:contact",
"leadtype": "about us:contact",
"variantname": "form-submit",
"action": "lead submitted|tool"
},
{
"pagename": "dc:about us:contact us:thank you",
"channel": "about us",
"hier": "about us:contact us",
"pagenamenovehicle": "dc:about us:contact us:thank you",
"slugs": "contact,contact-us",
"tool": "default form",
"tooldescriptor": "contact us:contact",
"leadtype": "contact us:contact",
"variantname": "form-submit",
"action": "lead submitted|tool"
},
{
"pagename": "dc:about us:careers:contact us:thank you",
"channel": "about us",
"hier": "about us:careers",
"pagenamenovehicle": "dc:about us:careers:contact us:thank you",
"slugs": "contact-us-careers,careers",
"tool": "default form",
"tooldescriptor": "careers:contact",
"leadtype": "careers:contact",
"variantname": "form-submit",
"action": "lead submitted|tool"
},
{
"pagename": "dc:test drive:thank you",
"channel": "test drive",
"hier": "shopping tools:test drive",
"pagenamenovehicle": "dc:test drive:thank you",
"slugs": "test-drive,schedule-test-drive,book-test-drive,test-drive-no-vehicle,book-a-test-drive-no-vehicle",
"tool": "event:lead submitted",
"tooldescriptor": "test drive",
"leadtype": "test drive",
"variantname": "test-drive-submit",
"action": "lead submitted|test drive|tool"
},
{
"pagename": "dc:value your trade:thank you",
"channel": "search inventory",
"hier": "shopping tools:value your trade",
"pagenamenovehicle": "dc:value your trade:thank you",
"slugs": "trade-in,trade-in-value,trade-in-appraisal,value-your-trade,trade-in-appraisal-no-vehicle,value-your-trade-no-vehicle",
"tool": "event:value your trade",
"tooldescriptor": "vehicle details:value your trade",
"leadtype": "vdp:value your trade",
"variantname": "vrmi-submit",
"action": "lead submitted|vehicle quote|tool"
},
{
"pagename": "dc:ev ownership:get updates:thank you",
"channel": "ev ownership",
"hier": "ev ownership",
"pagenamenovehicle": "dc:ev ownership:get updates:thank you",
"slugs": "ev-ownership-get-updates",
"tool": "ev ownership:get updates",
"tooldescriptor": "ev ownership:get updates",
"leadtype": "ev ownership:get updates",
"variantname": "form-submit",
"action": "lead submitted|tool"
}
],
"vehicle": [
{
"pagename": "dc:{new|used|cpo}:si:vehicle details:test drive:thank you:<nameplate>",
"channel": "test drive",
"hier": "shopping tools:test drive:<vehicle category>:<nameplate>",
"pagenamenovehicle": "dc:{new|used|cpo}:si:vehicle details:test drive:thank you",
"slugs": "test-drive,book-a-test-drive",
"tool": "event:lead submitted",
"tooldescriptor": "vehicle details:test drive",
"leadtype": "vdp:test drive",
"variantname": "test-drive-submit",
"action": "lead submitted|test drive|tool"
},
{
"pagename": "dc:home:vrmi:thank you:<nameplate>",
"channel": "home",
"hier": "home:<model year>:<vehicle category>:<nameplate>",
"pagenamenovehicle": "dc:home:vrmi:thank you",
"slugs": "vrmi-home",
"tool": "event:vrmi",
"tooldescriptor": "home:vrmi",
"leadtype": "home:vrmi",
"variantname": "value-your-trade-submit",
"action": "lead submitted|appraisals|tool"
},
{
"pagename": "dc:{new|used|cpo}:si:vls:vrmi:thank you:<nameplate>",
"channel": "get quote",
"hier": "shopping tools:get quote:<vehicle category>:<nameplate>",
"pagenamenovehicle": "dc:{new|used|cpo}:si:vls:vrmi:thank you",
"slugs": "get-quote,quick-quote",
"tool": "event:get quote",
"tooldescriptor": "search inventory:get quote",
"leadtype": "si:vrmi",
"variantname": "value-your-trade-submit",
"action": "lead submitted|appraisals|tool"
},
{
"pagename": "dc:{new|used|cpo}:si:vehicle details:vrmi:thank you:<nameplate>",
"channel": "get quote",
"hier": "shopping tools:get quote:<vehicle category>:<nameplate>",
"pagenamenovehicle": "dc:{new|used|cpo}:si:vehicle details:vrmi:thank you",
"slugs": "request-information,request-more-information,get-quote,quick-quote",
"tool": "event:get quote",
"tooldescriptor": "vehicle details:get quote",
"leadtype": "vdp:vrmi",
"variantname": "vrmi-submit",
"action": "lead submitted|appraisals|tool"
},
{
"pagename": "dc:{new|used|cpo}:si:vehicle details:value your trade:thank you:<nameplate>",
"channel": "search inventory",
"hier": "shopping tools:value your trade:<vehicle category>:<nameplate>",
"pagenamenovehicle": "dc:{new|used|cpo}:si:vehicle details:value your trade:thank you",
"slugs": "trade-in-appraisal,value-your-trade",
"tool": "event:value your trade",
"tooldescriptor": "vehicle details:value your trade",
"leadtype": "vdp:value your trade",
"variantname": "vrmi-submit",
"action": "lead submitted|vehicle quote|tool"
}
],
"vls": [
{
"pagename": "dc:{new|used|cpo}:si:vls:vrmi:thank you:<nameplate>",
"channel": "get quote",
"hier": "shopping tools:get quote:<vehicle category>:<nameplate>",
"pagenamenovehicle": "dc:{new|used|cpo}:si:vls:vrmi:thank you",
"slugs": "request-information,request-more-information",
"tool": "event:get quote",
"tooldescriptor": "search inventory:get quote",
"leadtype": "si:vrmi",
"variantname": "vrmi-submit",
"action": "lead submitted|appraisals|tool"
}
],
"home-vrmi": [
{
"pagename": "dc:home:vrmi:thank you:<nameplate>",
"channel": "home",
"hier": "home:<model year>:<vehicle category>:<nameplate>",
"pagenamenovehicle": "dc:home:vrmi:thank you",
"slugs": "home,request-information,request-more-information,ask-a-question,ask-question",
"tool": "event:vrmi",
"tooldescriptor": "home:vrmi",
"leadtype": "home:vrmi",
"variantname": "vrmi-submit",
"action": "lead submitted|appraisals|tool"
}
],
"pages": [
{
"pagename": "dc:ev lifestyle:test drive:thank you",
"channel": "ev landing page",
"hier": "shopping tools:ev lifestyle:test drive",
"pagenamenovehicle": "dc:ev lifestyle:test drive:thank you",
"slugs": "ev-lifestyle-test-drive-thank-you",
"tool": "event:lead submitted",
"tooldescriptor": "ev lifestyle:test drive",
"leadtype": "ev ownership:test drive:thank you",
"variantname": "test-drive-submit",
"action": "lead submitted|test drive|tool"
},
{
"pagename": "dc:ev ownership:contact us:thank you",
"channel": "ev ownership",
"hier": "ev ownership",
"pagenamenovehicle": "dc:ev ownership:contact us:thank you",
"slugs": "ev-ownership-contact-us-thank-you"
},
{
"pagename": "dc:ev vhp:contact us:thank you",
"channel": "ev vhp",
"hier": "shopping tools:ev vhp:contact us",
"pagenamenovehicle": "dc:ev vhp:contact us:thank you",
"slugs": "ev-vhp-contact-us-thank-you"
},
{
"pagename": "dc:ev ownership:contact us",
"channel": "ev ownership",
"hier": "ev ownership",
"pagenamenovehicle": "dc:ev ownership:contact us",
"slugs": "ev-ownership-contact-us,contact-us-ev-ownership"
},
{
"pagename": "dc:home",
"channel": "home",
"hier": "home",
"pagenamenovehicle": "dc:home",
"slugs": "home,welcome"
},
{
"pagename": "dc:help:privacy",
"channel": "help",
"hier": "help:privacy",
"pagenamenovehicle": "dc:help:privacy",
"slugs": "privacy"
},
{
"pagename": "dc:help:disclosures",
"channel": "help",
"hier": "help:disclosures",
"pagenamenovehicle": "dc:help:disclosures",
"slugs": "disclosures,terms-conditions"
},
{
"pagename": "dc:cpo overview",
"channel": "cpo overview",
"hier": "cpo overview",
"pagenamenovehicle": "dc:cpo overview",
"slugs": "cpo-overview"
},
{
"pagename": "dc:ford co pilot assist",
"channel": "ford co pilot assist",
"hier": "ford co pilot assist",
"pagenamenovehicle": "dc:ford co pilot assist",
"slugs": "ford-co-pilot,co-pilot-assist,ford-co-pilot-assist"
},
{
"pagename": "dc:value your trade",
"channel": "search inventory",
"hier": "shopping tools:value your trade",
"pagenamenovehicle": "dc:value your trade",
"slugs": "trade-in-value,value-your-trade,trade-in-vehicle-appraisal,trade-in-appraisal"
},
{
"pagename": "dc:test drive",
"channel": "test drive",
"hier": "shopping tools:test drive",
"pagenamenovehicle": "dc:test drive",
"slugs": "test-drive"
},
{
"pagename": "dc:service:request appointment",
"channel": "service and parts",
"hier": "service and parts:request appointment",
"pagenamenovehicle": "dc:service:request appointment",
"slugs": "book-an-appointment,book-appointment,request-appointment,service-appointment,schedule-appointment,schedule-service"
},
{
"pagename": "dc:service:service and parts",
"channel": "service and parts",
"hier": "service and parts",
"pagenamenovehicle": "dc:service:service and parts",
"slugs": "service,service-parts,service-department,parts-department"
},
{
"pagename": "dc:service:order parts",
"channel": "service and parts",
"hier": "service and parts:order parts",
"pagenamenovehicle": "dc:service:order parts",
"slugs": "parts,order-parts"
},
{
"pagename": "dc:service:quick lane",
"channel": "service and parts",
"hier": "service and parts:quick lane",
"pagenamenovehicle": "dc:service:quick lane",
"slugs": "quick-lane,quicklane"
},
{
"pagename": "dc:service:accessories",
"channel": "service and parts",
"hier": "service and parts:accessories",
"pagenamenovehicle": "dc:service:accessories",
"slugs": "accessories"
},
{
"pagename": "dc:service:extended warranty",
"channel": "service and parts",
"hier": "service and parts:extended warranty",
"pagenamenovehicle": "dc:service:extended warranty",
"slugs": "extended-warranty"
},
{
"pagename": "dc:service:owner advantage rewards",
"channel": "service and parts",
"hier": "service and parts:owner advantage rewards",
"pagenamenovehicle": "dc:service:owner advantage rewards",
"slugs": "owner-advantage-rewards,advantage-rewards,owner-advantage"
},
{
"pagename": "dc:service:fordpass",
"channel": "service and parts",
"hier": "service and parts:fordpass",
"pagenamenovehicle": "dc:service:fordpass",
"slugs": "fordpass"
},
{
"pagename": "dc:ev ownership:contact us",
"channel": "ev ownership",
"hier": "ev ownership",
"pagenamenovehicle": "dc:ev ownership:contact us",
"slugs": "ev-ownership-contact-us"
},
{
"pagename": "dc:ev lifestyle:contact us",
"channel": "ev landing page",
"hier": "ev lifestyle",
"pagenamenovehicle": "dc:ev lifestyle:contact us",
"slugs": "ev-lifestyle-contact-us"
},
{
"pagename": "dc:ev lifestyle:test drive",
"channel": "ev landing page",
"hier": "ev lifestyle",
"pagenamenovehicle": "dc:ev lifestyle:test drive",
"slugs": "ev-lifestyle-test-drive"
},
{
"pagename": "dc:ev vhp:test drive:thank you:<mach-e>",
"channel": "ev vhp",
"hier": "shopping tools:ev vhp:test drive:<mach-e>",
"pagenamenovehicle": "dc:ev vhp:test drive:thank you",
"slugs": "book-a-test-drive-mustang-mach-e-thank-you"
},
{
"pagename": "dc:ev vhp:test drive:thank you:<F150 lightning>",
"channel": "ev vhp",
"hier": "shopping tools:ev vhp:test drive:<F150 lightning>",
"pagenamenovehicle": "dc:ev vhp:test drive:thank you",
"slugs": "book-a-test-drive-f-150-lightning-thank-you"
},
{
"pagename": "dc:ev vhp:test drive",
"channel": "ev vhp",
"hier": "shopping tools:ev vhp:test drive",
"pagenamenovehicle": "dc:ev vhp:test drive",
"slugs": "book-a-test-drive-mustang-mach-e,book-a-test-drive-f-150-lightning"
},
{
"pagename": "dc:ev charging:contact us",
"channel": "ev landing page",
"hier": "ev charging",
"pagenamenovehicle": "dc:ev charging:contact us",
"slugs": "ev-charging-contact-us"
},
{
"pagename": "dc:ev vhp:contact us",
"channel": "ev vhp",
"hier": "shopping tools:ev vhp:contact us",
"pagenamenovehicle": "dc:ev vhp:contact us",
"slugs": "ev-vhp-contact-us"
},
{
"pagename": "dc:about us",
"channel": "about us",
"hier": "about us",
"pagenamenovehicle": "dc:about us",
"slugs": "about-us"
},
{
"pagename": "dc:about us:contact us",
"channel": "about us",
"hier": "about us:contact us",
"pagenamenovehicle": "dc:about us:contact us",
"slugs": "contact,contact-us"
},
{
"pagename": "dc:about us:meet our staff",
"channel": "about us",
"hier": "about us:meet our staff",
"pagenamenovehicle": "dc:about us:meet our staff",
"slugs": "staff,team,our-staff,our-team,meet-our-staff,meet-our-team"
},
{
"pagename": "dc:about us:community",
"channel": "about us",
"hier": "about us:community",
"pagenamenovehicle": "dc:about us:community",
"slugs": "community"
},
{
"pagename": "dc:about us:careers",
"channel": "about us",
"hier": "about us:careers",
"pagenamenovehicle": "dc:about us:careers",
"slugs": "careers"
},
{
"pagename": "dc:shopping tools:credit application",
"channel": "shopping tools",
"hier": "shopping tools",
"pagenamenovehicle": "dc:shopping tools:credit application",
"slugs": "credit-application,apply-credit,financing"
},
{
"pagename": "dc:ev ownership:get updates",
"channel": "ev ownership",
"hier": "ev ownership",
"pagenamenovehicle": "dc:ev ownership:get updates",
"slugs": "ev-ownership-get-updates"
},
{
"pagename": "dc:ev ownership",
"channel": "ev ownership",
"hier": "ev ownership",
"pagenamenovehicle": "dc:ev ownership",
"slugs": "ev-ownership"
},
{
"pagename": "dc:ev charging",
"channel": "ev landing page",
"hier": "ev charging",
"pagenamenovehicle": "dc:ev charging",
"slugs": "ev-charging"
},
{
"pagename": "dc:ev lifestyle",
"channel": "ev landing page",
"hier": "ev lifestyle",
"pagenamenovehicle": "dc:ev lifestyle",
"slugs": "ev-lifestyle"
},
{
"pagename": "dc:ev vhp:ev mach-e",
"channel": "ev vhp",
"hier": "ev vhp",
"pagenamenovehicle": "dc:ev vhp",
"slugs": "ev-mach-e"
},
{
"pagename": "dc:ev vhp:ev-lightning",
"channel": "ev vhp",
"hier": "ev vhp",
"pagenamenovehicle": "dc:ev vhp",
"slugs": "ev-lightning"
}
],
"formsrequestvls": [
{
"pagename": "dc:{new|used|cpo}:si:vls:vrmi:<nameplate>",
"channel": "get quote",
"hier": "shopping tools:get quote:<vehicle category>:<nameplate>",
"pagenamenovehicle": "dc:{new|used|cpo}:si:vls:vrmi",
"slugs": "request-information,request-more-information,get-quote,quick-quote"
}
],
"formsrequestvdp": [
{
"pagename": "dc:{new|used|cpo}:si:vehicle details:vrmi:<nameplate>",
"channel": "get quote",
"hier": "shopping tools:get quote:<vehicle category>:<nameplate>",
"pagenamenovehicle": "dc:{new|used|cpo}:si:vehicle details:vrmi",
"slugs": "request-information,request-more-information,get-quote,quick-quote"
},
{
"pagename": "dc:{new|used|cpo}:si:vehicle details:test drive:<nameplate>",
"channel": "test drive",
"hier": "shopping tools:test drive:<vehicle category>:<nameplate>",
"pagenamenovehicle": "dc:{new|used|cpo}:si:vehicle details:test drive",
"slugs": "test-drive,book-a-test-drive"
},
{
"pagename": "dc:{new|used|cpo}:si:vehicle details:value your trade:<nameplate>",
"channel": "search inventory",
"hier": "shopping tools:value your trade:<vehicle category>:<nameplate>",
"pagenamenovehicle": "dc:{new|used|cpo}:si:vehicle details:value your trade",
"slugs": "trade-in-appraisal,value-your-trade"
}
]
}
]
JSON;
function lbx_get_adobe_data_array() {
static $data = null;
if ($data === null) {
$data = json_decode(LBX_ADOBE_JSON, true);
if (!is_array($data)) $data = [];
}
return $data;
}
if (!function_exists('adobe_contains_value')) {
function adobe_contains_value($text, $words) {
$array = explode("-", strtolower($words));
$total_words = count($array);
$vehicle = array_map('strtolower', explode('-', $text));
$total_coincidences = 0;
foreach ($array as $item) {
$total_i = count(array_filter($vehicle, function ($var) use ($item) {
return strpos($var, $item) !== false;
}));
$total_p = count(array_filter($vehicle, function ($var) use ($item) {
return strpos(str_replace("-", "", $var), str_replace("-", " ", $item)) !== false;
}));
if ($total_i > 0 || $total_p)
$total_coincidences++;
}
return $total_words == $total_coincidences;
}
}
function get_adobe_data_from_slug($slug) {
$adobeData = lbx_get_adobe_data_array();
if (!empty($adobeData) && !empty($adobeData[0]['pages'])) {
$slug_lower = strtolower(trim($slug));
// Primero buscar coincidencia EXACTA
foreach ($adobeData[0]['pages'] as $aData) {
$slugs = array_map('trim', explode(',', $aData['slugs'] ?? ''));
foreach ($slugs as $aSlug) {
if ($aSlug !== '' && strtolower($aSlug) === $slug_lower) {
return $aData;
}
}
}
// Si no hay coincidencia exacta, buscar coincidencia por palabras
// (solo si tienen el mismo número de segmentos, para no matchear ej. ev-vhp-contact-us-thank-you con ev-vhp-contact-us)
$slug_parts = count(explode('-', $slug_lower));
foreach ($adobeData[0]['pages'] as $aData) {
$slugs = array_map('trim', explode(',', $aData['slugs'] ?? ''));
foreach ($slugs as $aSlug) {
if ($aSlug !== '' && count(explode('-', strtolower($aSlug))) === $slug_parts && adobe_contains_value($slug, $aSlug)) {
return $aData;
}
}
}
}
return null;
}
function get_adobe_forms_data_from_slug($slug, $veh = 'nonvehicle') {
$adobeData = lbx_get_adobe_data_array();
if (empty($adobeData)) return null;
// Selección del bloque
$key = in_array($veh, ['home-vrmi','vls','nonvehicle','vehicle'], true) ? $veh : 'nonvehicle';
$items = $adobeData[0][$key] ?? [];
$slug_lower = strtolower(trim($slug));
// Primero coincidencia exacta
foreach ($items as $aData) {
$slugs = array_map('trim', explode(',', $aData['slugs'] ?? ''));
foreach ($slugs as $aSlug) {
if ($aSlug !== '' && strtolower($aSlug) === $slug_lower) {
return $aData;
}
}
}
// Luego coincidencia por palabras
foreach ($items as $aData) {
$slugs = array_map('trim', explode(',', $aData['slugs'] ?? ''));
foreach ($slugs as $aSlug) {
if ($aSlug !== '' && adobe_contains_value($slug, $aSlug)) {
return $aData;
}
}
}
return null;
}
/* GET OEM PROGRAM */
function get_oem_program()
{
$oem_program = "leadbox";
$lbSettings = get_leadbox_settings();
if (
isset($lbSettings) && !empty($lbSettings) && isset($lbSettings["oem_program"])
&& !empty($lbSettings["oem_program"]) && (strlen($lbSettings["oem_program"]) > 0)
) {
$oem_program = strtolower($lbSettings["oem_program"]);
}
return $oem_program;
}
/* GET JLR ENVIRONMENT */
function get_jlr_environment()
{
$environment = "staging";
$lbSettings = get_leadbox_settings();
if (
isset($lbSettings) && !empty($lbSettings) && isset($lbSettings["jlr_version"])
&& !empty($lbSettings["jlr_version"]) && (strlen($lbSettings["jlr_version"]) > 0)
) {
$environment = strtolower($lbSettings["jlr_version"]);
}
return $environment;
}
/* GET JLR TAGGING */
function show_jlr_tagging()
{
$show = false;
$lbSettings = get_leadbox_settings();
if (
isset($lbSettings) && !empty($lbSettings) && isset($lbSettings["jlr_option"])
&& !empty($lbSettings["jlr_option"]) && (strtolower($lbSettings["jlr_option"]) == "enabled")
) {
$show = true;
}
return $show;
}
function jlr_contains_value($text, $words)
{
$array = explode("-", strtolower($words));
$total_words = count($array);
$vehicle = array_map('strtolower', explode('-', $text));
$total_coincidences = 0;
foreach ($array as $item) {
$total_i = count(array_filter($vehicle, function ($var) use ($item) {
return strpos($var, $item) !== false;
}));
$total_p = count(array_filter($vehicle, function ($var) use ($item) {
return strpos(str_replace("-", "", $var), str_replace("-", " ", $item)) !== false;
}));
if ($total_i > 0 || $total_p)
$total_coincidences++;
}
if ($total_words == $total_coincidences) {
return true;
} else {
return false;
}
}
const LBX_JLR_JSON = <<<JSON
[
{
"forms": [
{
"formtype": "Get a Quote",
"coincidences": "get-a-quick-quote"
},
{
"formtype": "Test Drive",
"coincidences": "test-drive, book-a-test-drive"
},
{
"formtype": "Request More Info",
"coincidences": "request-more-information, request-more-info,confirm-availability,check-availability"
},
{
"formtype": "email a Friend",
"coincidences": "email-a-friend"
},
{
"formtype": "General Contact",
"coincidences": "contact, contact-us"
},
{
"formtype": "Service",
"coincidences": "service"
},
{
"formtype": "Parts",
"coincidences": "parts, request-parts"
},
{
"formtype": "Schedule Service",
"coincidences": "schedule-service, service-appointment,book-an-appointment"
},
{
"formtype": "Employment",
"coincidences": "employment, job-opportunities, employment-opportunities"
},
{
"formtype": "Trade In",
"coincidences": "trade-in, trade-in-appraisal, trade-in-value"
},
{
"formtype": "Finance",
"coincidences": "finance,financing"
},
{
"formtype": "Payment Estimator",
"coincidences": "payment-estimator, payment-calculator"
},
{
"formtype": "Specials",
"coincidences": "specials"
},
{
"formtype": "Vehicle Finder",
"coincidences": "vehicle-finder"
},
{
"formtype": "Dealer Custom",
"coincidences": "dealer-custom"
},
{
"formtype": "Make an Offer",
"coincidences": "make-an-offer"
},
{
"formtype": "Send to Mobile",
"coincidences": "send-to-mobile"
},
{
"formtype": "Other",
"coincidences": "other"
}
]
}
]
JSON;
const LBX_JLR_PAGE_TYPES_JSON = <<<JSON
[
{
"pages": [
{
"pagename": "Home",
"coincidences": "Home, homepage"
},
{
"pagename": "Model Showroom",
"coincidences": "model-showroom, showroom"
},
{
"pagename": "Brochure",
"coincidences": "Brochure"
},
{
"pagename": "Trade In",
"coincidences": "trade-in-value,trade-in-appraisal"
},
{
"pagename": "Vehicle Listing",
"coincidences": "new-inventory, used-inventory"
},
{
"pagename": "Vehicle Details",
"coincidences": "view"
},
{
"pagename": "Test Drive",
"coincidences": "schedule-a-test-drive, test-drive"
},
{
"pagename": "Dealer Specials",
"coincidences": "new-vehicle-specials, used-vehicle-specials, specials"
},
{
"pagename": "OEM Incentives",
"coincidences": "oem-incentives"
},
{
"pagename": "Special Offers",
"coincidences": "gm-special-offers"
},
{
"pagename": "Service Specials",
"coincidences": "service-specials"
},
{
"pagename": "CPOV Program",
"coincidences": "cpov-program"
},
{
"pagename": "Finance",
"coincidences": "finance, financing"
},
{
"pagename": "Finance Prequalification",
"coincidences": "finance-prequalification"
},
{
"pagename": "Service",
"coincidences": "service"
},
{
"pagename": "Schedule Service",
"coincidences": "schedule-service,book-an-appointment"
},
{
"pagename": "Tire Store",
"coincidences": "tire-store,tire-centre"
},
{
"pagename": "Parts",
"coincidences": "order-parts, parts"
},
{
"pagename": "Accessories",
"coincidences": "accessories"
},
{
"pagename": "About Us",
"coincidences": "about-us"
},
{
"pagename": "Hours & Directions",
"coincidences": "hours-and-directions"
},
{
"pagename": "Contact Us",
"coincidences": "contact-us"
},
{
"pagename": "Custom Dealer Content",
"coincidences": "custom-dealer-content"
},
{
"pagename": "Fleet",
"coincidences": "fleet-commercial"
},
{
"pagename": "Other",
"coincidences": "other"
},
{
"pagename": "Blog",
"coincidences": "blog"
},
{
"pagename": "Business Elite",
"coincidences": "business-elite"
},
{
"pagename": "Onstar",
"coincidences": "onstar"
},
{
"pagename": "Service Home",
"coincidences": "service-home"
},
{
"pagename": "Parts Home",
"coincidences": "parts-home"
},
{
"pagename": "Parts Order Form",
"coincidences": "order-parts"
},
{
"pagename": "Parts Specials",
"coincidences": "parts-specials, special-parts"
},
{
"pagename": "Service Specials",
"coincidences": "service-specials, special-service"
},
{
"pagename": "Accessories Home",
"coincidences": "accessories-home"
},
{
"pagename": "DriverGear",
"coincidences": "drivergear"
},
{
"pagename": "Service Event",
"coincidences": "service-event"
},
{
"pagename": "Maintenance Menu",
"coincidences": "maintenance-menu"
},
{
"pagename": "VW Care Maintenance",
"coincidences": "vw-care-maintenance"
},
{
"pagename": "Service Xpress",
"coincidences": "service-xpress"
},
{
"pagename": "Service Credit Card",
"coincidences": "service-credit-card"
},
{
"pagename": "Competitive Advantage",
"coincidences": "competitive-advantage"
}
]
}
]
JSON;
function lbx_get_jlr_data_array() {
static $data = null;
if ($data === null) {
$data = json_decode(LBX_JLR_JSON, true);
if (!is_array($data)) $data = [];
}
return $data;
}
function lbx_get_jlr_page_types_data_array() {
static $data = null;
if ($data === null) {
$data = json_decode(LBX_JLR_PAGE_TYPES_JSON, true);
if (!is_array($data)) $data = [];
}
return $data;
}
function get_jlr_data_from_slug($slug, $checkForm = false)
{
if ($checkForm) {
$jlrData = lbx_get_jlr_data_array();
if (isset($jlrData)) {
foreach ($jlrData[0]["forms"] as $jData) {
$coincidences = explode(",", $jData["coincidences"]);
foreach ($coincidences as $coincidence) {
if (jlr_contains_value(trim($slug), trim($coincidence))) {
return $jData;
}
}
}
}
return ["formtype" => "Other"];
} else {
$jlrData = lbx_get_jlr_page_types_data_array();
if (isset($jlrData)) {
foreach ($jlrData[0]["pages"] as $jData) {
$coincidences = explode(",", $jData["coincidences"]);
foreach ($coincidences as $coincidence) {
if (jlr_contains_value(trim($slug), trim($coincidence))) {
return $jData;
}
}
}
}
return ["pagename" => "Other"];
}
}
/* GET FORD ADOBE ENVIRONMENT */
function get_ford_adobe_environment()
{
$environment = "staging";
$lbSettings = get_leadbox_settings();
if (
isset($lbSettings) && !empty($lbSettings) && isset($lbSettings["ford_adobe_version"])
&& !empty($lbSettings["ford_adobe_version"]) && (strlen($lbSettings["ford_adobe_version"]) > 0)
) {
$environment = strtolower($lbSettings["ford_adobe_version"]);
}
return $environment;
}
/* GET GENERAL ADOBE VALUES */
function get_general_adobe_values($post, $from, $vehicle_id)
{
// Manifest requests are erroring due to lack of get_post()
$post = $post ?? get_post();
if (is_null($post)) {
return [
'pagename' => null,
'channel' => null,
'hier' => null,
'pagenamenovehicle' => null,
];
}
$slug = $post->post_name;
$title = $post->post_title;
$home = is_front_page() || is_home();
$adobe_value = [];
if (isset($vehicle_id))
$data = get_vehicle_by_id($vehicle_id);
else
$data = [];
if ($home || strtolower($slug) == "home") {
$adobe_value["pagename"] = htmlspecialchars("dc:home", ENT_QUOTES);
$adobe_value["channel"] = "home";
$adobe_value["hier"] = "home";
$adobe_value["pagenamenovehicle"] = htmlspecialchars("dc:home", ENT_QUOTES);
} else {
if ((isset($from) && !empty($from)) || (isset($data) && !empty($data))) {
$adobe_value = get_adobe_forms_data_from_slug($slug, (isset($from) && strlen($from) > 0) ? 'vls' : ((isset($data) && count($data) > 0) ? 'vehicle' : 'nonvehicle'));
// Páginas thank-you y otras de formulario están en nonvehicle; si no hubo match, intentar nonvehicle
if (!isset($adobe_value) || empty($adobe_value)) {
$adobe_value = get_adobe_forms_data_from_slug($slug, 'nonvehicle');
}
} else {
$adobe_value = get_adobe_forms_data_from_slug($slug, 'nonvehicle');
if (!isset($adobe_value) || empty($adobe_value)) {
$adobe_value = get_adobe_data_from_slug($slug);
}
}
if (!has_block('leadbox/inventory-block', $post) && !isset($adobe_value)) {
$adobe_value["pagename"] = htmlspecialchars("dc:custom:" . strtolower($title), ENT_QUOTES);
$adobe_value["channel"] = "custom";
$adobe_value["hier"] = "custom";
$adobe_value["pagenamenovehicle"] = htmlspecialchars("dc:custom:" . strtolower($title), ENT_QUOTES);
}
}
return $adobe_value;
}
function get_leadbox_manufacturer()
{
$lbsettings = get_option('leadbox-settings');
if (isset($lbsettings) && !empty($lbsettings) && isset($lbsettings["manufacturer"]) && !empty($lbsettings["manufacturer"])) {
return strtolower(trim($lbsettings["manufacturer"]));
} else {
return "";
}
}
function getYoutubeEmbedUrl($url)
{
$rx = '~^(?:https?://)?(?:www[.])?(?:youtube[.]com/watch[?]v=|youtu[.]be/)([^&]{11})~x';
if (preg_match($rx, $url, $matches)) {
$youtube_id = $matches[count($matches) - 1];
}
return 'https://www.youtube.com/embed/' . $youtube_id;
}
function vdp_key($car_id, $date) {
return "vdp:{$car_id}:{$date}";
}
function vdp_record_view_transient($car_id) {
$car_id = (int) $car_id;
if ($car_id <= 0) return;
$today = current_time('Y-m-d');
$key = vdp_key($car_id, $today);
$count = get_transient($key);
if ($count === false) { $count = 0; }
$count++;
// guarda por 8 días para poder sumar últimos 7 con margen
set_transient($key, $count, DAY_IN_SECONDS * 8);
wp_cache_delete("vdp7d:$car_id", 'vdp');
}
function vdp_get_7d_count_transient($car_id) {
$car_id = (int) $car_id;
if ($car_id <= 0) return 0;
$cached = wp_cache_get("vdp7d:$car_id", 'vdp');
if ($cached !== false) {
return (int)$cached;
}
$sum = 0;
for ($i = 0; $i < 7; $i++) {
$date = date('Y-m-d', strtotime(current_time('Y-m-d') . " -$i days"));
$sum += (int) (get_transient(vdp_key($car_id, $date)) ?: 0);
}
wp_cache_set("vdp7d:$car_id", $sum, 'vdp', MINUTE_IN_SECONDS * 10);
return $sum;
}
function setVdpCountCar($id) {
vdp_record_view_transient($id);
}
function getVdpCountCar($id) {
return vdp_get_7d_count_transient($id);
}
function isKinstaUrl()
{
$actual_link = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
if (strpos($actual_link, 'kinsta') !== false && strpos($actual_link, 'cloud') !== false) {
//var_dump($actual_link);
if (strpos($actual_link, 'leadboxegyptqa') !== false) {
return false;
} else
return true;
}
}
function get_upgrade_name($name)
{
switch ($name) {
case 'G-1':
return 'One Owner';
break;
case 'G-2':
return 'Clean Carproof';
break;
case 'G-3':
return 'In Demand Color';
break;
case 'G-4':
return 'Low Kms';
break;
case 'G-5':
return 'New Brakes';
break;
case 'G-6':
return 'New Tires';
break;
case 'G-7':
return 'Oil Change';
break;
case 'G-8':
return 'New Wiper Blades';
break;
case 'G-9':
return 'New Air Filter';
break;
case 'G-10':
return 'Mpi Certified';
break;
case 'G-11':
return 'Vehicle Detailed';
break;
case 'G-12':
return 'New Arrival';
break;
default:
return '';
break;
}
}
function get_compare_add_url($lang = 'en')
{
$view = 'recherche';
if (strpos($lang, 'en') !== false) {
$view = 'search';
}
//$vehicle = get_vehicle_by_id($id);
return "/" . $view;
}
function get_local_line_up()
{
$route = '/resources/config/line-up.json';
$jsonPath = get_fileInGenius($route);
if (file_exists($jsonPath . $route)) {
return json_decode(file_get_contents($jsonPath . $route), true);
} else {
return null;
}
}
function get_local_used_line_up()
{
$route = '/resources/config/used-line-up.json';
$jsonPath = get_fileInGenius($route);
if (file_exists($jsonPath . $route)) {
return json_decode(file_get_contents($jsonPath . $route), true);
} else {
return null;
}
}
function enqueueIsolatedScript($name, $lib = null){
$theme_version = 0;
// Check if theme activated is child or parent
if (get_stylesheet() !== get_template())
$theme_version = wp_get_theme()->parent()->get('Version');
else
$theme_version = wp_get_theme()->get('Version');
$wp_scripts = wp_scripts();
if(! in_array("genius/isolated/{$name}", $wp_scripts->queue)) {
// Removed complicated lookup
$file = get_theme_file_uri("/public/scripts/isolated/{$name}.js");
wp_register_script("genius/isolated/{$name}", $file, [], $theme_version);
wp_enqueue_script("genius/isolated/{$name}", $lib, ['sage/vendor.js', 'sage/app.js'], null, true);
}
}
function mileage_format($n)
{
return (number_format(floatval($n), 0));
}
function createCarfaxBadge($vin, $accountNumber, $WebServiceToken)
{
$badge = "";
if (!$WebServiceToken)
$WebServiceToken = 'BE/s9XcA33ZXLiTl/ak3oXSu+pvkuewrU18T6xZChc9v/JYbMyYfAB3a0algBvj+q80PGUAjsl9UAwHD4BJxuYmsLaxaP3UlQyOjiDfSmDA7Jq8OphhSoDSmxycFIK7RV5tl1HTie6tGM9R6HLQgbxTTz03chsVY4LpWM7reM1FsSA1y/pbMsVVDTj7wx/ZBuYGh+0TLhdbEZD+N+g7TQVUkU2kxONCZ5T2Gi+0u7wwP7m/h/mgQHIzDYYQAe8F4rydJficMnedRH+jRr+eTEsr1V1a9K6/an2MyZGAkyVkXNO4mU0EVNTYaSoqLeXdUvYXsslQ/2/wOs+XlEp+X4GD2xLfKKELpc2KK8YuGvWLqRUr8aVS8moQ/ff4tk0MFR9ookE3sJF15roh8hgkXBw==';
$ch = curl_init();
$lang = "EN";
if (get_locale() == "fr_CA")
$lang = "FR";
$url = "https://badgingapi.carfax.ca/api/v2/badges/" . $vin . "?accountNumber=" . $accountNumber . "&language=" . $lang . "";
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt(
$ch,
CURLOPT_HTTPHEADER,
array(
'Accept: application/json',
'WebServiceToken: ' . $WebServiceToken . ' '
)
);
$resp = curl_exec($ch);
if ($e = curl_error($ch)) {
$e;
} else {
$decoded = json_decode($resp);
if($decoded){
if ($decoded->ResultCode == 1) {
$badge = "<a href='" . $decoded->BadgesList[0]->VhrReportUrl . "' target='_blank'>
<img class='pt-1 pb-1 m-auto' src='" . $decoded->BadgesList[0]->BadgesImageUrl . "'>
</a>";
curl_close($ch);
return $badge;
}
}
}
}
function getGraphqlAuthToken()
{
$endpoint = getGraphqlEndPoint();
$request_body = wp_json_encode([
'query' => '
mutation LoginUser {
login(
input: {clientMutationId: "uniqueId", username: "content-reader", password: "6det@avt1$J3^NfdBL4FcgGL"}
) {
authToken
}
}
'
]);
$response = wp_remote_request($endpoint, [
'method' => 'POST',
'timeout' => 50,
'headers' => [
'Content-Type' => 'application/json'
],
'body' => $request_body
]);
if (is_wp_error($response)) {
throw new \Exception($response->get_error_message());
}
$decoded_response = json_decode($response['body'], true);
$auth_token = $decoded_response['data']['login']['authToken'];
return $auth_token;
}
function getGraphqlEndPoint() {
$lbSettings = get_leadbox_settings();
if (!isset($lbSettings['graphql_url']) || empty($lbSettings['graphql_url'])) {
return 'https://minerva.stellate.sh/graphql';
}else{
return $lbSettings['graphql_url'];
}
}
function get_adobe_vehicle_type($type)
{
if (isset($type)) {
if (isFrench()) {
switch (strtolower($type)) {
case 'voiture':
return "car";
break;
case 'vus':
return "suv";
break;
case 'camion':
return "truck";
break;
case 'monospace':
return "van";
break;
case 'utilitaire':
return "commercial";
break;
default:
return "car";
break;
}
} else {
if (strtolower(str_replace(' ', '', trim($type))) == "other") {
return "car";
} else {
return strtolower(str_replace(' ', '', trim($type)));
}
}
}
//if there is not vehicle type set by default return car
return "car";
}
function get_tax_from_province()
{
$taxes = array(
"AB" => 5,
"BC" => 12,
"MB" => 12,
"NB" => 15,
"NL" => 15,
"NT" => 5,
"NS" => 15,
"NU" => 5,
"ON" => 13,
"PE" => 15,
"QC" => 15,
"SK" => 11,
"YT" => 5
);
$contact = get_dealer_contact();
if (isset($contact) && !empty($contact) && isset($contact["address_province"]) && !empty($contact["address_province"])) {
if (isset($taxes[$contact["address_province"]]))
return $taxes[$contact["address_province"]];
else
return 13;
} else
return 13;
}
function get_tax_label_province()
{
$label = array(
"AB" => 'GST',
"BC" => 'GST + PST',
"MB" => 'GST + PST',
"NB" => 'HST',
"NL" => 'HST',
"NT" => 'GST',
"NS" => 'HST',
"NU" => 'GST',
"ON" => 'HST',
"PE" => 'HST',
"QC" => 'GST + QST',
"SK" => 'GST + PST',
"YT" => 'GST'
);
$label_fr = array(
"AB" => 'TPS',
"BC" => 'TPS + TVP',
"MB" => 'TPS + TVP',
"NB" => 'TVH',
"NL" => 'TVH',
"NT" => 'TPS',
"NS" => 'TVH',
"NU" => 'TPS',
"ON" => 'TVH',
"PE" => 'TVH',
"QC" => 'TPS + TVQ',
"SK" => 'TPS + TVP',
"YT" => 'TPS'
);
$contact = get_dealer_contact();
if (isset($contact) && !empty($contact) && isset($contact["address_province"]) && !empty($contact["address_province"])) {
$lang = get_locale();
if ($lang == 'fr_CA'){
if (isset($label_fr[$contact["address_province"]]))
return $label_fr[$contact["address_province"]];
else
return 'TVH';
}
else{
if (isset($label[$contact["address_province"]]))
return $label[$contact["address_province"]];
else
return 'HST';
}
} else
return 'HST';
}
function find_url($url = NULL)
{
if (empty($url)) {
return false;
}
$response = wp_remote_head($url, array('timeout' => 5));
$accepted_response = array(200, 301, 302);
if (!is_wp_error($response) && in_array(wp_remote_retrieve_response_code($response), $accepted_response)) {
return true;
} else {
return false;
}
}
/**
* This function adds "async" and "defer" parameters to JavaScript resources.
* Just add "async" or "defer" anywhere in the resource name
* ("handle" attribute of the wp_register_script function).
*
* @param $tag
* @param $handle
*
* @return mixed
*/
function add_async_defer_attributes_to_scripts($tag, $handle)
{
// Search for the "async" value
if (strpos($handle, "async")):
$tag = str_replace(' src', ' async="async" src', $tag);
endif;
// Search for the "defer" value
if (strpos($handle, "defer")):
$tag = str_replace(' src', ' defer="defer" src', $tag);
endif;
return $tag;
}
add_filter('script_loader_tag', 'add_async_defer_attributes_to_scripts', 10, 2);
/**
* Returns the finance amount based on dealer frequency.
* @var int $price
* @var float $rate
* @var int $term
*
* @return int $financeTotal
*/
function getFinanceTotal($price = int, $rate = float, $term = int)
{
if ($price != 0 && $rate != 0 && $term != 0) {
$financeTotal = round(($price * ($rate / 1200) * pow(1 + ($rate / 1200), $term)) / (pow(1 + ($rate / 1200), $term) - 1) * 100) / 100;
$financeTotal = round($financeTotal, 2);
switch (get_leadbox_finance_settings()['finance_frequency']) {
case 'Weekly':
$financeTotal = round(($financeTotal * 12) / 52);
break;
case 'Bi-Weekly':
$financeTotal = round(((($financeTotal * 12) / 52) * 2));
break;
case 'Monthly':
$financeTotal = round($financeTotal);
break;
}
return $financeTotal;
}
return null;
}
/**
* Returns the lease amount based on dealer frequency.
* @var int $price
* @var int $term
* @var float $rate
* @var int $adjustment
* @var int $residual
*
* @return int $leaseTotal
*/
function getLeaseTotal($price = int, $term = int, $rate = float, $residual = int)
{
$moneyFactor = ($rate / 2400);
$newResidual = $price * ($residual / 100);
$depretiation = 0;
if ($term > 0)
$depretiation = ($price - ($price * ($residual / 100))) / $term;
$financeFee = ($price + $newResidual) * $moneyFactor;
$monthlyLease = $financeFee + $depretiation;
switch (get_leadbox_finance_settings()['lease_frequency']) {
case 'Weekly':
$leaseTotal = round(($monthlyLease * 12) / 52);
break;
case 'Bi-Weekly':
$leaseTotal = round((($monthlyLease * 12) / 26));
break;
case 'Monthly':
$leaseTotal = round($monthlyLease);
break;
}
return $leaseTotal;
}
/**
* Returns the structure that a custom sitemap must have in order to be readable by Yoast.
*
* @param string $url
*
* @return string $output
*/
function create_custom_sitemap_url($url)
{
$url = htmlspecialchars($url);
$output = "\t<url>\n";
$output .= "\t\t<loc>" . $url . "</loc>\n";
$output .= '';
$output .= "\t\t<lastmod>" . date('c', time()) . "</lastmod>\n";
$output .= "\t</url>\n";
return $output;
}
function cmp($a, $b)
{
$keyA = ($a['model'] ?? '') . ($a['year'] ?? '');
$keyB = ($b['model'] ?? '') . ($b['year'] ?? '');
if ($keyA == $keyB) {
return 0;
}
return ($keyA < $keyB) ? -1 : 1;
}
/**
* Returns the first segment of URL.
*
*
* @return string $output
*/
function check_url_first_segment() {
$current_url = $_SERVER['REQUEST_URI'];
$url_segments = explode('/', trim($current_url, '/'));
if (isset($url_segments[0])) {
return strtolower($url_segments[0]);
} else {
return "";
}
}
function get_local_dealer_stores()
{
$route = '/resources/config/dealer-stores.json';
$jsonPath = get_fileInGenius($route);
if (file_exists($jsonPath . $route)) {
return json_decode(file_get_contents($jsonPath . $route), true);
} else {
return null;
}
}
function get_dealer_stores($store) {
$dealerStores = get_local_dealer_stores();
if(isset($dealerStores) && !empty($dealerStores) && isset($dealerStores['stores']) && !empty($dealerStores['stores'])) {
$dealerStores = $dealerStores['stores'];
foreach ($dealerStores as $dealerStore) {
if ($dealerStore['lblocation'] == $store) {
return $dealerStore;
}
}
return null;
}
else {
return null;
}
}
/**
* Owning-site geo payload for the vehicle-card distance badge.
*
* Every vehicle on this site sits at the dealer (e.g. Derrick Dodge), so the
* badge shows the dealer city plus how far the BUYER is from it. This exposes
* the dealer's coordinates + city from Dealer Settings → Contact
* (`dealer-settings-contact-options`); the buyer side (geolocation + haversine)
* is computed client-side in spa-vehicle-card.vue.
*
* Returns null when the vehicle-card `show-location-distance` option is off, or
* when there is neither coordinates nor a city to show — keeping the badge fully
* opt-in. Consumed through the window.LBX_DEALER_LOCATION global injected in
* head.blade.php.
*
* @return array{lat: ?float, lng: ?float, city: string, name: string, locations: ?array<string, array{city: string, lat: ?float, lng: ?float}>}|null
*/
function get_dealer_geo_payload() {
$enabled = defined('GENIUS') && (
(GENIUS['vehicle-card']['data']['show-location-distance'] ?? false)
|| (GENIUS['vdp-title']['data']['show-location-distance'] ?? false)
);
if (!$enabled) {
return null;
}
$contact = get_dealer_contact();
if (empty($contact)) {
return null;
}
$latRaw = isset($contact['latitude']) ? lbx_normalize_coordinate($contact['latitude']) : '';
$lngRaw = isset($contact['longitude']) ? lbx_normalize_coordinate($contact['longitude']) : '';
$city = isset($contact['address_city']) ? trim($contact['address_city']) : '';
$name = isset($contact['dealer_name']) ? trim($contact['dealer_name']) : '';
// Per-store overrides for multi-location inventories: GENIUS['locations'] maps
// a vehicle's `location` (store name from the feed) to its own city and,
// optionally, coordinates. Entries can be "Store" => "City" or
// "Store" => { city, lat, lng }. Vehicles whose location is not in the map
// keep the owning-site city/coords above.
$locations = [];
$rawLocations = GENIUS['locations'] ?? [];
if (is_array($rawLocations)) {
foreach ($rawLocations as $store => $entry) {
if (is_string($entry)) {
$entry = ['city' => $entry];
}
if (!is_array($entry)) {
continue;
}
$entryCity = isset($entry['city']) ? trim((string) $entry['city']) : '';
$entryLat = isset($entry['lat']) ? lbx_normalize_coordinate($entry['lat']) : '';
$entryLng = isset($entry['lng']) ? lbx_normalize_coordinate($entry['lng']) : '';
if ($entryCity === '' && $entryLat === '' && $entryLng === '') {
continue;
}
$locations[$store] = [
'city' => $entryCity,
'lat' => $entryLat !== '' ? (float) $entryLat : null,
'lng' => $entryLng !== '' ? (float) $entryLng : null,
];
}
}
// No coordinates, no city and no per-store map => nothing worth showing.
if ($latRaw === '' && $lngRaw === '' && $city === '' && empty($locations)) {
return null;
}
return [
'lat' => $latRaw !== '' ? (float) $latRaw : null,
'lng' => $lngRaw !== '' ? (float) $lngRaw : null,
'city' => $city,
'name' => $name,
'locations' => !empty($locations) ? $locations : null,
// Which surfaces show the badge — so each only prompts for geolocation when
// its own badge is on (e.g. SRP off + VDP on => no prompt on the listing).
'srp' => (bool) (GENIUS['vehicle-card']['data']['show-location-distance'] ?? false),
'vdp' => (bool) (GENIUS['vdp-title']['data']['show-location-distance'] ?? false),
// City-only mode: `show-location-distance` set to "city" shows the store
// city but never prompts for geolocation nor renders a distance.
'srpCityOnly' => strtolower((string) (GENIUS['vehicle-card']['data']['show-location-distance'] ?? '')) === 'city',
'vdpCityOnly' => strtolower((string) (GENIUS['vdp-title']['data']['show-location-distance'] ?? '')) === 'city',
];
}
function is_store_open($hours) {
try {
$timezone = wp_timezone();
} catch (Exception $e) {
$timezone = new DateTimeZone('Canada/Eastern');
}
$now = new DateTime('now', $timezone);
if (empty($hours) || !str_contains($hours, '-') || stripos($hours, 'closed') !== false) {
return "Closed";
}
$split_hours = explode("-", $hours);
$hours_start = DateTime::createFromFormat('g:i A', trim($split_hours[0]), $timezone);
$hours_end = DateTime::createFromFormat('g:i A', trim($split_hours[1]), $timezone);
if ($hours_start && $hours_end) {
if ($hours_end < $hours_start) {
$hours_end->modify('+1 day');
}
if ($now >= $hours_start && $now <= $hours_end) {
return "Open";
}
}
return "Closed";
}
function findStatusInInventory($status)
{
$inventory = get_search_inventory();
$count = 0;
$vehicles = array_filter($inventory, function ($vehicle) use ($status, &$count) {
if ($status == 'certified' && $vehicle['certified']) {
$count++;
return true;
} else if ($status == 'salepending' && $vehicle['salepending']) {
$count++;
return true;
} else if ($status == 'special' && $vehicle['special']) {
$count++;
return true;
} else if ($status == 'new' && $vehicle['condition'] == 'New') {
$count++;
return true;
} else if ($status == 'used' && $vehicle['condition'] == 'Used') {
$count++;
return true;
}
return false;
});
return $count;
}
function textSalePhone() {
if (!isFrench()) {
return 'Sales';
} else {
return 'Ventes';
}
}
function textServicePhone() {
if (!isFrench()) {
return 'Service';
} else {
return 'Service';
}
}
function textPartsPhone() {
if (!isFrench()) {
return 'Parts';
} else {
return 'Pièces';
}
}
function is_current_time_in_range($timeRange, $currentTime) {
$isFrench = function_exists('isFrench') && isFrench();
// Considerar "Closed" o "Fermé" como cerrado
if ($timeRange === 'Closed' || ($isFrench && $timeRange === 'Fermé')) {
return false;
}
// Separar la hora de inicio y fin del rango, soportando diferentes tipos de guion
$timeParts = preg_split('/\s*[-–—]\s*/', $timeRange);
if (count($timeParts) < 2) return false; // Si no hay un rango válido, retorna falso
[$start, $end] = $timeParts;
// Convertir ambas a timestamps comparables
$startTime = strtotime($start);
$endTime = strtotime($end);
$now = strtotime($currentTime);
return ($now >= $startTime && $now <= $endTime);
}
// Función para agrupar días consecutivos con soporte para francés
function group_consecutive_days($days) {
$grouped = [];
$temp = [];
// Determinar si es francés
$isFrench = function_exists('isFrench') && isFrench();
// Usar el orden correcto según el idioma
$dayOrder = $isFrench
? ["Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi", "Dimanche"]
: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];
foreach ($dayOrder as $day) {
if (in_array($day, $days)) {
$temp[] = $day;
} else {
if (!empty($temp)) {
$grouped[] = $temp;
$temp = [];
}
}
}
if (!empty($temp)) {
$grouped[] = $temp;
}
return $grouped;
}
// Función para agrupar horarios con soporte para francés
function group_hours($hours) {
$groupedHours = [];
// Definir los días en inglés y su equivalente en francés
$dayOrder = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];
$dayOrderFr = ["Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi", "Dimanche"];
// Determinar si se debe traducir
$isFrench = function_exists('isFrench') && isFrench();
$dayMap = array_combine($dayOrder, $isFrench ? $dayOrderFr : $dayOrder);
foreach ($hours as $day => $time) {
$translatedDay = $dayMap[$day] ?? $day; // Traducir días si es necesario
$translatedTime = ($isFrench && $time === "Closed") ? "Fermé" : $time; // Traducir "Closed" a "Fermé"
$groupedHours[$translatedTime][] = $translatedDay;
}
// Ordenar los días dentro de cada grupo
foreach ($groupedHours as $time => &$days) {
$daysOrder = $isFrench ? $dayOrderFr : $dayOrder;
usort($days, function($a, $b) use ($daysOrder) {
return array_search($a, $daysOrder) <=> array_search($b, $daysOrder);
});
}
unset($days);
return $groupedHours;
}
function get_meta_yoast_inventory() {
// Ruta al archivo inventory.json
$inventory_file = wp_get_upload_dir()['basedir'] . '/data/inventory.json';
// Verificar si el archivo existe
if (!file_exists($inventory_file)) {
return []; // Retornar un array vacío si el archivo no existe
}
// Leer y decodificar el archivo JSON
$inventory = json_decode(file_get_contents($inventory_file), true);
if (json_last_error() !== JSON_ERROR_NONE || !isset($inventory['vehicles'])) {
return [];
}
$urls = []; // Array para almacenar las URLs
$current_language = get_locale();
//* Recorrer los vehículos en el inventario
foreach ($inventory['vehicles'] as $item) {
// Obtener la URL en el idioma actual
$slug = get_vdp_slug($item, $current_language);
$useVin = GENIUS['vehicle-card']['data']['use-slug-vin'] ?? false;
if ($useVin) {
$slug = str_replace('-' . $item['id'], '-' . $item['vin'] . '-' . $item['id'], $slug);
}
$full_url = get_site_url() . $slug;
array_push($urls, $full_url);
//* Si Polylang está activo y el idioma actual no es francés, agregar la URL en francés
if (function_exists('pll_default_language') && $current_language !== 'fr_FR') {
$slug_fr = get_vdp_slug($item, 'fr');
$full_url_fr = get_site_url() . $slug_fr;
array_push($urls, $full_url_fr);
}
}
return $urls; // Retornar el array de URLs
}
function generate_sitemap_xml() {
// Obtener las URLs del inventario
$urls = get_meta_yoast_inventory();
// Crear el elemento raíz del XML
$xml = new SimpleXMLElement('<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"/>');
// Iterar sobre las URLs y añadirlas al XML
foreach ($urls as $url) {
$url_node = $xml->addChild('url');
$url_node->addChild('loc', $url);
$url_node->addChild('lastmod', date('Y-m-d')); // Fecha actual
$url_node->addChild('changefreq', 'weekly'); // Frecuencia de cambio
$url_node->addChild('priority', '0.7'); // Prioridad
}
// Devolver el XML como una cadena
header('Content-Type: text/xml');
echo $xml->asXML();
exit;
}
function my_sitemap_rewrite_custom() {
add_rewrite_rule('^inventory\.xml$', 'index.php?custom_xml_sitemap=true', 'top');
}
function custom_xml_sitemap_query_var($vars) {
$vars[] = 'custom_xml_sitemap';
return $vars;
}
function custom_xml_sitemap_request($wp) {
if (isset($wp->query_vars['custom_xml_sitemap']) && $wp->query_vars['custom_xml_sitemap'] === 'true') {
generate_sitemap_xml();
}
}
function removeAccents($string)
{
$table = array(
'Š' => 'S',
'š' => 's',
'Đ' => 'Dj',
'đ' => 'dj',
'Ž' => 'Z',
'ž' => 'z',
'Č' => 'C',
'č' => 'c',
'Ć' => 'C',
'ć' => 'c',
'À' => 'A',
'Á' => 'A',
'Â' => 'A',
'Ã' => 'A',
'Ä' => 'A',
'Å' => 'A',
'Æ' => 'A',
'Ç' => 'C',
'È' => 'E',
'É' => 'E',
'Ê' => 'E',
'Ë' => 'E',
'Ì' => 'I',
'Í' => 'I',
'Î' => 'I',
'Ï' => 'I',
'Ñ' => 'N',
'Ò' => 'O',
'Ó' => 'O',
'Ô' => 'O',
'Õ' => 'O',
'Ö' => 'O',
'Ø' => 'O',
'Ù' => 'U',
'Ú' => 'U',
'Û' => 'U',
'Ü' => 'U',
'Ý' => 'Y',
'Þ' => 'B',
'ß' => 'Ss',
'à' => 'a',
'á' => 'a',
'â' => 'a',
'ã' => 'a',
'ä' => 'a',
'å' => 'a',
'æ' => 'a',
'ç' => 'c',
'è' => 'e',
'é' => 'e',
'ê' => 'e',
'ë' => 'e',
'ì' => 'i',
'í' => 'i',
'î' => 'i',
'ï' => 'i',
'ð' => 'o',
'ñ' => 'n',
'ò' => 'o',
'ó' => 'o',
'ô' => 'o',
'õ' => 'o',
'ö' => 'o',
'ø' => 'o',
'ù' => 'u',
'ú' => 'u',
'û' => 'u',
'ý' => 'y',
'ý' => 'y',
'þ' => 'b',
'ÿ' => 'y',
'Ŕ' => 'R',
'ŕ' => 'r',
);
return strtr($string, $table);
}
function get_lineup_totals_for_navigation($lineup, $condition)
{
$inventory = get_search_inventory();
$conditionLower = strtolower($condition);
// Reglas especiales: nombre del lineup => función de matching
$specialRules = [
'f-150' => fn($v, $field) => preg_match("/f-150(?! lightning)/i", $v[$field] ?? ''),
'bronco' => fn($v, $field) => ($v[$field] ?? '') === 'bronco',
'f-150 lightning' => fn($v, $field) => ($v[$field] ?? '') === 'f-150 lightning',
'transit' => fn($v, $field) => ($v[$field] ?? '') === 'transit',
'transit electric' => fn($v, $field) => ($v[$field] ?? '') === 'e-transit',
'shelby f-150' => fn($v, $field) => ($v['model'] ?? '') === 'f-150' && stripos($v['tags'] ?? '', 'shelby') !== false,
'roush mustang' => fn($v, $field) => ($v['model'] ?? '') === 'mustang' && stripos($v['tags'] ?? '', 'roush') !== false,
'roush f-150' => fn($v, $field) => ($v['model'] ?? '') === 'f-150' && stripos($v['tags'] ?? '', 'roush') !== false,
'roush f-250' => fn($v, $field) => stripos($v['model'] ?? '', 'f-250') !== false && stripos($v['tags'] ?? '', 'roush') !== false,
'bronco raptor' => fn($v, $field) => stripos($v['model'] ?? '', 'bronco') !== false && stripos($v['trim'] ?? '', 'raptor') !== false,
'ranger raptor' => fn($v, $field) => stripos($v['model'] ?? '', 'ranger') !== false && stripos($v['trim'] ?? '', 'raptor') !== false,
'f-150 raptor' => fn($v, $field) => stripos($v['model'] ?? '', 'f-150') !== false && stripos($v['trim'] ?? '', 'raptor') !== false,
];
// Casos especiales que ignoran la condición
$specialNoCondition = ['roush mustang', 'shelby f-150', 'roush f-150', 'roush f-250', 'bronco raptor', 'ranger raptor', 'f-150 raptor'];
// Pre-normalizar vehículos una sola vez
$normalizedInventory = [];
foreach ($inventory as $vehicle) {
if (!isset($vehicle['condition'])) continue;
$normalizedInventory[] = [
'original' => $vehicle,
'condition' => strtolower($vehicle['condition']),
'model' => strtolower($vehicle['model'] ?? ''),
'trim' => strtolower($vehicle['trim'] ?? ''),
'tags' => strtolower($vehicle['tags'] ?? ''),
];
}
foreach ($lineup as &$item) {
$total = 0;
$nameLower = strtolower($item['name'] ?? '');
$field = $item['field'] ?? '';
$regex = $item['regex'] ?? '';
$specialRule = $specialRules[$nameLower] ?? null;
$isSpecialNoCondition = in_array($nameLower, $specialNoCondition);
foreach ($normalizedInventory as $nv) {
$vehicle = $nv['original'];
$matchesCondition = $nv['condition'] === $conditionLower;
if (!$matchesCondition && !$isSpecialNoCondition) continue;
if ($specialRule) {
$vehicleLower = [
'model' => $nv['model'],
'trim' => $nv['trim'],
'tags' => $nv['tags'],
$field => strtolower($vehicle[$field] ?? ''),
];
if ($specialRule($vehicleLower, $field)) {
$total++;
}
} elseif ($matchesCondition && $regex) {
$fieldValue = strtolower($vehicle[$field] ?? '');
if (preg_match($regex, $fieldValue)) {
$total++;
}
}
}
$item['total'] = $total;
}
return $lineup;
}
function prepare_grouped_hours($groupedHours)
{
$isFrench = function_exists('isFrench') && isFrench();
$dayOrder = $isFrench ? ['Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi', 'Dimanche'] : ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];
$entries = [];
foreach ($groupedHours as $time => $days) {
foreach (group_consecutive_days($days) as $group) {
$entries[] = [
'days' => $group,
'time' => $time,
'firstIndex' => array_search($group[0], $dayOrder),
];
}
}
usort($entries, fn($a, $b) => $a['firstIndex'] <=> $b['firstIndex']);
return $entries;
}
/**
* Obtener ID de formulario Ninja Forms por nombre (cacheado en opciones)
*/
function lbx_remember_transient( $key, $callback, $expiration = HOUR_IN_SECONDS ) {
$cached = get_transient( $key );
if ( $cached !== false ) {
return $cached;
}
$value = is_callable($callback) ? $callback() : null;
set_transient( $key, $value, $expiration );
return $value;
}
// Obtener todos los formularios [id => título]
function _lbx_get_all_forms() {
if ( ! function_exists('Ninja_Forms') ) return [];
$forms = Ninja_Forms()->form()->get_forms();
return collect($forms)
->mapWithKeys(fn($form) => [(int) $form->get_id() => (string) $form->get_setting('title')])
->toArray();
}
function lbx_get_all_forms() {
return lbx_remember_transient('lbx_all_ninja_forms', '_lbx_get_all_forms', DAY_IN_SECONDS);
}
// Normalizar nombres
function lbx_normalize_form_name( $name ) {
$name = strtolower( remove_accents( (string) $name ) );
$name = str_replace('-', ' ', $name);
$name = preg_replace('/[^\p{L}\p{N}\s]+/u', ' ', $name);
$name = preg_replace('/\s+/u', ' ', $name);
return trim($name);
}
// Mapa normalizado => ID (cacheado)
function lbx_get_forms_name_map() {
return lbx_remember_transient('lbx_nf_name_map', function () {
$forms = lbx_get_all_forms(); // [id => title]
$map = [];
foreach ($forms as $id => $title) {
$norm = lbx_normalize_form_name($title);
// Si hay duplicados, conserva el primero o define tu política
if (!isset($map[$norm])) $map[$norm] = (int) $id;
}
return $map;
}, DAY_IN_SECONDS);
}
// Lookup por nombre
function lbx_get_form_id_by_name( $form_name ) {
if ( empty($form_name) ) return false;
$norm = lbx_normalize_form_name($form_name);
$map = lbx_get_forms_name_map();
return $map[$norm] ?? false;
}
function toLeadboxImageUrl($src, $size = '400') {
if (!$src) {
return null;
}
if (strpos($src, 'vehicleimages.leadboxhq.com') !== false) {
return preg_replace('/^http:/i', 'https:', $src);
}
$pattern = '/https?:\/\/[^\/]*blob\.core\.windows\.net\/([^\/]+)\/vehicles\/([^\/]+)\/pictures\/([a-f0-9-]+)(?:-[A-Z]+)?(?:\.\w+)?$/i';
if (preg_match($pattern, $src, $matches)) {
$dealer = $matches[1];
$vehicleId = $matches[2];
$imageId = $matches[3];
return "https://vehicleimages.leadboxhq.com/v1/{$dealer}/{$vehicleId}/{$imageId}-{$size}.jpg";
}
return $src;
}
// Invalidación cuando se guarda/actualiza un form
add_action('ninja_forms_save_form', function( $form_id ) {
// Recalcula la lista y el mapa en caliente
$all = _lbx_get_all_forms();
set_transient('lbx_all_ninja_forms', $all, DAY_IN_SECONDS);
$map = [];
foreach ($all as $id => $title) {
$norm = lbx_normalize_form_name($title);
if (!isset($map[$norm])) $map[$norm] = (int) $id;
}
set_transient('lbx_nf_name_map', $map, DAY_IN_SECONDS);
}, 9999, 1);
/**
* ============================================================================
* LEADBOX DATALAYER — Helpers (LBT-1395)
* ============================================================================
* Server-side support for window.dataLayer push of standardized lbx_* events.
* The JS side reads window.LBX_CONTEXT injected in head.blade.php.
*/
/**
* Master switch. All lbx_* tracking is skipped when this returns false.
*/
function is_lbx_datalayer_enabled()
{
$s = get_option('leadbox-settings');
return !empty($s['enable_lbx_datalayer'])
&& strtolower($s['enable_lbx_datalayer']) === 'enabled';
}
/**
* Canonical Leadbox account identifier for this dealer.
*
* Single source of truth: if Ops defines a different canonical field later
* (e.g. a constant, an API call, jlr_dealer_code), change ONLY this function.
*/
function get_lbx_account_id()
{
$s = get_option('leadbox-settings');
return !empty($s['leadbox_id']) ? $s['leadbox_id'] : null;
}
/**
* Language code for the current request. Returns 'en' or 'fr'.
*/
function get_lbx_language()
{
$locale = strtolower((string) get_locale());
return strpos($locale, 'fr') === 0 ? 'fr' : 'en';
}
/**
* Current page type per LBT-1395 spec (server-side detection).
* Returns one of: homepage, vdp, srp, specials, contact, directions,
* service, service_appointment, service_specials, parts, finance,
* credit_application, trade, careers, about, blog, thank_you, other.
*
* Detection priority:
* 1. vdp_string query var (canonical VDP signal)
* 2. Front page / blog home (homepage)
* 3. Known page slugs (matches this theme's inventory, contact, etc.)
* 4. Template filename pattern (strpos over get_page_template_slug)
* 5. Post type / archive fallbacks
* 6. other
*/
function get_lbx_page_type()
{
if (!empty(get_query_var('vdp_string'))) {
return 'vdp';
}
if (is_front_page() || is_home()) {
return 'homepage';
}
// --- Priority 3: match by WP page slug (most reliable in this theme) ---
$slugMap = [
'srp' => [
'new-inventory', 'used-inventory',
'inventaire-neufs', 'inventaire-doccasion',
],
'contact' => ['contact-us', 'contact', 'nous-joindre'],
'directions' => ['directions', 'hours-and-directions', 'heures-et-directions'],
'specials' => ['specials', 'special-offers', 'offers', 'promotions'],
'service' => ['service', 'service-department'],
'service_appointment' => ['service-appointment', 'schedule-service', 'schedule-an-appointment', 'book-service', 'prendre-rendez-vous'],
'service_specials' => ['service-specials', 'service-coupons'],
'parts' => ['parts', 'pieces'],
'finance' => ['finance', 'financement'],
'credit_application' => ['credit-application', 'apply-for-credit', 'demande-de-credit'],
'trade' => ['trade-in', 'trade', 'evaluation', 'value-my-trade'],
'build_and_price' => ['build-and-price', 'build-price', 'configurer', 'configurez'],
'careers' => ['careers', 'carrieres', 'jobs'],
'about' => ['about-us', 'about', 'a-propos'],
'thank_you' => ['thank-you', 'thankyou', 'merci'],
];
foreach ($slugMap as $type => $slugs) {
if (is_page($slugs)) {
return $type;
}
}
// --- Priority 4: template filename pattern match ---
$template = strtolower((string) get_page_template_slug());
if ($template !== '') {
if (strpos($template, 'srp') !== false) return 'srp';
if (strpos($template, 'vdp') !== false
|| strpos($template, 'template-model') !== false
|| strpos($template, 'template-full-model') !== false
|| strpos($template, 'template-product') !== false) return 'vdp';
if (strpos($template, 'homepage') !== false) return 'homepage';
if (strpos($template, 'service-appointment') !== false) return 'service_appointment';
if (strpos($template, 'service-specials') !== false) return 'service_specials';
if (strpos($template, 'service') !== false) return 'service';
if (strpos($template, 'credit') !== false) return 'credit_application';
if (strpos($template, 'finance') !== false) return 'finance';
// Tester finding 5 (LBT-1395): build-and-price is a configurator, not
// a trade-in tool. Ops approved a new 'build_and_price' page_type as a
// Leadbox extension to the universal spec. Coordinate deploy with the
// GTM container update so reporting doesn't blink.
if (strpos($template, 'build-and-price') !== false) return 'build_and_price';
if (strpos($template, 'trade') !== false) return 'trade';
if (strpos($template, 'special-offers') !== false
|| strpos($template, 'offers') !== false
|| strpos($template, 'promotion') !== false) return 'specials';
if (strpos($template, 'contact') !== false) return 'contact';
if (strpos($template, 'directions') !== false) return 'directions';
if (strpos($template, 'parts') !== false) return 'parts';
if (strpos($template, 'careers') !== false) return 'careers';
if (strpos($template, 'about') !== false) return 'about';
if (strpos($template, 'thankyou') !== false
|| strpos($template, 'thank-you') !== false) return 'thank_you';
if (strpos($template, 'blog') !== false) return 'blog';
}
// --- Priority 5: post type / archive fallbacks ---
if (is_singular('post') || is_category() || is_tag() || is_archive()) {
return 'blog';
}
return 'other';
}
/**
* Best-effort department of the page the user came from, derived from the
* HTTP referrer. Used so a thank_you page can "inherit from previous page"
* per the spec. Only same-host referrers are trusted; returns null when the
* referrer is missing, off-site, or doesn't map to a known department.
*/
function lbx_department_from_referer()
{
$ref = isset($_SERVER['HTTP_REFERER']) ? (string) $_SERVER['HTTP_REFERER'] : '';
if ($ref === '') {
return null;
}
// Only trust same-host referrers so an external link can't spoof it.
$refHost = strtolower((string) parse_url($ref, PHP_URL_HOST));
$ownHost = strtolower((string) parse_url(home_url(), PHP_URL_HOST));
if ($refHost !== '' && $ownHost !== '' && $refHost !== $ownHost) {
return null;
}
$path = strtolower((string) parse_url($ref, PHP_URL_PATH));
if ($path === '') {
return null;
}
$rules = [
'service' => ['/service', '/book-service', '/service-appointment', '/prendre-rendez-vous', '/rendez-vous'],
'parts' => ['/parts', '/pieces'],
'finance' => ['/finance', '/financement', '/credit', '/demande-de-credit'],
'sales' => ['/new-inventory', '/used-inventory', '/inventaire', '/inventory', '/vehicle', '/vdp', '/trade', '/value-my-trade', '/build-and-price', '/specials', '/promotions'],
];
foreach ($rules as $dept => $needles) {
foreach ($needles as $needle) {
if (strpos($path, $needle) !== false) {
return $dept;
}
}
}
return null;
}
/**
* Department inferred from page type. Used as default for lbx_page_view.
*/
function get_lbx_department_for_page_type($pageType)
{
$map = [
'homepage' => 'general',
'vdp' => 'sales',
'srp' => 'sales',
'specials' => 'sales',
'trade' => 'sales',
'contact' => 'general',
'directions' => 'general',
'service' => 'service',
'service_appointment' => 'service',
'service_specials' => 'service',
'parts' => 'parts',
'finance' => 'finance',
'credit_application' => 'finance',
'careers' => 'general',
'about' => 'general',
'blog' => 'general',
'thank_you' => 'general',
'other' => 'general',
];
$dept = isset($map[$pageType]) ? $map[$pageType] : 'general';
// thank_you "inherits from previous page" per the spec: derive the
// department from the referring page when we can, else keep 'general'.
if ($pageType === 'thank_you') {
$inherited = lbx_department_from_referer();
if ($inherited) {
return $inherited;
}
}
return $dept;
}
/**
* Normalize a vehicle data array (from get_vehicle_by_id) into the shape
* the dataLayer spec expects. Values are lowercased where string,
* numeric where numeric, and null when unavailable.
*
* Field sources (from the per-vehicle {id}.json in uploads/data/):
* - condition : 'condition' + 'certified' (used+certified → 'certified')
* - bodystyle : 'bodystyle'
* - fuel_type : 'fueltype'
* - mileage : 'mileage'
* - msrp : 'msrp' (left as-is even when 0, per user preference)
* - price : 'price' (fallback 'saleprice')
* - discount_price: 'specialprice' if > 0, else null
* - incentive : 'promocode' (no structured incentive name in feed)
* - location : 'location'
* - status : derived from incoming/salepending/reserved/ininventory
* - photo_count : 'numberofpics' (authoritative; falls back to count(pictures))
* - days_in_inv : 'age'
* - payment_* : not in the JSON feed — populated client-side by calculator
*
* Returns null if the input is empty (non-VDP page).
*/
function get_lbx_vehicle_context($data)
{
if (empty($data) || !is_array($data)) {
return null;
}
$lc = function ($v) {
if ($v === null || $v === '') return null;
return strtolower(trim((string) $v));
};
$num = function ($v) {
if ($v === null || $v === '' || !is_numeric($v)) return null;
return $v + 0;
};
$positiveNum = function ($v) {
if ($v === null || $v === '' || !is_numeric($v)) return null;
$n = $v + 0;
return $n > 0 ? $n : null;
};
// Condition: used+certified collapses to 'certified' per spec.
$condition = $lc($data['condition'] ?? null);
if ($condition === 'used' && !empty($data['certified'])) {
$condition = 'certified';
}
// Inventory status: derive from the flags present in the feed.
$status = null;
if (!empty($data['salepending']) || !empty($data['reserved'])) {
$status = 'sold';
} elseif (!empty($data['incoming'])) {
$status = 'in-transit';
} elseif (array_key_exists('ininventory', $data) && $data['ininventory'] === false) {
$status = 'on-order';
} elseif (array_key_exists('ininventory', $data) && $data['ininventory'] === true) {
$status = 'in-stock';
} else {
// ininventory is null/missing: if we have a stocknumber and onweb is true,
// treat it as in-stock. Otherwise null.
if (!empty($data['stocknumber']) && !empty($data['onweb'])) {
$status = 'in-stock';
}
}
// Photo count: 'numberofpics' is the authoritative feed value; fall back
// to counting 'pictures' if that isn't present.
$photoCount = null;
if (isset($data['numberofpics']) && is_numeric($data['numberofpics'])) {
$photoCount = (int) $data['numberofpics'];
} elseif (isset($data['pictures']) && is_array($data['pictures'])) {
$photoCount = count($data['pictures']);
}
// Discount price: the feed exposes 'specialprice' (0 means no special).
$discountPrice = $positiveNum($data['specialprice'] ?? null);
return [
'vehicle_vin' => $lc($data['vin'] ?? null),
'vehicle_stock_number' => $lc($data['stocknumber'] ?? null),
'vehicle_condition' => $condition,
'vehicle_make' => $lc($data['make'] ?? null),
'vehicle_model' => $lc($data['model'] ?? null),
'vehicle_year' => $num($data['year'] ?? null),
'vehicle_trim' => $lc($data['trim'] ?? null),
'vehicle_bodystyle' => $lc($data['bodystyle'] ?? null),
'vehicle_fuel_type' => $lc($data['fueltype'] ?? ($data['fuel'] ?? null)),
'vehicle_mileage' => $num($data['mileage'] ?? null),
'vehicle_msrp' => $num($data['msrp'] ?? null),
'vehicle_price' => $num($data['price'] ?? ($data['saleprice'] ?? null)),
'vehicle_discount_price' => $discountPrice,
'vehicle_incentive_name' => $lc($data['promocode'] ?? null),
'vehicle_payment_monthly' => null,
'vehicle_payment_type' => null,
'vehicle_location' => $lc($data['location'] ?? null),
'vehicle_status' => $status,
'vehicle_photo_count' => $photoCount,
'vehicle_days_in_inventory' => $num($data['age'] ?? null),
];
}
/**
* Build the full LBX_CONTEXT payload injected into window in head.blade.php.
* Returns null when tracking is disabled so callers can skip the <script> block.
*/
function get_lbx_context_payload($vehicleData = null)
{
if (!is_lbx_datalayer_enabled()) {
return null;
}
$pageType = get_lbx_page_type();
$location = get_lbx_dealer_location();
return [
'leadbox_id' => get_lbx_account_id(),
'page_type' => $pageType,
'department' => get_lbx_department_for_page_type($pageType),
'language' => get_lbx_language(),
'vehicle' => get_lbx_vehicle_context($vehicleData),
// Tester finding 9 (LBT-1395 round 2): make dealer name and full
// address available as page-global fallback for lbx_directions_click,
// so anchors that don't carry per-click data-lbx-location-* still
// emit usable values instead of null / leaked template tokens.
'location_name' => $location['name'],
'location_address' => $location['address'],
];
}
/**
* Single dealer location for the dataLayer. Returns null fields when the
* dealer settings are empty, which signals to the JS to keep the field null
* rather than fall back to anchor textContent (where it would pick up
* unfilled template placeholders like "*address_line_1*").
*/
function get_lbx_dealer_location()
{
$c = get_dealer_contact();
if (!is_array($c)) {
return ['name' => null, 'address' => null];
}
$name = !empty($c['dealer_name']) ? trim($c['dealer_name']) : null;
$parts = [];
foreach (['address_line_1', 'address_line_2', 'address_city', 'address_province', 'address_postal_code'] as $k) {
if (!empty($c[$k]) && strpos($c[$k], '*') !== 0) {
$parts[] = trim($c[$k]);
}
}
return [
'name' => $name,
'address' => $parts ? implode(', ', $parts) : null,
];
}