/** * Destination SEO guides — registry, URL helpers, category resolve, CMS seed/sync. * Clean URLs are registered by the vb_destinations plugin (routes must load before Rewrite::init). */ require_once dirname(__FILE__) . '/vb-destination-intros.php'; if (!function_exists('vb_destinations')) { function vb_destinations() { return array( 'europe' => array( 'type' => 'region', 'label' => 'Europe', 'category_slug' => 'europe', 'parent' => null, 'related' => array('spain', 'france', 'italy', 'greece'), ), 'south-america' => array( 'type' => 'region', 'label' => 'Americas', 'category_slug' => 'americas', 'parent' => null, 'related' => array('mexico', 'costa-rica', 'argentina', 'brazil'), ), 'asia' => array( 'type' => 'region', 'label' => 'Asia', 'category_slug' => 'asia', 'parent' => null, 'related' => array('japan', 'india', 'china', 'thailand', 'vietnam', 'southeast-asia'), ), 'southeast-asia' => array( 'type' => 'region', 'label' => 'Southeast Asia', 'category_slug' => 'southeast-asia', 'parent' => null, 'related' => array('thailand', 'vietnam', 'china', 'asia'), ), 'africa' => array( 'type' => 'region', 'label' => 'Africa', 'category_slug' => 'africa', 'parent' => null, 'related' => array(), ), 'middle-east' => array( 'type' => 'region', 'label' => 'Middle East', 'category_slug' => 'middle-east', 'parent' => null, 'related' => array(), ), 'oceania' => array( 'type' => 'region', 'label' => 'Oceania', 'category_slug' => 'oceania', 'parent' => null, 'related' => array(), ), 'spain' => array( 'type' => 'country', 'label' => 'Spain', 'category_slug' => 'spain', 'parent' => 'europe', 'related' => array('france', 'italy', 'greece', 'europe'), ), 'france' => array( 'type' => 'country', 'label' => 'France', 'category_slug' => 'france', 'parent' => 'europe', 'related' => array('spain', 'italy', 'greece', 'europe'), ), 'italy' => array( 'type' => 'country', 'label' => 'Italy', 'category_slug' => 'italy', 'parent' => 'europe', 'related' => array('spain', 'france', 'greece', 'europe'), ), 'greece' => array( 'type' => 'country', 'label' => 'Greece', 'category_slug' => 'greece', 'parent' => 'europe', 'related' => array('spain', 'france', 'italy', 'europe'), ), 'mexico' => array( 'type' => 'country', 'label' => 'Mexico', 'category_slug' => 'mexico', 'parent' => 'south-america', 'related' => array('costa-rica', 'argentina', 'brazil', 'south-america'), ), 'costa-rica' => array( 'type' => 'country', 'label' => 'Costa Rica', 'category_slug' => 'costa-rica', 'parent' => 'south-america', 'related' => array('mexico', 'argentina', 'brazil', 'south-america'), ), 'argentina' => array( 'type' => 'country', 'label' => 'Argentina', 'category_slug' => 'argentina', 'parent' => 'south-america', 'related' => array('mexico', 'costa-rica', 'brazil', 'south-america'), ), 'brazil' => array( 'type' => 'country', 'label' => 'Brazil', 'category_slug' => 'brazil', 'parent' => 'south-america', 'related' => array('mexico', 'costa-rica', 'argentina', 'south-america'), ), 'japan' => array( 'type' => 'country', 'label' => 'Japan', 'category_slug' => 'japan', 'parent' => 'asia', 'related' => array('india', 'china', 'thailand', 'asia'), ), 'india' => array( 'type' => 'country', 'label' => 'India', 'category_slug' => 'india', 'parent' => 'asia', 'related' => array('japan', 'thailand', 'china', 'asia'), ), 'china' => array( 'type' => 'country', 'label' => 'China', 'category_slug' => 'china', 'parent' => 'southeast-asia', 'related' => array('thailand', 'vietnam', 'japan', 'southeast-asia', 'asia'), ), 'thailand' => array( 'type' => 'country', 'label' => 'Thailand', 'category_slug' => 'thailand', 'parent' => 'southeast-asia', 'related' => array('vietnam', 'china', 'india', 'southeast-asia', 'asia'), ), 'vietnam' => array( 'type' => 'country', 'label' => 'Vietnam', 'category_slug' => 'vietnam', 'parent' => 'southeast-asia', 'related' => array('thailand', 'china', 'southeast-asia', 'asia'), ), ); } } if (!function_exists('vb_destination')) { function vb_destination($key) { $all = vb_destinations(); $key = strtolower(trim((string) $key)); return isset($all[$key]) ? $all[$key] : null; } } if (!function_exists('vb_destination_category_aliases')) { function vb_destination_category_aliases() { return array( 'southeast-asia' => array('southeast-asia', 'asia'), 'south-america' => array('americas', 'south-america'), 'americas' => array('americas', 'south-america'), 'europe' => array('europe'), 'africa' => array('africa'), 'asia' => array('asia'), 'middle-east' => array('middle-east'), 'oceania' => array('oceania'), ); } } if (!function_exists('vb_destination_resolve_category')) { function vb_destination_resolve_category($key) { $dest = vb_destination($key); if ($dest === null) { return null; } $slug = isset($dest['category_slug']) ? $dest['category_slug'] : $key; $aliases = vb_destination_category_aliases(); $try = isset($aliases[$slug]) ? $aliases[$slug] : array($slug); if (!in_array($slug, $try, true)) { array_unshift($try, $slug); } if (!in_array($key, $try, true)) { $try[] = $key; } foreach ($try as $candidate) { $cat = Category::newInstance()->findBySlug($candidate); if (is_array($cat) && !empty($cat['pk_i_id'])) { return $cat; } } return null; } } if (!function_exists('vb_destination_key_for_category_slug')) { /** * Map a category slug to a destination registry key (if any). * * @param string $slug * @return string|null */ function vb_destination_key_for_category_slug($slug) { $slug = strtolower(trim((string) $slug)); if ($slug === '') { return null; } if (vb_destination($slug) !== null) { return $slug; } // americas browse → Americas regional guide (south-america key) if ($slug === 'americas' && vb_destination('south-america') !== null) { return 'south-america'; } foreach (vb_destinations() as $key => $dest) { $cat_slug = isset($dest['category_slug']) ? $dest['category_slug'] : $key; if ($cat_slug === $slug) { return $key; } } $aliases = vb_destination_category_aliases(); foreach ($aliases as $alias_key => $list) { if (in_array($slug, $list, true) && vb_destination($alias_key) !== null) { return $alias_key; } } return null; } } if (!function_exists('vb_destination_key_for_current_search')) { /** * Best-matching destination key for the current search category context. * * @return string|null */ function vb_destination_key_for_current_search() { if (!function_exists('osc_search_category_id')) { return null; } $ids = osc_search_category_id(); if (!is_array($ids) || count($ids) === 0) { return null; } $country_key = null; $region_key = null; foreach ($ids as $id) { $cat = Category::newInstance()->findByPrimaryKey((int) $id); if (!is_array($cat) || empty($cat['s_slug'])) { continue; } $key = vb_destination_key_for_category_slug($cat['s_slug']); if ($key === null) { continue; } $dest = vb_destination($key); if ($dest === null) { continue; } if (isset($dest['type']) && $dest['type'] === 'country') { $country_key = $key; break; } if ($region_key === null) { $region_key = $key; } } return $country_key !== null ? $country_key : $region_key; } } if (!function_exists('vb_destinations_url')) { function vb_destinations_url() { if (function_exists('osc_route_url')) { $url = osc_route_url('vb-destinations'); if ($url !== '') { return $url; } } return osc_base_url() . 'destinations'; } } if (!function_exists('vb_destination_url')) { function vb_destination_url($key) { $key = strtolower(trim((string) $key)); if ($key === '' || vb_destination($key) === null) { return vb_destinations_url(); } if (function_exists('osc_route_url')) { $url = osc_route_url('vb-destination', array('slug' => $key)); if ($url !== '') { return $url; } } return osc_base_url() . 'volunteering-in-' . rawurlencode($key); } } if (!function_exists('vb_destination_internal_name')) { function vb_destination_internal_name($key) { return 'volunteering-in-' . strtolower(trim((string) $key)); } } if (!function_exists('vb_destination_meta_description')) { function vb_destination_meta_description($html, $fallback = '') { $text = trim(preg_replace('/\s+/', ' ', strip_tags((string) $html))); if ($text === '') { $text = trim((string) $fallback); } if (function_exists('mb_substr')) { return mb_substr($text, 0, 160); } return substr($text, 0, 160); } } if (!function_exists('vb_destination_locale_code')) { function vb_destination_locale_code() { $locale = function_exists('osc_current_user_locale') ? osc_current_user_locale() : ''; if ($locale === '' && function_exists('osc_language')) { $locale = osc_language(); } if ($locale === '') { $locale = 'en_US'; } return $locale; } } if (!function_exists('vb_destination_page_title_for_key')) { function vb_destination_page_title_for_key($key) { $dest = vb_destination($key); $label = ($dest && isset($dest['label'])) ? $dest['label'] : ucwords(str_replace('-', ' ', $key)); return 'Volunteering in ' . $label; } } if (!function_exists('vb_destination_seed_pages')) { /** * Create any missing hub + guide CMS pages (safe to run repeatedly). * * @return void */ function vb_destination_seed_pages() { $locale = vb_destination_locale_code(); $meta_dest = json_encode(array('template' => 'page-destination.php')); $meta_hub = json_encode(array('template' => 'page-destinations.php')); $pages = array( 'destinations' => array( 'title' => 'Volunteering destinations', 'text' => '
Explore region and country guides for moneyless volunteering projects on Volunteers Base. Each guide highlights recent listings and links to browse all projects in that area.
Looking for how the exchange works? Read the pages for Hosts and Volunteers, then browse live projects.
', 'meta' => $meta_hub, ), ); foreach (vb_destinations() as $key => $dest) { $internal = vb_destination_internal_name($key); $pages[$internal] = array( 'title' => vb_destination_page_title_for_key($key), 'text' => vb_destination_intro_html($key), 'meta' => $meta_dest, ); } foreach ($pages as $internal => $data) { $existing = Page::newInstance()->findByInternalName($internal); if (is_array($existing) && !empty($existing['pk_i_id'])) { continue; } Page::newInstance()->insert( array( 's_internal_name' => $internal, 'b_indelible' => 0, 'b_link' => 0, 's_meta' => $data['meta'], ), array( $locale => array( 's_title' => $data['title'], 's_text' => $data['text'], ), ) ); } osc_set_preference('vb_destinations_seeded', '1', 'repurpose', 'BOOLEAN'); } } if (!function_exists('vb_destination_sync_intros')) { /** * One-shot: push expanded intros into existing CMS page bodies. * * @return void */ function vb_destination_sync_intros() { if (osc_get_preference('vb_dest_intros_v4', 'repurpose') === '1') { return; } $locale = vb_destination_locale_code(); foreach (vb_destinations() as $key => $dest) { $internal = vb_destination_internal_name($key); $page = Page::newInstance()->findByInternalName($internal); if (!is_array($page) || empty($page['pk_i_id'])) { continue; } $title = vb_destination_page_title_for_key($key); Page::newInstance()->updateDescription( (int) $page['pk_i_id'], $locale, $title, vb_destination_intro_html($key) ); } osc_set_preference('vb_dest_intros_v4', '1', 'repurpose', 'BOOLEAN'); if (function_exists('osc_reset_preferences')) { osc_reset_preferences(); } } } osc_add_hook('init', function () { if (!function_exists('vb_destination_seed_pages')) { return; } vb_destination_seed_pages(); if (function_exists('vb_destination_sync_intros')) { vb_destination_sync_intros(); } }); ?>