array( 'about-us', 'about' ), 'contact' => array( 'contact-us', 'contact' ), 'faq' => array( 'faq', 'faqs' ), 'blog' => array( 'blogs', 'blog' ), ) ); } /** * Which design the current request uses: about|contact|faq|blog|post, or ''. */ function hoho_page_kind() { static $kind = null; if ( null !== $kind ) { return $kind; } // The query is not resolved yet: answer, but don't cache the answer. if ( ! did_action( 'wp' ) ) { return ''; } $kind = ''; if ( is_singular( 'post' ) ) { $kind = 'post'; } elseif ( is_home() && ! is_front_page() ) { // The Posts page — but never a "Your latest posts" homepage. $kind = 'blog'; } elseif ( is_page() ) { foreach ( hoho_page_slugs() as $name => $slugs ) { if ( is_page( $slugs ) ) { $kind = $name; break; } } } return $kind; } function hoho_asset( $path ) { return get_stylesheet_directory_uri() . '/assets/' . ltrim( $path, '/' ); } /** * Social profile links (footer + contact page). Override with the * `hoho_socials` filter. */ function hoho_socials() { return apply_filters( 'hoho_socials', array( 'whatsapp' => '#', 'instagram' => '#', 'telegram' => '#', 'facebook' => '#', ) ); } add_filter( 'template_include', function ( $template ) { $kind = hoho_page_kind(); if ( '' === $kind ) { return $template; } $path = get_stylesheet_directory() . '/templates/' . $kind . '.php'; return file_exists( $path ) ? $path : $template; }, 99 ); // Full-width, no-sidebar canvas under Astra (same treatment as the plugin pages). add_filter( 'body_class', function ( $classes ) { if ( hoho_page_kind() ) { $classes[] = 'hoho-fullwidth'; } return $classes; } ); add_filter( 'astra_page_layout', function ( $layout ) { return hoho_page_kind() ? 'no-sidebar' : $layout; } ); add_filter( 'astra_get_content_layout', function ( $layout ) { return hoho_page_kind() ? 'page-builder' : $layout; } ); add_action( 'wp_enqueue_scripts', function () { if ( ! hoho_page_kind() ) { return; } $ver = wp_get_theme()->get( 'Version' ); // pages.css is the whole design stylesheet scoped to .hoho-page; the // Astra overrides load after it so they win ties. wp_enqueue_style( 'hoho-pages', hoho_asset( 'pages.css' ), array( 'hoho-chrome' ), $ver ); wp_enqueue_style( 'hoho-pages-wp', hoho_asset( 'pages-wp.css' ), array( 'hoho-pages' ), $ver ); wp_enqueue_script( 'hoho-pages', hoho_asset( 'pages.js' ), array(), $ver, true ); wp_localize_script( 'hoho-pages', 'hohoPages', array( 'sending' => __( 'Sending…', 'hoponhopoff' ), 'invalid' => __( 'Please fill in your name, a valid email and your message.', 'hoponhopoff' ), 'failed' => hoho_contact_message( 'error' ), 'copied' => __( 'Link copied', 'hoponhopoff' ), 'more' => __( 'Show all reviews', 'hoponhopoff' ), 'fewer' => __( 'Show fewer reviews', 'hoponhopoff' ), ) ); }, 30 ); // Icons the design pages use that the site-wide sprite lacks. add_action( 'wp_footer', function () { if ( hoho_page_kind() ) { echo file_get_contents( get_stylesheet_directory() . '/assets/sprite-pages.svg' ); // phpcs:ignore } }, 2 ); /* --------------------------------------------------------------------------- * Blog * ------------------------------------------------------------------------- */ /** * Blog list state from the query string. `q` (not `s`) so WordPress does not * switch to its search template; `pg` so paging works the same whether the * list is the Posts page or an ordinary page. */ function hoho_blog_state() { $q = isset( $_GET['q'] ) ? sanitize_text_field( wp_unslash( $_GET['q'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification $sort = isset( $_GET['sort'] ) ? sanitize_key( $_GET['sort'] ) : 'newest'; // phpcs:ignore WordPress.Security.NonceVerification $pg = isset( $_GET['pg'] ) ? max( 1, absint( $_GET['pg'] ) ) : 1; // phpcs:ignore WordPress.Security.NonceVerification if ( ! in_array( $sort, array( 'newest', 'oldest', 'title' ), true ) ) { $sort = 'newest'; } return compact( 'q', 'sort', 'pg' ); } function hoho_blog_query( array $state ) { $order = array( 'newest' => array( 'date', 'DESC' ), 'oldest' => array( 'date', 'ASC' ), 'title' => array( 'title', 'ASC' ), ); return new WP_Query( array( 'post_type' => 'post', 'post_status' => 'publish', 'posts_per_page' => 12, 'paged' => $state['pg'], 's' => $state['q'], 'orderby' => $order[ $state['sort'] ][0], 'order' => $order[ $state['sort'] ][1], 'ignore_sticky_posts' => true, ) ); } /** * Card date chip, as in the design: relative for the last week, then a date. */ function hoho_time_label( $post = null ) { $time = get_post_time( 'U', true, $post ); if ( time() - $time < WEEK_IN_SECONDS ) { /* translators: %s: human time difference, e.g. "3 hours". */ return sprintf( __( '%s ago', 'hoponhopoff' ), human_time_diff( $time ) ); } return get_the_date( 'Y/m/d', $post ); } /** * Image for a post card/hero: the featured image, else a design photo. */ function hoho_post_image_url( $post = null, $size = 'large' ) { $url = get_the_post_thumbnail_url( $post, $size ); if ( $url ) { return $url; } $fallbacks = array( 'tour-london', 'tour-paris', 'tour-sydney', 'tour-san-diego' ); return hoho_asset( 'img/' . $fallbacks[ get_post( $post )->ID % count( $fallbacks ) ] . '.webp' ); } /** * One article card (.acard). $wrap: 'li' (blog grid, wrapped in .titem) or * 'related' (the post page's related row, where the card is the
  • ). */ function hoho_article_card( $post, $wrap = 'li' ) { $post = get_post( $post ); $heading = 'related' === $wrap ? 'h3' : 'h2'; ob_start(); ?>
    < class="acard__title">>

    ' . $inner . '
  • '; } return '
  • ' . $inner . '
  • '; } /* --------------------------------------------------------------------------- * Contact form * ------------------------------------------------------------------------- */ function hoho_contact_message( $status ) { return 'sent' === $status ? __( 'Thanks! Your ticket has been sent. We will reply by email.', 'hoponhopoff' ) : __( 'Sorry, your message could not be sent. Please check the fields and try again.', 'hoponhopoff' ); } /** * Recipient: "Contact email" on Settings → Viator Collector, else the site * admin email. */ function hoho_contact_recipient() { $settings = get_option( 'vc_settings', array() ); $email = is_array( $settings ) && ! empty( $settings['contact_email'] ) ? $settings['contact_email'] : ''; return is_email( $email ) ? $email : get_option( 'admin_email' ); } function hoho_handle_contact() { $ajax = wp_doing_ajax(); $ok = false; $valid_nonce = isset( $_POST['hoho_contact_nonce'] ) && wp_verify_nonce( sanitize_key( wp_unslash( $_POST['hoho_contact_nonce'] ) ), 'hoho_contact' ); $name = isset( $_POST['name'] ) ? sanitize_text_field( wp_unslash( $_POST['name'] ) ) : ''; $email = isset( $_POST['email'] ) ? sanitize_email( wp_unslash( $_POST['email'] ) ) : ''; $message = isset( $_POST['message'] ) ? sanitize_textarea_field( wp_unslash( $_POST['message'] ) ) : ''; $trap = isset( $_POST['website'] ) ? trim( (string) wp_unslash( $_POST['website'] ) ) : ''; if ( '' !== $trap ) { // A bot filled the hidden field: pretend it worked, send nothing. $ok = true; } elseif ( $valid_nonce && '' !== $name && is_email( $email ) && '' !== $message ) { $subject = sprintf( /* translators: 1: site name, 2: sender name. */ __( '[%1$s] Contact form: %2$s', 'hoponhopoff' ), wp_specialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES ), $name ); $body = sprintf( "Name: %s\nEmail: %s\n\n%s\n", $name, $email, $message ); $headers = array( 'Reply-To: ' . str_replace( array( "\r", "\n" ), '', $name ) . ' <' . $email . '>' ); $ok = wp_mail( hoho_contact_recipient(), $subject, $body, $headers ); } if ( $ajax ) { if ( $ok ) { wp_send_json_success( array( 'message' => hoho_contact_message( 'sent' ) ) ); } wp_send_json_error( array( 'message' => hoho_contact_message( 'error' ) ) ); } $back = wp_get_referer() ? wp_get_referer() : home_url( '/contact-us/' ); wp_safe_redirect( add_query_arg( 'contact', $ok ? 'sent' : 'error', remove_query_arg( 'contact', $back ) ) . '#ticketForm' ); exit; } foreach ( array( 'admin_post_hoho_contact', 'admin_post_nopriv_hoho_contact', 'wp_ajax_hoho_contact', 'wp_ajax_nopriv_hoho_contact' ) as $hoho_hook ) { add_action( $hoho_hook, 'hoho_handle_contact' ); } unset( $hoho_hook );