File: /var/www/viitorx.stgviitor.com/wp-content/themes/viitorx/functions.php
<?php
/**
* ViitorX functions and definitions
*
* @link https://developer.wordpress.org/themes/basics/theme-functions/
*
* @package ViitorX
*/
if (! defined('_S_VERSION')) {
// Replace the version number of the theme on each release.
define('_S_VERSION', '1.0.0');
}
/**
* Sets up theme defaults and registers support for various WordPress features.
*
* Note that this function is hooked into the after_setup_theme hook, which
* runs before the init hook. The init hook is too late for some features, such
* as indicating support for post thumbnails.
*/
function viitorx_setup()
{
/*
* Make theme available for translation.
* Translations can be filed in the /languages/ directory.
* If you're building a theme based on ViitorX, use a find and replace
* to change 'viitorx' to the name of your theme in all the template files.
*/
load_theme_textdomain('viitorx', get_template_directory() . '/languages');
// Add default posts and comments RSS feed links to head.
add_theme_support('automatic-feed-links');
/*
* Let WordPress manage the document title.
* By adding theme support, we declare that this theme does not use a
* hard-coded <title> tag in the document head, and expect WordPress to
* provide it for us.
*/
add_theme_support('title-tag');
/*
* Enable support for Post Thumbnails on posts and pages.
*
* @link https://developer.wordpress.org/themes/functionality/featured-images-post-thumbnails/
*/
add_theme_support('post-thumbnails');
// This theme uses wp_nav_menu() in one location.
register_nav_menus(
array(
'menu-1' => esc_html__('Primary', 'viitorx'),
)
);
/*
* Switch default core markup for search form, comment form, and comments
* to output valid HTML5.
*/
add_theme_support(
'html5',
array(
'search-form',
'comment-form',
'comment-list',
'gallery',
'caption',
'style',
'script',
)
);
// Set up the WordPress core custom background feature.
add_theme_support(
'custom-background',
apply_filters(
'viitorx_custom_background_args',
array(
'default-color' => 'ffffff',
'default-image' => '',
)
)
);
// Add theme support for selective refresh for widgets.
add_theme_support('customize-selective-refresh-widgets');
/**
* Add support for core custom logo.
*
* @link https://codex.wordpress.org/Theme_Logo
*/
add_theme_support(
'custom-logo',
array(
'height' => 250,
'width' => 250,
'flex-width' => true,
'flex-height' => true,
)
);
}
add_action('after_setup_theme', 'viitorx_setup');
/**
* Blog Listing page template (shared marketing header/footer with header.php / footer.php).
*
* @return bool
*/
function viitorx_is_blog_listing_template()
{
return is_page_template('template-blog-listing.php');
}
/**
* Permalink for the first page using a given template file name.
*
* @param string $relative_template e.g. template-contact-us.php.
* @return string URL or home URL if none.
*/
function viitorx_get_page_url_by_template($relative_template)
{
static $cache = array();
if (isset($cache[$relative_template])) {
return $cache[$relative_template];
}
$pages = get_pages(
array(
'meta_key' => '_wp_page_template',
'meta_value' => $relative_template,
'number' => 1,
)
);
$url = '';
if (! empty($pages)) {
$url = get_permalink($pages[0]->ID);
}
$cache[$relative_template] = $url ? $url : home_url('/');
return $cache[$relative_template];
}
/**
* Front-page marketing chrome (sticky nav, drawer, scripts, footer).
*
* @return bool
*/
function viitorx_use_front_page_chrome()
{
return is_front_page()
|| viitorx_is_blog_listing_template()
|| is_page_template('template-contact-us.php')
|| is_page_template('template-offerings.php')
|| is_page_template('template-industries.php')
|| is_page_template('template-thank-you.php')
|| is_singular('post')
|| is_post_type_archive('case_study')
|| is_singular('case_study')
|| is_404();
}
/**
* Body classes for routes that reuse front-page chrome (not the homepage itself).
*
* @param string[] $classes Classes.
* @return string[]
*/
function viitorx_marketing_shell_body_class($classes)
{
if (! viitorx_use_front_page_chrome() || is_front_page()) {
return $classes;
}
$classes[] = 'viitorx-marketing-inner';
if (viitorx_is_blog_listing_template()) {
$classes[] = 'viitorx-blog-listing-body';
$classes[] = 'blog-page';
}
if (is_singular('post')) {
$classes[] = 'viitorx-single-post-body';
}
if (is_page_template('template-contact-us.php')) {
$classes[] = 'contact-us-page';
}
if (is_page_template('template-offerings.php')) {
$classes[] = 'offerings-page';
}
if (is_page_template('template-industries.php')) {
$classes[] = 'industries-page';
}
if (is_page_template('template-thank-you.php')) {
$classes[] = 'thank-you-page';
}
if (is_post_type_archive('case_study')) {
$classes[] = 'viitorx-case-study-archive';
/* Match Insights listing: breadcrumbs + shared blog.css tokens */
$classes[] = 'viitorx-blog-listing-body';
$classes[] = 'blog-page';
}
if (is_singular('case_study')) {
$classes[] = 'viitorx-single-case-study';
$classes[] = 'case-study-detail-page';
}
if (is_404()) {
$classes[] = 'viitorx-error-404-page';
}
return $classes;
}
add_filter('body_class', 'viitorx_marketing_shell_body_class');
/**
* Preserve marketing document title on the static front page (output via wp_head()).
*
* @param string $title Document title.
* @return string
*/
function viitorx_front_page_document_title($title)
{
if (is_front_page()) {
return __('ViitorX | Digital Experience and Immersive Solutions', 'viitorx');
}
return $title;
}
add_filter('pre_get_document_title', 'viitorx_front_page_document_title');
/**
* Set the content width in pixels, based on the theme's design and stylesheet.
*
* Priority 0 to make it available to lower priority callbacks.
*
* @global int $content_width
*/
function viitorx_content_width()
{
$GLOBALS['content_width'] = apply_filters('viitorx_content_width', 640);
}
add_action('after_setup_theme', 'viitorx_content_width', 0);
/**
* Register widget area.
*
* @link https://developer.wordpress.org/themes/functionality/sidebars/#registering-a-sidebar
*/
function viitorx_widgets_init()
{
register_sidebar(
array(
'name' => esc_html__('Sidebar', 'viitorx'),
'id' => 'sidebar-1',
'description' => esc_html__('Add widgets here.', 'viitorx'),
'before_widget' => '<section id="%1$s" class="widget %2$s">',
'after_widget' => '</section>',
'before_title' => '<h2 class="widget-title">',
'after_title' => '</h2>',
)
);
}
add_action('widgets_init', 'viitorx_widgets_init');
/**
* Enqueue scripts and styles.
*/
/**
* Whether self-hosted font CSS has been generated (via npm run download:fonts).
*/
function viitorx_has_local_fonts() {
static $result = null;
if ( $result === null ) {
$result = file_exists( get_template_directory() . '/css/fonts.css' );
}
return $result;
}
function viitorx_scripts()
{
// Self-hosted fonts take priority; Google Fonts is the fallback (loaded in header.php).
if ( viitorx_has_local_fonts() ) {
wp_enqueue_style( 'viitorx-fonts', get_template_directory_uri() . '/css/fonts.css', array(), _S_VERSION );
}
wp_enqueue_style('viitorx-style', get_stylesheet_uri(), array(), _S_VERSION);
wp_style_add_data('viitorx-style', 'rtl', 'replace');
if (is_page_template('template-contact-us.php')) {
wp_enqueue_style(
'viitorx-contact-us',
get_template_directory_uri() . '/contact-us-page/contact-us-page/style.css',
array(),
_S_VERSION
);
}
if (is_page_template('template-offerings.php')) {
wp_enqueue_style(
'viitorx-offerings',
get_template_directory_uri() . '/css/offerings.css',
array(),
_S_VERSION
);
}
if (is_page_template('template-industries.php')) {
wp_enqueue_style(
'viitorx-industries',
get_template_directory_uri() . '/css/industries.css',
array(),
_S_VERSION
);
}
if (is_page_template('template-offerings.php') || is_page_template('template-industries.php')) {
$viitorx_section_reveal_deps = array();
if (is_page_template('template-offerings.php')) {
$viitorx_section_reveal_deps[] = 'viitorx-offerings';
}
if (is_page_template('template-industries.php')) {
$viitorx_section_reveal_deps[] = 'viitorx-industries';
}
wp_enqueue_style(
'viitorx-section-reveal',
get_template_directory_uri() . '/css/section-reveal.css',
$viitorx_section_reveal_deps,
_S_VERSION
);
wp_enqueue_script(
'viitorx-section-reveal',
get_template_directory_uri() . '/js/section-reveal.js',
array(),
_S_VERSION,
true
);
}
if (is_page_template('template-offerings.php')) {
wp_enqueue_script(
'viitorx-offerings-animate',
get_template_directory_uri() . '/js/offerings-animate.js',
array('viitorx-section-reveal'),
_S_VERSION,
true
);
}
if (is_page_template('template-thank-you.php')) {
wp_enqueue_style(
'viitorx-thank-you',
get_template_directory_uri() . '/thank-you-page/thank-you-page/style.css',
array(),
_S_VERSION
);
}
if (is_home() || is_archive() || is_search() || viitorx_is_blog_listing_template()) {
wp_enqueue_style(
'viitorx-blog',
get_template_directory_uri() . '/css/blog.css',
array(),
_S_VERSION
);
}
if (is_post_type_archive('case_study')) {
wp_enqueue_style(
'viitorx-section-reveal',
get_template_directory_uri() . '/css/section-reveal.css',
array(),
_S_VERSION
);
wp_enqueue_style(
'viitorx-case-study-archive',
get_template_directory_uri() . '/css/archive-case-study.css',
array('viitorx-blog', 'viitorx-section-reveal'),
_S_VERSION
);
wp_enqueue_script(
'viitorx-section-reveal',
get_template_directory_uri() . '/js/section-reveal.js',
array(),
_S_VERSION,
true
);
}
if (is_singular('case_study')) {
wp_enqueue_style(
'viitorx-case-study-single',
get_template_directory_uri() . '/css/single-case-study.css',
array(),
_S_VERSION
);
wp_enqueue_style(
'viitorx-section-reveal',
get_template_directory_uri() . '/css/section-reveal.css',
array('viitorx-case-study-single'),
_S_VERSION
);
wp_enqueue_script(
'viitorx-section-reveal',
get_template_directory_uri() . '/js/section-reveal.js',
array(),
_S_VERSION,
true
);
}
if (is_404()) {
wp_enqueue_style(
'viitorx-404',
get_template_directory_uri() . '/css/404.css',
array(),
_S_VERSION
);
}
if (is_singular('post')) {
wp_enqueue_style(
'viitorx-blog-single',
get_template_directory_uri() . '/css/blog-single.css',
array(),
_S_VERSION
);
wp_enqueue_style(
'viitorx-section-reveal',
get_template_directory_uri() . '/css/section-reveal.css',
array('viitorx-blog-single'),
_S_VERSION
);
wp_enqueue_script(
'viitorx-blog-single',
get_template_directory_uri() . '/js/blog-single.js',
array(),
_S_VERSION,
true
);
wp_enqueue_script(
'viitorx-section-reveal',
get_template_directory_uri() . '/js/section-reveal.js',
array('viitorx-blog-single'),
_S_VERSION,
true
);
}
if (is_singular(array('post', 'case_study'))) {
wp_enqueue_style(
'viitorx-content-blocks-reveal',
get_template_directory_uri() . '/css/content-blocks-reveal.css',
array(),
_S_VERSION
);
wp_enqueue_script(
'viitorx-content-blocks-reveal',
get_template_directory_uri() . '/js/content-blocks-reveal.js',
array('viitorx-section-reveal'),
_S_VERSION,
true
);
}
if (viitorx_is_blog_listing_template()) {
wp_enqueue_script(
'viitorx-blog-listing',
get_template_directory_uri() . '/js/blog-listing.js',
array(),
_S_VERSION,
true
);
wp_localize_script(
'viitorx-blog-listing',
'viitorxBlogListing',
array(
'ajaxUrl' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('viitorx_blog_search'),
)
);
}
wp_enqueue_script('viitorx-navigation', get_template_directory_uri() . '/js/navigation.js', array(), _S_VERSION, true);
if (is_singular() && comments_open() && get_option('thread_comments')) {
wp_enqueue_script('comment-reply');
}
if ( viitorx_use_front_page_chrome() ) {
// Shared marketing styles (nav, footer, cursor) — all marketing pages.
wp_enqueue_style(
'viitorx-marketing-shared',
get_template_directory_uri() . '/css/marketing-shared.css',
array( 'viitorx-style' ),
_S_VERSION
);
wp_enqueue_style(
'viitorx-marketing-shared-responsive',
get_template_directory_uri() . '/css/marketing-shared-responsive.css',
array( 'viitorx-marketing-shared' ),
_S_VERSION
);
}
if ( viitorx_use_front_page_chrome() ) {
// Loads on all marketing pages — contains form, CTA, button, contact,
// and hero styles shared across offerings, industries, blog, case studies, 404.
wp_enqueue_style(
'viitorx-front-page',
get_template_directory_uri() . '/css/front-page.css',
array( 'viitorx-marketing-shared' ),
_S_VERSION
);
wp_enqueue_style(
'viitorx-front-page-responsive',
get_template_directory_uri() . '/css/front-page-responsive.css',
array( 'viitorx-front-page' ),
_S_VERSION
);
}
if ( is_front_page() ) {
// Reviews section uses dynamic upload URLs — inject after the linked stylesheet.
wp_add_inline_style(
'viitorx-front-page',
'.reviews-sticky{background-image:url("' . esc_url( site_url( '/wp-content/uploads/2026/04/reviews-bg.webp' ) ) . '")}' .
'@media(max-width:991px){.reviews-sticky::before{background-image:url("' . esc_url( site_url( '/wp-content/uploads/2026/04/testimonials-m.webp' ) ) . '")}}'
);
}
}
add_action('wp_enqueue_scripts', 'viitorx_scripts');
/**
* Shared CSS overrides (e.g. intl-tel-input). Loads late so it wins over plugin defaults.
*/
function viitorx_common_styles()
{
wp_enqueue_style(
'viitorx-common',
get_template_directory_uri() . '/css/common.css',
array('viitorx-style'),
_S_VERSION
);
}
add_action('wp_enqueue_scripts', 'viitorx_common_styles', 101);
/**
* Move form-related scripts from <head> to footer.
* Scripts in the footer execute after HTML is parsed — no render-blocking,
* same benefit as defer but without the async timing issues that break
* intl-tel-input and wpcf7mailsent event dispatch.
*/
function viitorx_perf_move_scripts() {
if ( is_admin() ) {
return;
}
// intl-tel-input (pcafe_spf_intl): must NOT be deferred, just footer-placed.
wp_scripts()->add_data( 'pcafe_spf_intl', 'group', 1 );
// CF7 main script: move to footer so it doesn't block first paint.
// Must remain synchronous (not deferred) so wpcf7mailsent fires correctly.
wp_scripts()->add_data( 'contact-form-7', 'group', 1 );
}
add_action( 'wp_enqueue_scripts', 'viitorx_perf_move_scripts', 999 );
/**
* Add defer to render-blocking scripts.
* jQuery blocks for ~3 s; pcafe_spf_intl blocks for ~4 s.
* defer = download in parallel with HTML parse, execute after parse in document order.
*/
function viitorx_perf_defer_scripts( $tag, $handle, $src ) {
if ( is_admin() ) {
return $tag;
}
// section-reveal, offerings-animate, content-blocks-reveal must defer too: they appear after
// the manually-deferred GSAP/ScrollTrigger tags in the HTML, so defer preserves the correct
// execution order (GSAP defined before these scripts run).
// pcafe_spf_intl (intl-tel-input) must NOT be deferred — it initialises
// the phone field synchronously and deferring it breaks the phone widget.
$defer_handles = array( 'jquery-core', 'jquery-migrate', 'viitorx-section-reveal', 'viitorx-offerings-animate', 'viitorx-content-blocks-reveal' );
if ( in_array( $handle, $defer_handles, true ) && false === strpos( $tag, ' defer' ) ) {
$tag = str_replace( ' src=', ' defer src=', $tag );
}
return $tag;
}
add_filter( 'script_loader_tag', 'viitorx_perf_defer_scripts', 10, 3 );
/**
* Load non-critical CSS non-blocking (preload + onload pattern).
*
* Above-fold styles now live in css/critical.css, inlined in header.php.
* Every enqueued stylesheet listed here is safe to async-load because:
* viitorx-style — WP theme base; accessibility utils inlined in critical.css
* viitorx-fonts — @font-face only; font-display:swap means no render block
* viitorx-marketing-shared — nav/footer/cursor; critical portion inlined in critical.css
* viitorx-marketing-shared-responsive — responsive overrides, always below first paint
* viitorx-marketing-inner-layout — fully inlined in critical.css; async here is a no-op safety net
* viitorx-offerings — hero layout inlined in critical.css; rest is below fold
* viitorx-section-reveal — scroll-animation CSS; hero override inlined in critical.css
* viitorx-common — low-priority overrides (enqueued at priority 101)
* pcafe_spf_intl / pcafe_spf_style — phone-input plugin, only needed at form interaction
*/
function viitorx_perf_async_css( $html, $handle, $href, $media ) {
if ( is_admin() || 'all' !== $media ) {
return $html;
}
$async_handles = array(
// Global — safe on every marketing page
'viitorx-style',
'viitorx-fonts',
'viitorx-marketing-shared',
'viitorx-marketing-shared-responsive',
'viitorx-marketing-inner-layout',
'viitorx-section-reveal',
'viitorx-common',
// Plugin CSS
'pcafe_spf_intl',
'pcafe_spf_style',
// Page-specific CSS whose above-fold portion is covered by critical.css
'viitorx-offerings',
'viitorx-industries',
'viitorx-contact-us',
// Case study pages — hero styles in critical.css; body content below fold
'viitorx-case-study-single',
'viitorx-case-study-archive',
);
if ( ! is_front_page() ) {
// front-page.css contains only homepage-specific sections; hero styles are in critical.css.
$async_handles[] = 'viitorx-front-page';
$async_handles[] = 'viitorx-front-page-responsive';
}
if ( in_array( $handle, $async_handles, true ) ) {
$esc = esc_attr( $href );
return '<link rel="preload" as="style" href="' . $esc . '" onload="this.onload=null;this.rel=\'stylesheet\'">' . "\n"
. '<noscript><link rel="stylesheet" href="' . $esc . '"></noscript>' . "\n";
}
return $html;
}
add_filter( 'style_loader_tag', 'viitorx_perf_async_css', 10, 4 );
/**
* AJAX blog listing search (posts only).
*/
function viitorx_ajax_blog_search()
{
check_ajax_referer('viitorx_blog_search', 'nonce');
$search = isset($_POST['s']) ? sanitize_text_field(wp_unslash($_POST['s'])) : '';
$paged = isset($_POST['paged']) ? max(1, (int) wp_unslash($_POST['paged'])) : 1;
$args = array(
'post_type' => 'post',
'posts_per_page' => 9,
'paged' => $paged,
'post_status' => 'publish',
);
if ('' !== $search) {
$args['s'] = $search;
}
$blog_query = new WP_Query($args);
ob_start();
if ($blog_query->have_posts()) {
while ($blog_query->have_posts()) {
$blog_query->the_post();
get_template_part('template-parts/blog', 'card');
}
} else {
echo '<p class="blog-listing__empty">' . esc_html__('No posts found.', 'viitorx') . '</p>';
}
$html = ob_get_clean();
$pagination_html = '';
if ($blog_query->max_num_pages > 1 && '' === $search) {
$listing_url = viitorx_get_page_url_by_template('template-blog-listing.php');
$pag_args = array(
'total' => $blog_query->max_num_pages,
'current' => $paged,
'mid_size' => 2,
'prev_text' => __('« Previous', 'viitorx'),
'next_text' => __('Next »', 'viitorx'),
'type' => 'list',
);
if ($listing_url && get_option('permalink_structure')) {
$pag_args['base'] = user_trailingslashit(trailingslashit($listing_url) . 'page/%#%/');
} elseif ($listing_url) {
$pag_args['base'] = esc_url_raw(add_query_arg('page', '%#%', $listing_url));
}
ob_start();
echo '<nav class="blog-pagination" aria-label="' . esc_attr__('Posts pagination', 'viitorx') . '">';
echo paginate_links($pag_args);
echo '</nav>';
$pagination_html = ob_get_clean();
}
wp_reset_postdata();
wp_send_json_success(
array(
'html' => $html,
'paginationHtml' => $pagination_html,
'showPagination' => ($blog_query->max_num_pages > 1 && '' === $search),
)
);
}
add_action('wp_ajax_viitorx_blog_search', 'viitorx_ajax_blog_search');
add_action('wp_ajax_nopriv_viitorx_blog_search', 'viitorx_ajax_blog_search');
/**
* Gutters on inner marketing routes match front-page :root --section-inline (caps at 100px).
* Printed after page-specific CSS (priority 100).
*/
function viitorx_marketing_inner_layout_styles()
{
if (! viitorx_use_front_page_chrome() || is_front_page()) {
return;
}
wp_enqueue_style(
'viitorx-marketing-inner-layout',
get_template_directory_uri() . '/css/marketing-inner-layout.css',
array(),
_S_VERSION
);
}
add_action('wp_enqueue_scripts', 'viitorx_marketing_inner_layout_styles', 100);
/**
* Register Custom Post Type: Case Study
*/
function viitorx_register_case_study_cpt()
{
$labels = array(
'name' => _x('Case Studies', 'Post Type General Name', 'viitorx'),
'singular_name' => _x('Case Study', 'Post Type Singular Name', 'viitorx'),
'menu_name' => __('Case Studies', 'viitorx'),
'name_admin_bar' => __('Case Study', 'viitorx'),
'archives' => __('Case Study Archives', 'viitorx'),
'attributes' => __('Case Study Attributes', 'viitorx'),
'parent_item_colon' => __('Parent Case Study:', 'viitorx'),
'all_items' => __('All Case Studies', 'viitorx'),
'add_new_item' => __('Add New Case Study', 'viitorx'),
'add_new' => __('Add New', 'viitorx'),
'new_item' => __('New Case Study', 'viitorx'),
'edit_item' => __('Edit Case Study', 'viitorx'),
'update_item' => __('Update Case Study', 'viitorx'),
'view_item' => __('View Case Study', 'viitorx'),
'view_items' => __('View Case Studies', 'viitorx'),
'search_items' => __('Search Case Study', 'viitorx'),
'not_found' => __('Not found', 'viitorx'),
'not_found_in_trash' => __('Not found in Trash', 'viitorx'),
'featured_image' => __('Featured Image', 'viitorx'),
'set_featured_image' => __('Set featured image', 'viitorx'),
'remove_featured_image' => __('Remove featured image', 'viitorx'),
'use_featured_image' => __('Use as featured image', 'viitorx'),
'insert_into_item' => __('Insert into case study', 'viitorx'),
'uploaded_to_this_item' => __('Uploaded to this case study', 'viitorx'),
'items_list' => __('Case studies list', 'viitorx'),
'items_list_navigation' => __('Case studies list navigation', 'viitorx'),
'filter_items_list' => __('Filter case studies list', 'viitorx'),
);
$args = array(
'label' => __('Case Study', 'viitorx'),
'description' => __('Case Studies for ViitorX', 'viitorx'),
'labels' => $labels,
'supports' => array('title', 'editor', 'thumbnail', 'excerpt', 'page-attributes', 'custom-fields'),
'hierarchical' => false,
'public' => true,
'show_ui' => true,
'show_in_menu' => true,
'menu_position' => 5,
'menu_icon' => 'dashicons-portfolio',
'show_in_admin_bar' => true,
'show_in_nav_menus' => true,
'can_export' => true,
'has_archive' => true,
'exclude_from_search' => false,
'publicly_queryable' => true,
'capability_type' => 'page',
'show_in_rest' => true,
'rewrite' => array(
'slug' => 'case-studies',
),
);
register_post_type('case_study', $args);
}
add_action('init', 'viitorx_register_case_study_cpt', 0);
/**
* Implement the Custom Header feature.
*/
require get_template_directory() . '/inc/custom-header.php';
/**
* Custom template tags for this theme.
*/
require get_template_directory() . '/inc/template-tags.php';
/**
* Functions which enhance the theme by hooking into WordPress.
*/
require get_template_directory() . '/inc/template-functions.php';
/**
* Customizer additions.
*/
require get_template_directory() . '/inc/customizer.php';
/**
* Load Jetpack compatibility file.
*/
if (defined('JETPACK__VERSION')) {
require get_template_directory() . '/inc/jetpack.php';
}
function enable_svg_upload($upload_mimes)
{
$upload_mimes['svg'] = 'image/svg+xml';
$upload_mimes['svgz'] = 'image/svg+xml';
return $upload_mimes;
}
add_filter('upload_mimes', 'enable_svg_upload', 10, 1);
// Disable Gutenberg for all post types
add_filter('use_block_editor_for_post', '__return_false', 10);
// This will call the SMTP(config-file) to submit the form
function mailtrap($phpmailer)
{
$phpmailer->isSMTP();
$phpmailer->Host = SMTP_HOST;
$phpmailer->SMTPAuth = true;
$phpmailer->Port = SMTP_PORT;
$phpmailer->Username = SMTP_USER;
$phpmailer->Password = SMTP_PASS;
$phpmailer->SMTPSecure = SMTP_SECURE;
$phpmailer->From = SMTP_FROM;
$phpmailer->FromName = SMTP_FROM_NAME;
}
add_action('phpmailer_init', 'mailtrap');
// Action Hook to redirect to thank you page after form submission
add_action('wp_footer', 'redirect_cf7');
function redirect_cf7()
{
// Get dynamic URL of the thank you page
$thank_you_url = home_url('/thank-you/');
?>
<script type="text/javascript">
document.addEventListener('wpcf7mailsent', function(event) {
location = '<?php echo esc_url($thank_you_url); ?>';
}, false);
</script>
<?php
}
require_once get_template_directory() . '/inc/seo-schema.php';
require_once get_template_directory() . '/inc/seo-meta.php';
/**
* Performance: strip unneeded WordPress head output and bundled assets.
*/
function viitorx_clean_head() {
// WordPress generator meta tag (security + bytes).
remove_action( 'wp_head', 'wp_generator' );
// RSD and WLW manifest links — unused by this theme.
remove_action( 'wp_head', 'rsd_link' );
remove_action( 'wp_head', 'wlwmanifest_link' );
// Emoji detection script/style — not needed.
remove_action( 'wp_head', 'print_emoji_detection_script', 7 );
remove_action( 'wp_print_styles', 'print_emoji_styles' );
remove_filter( 'the_content_feed', 'wp_staticize_emoji' );
remove_filter( 'comment_text_rss', 'wp_staticize_emoji' );
remove_filter( 'wp_mail', 'wp_staticize_emoji_for_email' );
}
add_action( 'init', 'viitorx_clean_head' );
/**
* Performance: remove Gutenberg block CSS (block editor is disabled sitewide).
*/
function viitorx_dequeue_block_assets() {
wp_dequeue_style( 'wp-block-library' );
wp_dequeue_style( 'wp-block-library-theme' );
wp_dequeue_style( 'global-styles' );
wp_deregister_script( 'wp-embed' );
}
add_action( 'wp_enqueue_scripts', 'viitorx_dequeue_block_assets', 100 );
/**
* Performance: load CF7 only on pages that actually render a contact form.
* - JS must load on every viitorx_use_front_page_chrome() page because
* template-parts/contact-form-section.php is included there — without it
* wpcf7mailsent never fires and the thank-you redirect breaks.
* - CSS is always disabled; we provide our own form styles.
*/
function viitorx_limit_cf7_assets() {
add_filter( 'wpcf7_load_css', '__return_false' );
if ( ! viitorx_use_front_page_chrome() ) {
add_filter( 'wpcf7_load_js', '__return_false' );
}
}
add_action( 'wp_enqueue_scripts', 'viitorx_limit_cf7_assets', 1 );
add_filter( 'acf/settings/save_json', function () {
return get_template_directory() . '/acf-json';
} );
add_filter( 'acf/settings/load_json', function ( $paths ) {
$paths[] = get_template_directory() . '/acf-json';
return $paths;
} );
if ( function_exists( 'acf_add_options_page' ) ) {
acf_add_options_page(
array(
'page_title' => 'Theme Settings',
'menu_title' => 'Theme Settings',
'menu_slug' => 'theme-settings',
'capability' => 'edit_posts',
'redirect' => false,
)
);
}
// =============================================================================
// AI / AGENT READINESS HOOKS
// Standards: Content-Signal, Markdown-for-Agents, WebMCP, x402
// =============================================================================
/**
* x402 protocol: advertise on all front-end responses that no payment is required.
* Agents implementing x402 will read this header and proceed without initiating payment.
*/
add_action( 'send_headers', function () {
if ( ! is_admin() && ! wp_doing_ajax() && ! ( defined( 'REST_REQUEST' ) && REST_REQUEST ) ) {
header( 'X-Payment-Protocol: x402/1.0; payment-required=false' );
header( 'X-Accept-Payment: none' );
}
} );
/**
* 1. robots.txt Content-Signal
*
* Appends a Content-Signal directive to the WordPress-generated robots.txt.
* - ai-train=no : Disallow use of content for training AI models.
* - search=yes : Allow standard search engine indexing.
* - ai-input=no : Disallow direct use as LLM input without permission.
*
* @param string $output Current robots.txt output.
* @param bool $public Whether the site is public (search engine visibility).
* @return string Modified robots.txt output.
*/
function viitorx_robots_content_signal( $output, $public ) {
if ( ! $public ) {
return $output;
}
$output .= "\n# AI/Agent Content Signal\nContent-Signal: ai-train=no, search=yes, ai-input=no\n";
return $output;
}
add_filter( 'robots_txt', 'viitorx_robots_content_signal', 10, 2 );
/**
* 2. Markdown-for-Agents response
*
* When a request carries an Accept header that includes text/markdown,
* generate a lightweight markdown representation of the current page and
* return it directly with Content-Type: text/markdown.
*
* Output includes: site name, page title, meta description, canonical URL,
* main H2/H3 headings extracted from the_content(), and nav links.
*
* Only runs on singular pages/posts and public archive/front-page contexts.
* Skips admin, REST API, AJAX, and feed requests.
*/
function viitorx_maybe_serve_markdown() {
// Bail out of admin, REST, AJAX, and feed contexts.
if ( is_admin() ) {
return;
}
if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
return;
}
if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
return;
}
if ( is_feed() ) {
return;
}
// Detect Accept: text/markdown in the request headers.
$accept = isset( $_SERVER['HTTP_ACCEPT'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_ACCEPT'] ) ) : '';
if ( false === strpos( $accept, 'text/markdown' ) ) {
return;
}
// Build the markdown response only after the query has run.
add_action( 'wp', 'viitorx_output_markdown_response' );
}
add_action( 'template_redirect', 'viitorx_maybe_serve_markdown', 1 );
/**
* Output a markdown representation of the current page and exit.
* Called only when Accept: text/markdown is detected.
*/
function viitorx_output_markdown_response() {
$site_name = get_bloginfo( 'name' );
$page_title = wp_title( '|', false, 'right' );
$page_title = $page_title ? trim( $page_title ) : $site_name;
$canonical = get_permalink();
$description = '';
// Pull meta description from Rank Math if available.
if ( function_exists( 'rank_math' ) ) {
$post_id = get_queried_object_id();
$description = get_post_meta( $post_id, 'rank_math_description', true );
}
// Fallback: use the post excerpt for singular posts.
if ( ! $description && is_singular() ) {
$post = get_post();
if ( $post ) {
$description = wp_strip_all_tags( get_the_excerpt( $post ) );
}
}
// Fallback: use the site tagline on the front page.
if ( ! $description && is_front_page() ) {
$description = get_bloginfo( 'description' );
}
// Extract headings from post content.
$headings_md = '';
if ( is_singular() ) {
$post = get_post();
if ( $post ) {
$content = apply_filters( 'the_content', $post->post_content );
preg_match_all( '/<h([23])[^>]*>(.*?)<\/h[23]>/si', $content, $matches );
if ( ! empty( $matches[1] ) ) {
foreach ( $matches[1] as $i => $level ) {
$text = wp_strip_all_tags( $matches[2][ $i ] );
$prefix = ( '2' === $level ) ? '## ' : '### ';
$headings_md .= $prefix . $text . "\n";
}
}
}
}
// Collect primary nav links.
$nav_links_md = '';
$nav_items = wp_get_nav_menu_items( 'primary' );
if ( is_array( $nav_items ) ) {
foreach ( $nav_items as $item ) {
$nav_links_md .= '- [' . esc_html( $item->title ) . '](' . esc_url( $item->url ) . ")\n";
}
}
// Assemble the markdown document.
$md = '# ' . $page_title . "\n\n";
if ( $description ) {
$md .= '> ' . $description . "\n\n";
}
if ( $canonical ) {
$md .= '**URL:** ' . esc_url( $canonical ) . "\n\n";
}
if ( $headings_md ) {
$md .= "## Page Sections\n\n" . $headings_md . "\n";
}
if ( $nav_links_md ) {
$md .= "## Site Navigation\n\n" . $nav_links_md . "\n";
}
$md .= "---\n*" . $site_name . " — " . esc_url( home_url( '/' ) ) . "*\n";
// Send response and stop further execution.
if ( ! headers_sent() ) {
header( 'Content-Type: text/markdown; charset=utf-8' );
header( 'X-Robots-Tag: noindex' );
}
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo $md;
exit;
}
/**
* 3. WebMCP context injection (all marketing pages)
*
* Injects a <script> block early in <head> so agents that navigate to any
* page can discover tools without waiting for the full page to load.
* Extended to all viitorx_use_front_page_chrome() pages (not just front page)
* so the checker's 8-second navigation timeout is not exceeded.
*/
function viitorx_webmcp_inject() {
if ( ! viitorx_use_front_page_chrome() ) {
return;
}
?>
<script>
/* WebMCP context injection — viitorx.com */
if ( typeof navigator !== 'undefined' && navigator.modelContext && typeof navigator.modelContext.provideContext === 'function' ) {
navigator.modelContext.provideContext( {
name: 'ViitorX Agency Website',
description: 'ViitorX is a full-service digital agency. Use the tools below to browse offerings, view case studies, or navigate to the contact page.',
tools: [
{
name: 'browse_offerings',
description: 'Browse the services and technology offerings provided by ViitorX, including web development, mobile apps, UI/UX design, and digital strategy.',
parameters: {},
action: {
type: 'navigate',
url: 'https://viitorx.com/offerings/'
}
},
{
name: 'view_case_studies',
description: 'View ViitorX portfolio entries and case studies. Also available as structured JSON via the REST API.',
parameters: {
format: {
type: 'string',
enum: [ 'html', 'json' ],
description: 'Response format: html (browse the archive page) or json (WordPress REST API).',
default: 'html'
}
},
action: {
type: 'navigate',
url: 'https://viitorx.com/case-studies/',
rest_url: 'https://viitorx.com/wp-json/wp/v2/case_study'
}
},
{
name: 'contact_viitorx',
description: 'Navigate to the ViitorX contact page where a user can submit a project inquiry or general message.',
parameters: {},
action: {
type: 'navigate',
url: 'https://viitorx.com/contact-us/'
}
}
]
} );
}
</script>
<?php
}
add_action( 'wp_head', 'viitorx_webmcp_inject', 99 );
// =============================================================================
// END AI / AGENT READINESS HOOKS
// =============================================================================