/** * CREHQ Modern Theme Functions * * @package CREHQ_Modern * @since 1.0.0 */ // Exit if accessed directly if (!defined('ABSPATH')) { exit; } // Include Pro Features for company profiles require_once get_template_directory() . "/inc/pro-features.php"; /** * Theme Setup */ function crehq_modern_setup() { // Add default posts and comments RSS feed links to head add_theme_support('automatic-feed-links'); // Let WordPress manage the document title add_theme_support('title-tag'); // Enable support for Post Thumbnails on posts and pages add_theme_support('post-thumbnails'); // Set default thumbnail size set_post_thumbnail_size(1200, 675, true); // Register navigation menus register_nav_menus(array( 'primary' => __('Primary Menu', 'crehq-modern'), 'footer' => __('Footer Menu', 'crehq-modern'), )); // Switch default core markup to output valid HTML5 add_theme_support('html5', array( 'search-form', 'comment-form', 'comment-list', 'gallery', 'caption', 'script', 'style', )); // Add theme support for Custom Logo add_theme_support('custom-logo', array( 'height' => 50, 'width' => 200, 'flex-width' => true, 'flex-height' => true, )); // Add support for responsive embedded content add_theme_support('responsive-embeds'); // Add support for editor styles add_theme_support('editor-styles'); // Add support for wide alignment add_theme_support('align-wide'); } add_action('after_setup_theme', 'crehq_modern_setup'); /** * Enqueue Scripts and Styles */ function crehq_modern_scripts() { // Enqueue Google Fonts - Inter for modern, professional typography wp_enqueue_style( 'crehq-modern-fonts', 'https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap', array(), null ); // Enqueue Tailwind CSS from CDN wp_enqueue_style( 'tailwindcss', get_template_directory_uri() . '/assets/css/tailwind.min.css', array(), '3.4.1' ); // Enqueue main stylesheet (after Tailwind for overrides) wp_enqueue_style('crehq-modern-style', get_stylesheet_uri(), array('tailwindcss'), '1.0.1'); // Enqueue main theme script (if file exists) $main_js = get_template_directory() . '/assets/js/main.js'; if (file_exists($main_js)) { wp_enqueue_script( 'crehq-modern-script', get_template_directory_uri() . '/assets/js/main.js', array(), '1.0.0', true ); } // Enqueue comment reply script if (is_singular() && comments_open() && get_option('thread_comments')) { wp_enqueue_script('comment-reply'); } } add_action('wp_enqueue_scripts', 'crehq_modern_scripts'); /** * Register Widget Areas */ function crehq_modern_widgets_init() { // Sidebar widget area register_sidebar(array( 'name' => __('Sidebar', 'crehq-modern'), 'id' => 'sidebar-1', 'description' => __('Add widgets here to appear in your sidebar.', 'crehq-modern'), 'before_widget' => '
', 'after_widget' => '
', 'before_title' => '

', 'after_title' => '

', )); // Footer widget area 1 register_sidebar(array( 'name' => __('Footer 1', 'crehq-modern'), 'id' => 'footer-1', 'description' => __('Add widgets here to appear in your footer.', 'crehq-modern'), 'before_widget' => '
', 'after_widget' => '
', 'before_title' => '

', 'after_title' => '

', )); // Footer widget area 2 register_sidebar(array( 'name' => __('Footer 2', 'crehq-modern'), 'id' => 'footer-2', 'description' => __('Add widgets here to appear in your footer.', 'crehq-modern'), 'before_widget' => '
', 'after_widget' => '
', 'before_title' => '

', 'after_title' => '

', )); // Footer widget area 3 register_sidebar(array( 'name' => __('Footer 3', 'crehq-modern'), 'id' => 'footer-3', 'description' => __('Add widgets here to appear in your footer.', 'crehq-modern'), 'before_widget' => '
', 'after_widget' => '
', 'before_title' => '

', 'after_title' => '

', )); } add_action('widgets_init', 'crehq_modern_widgets_init'); /** * Custom excerpt length */ function crehq_modern_excerpt_length($length) { return 30; } add_filter('excerpt_length', 'crehq_modern_excerpt_length'); /** * Custom excerpt more */ function crehq_modern_excerpt_more($more) { return '...'; } add_filter('excerpt_more', 'crehq_modern_excerpt_more'); /** * Include helper files */ require_once get_template_directory() . '/inc/post-types.php'; require_once get_template_directory() . '/inc/membership-functions.php'; require_once get_template_directory() . '/inc/company-functions.php'; require_once get_template_directory() . '/inc/customizer.php'; /** * Enqueue additional scripts for advanced functionality */ function crehq_modern_enqueue_advanced_scripts() { // Dark mode script wp_enqueue_script( 'crehq-dark-mode', get_template_directory_uri() . '/assets/js/dark-mode.js', array(), '1.0.0', true ); // Company search and filters (only on company archive) if (is_post_type_archive('company') || is_tax('company_category')) { wp_enqueue_script( 'crehq-company-search', get_template_directory_uri() . '/assets/js/company-search.js', array('jquery'), '1.0.0', true ); wp_enqueue_script( 'crehq-company-filters', get_template_directory_uri() . '/assets/js/company-filters.js', array('jquery'), '1.0.0', true ); // Localize script for AJAX wp_localize_script('crehq-company-search', 'crehqAjax', array( 'ajaxurl' => admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('crehq_search_nonce'), )); } // Company tabs (only on single company) if (is_singular('company')) { wp_enqueue_script( 'crehq-company-tabs', get_template_directory_uri() . '/assets/js/company-tabs.js', array(), '1.0.0', true ); } } add_action('wp_enqueue_scripts', 'crehq_modern_enqueue_advanced_scripts'); /** * AJAX handler for company search */ function crehq_ajax_company_search() { check_ajax_referer('crehq_search_nonce', 'nonce'); $search_term = isset($_POST['search']) ? sanitize_text_field($_POST['search']) : ''; $args = array( 'post_type' => 'company', 'post_status' => 'publish', 'posts_per_page' => 10, 's' => $search_term, ); $query = new WP_Query($args); $results = array(); if ($query->have_posts()) { while ($query->have_posts()) { $query->the_post(); $results[] = array( 'id' => get_the_ID(), 'title' => get_the_title(), 'url' => get_permalink(), 'logo' => crehq_get_company_logo(get_the_ID(), 'thumbnail'), 'location' => get_post_meta(get_the_ID(), 'company_location', true), 'store_count' => get_post_meta(get_the_ID(), 'store_count', true), ); } } wp_reset_postdata(); wp_send_json_success($results); } add_action('wp_ajax_crehq_company_search', 'crehq_ajax_company_search'); add_action('wp_ajax_nopriv_crehq_company_search', 'crehq_ajax_company_search'); /** * AJAX handler for saving searches */ function crehq_ajax_save_search() { check_ajax_referer('crehq_search_nonce', 'nonce'); if (!is_user_logged_in()) { wp_send_json_error(array('message' => __('Please log in to save searches.', 'crehq-modern'))); } $search_name = isset($_POST['name']) ? sanitize_text_field($_POST['name']) : ''; $search_params = isset($_POST['params']) ? $_POST['params'] : array(); if (empty($search_name)) { wp_send_json_error(array('message' => __('Please provide a name for your search.', 'crehq-modern'))); } $result = crehq_save_user_search($search_name, $search_params); if ($result) { wp_send_json_success(array('message' => __('Search saved successfully!', 'crehq-modern'))); } else { wp_send_json_error(array('message' => __('Failed to save search. Premium membership required.', 'crehq-modern'))); } } add_action('wp_ajax_crehq_save_search', 'crehq_ajax_save_search'); /** * Add body classes for theme features */ function crehq_modern_body_classes($classes) { // Add class if user is premium if (crehq_is_premium_user()) { $classes[] = 'premium-user'; } // Add class for current view (if set in cookie/localStorage) if (isset($_COOKIE['crehq_view'])) { $classes[] = 'view-' . sanitize_html_class($_COOKIE['crehq_view']); } return $classes; } add_filter('body_class', 'crehq_modern_body_classes'); /** * Modify the company archive query */ function crehq_modify_company_archive($query) { if (!is_admin() && $query->is_main_query() && is_post_type_archive('company')) { $query->set('posts_per_page', 24); // Handle sorting if (!empty($_GET['orderby'])) { switch ($_GET['orderby']) { case 'title': $query->set('orderby', 'title'); $query->set('order', 'ASC'); break; case 'date': $query->set('orderby', 'date'); $query->set('order', 'DESC'); break; case 'store_count': $query->set('meta_key', 'store_count'); $query->set('orderby', 'meta_value_num'); $query->set('order', 'DESC'); break; } } } } add_action('pre_get_posts', 'crehq_modify_company_archive'); // ============================================================================= // USER PROFILE FUNCTIONS // ============================================================================= if (!function_exists('crehq_get_user_types')) { /** * Get available user types for profile selection */ function crehq_get_user_types() { return array( 'cre_professional' => array( 'label' => 'CRE Professional', 'description' => 'Broker, developer, property manager, or other CRE professional', 'icon' => '🏢', 'public_profile' => true ), 'building_owner' => array( 'label' => 'Property Owner', 'description' => 'I own or manage commercial properties', 'icon' => '🏠', 'public_profile' => true ), 'investor' => array( 'label' => 'Investor', 'description' => 'I invest in commercial real estate', 'icon' => '💰', 'public_profile' => true ), 'business_owner' => array( 'label' => 'Business Owner/Tenant', 'description' => 'Looking for retail or commercial space', 'icon' => '🏪', 'public_profile' => false ), 'city_employee' => array( 'label' => 'Government/EDC', 'description' => 'Economic development or city planning', 'icon' => '🏛️', 'public_profile' => true ), 'other' => array( 'label' => 'Other', 'description' => 'Researcher, student, or other interest', 'icon' => '👤', 'public_profile' => false ) ); } } if (!function_exists('crehq_get_professional_roles')) { /** * Get professional role categories for directory */ function crehq_get_professional_roles() { return array( 'broker' => 'Broker/Agent', 'developer' => 'Developer', 'property_manager' => 'Property Manager', 'appraiser' => 'Appraiser', 'lender' => 'Lender/Capital Markets', 'attorney' => 'Attorney', 'consultant' => 'Consultant', 'asset_manager' => 'Asset Manager', 'architect' => 'Architect/Designer', 'contractor' => 'Contractor/Construction', 'investor' => 'Investor', 'other' => 'Other CRE Professional' ); } } if (!function_exists('crehq_get_property_specializations')) { /** * Get property type specializations */ function crehq_get_property_specializations() { return array( 'office' => 'Office', 'retail' => 'Retail', 'industrial' => 'Industrial', 'multifamily' => 'Multifamily', 'hospitality' => 'Hospitality', 'healthcare' => 'Healthcare', 'land' => 'Land', 'mixed_use' => 'Mixed-Use', 'net_lease' => 'Net Lease', 'self_storage' => 'Self Storage' ); } } if (!function_exists('crehq_get_profile_fields')) { /** * Get profile fields based on user type */ function crehq_get_profile_fields($user_type = '') { $common_fields = array( 'phone' => array( 'label' => 'Phone Number', 'type' => 'tel', 'placeholder' => '(555) 123-4567' ), 'city' => array( 'label' => 'City', 'type' => 'text', 'placeholder' => 'e.g., Chicago' ), 'state' => array( 'label' => 'State', 'type' => 'select', 'options' => array('' => 'Select State') + array('AL'=>'Alabama','AK'=>'Alaska','AZ'=>'Arizona','AR'=>'Arkansas','CA'=>'California','CO'=>'Colorado','CT'=>'Connecticut','DE'=>'Delaware','FL'=>'Florida','GA'=>'Georgia','HI'=>'Hawaii','ID'=>'Idaho','IL'=>'Illinois','IN'=>'Indiana','IA'=>'Iowa','KS'=>'Kansas','KY'=>'Kentucky','LA'=>'Louisiana','ME'=>'Maine','MD'=>'Maryland','MA'=>'Massachusetts','MI'=>'Michigan','MN'=>'Minnesota','MS'=>'Mississippi','MO'=>'Missouri','MT'=>'Montana','NE'=>'Nebraska','NV'=>'Nevada','NH'=>'New Hampshire','NJ'=>'New Jersey','NM'=>'New Mexico','NY'=>'New York','NC'=>'North Carolina','ND'=>'North Dakota','OH'=>'Ohio','OK'=>'Oklahoma','OR'=>'Oregon','PA'=>'Pennsylvania','RI'=>'Rhode Island','SC'=>'South Carolina','SD'=>'South Dakota','TN'=>'Tennessee','TX'=>'Texas','UT'=>'Utah','VT'=>'Vermont','VA'=>'Virginia','WA'=>'Washington','WV'=>'West Virginia','WI'=>'Wisconsin','WY'=>'Wyoming') ), 'linkedin' => array( 'label' => 'LinkedIn Profile', 'type' => 'url', 'placeholder' => 'https://linkedin.com/in/yourprofile' ), 'bio' => array( 'label' => 'Bio / About', 'type' => 'textarea', 'rows' => 4, 'placeholder' => 'Tell us about yourself and your experience...' ) ); $professional_fields = array( 'professional_role' => array( 'label' => 'Professional Role', 'type' => 'select', 'options' => array('' => 'Select your role') + crehq_get_professional_roles(), 'required' => true ), 'company_name' => array( 'label' => 'Company Name', 'type' => 'text', 'placeholder' => 'Your company or brokerage' ), 'brokerage' => array( 'label' => 'Brokerage/Firm', 'type' => 'text', 'placeholder' => 'e.g., CBRE, JLL, Cushman & Wakefield' ), 'years_experience' => array( 'label' => 'Years of Experience', 'type' => 'select', 'options' => array( '' => 'Select', '1' => '1-2 years', '3' => '3-5 years', '6' => '6-10 years', '11' => '11-20 years', '20' => '20+ years' ) ), 'specializations' => array( 'label' => 'Property Type Specializations', 'type' => 'checkboxes', 'options' => crehq_get_property_specializations() ), 'public_profile' => array( 'label' => 'List in Professional Directory', 'type' => 'checkbox', 'description' => 'Make my profile visible in the public CRE Professional Directory (free for all members)' ), 'profile_photo' => array( 'label' => 'Profile Photo', 'type' => 'file', 'accept' => 'image/*' ) ); $owner_fields = array( 'company_name' => array( 'label' => 'Company/Entity Name', 'type' => 'text', 'placeholder' => 'Your company or LLC' ), 'portfolio_size' => array( 'label' => 'Portfolio Size', 'type' => 'select', 'options' => array( '' => 'Select', '1-5' => '1-5 properties', '6-20' => '6-20 properties', '21-50' => '21-50 properties', '50+' => '50+ properties' ) ), 'property_types' => array( 'label' => 'Property Types Owned', 'type' => 'checkboxes', 'options' => crehq_get_property_specializations() ), 'public_profile' => array( 'label' => 'List in Professional Directory', 'type' => 'checkbox', 'description' => 'Make my profile visible in the public CRE Professional Directory' ) ); switch ($user_type) { case 'cre_professional': case 'cre_agent': // Legacy support return array_merge($professional_fields, $common_fields); case 'building_owner': return array_merge($owner_fields, $common_fields); case 'investor': return array_merge(array( 'investment_focus' => array( 'label' => 'Investment Focus', 'type' => 'checkboxes', 'options' => crehq_get_property_specializations() ), 'investment_range' => array( 'label' => 'Investment Range', 'type' => 'select', 'options' => array( '' => 'Select', 'under_1m' => 'Under $1M', '1m_5m' => '$1M - $5M', '5m_25m' => '$5M - $25M', '25m_plus' => '$25M+' ) ), 'public_profile' => array( 'label' => 'List in Professional Directory', 'type' => 'checkbox', 'description' => 'Make my profile visible in the public CRE Professional Directory' ) ), $common_fields); case 'city_employee': return array_merge(array( 'organization' => array( 'label' => 'Organization/Agency', 'type' => 'text', 'placeholder' => 'e.g., City of Chicago EDC' ), 'title' => array( 'label' => 'Title/Position', 'type' => 'text', 'placeholder' => 'Your job title' ), 'public_profile' => array( 'label' => 'List in Professional Directory', 'type' => 'checkbox', 'description' => 'Make my profile visible in the public CRE Professional Directory' ) ), $common_fields); default: return $common_fields; } } } if (!function_exists('crehq_save_user_profile')) { /** * Save user profile data */ function crehq_save_user_profile($user_id, $data) { // Fields to save $meta_fields = array( 'user_type', 'professional_role', 'phone', 'city', 'state', 'company_name', 'brokerage', 'years_experience', 'bio', 'linkedin', 'portfolio_size', 'investment_range', 'organization', 'title' ); foreach ($meta_fields as $field) { if (isset($data[$field])) { update_user_meta($user_id, '_crehq_' . $field, sanitize_text_field($data[$field])); } } // Handle arrays (checkboxes) $array_fields = array('specializations', 'property_types', 'investment_focus'); foreach ($array_fields as $field) { if (isset($data[$field]) && is_array($data[$field])) { update_user_meta($user_id, '_crehq_' . $field, array_map('sanitize_text_field', $data[$field])); } elseif (isset($data[$field])) { update_user_meta($user_id, '_crehq_' . $field, array()); } } // Handle public profile checkbox $public_profile = isset($data['public_profile']) && $data['public_profile'] === '1' ? '1' : '0'; update_user_meta($user_id, '_crehq_public_profile', $public_profile); // Handle profile photo upload if (!empty($_FILES['profile_photo']['tmp_name'])) { require_once(ABSPATH . 'wp-admin/includes/image.php'); require_once(ABSPATH . 'wp-admin/includes/file.php'); require_once(ABSPATH . 'wp-admin/includes/media.php'); $attachment_id = media_handle_upload('profile_photo', 0); if (!is_wp_error($attachment_id)) { update_user_meta($user_id, '_crehq_profile_photo_id', $attachment_id); update_user_meta($user_id, '_crehq_profile_photo', wp_get_attachment_url($attachment_id)); } } // Calculate and update profile completion $completion = crehq_calculate_profile_completion($user_id); update_user_meta($user_id, '_crehq_profile_completion', $completion); return true; } } if (!function_exists('crehq_calculate_profile_completion')) { /** * Calculate profile completion percentage */ function crehq_calculate_profile_completion($user_id) { $user = get_user_by('ID', $user_id); if (!$user) return 0; $fields_to_check = array( 'first_name' => $user->first_name, 'last_name' => $user->last_name, 'user_type' => get_user_meta($user_id, '_crehq_user_type', true), 'city' => get_user_meta($user_id, '_crehq_city', true), 'state' => get_user_meta($user_id, '_crehq_state', true), 'bio' => get_user_meta($user_id, '_crehq_bio', true), 'professional_role' => get_user_meta($user_id, '_crehq_professional_role', true), 'company_name' => get_user_meta($user_id, '_crehq_company_name', true) ); $completed = 0; $total = count($fields_to_check); foreach ($fields_to_check as $field => $value) { if (!empty($value)) { $completed++; } } return round(($completed / $total) * 100); } } // Redirect /agents/ to /professionals/ add_action('template_redirect', function() { if (is_page('agents') || strpos($_SERVER['REQUEST_URI'], '/agents/') !== false || strpos($_SERVER['REQUEST_URI'], '/agents') !== false) { $new_url = str_replace('/agents', '/professionals', $_SERVER['REQUEST_URI']); wp_redirect(home_url($new_url), 301); exit; } }); // ============================================================================= // PROFESSIONAL PROFILE URL REWRITE // ============================================================================= // Add rewrite rules for professional profiles add_action('init', function() { add_rewrite_rule( '^professional/([^/]+)/?$', 'index.php?professional_name=$matches[1]', 'top' ); // Legacy support - redirect /agent/ to /professional/ add_rewrite_rule( '^agent/([^/]+)/?$', 'index.php?redirect_agent=$matches[1]', 'top' ); }); // Register query vars add_filter('query_vars', function($vars) { $vars[] = 'professional_name'; $vars[] = 'redirect_agent'; $vars[] = 'agent_name'; // Legacy support return $vars; }); // Handle template loading and redirects add_action('template_redirect', function() { // Redirect /agent/{name}/ to /professional/{name}/ $redirect_agent = get_query_var('redirect_agent'); if ($redirect_agent) { wp_redirect(home_url('/professional/' . $redirect_agent . '/'), 301); exit; } // Load professional profile template $professional_name = get_query_var('professional_name'); if ($professional_name) { // Set for template compatibility set_query_var('agent_name', $professional_name); include(get_template_directory() . '/template-agent-profile.php'); exit; } }, 5); // ============================================================================= // CRE INTELLIGENCE METRICS FUNCTIONS // ============================================================================= /** * Count development contacts for a company * Counts CI_Name_* fields that have values */ function crehq_count_development_contacts($company_id) { $count = 0; // Check contacts meta field first (if stored as count) $contacts_count = get_post_meta($company_id, 'contacts', true); if ($contacts_count && is_numeric($contacts_count)) { return intval($contacts_count); } // Otherwise count CI_Name_* fields for ($i = 1; $i <= 20; $i++) { $name = get_post_meta($company_id, 'CI_Name_' . $i, true); if (!empty($name)) { $count++; } } // Also check CIName_* format if ($count === 0) { for ($i = 1; $i <= 20; $i++) { $name = get_post_meta($company_id, 'CIName_' . $i, true); if (!empty($name)) { $count++; } } } return $count; } /** * Count site requirement data points for a company * Counts REC* fields that have meaningful values */ function crehq_count_site_data_points($company_id) { $count = 0; // Key REC fields to check $rec_fields = array( 'RECSQFootageMin_1', 'RECSQFootageMax_1', 'RECsite_acreage_min_1', 'RECsite_acreage_max_1', 'RECTraffic_1', 'RECPopulation_1', 'RECPopulationDaytime_1', 'RECMinimumParking_1', 'RECFTFrontageMin_1', 'RECFTFrontageMax_1', 'RECMedianIncome_1', 'REChouseholds_1', 'RECgrowth_rate_1', 'RECsite_characteristics_1', 'RECtarget_markets_1', 'RECco_tenancy_1', 'RECcorner_preference_1', 'RECaccess_points_1', 'RECbuilding_dimensions_1', 'RECbuilding_height_1', 'RECdrive_thru_stack_1', 'RECexclusions_1', 'RECmarket_notes_1', 'RECconcept_one_1', 'RECProcessSteps_1', 'RECTimeline_1' ); foreach ($rec_fields as $field) { $value = get_post_meta($company_id, $field, true); if (!empty($value) && $value !== '0') { $count++; } } return $count; } /** * Get expansion status label and color */ function crehq_get_expansion_status_display($company_id) { $status = get_post_meta($company_id, 'expansion_status', true); $statuses = array( 'actively_expanding' => array( 'label' => 'Actively Expanding', 'color' => 'emerald', 'icon' => 'trending-up' ), 'selective_growth' => array( 'label' => 'Selective Growth', 'color' => 'blue', 'icon' => 'target' ), 'stable' => array( 'label' => 'Stable', 'color' => 'gray', 'icon' => 'minus' ), 'restructuring' => array( 'label' => 'Restructuring', 'color' => 'amber', 'icon' => 'refresh' ), 'contracting' => array( 'label' => 'Contracting', 'color' => 'red', 'icon' => 'trending-down' ) ); if (isset($statuses[$status])) { return $statuses[$status]; } // Default if no status set return array( 'label' => 'Status Unknown', 'color' => 'gray', 'icon' => 'question' ); } /** * Format store count for display */ if (!function_exists('crehq_format_store_count')) { function crehq_format_store_count($count) { if ($count >= 1000) { return number_format($count / 1000, 1) . 'K'; } return number_format($count); } } /** * Redirect users to customer dashboard after login instead of wp-admin * Admins can still access wp-admin via the Admin link in header */ add_filter('login_redirect', function($redirect_to, $requested_redirect_to, $user) { // If user object isn't valid, return default if (!is_a($user, 'WP_User')) { return $redirect_to; } // If explicitly requesting wp-admin (e.g., came from admin page), allow it if (strpos($requested_redirect_to, 'wp-admin') !== false) { return $redirect_to; } // Redirect all users to customer dashboard by default return home_url('/dashboard/'); }, 10, 3); /** * Security: Disable user enumeration via REST API * Prevents unauthenticated access to /wp-json/wp/v2/users */ add_filter('rest_endpoints', function($endpoints) { if (!is_user_logged_in()) { if (isset($endpoints['/wp/v2/users'])) { unset($endpoints['/wp/v2/users']); } if (isset($endpoints['/wp/v2/users/(?P[\d]+)'])) { unset($endpoints['/wp/v2/users/(?P[\d]+)']); } } return $endpoints; }); /** * Security: Disable author archives to prevent user enumeration */ add_action('template_redirect', function() { if (is_author() && !is_user_logged_in()) { wp_redirect(home_url(), 301); exit; } }); /** * Get s2Member checkout shortcode for membership plans * * @param string $plan 'annual' or 'monthly' * @return string The rendered shortcode output */ function crehq_get_checkout_shortcode($plan = 'annual') { if ($plan === 'monthly') { // Monthly Pro membership - $49.99/month $shortcode = '[s2Member-Pro-Stripe-Form level="1" ccaps="" desc="CREHQ Pro Monthly ($49.99/month)" cc="USD" custom="crehq.com" ta="0" tp="0" tt="D" ra="49.99" rp="1" rt="M" rr="1" coupon="" accept_coupons="1" default_country_code="US" captcha="0" /]'; } else { // Annual Pro membership - $539.88/year ($44.99/month) $shortcode = '[s2Member-Pro-Stripe-Form level="1" ccaps="" desc="CREHQ Pro Annual ($539.88/year)" cc="USD" custom="crehq.com" ta="0" tp="0" tt="D" ra="539.88" rp="1" rt="Y" rr="1" coupon="" accept_coupons="1" default_country_code="US" captcha="0" /]'; } return do_shortcode($shortcode); } /** * SEO: Custom meta descriptions for Data Store pages */ add_filter('wpseo_metadesc', function($description) { // Dataset single page if (get_query_var('crehq_dataset_slug')) { $slug = get_query_var('crehq_dataset_slug'); if (class_exists('CREHQ\CompanyLocations\DataStore\Dataset')) { $dataset = \CREHQ\CompanyLocations\DataStore\Dataset::find_by_slug($slug); if ($dataset) { return sprintf( 'Download %s store location data with %s locations across %s. Includes addresses, coordinates, phone numbers, and hours. CSV, JSON, GeoJSON formats.', $dataset->name, number_format($dataset->location_count), implode(', ', array_slice($dataset->countries, 0, 3)) ); } } } // Data store listing page if (is_page('data-store')) { return 'Download retail store location datasets for market analysis. 200+ brands with addresses, coordinates, hours, and phone numbers. CSV, JSON, GeoJSON formats available.'; } return $description; }); /** * SEO: Custom titles for Data Store pages */ add_filter('wpseo_title', function($title) { // Dataset single page if (get_query_var('crehq_dataset_slug')) { $slug = get_query_var('crehq_dataset_slug'); if (class_exists('CREHQ\CompanyLocations\DataStore\Dataset')) { $dataset = \CREHQ\CompanyLocations\DataStore\Dataset::find_by_slug($slug); if ($dataset) { return sprintf('%s Store Locations Data | %s Locations | CREHQ', $dataset->name, number_format($dataset->location_count)); } } } return $title; }); /** * SEO: Open Graph tags for Data Store pages */ add_filter('wpseo_opengraph_desc', function($description) { if (get_query_var('crehq_dataset_slug')) { $slug = get_query_var('crehq_dataset_slug'); if (class_exists('CREHQ\CompanyLocations\DataStore\Dataset')) { $dataset = \CREHQ\CompanyLocations\DataStore\Dataset::find_by_slug($slug); if ($dataset) { return sprintf( 'Download %s location data - %s store locations with addresses, geo coordinates, hours, and contact info.', $dataset->name, number_format($dataset->location_count) ); } } } return $description; }); /** * SEO: Add structured data for datasets (Schema.org Dataset) */ add_action('wp_head', function() { if (!get_query_var('crehq_dataset_slug')) return; $slug = get_query_var('crehq_dataset_slug'); if (!class_exists('CREHQ\CompanyLocations\DataStore\Dataset')) return; $dataset = \CREHQ\CompanyLocations\DataStore\Dataset::find_by_slug($slug); if (!$dataset) return; $schema = [ '@context' => 'https://schema.org', '@type' => 'Dataset', 'name' => $dataset->name . ' Store Locations', 'description' => sprintf('Location data for %s stores including addresses, coordinates, hours, and contact information.', $dataset->name), 'url' => home_url('/data-store/' . $dataset->slug . '/'), 'keywords' => [$dataset->name, 'store locations', 'retail data', 'location data', $dataset->category], 'creator' => [ '@type' => 'Organization', 'name' => 'CREHQ', 'url' => home_url('/') ], 'distribution' => [ [ '@type' => 'DataDownload', 'encodingFormat' => 'text/csv', 'contentUrl' => home_url('/data-store/' . $dataset->slug . '/') ], [ '@type' => 'DataDownload', 'encodingFormat' => 'application/json', 'contentUrl' => home_url('/data-store/' . $dataset->slug . '/') ] ], 'variableMeasured' => 'Store count: ' . number_format($dataset->location_count), 'spatialCoverage' => implode(', ', $dataset->countries), 'dateModified' => $dataset->last_updated ?: date('Y-m-d') ]; echo '' . " "; }, 5); /** * SEO: Add rewrite rules for Data Store category pages * Creates URLs like /data-store/category/fast-food/ */ add_action('init', function() { add_rewrite_rule( '^data-store/category/([^/]+)/?$', 'index.php?crehq_datastore=1&ds_category=$matches[1]', 'top' ); }); add_filter('query_vars', function($vars) { $vars[] = 'ds_category'; return $vars; }); /** * SEO: Meta descriptions for category pages */ add_filter('wpseo_metadesc', function($description) { // Parse URL directly since query vars may not be set when Yoast runs $uri = $_SERVER['REQUEST_URI'] ?? ''; if (preg_match('#/data-store/category/([^/]+)/?#', $uri, $matches)) { $category_name = ucwords(str_replace('-', ' ', $matches[1])); return sprintf( 'Download %s store location datasets. Browse verified retail data with addresses, coordinates, and hours. CSV, JSON, GeoJSON formats.', $category_name ); } return $description; }, 999); add_filter('wpseo_title', function($title) { // Parse URL directly since query vars may not be set when Yoast runs $uri = $_SERVER['REQUEST_URI'] ?? ''; if (preg_match('#/data-store/category/([^/]+)/?#', $uri, $matches)) { $category_name = ucwords(str_replace('-', ' ', $matches[1])); return sprintf('%s Location Datasets | Data Store | CREHQ', $category_name); } return $title; }, 999); /** * SEO: Override document title for category pages (higher priority than Yoast) */ add_filter('pre_get_document_title', function($title) { $uri = $_SERVER['REQUEST_URI'] ?? ''; if (preg_match('#/data-store/category/([^/]+)/?#', $uri, $matches)) { $category_name = ucwords(str_replace('-', ' ', $matches[1])); return sprintf('%s Location Datasets | Data Store | CREHQ', $category_name); } return $title; }, 999); /** * SEO: Fix canonical URL for category pages */ add_filter('wpseo_canonical', function($canonical) { $uri = $_SERVER['REQUEST_URI'] ?? ''; if (preg_match('#/data-store/category/([^/]+)/?#', $uri, $matches)) { return home_url('/data-store/category/' . $matches[1] . '/'); } return $canonical; }, 999); /** * Get related datasets by category */ function crehq_get_related_datasets($current_dataset, $limit = 4) { if (!class_exists('CREHQ\CompanyLocations\DataStore\Dataset')) { return []; } $datasets = \CREHQ\CompanyLocations\DataStore\Dataset::query([ 'status' => 'active', 'category' => $current_dataset->category, 'limit' => $limit + 1, // +1 to account for current dataset 'orderby' => 'location_count', 'order' => 'DESC' ]); $related = []; foreach ($datasets as $ds) { if ($ds->slug === $current_dataset->slug) continue; if ($ds->location_count > 0) { $related[] = $ds; if (count($related) >= $limit) break; } } return $related; } /** * Add Data Store datasets to Yoast sitemap */ add_filter('wpseo_sitemap_index', function($sitemap_custom_items) { global $wpdb; $table = $wpdb->prefix . 'crehq_datasets'; $last_modified = $wpdb->get_var("SELECT MAX(last_updated) FROM $table WHERE status = 'active'"); if (!$last_modified) $last_modified = current_time('c'); $sitemap_custom_items .= '' . PHP_EOL; $sitemap_custom_items .= '' . home_url('/datastore-sitemap.xml') . '' . PHP_EOL; $sitemap_custom_items .= '' . date('c', strtotime($last_modified)) . '' . PHP_EOL; $sitemap_custom_items .= '' . PHP_EOL; return $sitemap_custom_items; }); /** * Register custom sitemap route for data store */ add_action('init', function() { add_rewrite_rule('^datastore-sitemap\.xml$', 'index.php?crehq_datastore_sitemap=1', 'top'); }); add_filter('query_vars', function($vars) { $vars[] = 'crehq_datastore_sitemap'; return $vars; }); add_action('template_redirect', function() { if (!get_query_var('crehq_datastore_sitemap')) return; global $wpdb; $table = $wpdb->prefix . 'crehq_datasets'; $datasets = $wpdb->get_results("SELECT slug, last_updated FROM $table WHERE status = 'active' ORDER BY name"); header('Content-Type: application/xml; charset=UTF-8'); echo '' . PHP_EOL; echo '' . PHP_EOL; // Main data store page echo '' . PHP_EOL; echo '' . home_url('/data-store/') . '' . PHP_EOL; echo 'weekly' . PHP_EOL; echo '0.8' . PHP_EOL; echo '' . PHP_EOL; // Category pages $categories = $wpdb->get_col("SELECT DISTINCT category FROM $table WHERE status = 'active' AND category IS NOT NULL"); foreach ($categories as $cat) { echo '' . PHP_EOL; echo '' . home_url('/data-store/category/' . sanitize_title($cat) . '/') . '' . PHP_EOL; echo 'weekly' . PHP_EOL; echo '0.7' . PHP_EOL; echo '' . PHP_EOL; } // Individual dataset pages foreach ($datasets as $ds) { echo '' . PHP_EOL; echo '' . home_url('/data-store/' . $ds->slug . '/') . '' . PHP_EOL; echo '' . date('c', strtotime($ds->last_updated)) . '' . PHP_EOL; echo 'monthly' . PHP_EOL; echo '0.6' . PHP_EOL; echo '' . PHP_EOL; } echo ''; exit; }); /** * Get dataset for company by company_id */ function crehq_get_company_dataset($company_id) { if (!class_exists('CREHQ\CompanyLocations\DataStore\Dataset')) { return null; } global $wpdb; $table = $wpdb->prefix . 'crehq_datasets'; $dataset = $wpdb->get_row($wpdb->prepare( "SELECT * FROM $table WHERE company_id = %d AND status = 'active' LIMIT 1", $company_id )); return $dataset; } /** * Get homepage statistics for company counts */ function crehq_get_homepage_stats() { $stats = get_transient("crehq_homepage_stats"); if (false === $stats) { $company_count = wp_count_posts("companies"); $stats = array( "companies" => isset($company_count->publish) ? $company_count->publish : 2400, "locations" => 500000, "contacts" => 15000 ); set_transient("crehq_homepage_stats", $stats, HOUR_IN_SECONDS); } return $stats; } /** * Company Notes & Reminders System */ // ========================================================================= // COMPANY NOTES & REMINDERS SYSTEM // ========================================================================= /** * Create notes table on activation */ function crehq_create_notes_table() { global $wpdb; $table_name = $wpdb->prefix . 'crehq_company_notes'; $charset_collate = $wpdb->get_charset_collate(); $sql = "CREATE TABLE IF NOT EXISTS $table_name ( id bigint(20) NOT NULL AUTO_INCREMENT, user_id bigint(20) NOT NULL, company_id bigint(20) NOT NULL, note_type varchar(50) DEFAULT 'general', note_content longtext NOT NULL, tagged_contacts text, reminder_date datetime DEFAULT NULL, reminder_sent tinyint(1) DEFAULT 0, is_pinned tinyint(1) DEFAULT 0, created_at datetime DEFAULT CURRENT_TIMESTAMP, updated_at datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY user_id (user_id), KEY company_id (company_id), KEY reminder_date (reminder_date) ) $charset_collate;"; require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); dbDelta($sql); } add_action('after_switch_theme', 'crehq_create_notes_table'); // Run once to create table if (!get_option('crehq_notes_table_created')) { crehq_create_notes_table(); update_option('crehq_notes_table_created', true); } /** * Get notes for a company */ function crehq_get_company_notes($company_id, $user_id = null) { global $wpdb; $table_name = $wpdb->prefix . 'crehq_company_notes'; if (!$user_id) { $user_id = get_current_user_id(); } $notes = $wpdb->get_results($wpdb->prepare( "SELECT * FROM $table_name WHERE company_id = %d AND user_id = %d ORDER BY is_pinned DESC, created_at DESC", $company_id, $user_id )); return $notes; } /** * Add a note */ function crehq_add_company_note($data) { global $wpdb; $table_name = $wpdb->prefix . 'crehq_company_notes'; $result = $wpdb->insert($table_name, array( 'user_id' => get_current_user_id(), 'company_id' => intval($data['company_id']), 'note_type' => sanitize_text_field($data['note_type']), 'note_content' => wp_kses_post($data['note_content']), 'tagged_contacts' => isset($data['tagged_contacts']) ? sanitize_text_field($data['tagged_contacts']) : '', 'reminder_date' => !empty($data['reminder_date']) ? sanitize_text_field($data['reminder_date']) : null, 'is_pinned' => isset($data['is_pinned']) ? 1 : 0 )); if ($result) { return $wpdb->insert_id; } return false; } /** * Update a note */ function crehq_update_company_note($note_id, $data) { global $wpdb; $table_name = $wpdb->prefix . 'crehq_company_notes'; $update_data = array(); if (isset($data['note_content'])) { $update_data['note_content'] = wp_kses_post($data['note_content']); } if (isset($data['note_type'])) { $update_data['note_type'] = sanitize_text_field($data['note_type']); } if (isset($data['tagged_contacts'])) { $update_data['tagged_contacts'] = sanitize_text_field($data['tagged_contacts']); } if (isset($data['reminder_date'])) { $update_data['reminder_date'] = !empty($data['reminder_date']) ? sanitize_text_field($data['reminder_date']) : null; } if (isset($data['is_pinned'])) { $update_data['is_pinned'] = $data['is_pinned'] ? 1 : 0; } return $wpdb->update( $table_name, $update_data, array('id' => $note_id, 'user_id' => get_current_user_id()) ); } /** * Delete a note */ function crehq_delete_company_note($note_id) { global $wpdb; $table_name = $wpdb->prefix . 'crehq_company_notes'; return $wpdb->delete($table_name, array( 'id' => $note_id, 'user_id' => get_current_user_id() )); } /** * Toggle pin status */ function crehq_toggle_note_pin($note_id) { global $wpdb; $table_name = $wpdb->prefix . 'crehq_company_notes'; $current = $wpdb->get_var($wpdb->prepare( "SELECT is_pinned FROM $table_name WHERE id = %d AND user_id = %d", $note_id, get_current_user_id() )); return $wpdb->update( $table_name, array('is_pinned' => $current ? 0 : 1), array('id' => $note_id, 'user_id' => get_current_user_id()) ); } /** * Get upcoming reminders for user */ function crehq_get_user_reminders($user_id = null, $days_ahead = 7) { global $wpdb; $table_name = $wpdb->prefix . 'crehq_company_notes'; if (!$user_id) { $user_id = get_current_user_id(); } $reminders = $wpdb->get_results($wpdb->prepare( "SELECT n.*, p.post_title as company_name FROM $table_name n LEFT JOIN {$wpdb->posts} p ON n.company_id = p.ID WHERE n.user_id = %d AND n.reminder_date IS NOT NULL AND n.reminder_date <= DATE_ADD(NOW(), INTERVAL %d DAY) AND n.reminder_date >= NOW() ORDER BY n.reminder_date ASC", $user_id, $days_ahead )); return $reminders; } // ========================================================================= // AJAX HANDLERS // ========================================================================= /** * Get notes AJAX */ function crehq_ajax_get_notes() { check_ajax_referer('crehq_notes_nonce', 'nonce'); if (!is_user_logged_in()) { wp_send_json_error('Not logged in'); } $company_id = intval($_POST['company_id']); $notes = crehq_get_company_notes($company_id); wp_send_json_success(array('notes' => $notes)); } add_action('wp_ajax_crehq_get_notes', 'crehq_ajax_get_notes'); /** * Add note AJAX */ function crehq_ajax_add_note() { check_ajax_referer('crehq_notes_nonce', 'nonce'); if (!is_user_logged_in()) { wp_send_json_error('Not logged in'); } $note_id = crehq_add_company_note($_POST); if ($note_id) { $notes = crehq_get_company_notes(intval($_POST['company_id'])); wp_send_json_success(array('note_id' => $note_id, 'notes' => $notes)); } else { wp_send_json_error('Failed to add note'); } } add_action('wp_ajax_crehq_add_note', 'crehq_ajax_add_note'); /** * Update note AJAX */ function crehq_ajax_update_note() { check_ajax_referer('crehq_notes_nonce', 'nonce'); if (!is_user_logged_in()) { wp_send_json_error('Not logged in'); } $note_id = intval($_POST['note_id']); $result = crehq_update_company_note($note_id, $_POST); if ($result !== false) { $notes = crehq_get_company_notes(intval($_POST['company_id'])); wp_send_json_success(array('notes' => $notes)); } else { wp_send_json_error('Failed to update note'); } } add_action('wp_ajax_crehq_update_note', 'crehq_ajax_update_note'); /** * Delete note AJAX */ function crehq_ajax_delete_note() { check_ajax_referer('crehq_notes_nonce', 'nonce'); if (!is_user_logged_in()) { wp_send_json_error('Not logged in'); } $note_id = intval($_POST['note_id']); $company_id = intval($_POST['company_id']); $result = crehq_delete_company_note($note_id); if ($result) { $notes = crehq_get_company_notes($company_id); wp_send_json_success(array('notes' => $notes)); } else { wp_send_json_error('Failed to delete note'); } } add_action('wp_ajax_crehq_delete_note', 'crehq_ajax_delete_note'); /** * Toggle pin AJAX */ function crehq_ajax_toggle_pin() { check_ajax_referer('crehq_notes_nonce', 'nonce'); if (!is_user_logged_in()) { wp_send_json_error('Not logged in'); } $note_id = intval($_POST['note_id']); $company_id = intval($_POST['company_id']); crehq_toggle_note_pin($note_id); $notes = crehq_get_company_notes($company_id); wp_send_json_success(array('notes' => $notes)); } add_action('wp_ajax_crehq_toggle_pin', 'crehq_ajax_toggle_pin'); /** * Get reminders AJAX (for dashboard widget) */ function crehq_ajax_get_reminders() { check_ajax_referer('crehq_notes_nonce', 'nonce'); if (!is_user_logged_in()) { wp_send_json_error('Not logged in'); } $days = isset($_POST['days']) ? intval($_POST['days']) : 7; $reminders = crehq_get_user_reminders(null, $days); wp_send_json_success(array('reminders' => $reminders)); } add_action('wp_ajax_crehq_get_reminders', 'crehq_ajax_get_reminders');

Company Directory

Explore our comprehensive database of 2,408 companies with detailed real estate requirements, contacts, and expansion plans.

2,408 Companies
367,716 Locations
85 Categories
24 Countries

All Companies

Showing 1153-1164 of 2391 companies

Unlock full details with membership Join Now
Company Category Location Stores Expansion Franchise Actions
Orlando, Florida, United States 1
Premium
- View Details
Scottsdale, Arizona, United States
Premium
- View Details
Quick Service Rochester, NY, USA
Premium
- View Details
Quick Service Restaurant (QSR) Potomac, Maryland, United States 22
Premium
Yes View Details
Full Service Restaurant Eugene, Oregon, United States 10
Premium
Yes View Details
Full Service Restaurant Youngstown, Ohio, United States 129
Premium
Yes View Details
Coral Gables, Florida, United States 27
Premium
Yes View Details
Dallas, Texas, United States 32
Premium
Yes View Details
Full Service Restaurant San Bernardino, CA, USA 38
Premium
- View Details
Full Service Restaurant Broomfield, Colorado, United States
Premium
- View Details
Full Service Restaurant Morristown, New Jersey, United States 35
Premium
- View Details
Quick Service Restaurant (QSR) Sterling Heights, Michigan, United States
Premium
- View Details

Unlock Full Company Intelligence

Get unlimited access to detailed company profiles, contact information, and real estate requirements

Complete Contact Database
Real Estate Requirements
Expansion Plans & Timelines
Franchise Information
Direct Site Submission
Priority Support
CREHQ Membership Benefits