' . $items . '
';
}
$pg = self::pager( $q, $pager, $page, $s );
self::$parts = array(
'items' => 'carousel' === $layout ? preg_replace( '/
(int) $q->max_num_pages,
'pager' => $pg,
);
$data = array(
'post' => (int) $post_id,
'el' => $id,
'pager' => $pager,
'max' => (int) $q->max_num_pages,
'page' => $page,
'ctx' => $ctx,
);
wp_reset_postdata();
return '' . $filter . $body . $pg . '
';
}
private static function pager( \WP_Query $q, $type, $page, $s ) {
if ( 'none' === $type || $q->max_num_pages < 2 ) {
return '';
}
if ( 'more' === $type || 'infinite' === $type ) {
return 'more' === $type ? '' : '';
}
$base = remove_query_arg( 'nxp' );
if ( 'prevnext' === $type ) {
$out = '';
}
$out = '';
}
private static function loop_items( \WP_Query $q, array $s ) {
$tpl = (int) self::v( $s, 'tpl', 0 );
$html = '';
$meta = (array) self::v( $s, 'meta', array( 'date', 'read' ) );
$size = sanitize_key( self::v( $s, 'imgSize', 'medium_large' ) );
$tag = in_array( self::v( $s, 'titleTag', 'h3' ), array( 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'div', 'span' ), true ) ? self::v( $s, 'titleTag', 'h3' ) : 'h3';
$words = (int) self::v( $s, 'excerpt', 18 );
while ( $q->have_posts() ) {
$q->the_post();
$pid = get_the_ID();
if ( $tpl ) {
$html .= '' . Frontend::render_post( $tpl ) . '';
continue;
}
$link = get_permalink();
$title = get_the_title();
$img = '';
if ( self::v( $s, 'showImg', true ) && has_post_thumbnail() ) {
$badge = '';
if ( self::v( $s, 'showBadge', true ) ) {
$cats = get_the_terms( $pid, 'product' === get_post_type() ? 'product_cat' : 'category' );
if ( $cats && ! is_wp_error( $cats ) ) {
$badge = '' . esc_html( $cats[0]->name ) . '';
}
}
$img = '' . get_the_post_thumbnail( $pid, $size, array(
'loading' => 'lazy',
'decoding' => 'async',
) ) . $badge . '';
}
$m = array();
foreach ( $meta as $key ) {
switch ( $key ) {
case 'author':
$m[] = '' . esc_html( get_the_author() ) . '';
break;
case 'date':
$m[] = '';
break;
case 'cats':
$c = get_the_category_list( ', ' );
if ( $c ) {
$m[] = '' . wp_kses_post( $c ) . '';
}
break;
case 'comments':
/* translators: %d: comment count */
$m[] = '' . esc_html( sprintf( _n( '%d comment', '%d comments', get_comments_number(), 'akram' ), get_comments_number() ) ) . '';
break;
case 'read':
$m[] = '' . esc_html( Dynamic::value( 'reading_time', array() ) ) . '';
break;
case 'price':
if ( function_exists( 'wc_get_product' ) && 'product' === get_post_type() ) {
$p = wc_get_product( $pid );
$m[] = '' . wp_kses_post( $p ? $p->get_price_html() : '' ) . '';
}
break;
}
}
$excerpt = $words > 0 ? '' . esc_html( wp_trim_words( get_the_excerpt(), $words ) ) . '
' : '';
$more = self::v( $s, 'more', '' ) ? '' . esc_html( self::v( $s, 'more' ) ) . self::icon( 'arrow' ) . '' : '';
$html .= '';
}
return $html;
}
/** Public AJAX endpoint for pagination / load more / filters. */
public static function rest_loop( \WP_REST_Request $r ) {
$p = $r->get_json_params();
$post = (int) ( $p['post'] ?? 0 );
$el = sanitize_key( (string) ( $p['el'] ?? '' ) );
$status = get_post_status( $post );
if ( ! $post || ! $el || ( 'publish' !== $status && ! current_user_can( 'edit_post', $post ) ) ) {
return new \WP_Error( 'akram_missing', 'Not found', array( 'status' => 404 ) );
}
$out = Document::get_out( $post );
$d = $out['dyn'][ $el ] ?? null;
if ( ! $d || ! in_array( $d['t'], array( 'posts', 'products' ), true ) ) {
return new \WP_Error( 'akram_missing', 'Not found', array( 'status' => 404 ) );
}
$s = (array) $d['s'];
$page = max( 1, (int) ( $p['page'] ?? 1 ) );
$term = (string) ( $p['term'] ?? '' );
$ctx = is_array( $p['ctx'] ?? null ) ? $p['ctx'] : array();
self::$parts = array(
'items' => '',
'max' => 1,
'pager' => '',
);
if ( 'products' === $d['t'] ) {
self::w_products( $s, $el, $post, false, $page, $term );
} else {
self::w_posts( $s, $el, $post, false, $page, $term, $ctx );
}
return self::$parts;
}
// ------------------------------------------------------------------
// Navigation & site
// ------------------------------------------------------------------
private static function w_nav_menu( array $s, $id, $post_id, $preview ) {
$menu = (int) self::v( $s, 'menu', 0 );
if ( ! $menu ) {
$menus = wp_get_nav_menus();
$locs = get_nav_menu_locations();
$menu = $locs ? (int) reset( $locs ) : ( $menus ? (int) $menus[0]->term_id : 0 );
}
$args = array(
'container' => false,
'menu_class' => 'nx-menu',
'echo' => false,
'fallback_cb' => '__return_empty_string',
'walker' => new Nav_Walker( self::v( $s, 'indicator', 'chevron' ) ),
'depth' => 4,
);
if ( $menu ) {
$args['menu'] = $menu;
}
$list = wp_nav_menu( $args );
if ( ! $list ) {
$pages = wp_list_pages( array(
'echo' => false,
'title_li' => '',
'depth' => 2,
'number' => 6,
) );
$list = '';
}
$label = $menu ? wp_get_nav_menu_object( $menu ) : null;
$bp = self::v( $s, 'bp', 't' );
$logo = '';
if ( self::v( $s, 'mLogo', true ) ) {
$lid = (int) get_theme_mod( 'custom_logo' );
$logo = $lid ? wp_get_attachment_image( $lid, 'medium', false, array( 'loading' => 'lazy' ) ) : '' . esc_html( get_bloginfo( 'name' ) ) . '';
}
$cta = self::v( $s, 'mCta', '' ) ? '' . esc_html( self::v( $s, 'mCta' ) )
. '' : '';
$cls = 'nx-nav is-' . esc_attr( self::v( $s, 'layout', 'horizontal' ) ) . ' j-'
. esc_attr( self::v( $s, 'just', 'start' ) ) . ' p-'
. esc_attr( self::v( $s, 'pointer', 'underline' ) ) . ' dd-'
. esc_attr( self::v( $s, 'dropAnim', 'fade-up' ) ) . ' m-'
. esc_attr( self::v( $s, 'mStyle', 'offcanvas' ) ) . ( 'none' !== $bp ? ' bp-coll' : '' );
return '';
}
private static function w_site_logo( array $s ) {
$img = $s['image'] ?? null;
$stuck = $s['stuck'] ?? null;
$html = '';
if ( ! empty( $img['url'] ) ) {
$html = '
';
} else {
$lid = (int) get_theme_mod( 'custom_logo' );
if ( $lid ) {
$html = wp_get_attachment_image( $lid, 'full', false, array(
'alt' => get_bloginfo( 'name' ),
'fetchpriority' => 'high',
'loading' => 'eager',
) );
} elseif ( 'title' === self::v( $s, 'fallback', 'title' ) ) {
$html = '' . esc_html( get_bloginfo( 'name' ) ) . '';
}
}
if ( ! empty( $stuck['url'] ) ) {
$html .= '
';
}
$cls = 'nx-logo' . ( ! empty( $stuck['url'] ) ? ' has-stuck' : '' );
return self::v( $s, 'link', true ) ? '' . $html . '' : '' . $html . '';
}
private static function w_site_title( array $s ) {
$tag = in_array( self::v( $s, 'tag', 'div' ), array( 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'div', 'span' ), true ) ? self::v( $s, 'tag', 'div' ) : 'div';
$text = esc_html( get_bloginfo( self::v( $s, 'tagline', false ) ? 'description' : 'name' ) );
return '<' . $tag . ' class="nx-site-title">'
. ( self::v( $s, 'link', true ) ? '' . $text . '' : $text )
. '' . $tag . '>';
}
private static function w_breadcrumbs( array $s ) {
$sep = array(
'chevron' => '›',
'slash' => '/',
'arrow' => '→',
'dot' => '•',
)[ self::v( $s, 'sep', 'chevron' ) ] ?? '›';
$items = array( array( self::v( $s, 'home', __( 'Home', 'akram' ) ), home_url( '/' ) ) );
if ( is_singular() ) {
$p = get_queried_object();
if ( $p && 'page' !== $p->post_type ) {
$pto = get_post_type_object( $p->post_type );
if ( 'post' === $p->post_type ) {
$blog = (int) get_option( 'page_for_posts' );
if ( $blog ) {
$items[] = array( get_the_title( $blog ), get_permalink( $blog ) );
}
$cats = get_the_category( $p->ID );
if ( $cats ) {
foreach ( array_reverse( get_ancestors( $cats[0]->term_id, 'category' ) ) as $a ) {
$items[] = array( get_cat_name( $a ), get_category_link( $a ) );
}
$items[] = array( $cats[0]->name, get_category_link( $cats[0] ) );
}
} elseif ( $pto && $pto->has_archive ) {
$items[] = array( $pto->labels->name, get_post_type_archive_link( $p->post_type ) );
}
}
if ( $p ) {
foreach ( array_reverse( get_post_ancestors( $p ) ) as $a ) {
$items[] = array( get_the_title( $a ), get_permalink( $a ) );
}
$items[] = array( get_the_title( $p ), '' );
}
} elseif ( is_category() || is_tag() || is_tax() ) {
$t = get_queried_object();
foreach ( array_reverse( get_ancestors( $t->term_id, $t->taxonomy ) ) as $a ) {
$at = get_term( $a, $t->taxonomy );
$items[] = array( $at->name, get_term_link( $at ) );
}
$items[] = array( $t->name, '' );
} elseif ( is_search() ) {
/* translators: %s: search query */
$items[] = array( sprintf( __( 'Search: %s', 'akram' ), get_search_query() ), '' );
} elseif ( is_404() ) {
$items[] = array( __( 'Page not found', 'akram' ), '' );
} elseif ( is_post_type_archive() ) {
$items[] = array( post_type_archive_title( '', false ), '' );
} elseif ( is_author() ) {
$items[] = array( get_the_author_meta( 'display_name', get_queried_object_id() ), '' );
} elseif ( is_archive() ) {
$items[] = array( wp_strip_all_tags( get_the_archive_title() ), '' );
} elseif ( is_home() && ! is_front_page() ) {
$items[] = array( get_the_title( (int) get_option( 'page_for_posts' ) ), '' );
}
if ( ! self::v( $s, 'current', true ) && count( $items ) > 1 ) {
array_pop( $items );
}
$html = '';
if ( self::v( $s, 'schema', true ) ) {
$html .= wp_get_inline_script_tag( wp_json_encode( array(
'@context' => 'https://schema.org',
'@type' => 'BreadcrumbList',
'itemListElement' => $ld,
), JSON_HEX_TAG | JSON_HEX_AMP | JSON_UNESCAPED_SLASHES ), array( 'type' => 'application/ld+json' ) );
}
return $html;
}
private static function w_shortcode( array $s ) {
return do_shortcode( (string) self::v( $s, 'code', '' ) );
}
private static function w_sitemap( array $s ) {
$out = '';
foreach ( array_filter( array_map( 'trim', explode( ',', (string) self::v( $s, 'types', 'page,post' ) ) ) ) as $type ) {
if ( ! post_type_exists( $type ) ) {
continue;
}
$out .= '
' . esc_html( get_post_type_object( $type )->labels->name ) . '
';
if ( is_post_type_hierarchical( $type ) ) {
$out .= wp_list_pages( array(
'post_type' => $type,
'title_li' => '',
'echo' => false,
) );
} else {
foreach ( get_posts( array(
'post_type' => $type,
'posts_per_page' => 100,
) ) as $p ) {
$out .= '- ' . esc_html( get_the_title( $p ) ) . '
';
}
}
$out .= '
';
}
return $out . '
';
}
private static function w_login( array $s ) {
if ( is_user_logged_in() ) {
$u = wp_get_current_user();
return '';
}
$form = wp_login_form( array(
'echo' => false,
'redirect' => self::v( $s, 'redirect', '' ) ? esc_url_raw( self::v( $s, 'redirect' ) ) : ( is_singular() ? get_permalink() : home_url( '/' ) ),
'remember' => (bool) self::v( $s, 'remember', true ),
) );
$links = array();
if ( self::v( $s, 'lost', true ) ) {
$links[] = '' . esc_html__( 'Lost your password?', 'akram' ) . '';
}
if ( self::v( $s, 'register', false ) && get_option( 'users_can_register' ) ) {
$links[] = '' . esc_html__( 'Create an account', 'akram' ) . '';
}
return '' . $form . ( $links ? '
' . implode( '', $links ) . '
' : '' ) . '
';
}
// ------------------------------------------------------------------
// Single post parts
// ------------------------------------------------------------------
private static function w_post_title( array $s ) {
$tag = in_array( self::v( $s, 'tag', 'h1' ), array( 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'div', 'span' ), true ) ? self::v( $s, 'tag', 'h1' ) : 'h1';
$title = esc_html( wp_strip_all_tags( get_the_title() ) );
return '<' . $tag . ' class="nx-h">'
. ( self::v( $s, 'link', false ) ? '' . $title . '' : $title )
. '' . $tag . '>';
}
private static function w_post_content( array $s, $id, $post_id ) {
$pid = get_the_ID();
if ( ! $pid ) {
return '';
}
if ( in_array( $pid, Frontend::current_stack(), true ) ) {
return '';
}
$content = get_the_content( null, false, $pid );
return '' . apply_filters( 'the_content', $content ) . '
'; // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- reviewed.
}
private static function w_post_excerpt( array $s ) {
return '' . esc_html( wp_trim_words( get_the_excerpt(), (int) self::v( $s, 'len', 40 ) ) ) . '
';
}
private static function w_featured_image( array $s ) {
$tid = get_post_thumbnail_id();
if ( ! $tid ) {
$fb = $s['fallback'] ?? null;
return ! empty( $fb['url'] ) ? '
' : '';
}
$cap = self::v( $s, 'caption', false ) ? wp_get_attachment_caption( $tid ) : '';
return '' . wp_get_attachment_image( $tid, sanitize_key( self::v( $s, 'size', 'large' ) ), false, array(
'loading' => 'eager',
'fetchpriority' => 'high',
) ) . ( $cap ? '' . esc_html( $cap ) . '' : '' ) . '';
}
private static function w_post_meta( array $s ) {
$items = (array) self::v( $s, 'items', array( 'author', 'date', 'cats', 'read' ) );
$ic = self::v( $s, 'icons', false );
$out = array();
foreach ( $items as $k ) {
switch ( $k ) {
case 'avatar':
$out[] = get_avatar( get_the_author_meta( 'ID' ), 28 );
break;
case 'author':
$out[] = ( $ic ? self::icon( 'user' ) : '' ) . ''
. esc_html( get_the_author() ) . '';
break;
case 'date':
$out[] = ( $ic ? self::icon( 'calendar' ) : '' ) . '';
break;
case 'modified':
/* translators: %s: date */
$out[] = ( $ic ? self::icon( 'clock' ) : '' ) . esc_html( sprintf( __( 'Updated %s', 'akram' ), get_the_modified_date() ) );
break;
case 'cats':
$c = get_the_category_list( ', ' );
if ( $c ) {
$out[] = ( $ic ? self::icon( 'folder' ) : '' ) . wp_kses_post( $c );
}
break;
case 'tags':
$t = get_the_tag_list( '', ', ' );
if ( $t && ! is_wp_error( $t ) ) {
$out[] = ( $ic ? self::icon( 'tag' ) : '' ) . wp_kses_post( $t );
}
break;
case 'comments':
$out[] = ( $ic ? self::icon( 'comment' ) : '' )
. esc_html( sprintf( /* translators: %d: comment count */ _n( '%d comment', '%d comments', get_comments_number(), 'akram' ), get_comments_number() ) );
break;
case 'read':
$out[] = ( $ic ? self::icon( 'clock' ) : '' ) . esc_html( Dynamic::value( 'reading_time', array() ) );
break;
}
}
return ''
. implode( '' . esc_html( self::v( $s, 'sep', '·' ) ) . '', array_map( static function ( $x ) {
return '' . $x . '';
}, $out ) ) . '
';
}
private static function w_author_box( array $s ) {
$a = (int) get_post_field( 'post_author', get_the_ID() );
if ( ! $a ) {
return '';
}
$name = esc_html( get_the_author_meta( 'display_name', $a ) );
if ( self::v( $s, 'link', true ) ) {
$name = '' . $name . '';
}
return ''
. ( self::v( $s, 'avatar', true ) ? get_avatar( $a, 144 ) : '' ) . '
' . $name . '
'
. ( self::v( $s, 'bio', true ) ? '
' . esc_html( get_the_author_meta( 'description', $a ) ) . '
' : '' )
. '
';
}
private static function w_post_nav( array $s ) {
$same = (bool) self::v( $s, 'sameTerm', false );
$prev = get_previous_post( $same );
$next = get_next_post( $same );
$mk = static function ( $p, $label, $cls ) use ( $s ) {
if ( ! $p ) {
return '';
}
$thumb = self::v( $s, 'thumbs', false ) ? get_the_post_thumbnail( $p, 'thumbnail' ) : '';
$text = ( self::v( $s, 'labels', true ) ? '' . esc_html( $label ) . '' : '' )
. ( self::v( $s, 'titles', true ) ? '' . esc_html( get_the_title( $p ) ) . '' : '' );
return ''
. ( 'is-prev' === $cls ? $thumb . '' . $text . '' : '' . $text . '' . $thumb )
. '';
};
return '';
}
private static function w_comments( array $s, $id, $post_id, $preview ) {
if ( $preview ) {
return '' . esc_html__( 'Comments', 'akram' ) . ''
. esc_html__( 'The comment list and form render on the live page.', 'akram' )
. '
';
}
if ( ! comments_open() && ! get_comments_number() ) {
return '';
}
ob_start();
comments_template();
return ob_get_clean();
}
private static function w_archive_title( array $s ) {
$tag = in_array( self::v( $s, 'tag', 'h1' ), array( 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'div', 'span' ), true ) ? self::v( $s, 'tag', 'h1' ) : 'h1';
if ( ! self::v( $s, 'prefix', false ) ) {
add_filter( 'get_the_archive_title_prefix', '__return_empty_string', 99 );
}
$title = is_search() ? sprintf( /* translators: %s: query */ __( 'Results for “%s”', 'akram' ), get_search_query() ) : ( is_home() ? get_the_title( (int) get_option( 'page_for_posts' ) ) : get_the_archive_title() );
remove_filter( 'get_the_archive_title_prefix', '__return_empty_string', 99 );
return '<' . $tag . ' class="nx-h">' . wp_kses_post( $title ?: __( 'Blog', 'akram' ) ) . '' . $tag . '>';
}
private static function w_archive_desc() {
return '' . wp_kses_post( get_the_archive_description() ) . '
';
}
private static function w_terms( array $s ) {
$tax = sanitize_key( self::v( $s, 'tax', 'category' ) );
$terms = get_the_terms( get_the_ID(), $tax );
if ( ! $terms || is_wp_error( $terms ) ) {
return '';
}
$links = array_map( static function ( $t ) {
return '' . esc_html( $t->name ) . '';
}, $terms );
return ''
. implode( 'text' === self::v( $s, 'style', 'pills' ) ? ', ' : '', $links ) . '
';
}
// ------------------------------------------------------------------
// WooCommerce
// ------------------------------------------------------------------
private static function product() {
if ( ! function_exists( 'wc_get_product' ) ) {
return null;
}
global $product;
$p = wc_get_product( get_the_ID() );
if ( $p ) {
$product = $p; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited, WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- WooCommerce's own global product, needed by its template functions.
}
return $p;
}
private static function w_products( array $s, $id, $post_id, $preview = false, $page = null, $term = '' ) {
if ( ! function_exists( 'wc_get_product' ) ) {
return $preview ? '' . esc_html__( 'WooCommerce is not active.', 'akram' ) . '
' : '';
}
$page = $page ?: max( 1, isset( $_GET['nxp'] ) ? (int) $_GET['nxp'] : 1 ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only request value; it changes nothing and is sanitised.
$count = max( 1, (int) self::v( $s, 'count', 8 ) );
$args = array(
'post_type' => 'product',
'post_status' => 'publish',
'posts_per_page' => $count,
'paged' => $page,
);
$ob = self::v( $s, 'orderby', 'date' );
$order = 'ASC' === self::v( $s, 'order', 'DESC' ) ? 'ASC' : 'DESC';
$ordering = WC()->query->get_catalog_ordering_args( 'popularity' === $ob ? 'popularity' : ( 'rating' === $ob ? 'rating' : ( 'price' === $ob ? 'price' : $ob ) ), $order );
$args = array_merge( $args, array(
'orderby' => $ordering['orderby'],
'order' => $ordering['order'],
) );
if ( ! empty( $ordering['meta_key'] ) ) {
$args['meta_key'] = $ordering['meta_key']; // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- bounded query on a builder meta key.
}
$tax = array( 'relation' => 'AND' );
$meta = array();
switch ( self::v( $s, 'query', 'recent' ) ) {
case 'featured':
$tax[] = array(
'taxonomy' => 'product_visibility',
'field' => 'name',
'terms' => 'featured',
);
break;
case 'sale':
$args['post__in'] = array_merge( array( 0 ), wc_get_product_ids_on_sale() );
break;
case 'best':
$args['meta_key'] = 'total_sales'; // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- bounded query on a builder meta key.
$args['orderby'] = 'meta_value_num';
break;
case 'rated':
$args['meta_key'] = '_wc_average_rating'; // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- bounded query on a builder meta key.
$args['orderby'] = 'meta_value_num';
break;
case 'related':
$args['post__in'] = array_merge( array( 0 ), wc_get_related_products( get_the_ID(), $count ) );
break;
case 'upsell':
$p = self::product();
$args['post__in'] = array_merge( array( 0 ), $p ? $p->get_upsell_ids() : array() );
break;
case 'cross':
$args['post__in'] = array_merge( array( 0 ), WC()->cart ? WC()->cart->get_cross_sells() : array() );
break;
case 'manual':
$args['post__in'] = array_merge( array( 0 ), array_map( 'absint', explode( ',', (string) self::v( $s, 'ids', '' ) ) ) );
$args['orderby'] = 'post__in';
break;
case 'current':
global $wp_query;
foreach ( array( 'product_cat', 'product_tag', 's' ) as $k ) {
if ( ! empty( $wp_query->query[ $k ] ) ) {
$args[ $k ] = sanitize_text_field( $wp_query->query[ $k ] );
}
}
break;
}
$cats = array_filter( array_map( 'trim', explode( ',', (string) self::v( $s, 'cats', '' ) ) ) );
if ( $cats ) {
$tax[] = array(
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => $cats,
);
}
if ( ! in_array( self::v( $s, 'query', 'recent' ), array( 'related', 'upsell', 'cross', 'manual' ), true ) && ! self::v( $s, 'ignoreFilters', false ) ) {
self::apply_product_filters( $args, $tax, $meta );
}
if ( $term ) {
$tax[] = array(
'taxonomy' => 'product_cat',
'terms' => array( (int) $term ),
);
}
if ( self::v( $s, 'hideOos', false ) ) {
$tax[] = array(
'taxonomy' => 'product_visibility',
'field' => 'name',
'terms' => 'outofstock',
'operator' => 'NOT IN',
);
}
$tax[] = array(
'taxonomy' => 'product_visibility',
'field' => 'name',
'terms' => array( 'exclude-from-catalog' ),
'operator' => 'NOT IN',
);
$args['tax_query'] = $tax; // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query -- bounded query on a builder meta key.
$q = new \WP_Query( $args );
$show = (array) self::v( $s, 'show', array( 'cat', 'rating', 'price', 'atc', 'sale' ) );
$items = '';
while ( $q->have_posts() ) {
$q->the_post();
$p = wc_get_product( get_the_ID() );
if ( ! $p ) {
continue;
}
$GLOBALS['product'] = $p; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited, WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- WooCommerce's own global product, needed by its template functions.
$img = $p->get_image( 'woocommerce_thumbnail', array( 'loading' => 'lazy' ) );
$gal = $p->get_gallery_image_ids();
$alt = self::v( $s, 'swap', true ) && $gal ? wp_get_attachment_image( $gal[0], 'woocommerce_thumbnail', false, array(
'class' => 'is-alt',
'loading' => 'lazy',
'alt' => '',
) ) : '';
$sale = in_array( 'sale', $show, true ) && $p->is_on_sale() ? ''
. esc_html( Dynamic::value( 'woo_sale_badge', array() ) ?: __( 'Sale', 'akram' ) )
. '' : '';
$cat = '';
if ( in_array( 'cat', $show, true ) ) {
$terms = get_the_terms( $p->get_id(), 'product_cat' );
$cat = $terms && ! is_wp_error( $terms ) ? '' . esc_html( $terms[0]->name ) . '' : '';
}
$atc = '';
if ( in_array( 'atc', $show, true ) ) {
ob_start();
woocommerce_template_loop_add_to_cart();
$atc = '' . ob_get_clean() . '
';
}
$acts = '';
foreach ( array(
'wish' => array( 'heart', __( 'Add to wishlist', 'akram' ) ),
'quick' => array( 'eye', __( 'Quick view', 'akram' ) ),
'compare' => array( 'compare', __( 'Compare', 'akram' ) ),
) as $k => $a ) {
if ( in_array( $k, $show, true ) ) {
$acts .= '';
}
}
if ( $acts ) {
Frontend::add_module( 'shop' );
$acts = '' . $acts . '
';
}
$items .= '' . $acts . ''
. $sale . $img . $alt . '' . $cat . ''
. ( in_array( 'rating', $show, true ) ? wc_get_rating_html( (float) $p->get_average_rating() ) : '' )
. ( in_array( 'price', $show, true ) ? '' . $p->get_price_html() . '' : '' ) . $atc . '';
}
wp_reset_postdata();
if ( ! $items ) {
return $preview ? '' . esc_html__( 'No products match this query yet.', 'akram' ) . '
' : '';
}
$sorting = '';
if ( self::v( $s, 'sorting', false ) && ! $preview ) {
ob_start();
woocommerce_result_count();
woocommerce_catalog_ordering();
$sorting = '' . ob_get_clean() . '
';
}
$pager = self::pager( $q, self::v( $s, 'pager', 'none' ), $page, $s );
self::$parts = array(
'items' => $items,
'max' => (int) $q->max_num_pages,
'pager' => $pager,
);
$data = array(
'post' => (int) $post_id,
'el' => $id,
'pager' => self::v( $s, 'pager', 'none' ),
'max' => (int) $q->max_num_pages,
'page' => $page,
);
return ''
. $sorting . '
' . $pager . '
';
}
private static function w_product_related( array $s, $id, $post_id, $preview ) {
$s['query'] = 'related';
return self::w_products( $s, $id, $post_id, $preview );
}
private static function w_product_categories( array $s ) {
$parent = self::v( $s, 'parent', 'top' );
$args = array(
'taxonomy' => 'product_cat',
'hide_empty' => (bool) self::v( $s, 'hideEmpty', true ),
'number' => (int) self::v( $s, 'count', 8 ),
);
if ( 'top' === $parent ) {
$args['parent'] = 0;
} elseif ( 'current' === $parent && is_tax( 'product_cat' ) ) {
$args['parent'] = get_queried_object_id();
}
$terms = get_terms( $args );
if ( ! $terms || is_wp_error( $terms ) ) {
return '';
}
$out = '';
foreach ( $terms as $t ) {
if ( 'uncategorized' === $t->slug ) {
continue;
}
$thumb = (int) get_term_meta( $t->term_id, 'thumbnail_id', true );
$out .= '
'
. ( $thumb ? wp_get_attachment_image( $thumb, 'woocommerce_thumbnail', false, array( 'loading' => 'lazy' ) ) : '' )
. '' . esc_html( $t->name )
. ( self::v( $s, 'showCount', true ) ? '' . esc_html( sprintf( /* translators: %d: number of products */ _n( '%d product', '%d products', $t->count, 'akram' ), $t->count ) ) . '' : '' )
. '';
}
return $out . '
';
}
/** Output of a WooCommerce product part; $cb is a closure from the widget renderers below. */
private static function woo_part( \Closure $cb ) {
$p = self::product();
if ( ! $p ) {
return '';
}
ob_start();
$cb( $p );
return '' . ob_get_clean() . '
';
}
private static function w_product_title( array $s ) {
$p = self::product();
$tag = in_array( self::v( $s, 'tag', 'h1' ), array( 'h1', 'h2', 'h3', 'div' ), true ) ? self::v( $s, 'tag', 'h1' ) : 'h1';
return $p ? '<' . $tag . ' class="nx-h product_title">' . esc_html( $p->get_name() ) . '' . $tag . '>' : '';
}
private static function w_product_price() {
return self::woo_part( static function ( $p ) {
echo '' . wp_kses_post( $p->get_price_html() ) . '
';
} );
}
private static function w_product_atc( array $s ) {
$pid = (int) self::v( $s, 'product', 0 );
if ( $pid && function_exists( 'wc_get_product' ) ) {
$p = wc_get_product( $pid );
if ( ! $p ) {
return '';
}
$text = self::v( $s, 'text', '' ) ?: $p->add_to_cart_text();
return '';
}
return self::woo_part( static function () {
echo '';
woocommerce_template_single_add_to_cart();
echo '
';
} );
}
private static function w_product_gallery() {
return self::woo_part( static function () {
wp_enqueue_script( 'wc-single-product' );
woocommerce_show_product_images();
} );
}
private static function w_product_rating( array $s ) {
return self::woo_part( static function ( $p ) use ( $s ) {
echo wp_kses_post( wc_get_rating_html( (float) $p->get_average_rating(), $p->get_rating_count() ) );
if ( self::v( $s, 'count', true ) && $p->get_review_count() ) {
echo ' '
. esc_html( sprintf( /* translators: %d: reviews */ _n( '(%d review)', '(%d reviews)', $p->get_review_count(), 'akram' ), $p->get_review_count() ) )
. '';
}
} );
}
private static function w_product_stock() {
return self::woo_part( static function ( $p ) {
echo wp_kses_post( wc_get_stock_html( $p ) ?: '' . esc_html__( 'In stock', 'akram' ) . '
' );
} );
}
private static function w_product_meta( array $s ) {
return self::woo_part( static function ( $p ) use ( $s ) {
$items = (array) self::v( $s, 'items', array( 'sku', 'cats', 'tags' ) );
echo '';
if ( in_array( 'sku', $items, true ) && $p->get_sku() ) {
echo '' . esc_html__( 'SKU:', 'akram' ) . ' ' . esc_html( $p->get_sku() ) . ' ';
}
if ( in_array( 'cats', $items, true ) ) {
echo wp_kses_post( wc_get_product_category_list( $p->get_id(), ', ', '' . esc_html__( 'Category:', 'akram' ) . ' ', ' ' ) );
}
if ( in_array( 'tags', $items, true ) ) {
echo wp_kses_post( wc_get_product_tag_list( $p->get_id(), ', ', '' . esc_html__( 'Tags:', 'akram' ) . ' ', '' ) );
}
echo '
';
} );
}
private static function w_product_short() {
return self::woo_part( static function ( $p ) {
echo '' . wp_kses_post( apply_filters( 'woocommerce_short_description', $p->get_short_description() ) ) . '
'; // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- core or third-party hook.
} );
}
private static function w_product_tabs() {
return self::woo_part( static function () {
woocommerce_output_product_data_tabs();
} );
}
private static function w_cart_icon( array $s ) {
if ( ! function_exists( 'WC' ) || ! WC()->cart ) {
return '' . self::icon( 'cart' ) . '0';
}
$n = WC()->cart->get_cart_contents_count();
return '' . self::icon( 'cart' ) . '' . (int) $n . ''
. ( self::v( $s, 'total', true ) ? '' . wp_kses_post( WC()->cart->get_cart_total() ) . '' : '' )
. '';
}
private static function w_wc_page( array $s, $id, $post_id, $preview ) {
$map = array(
'cart' => 'woocommerce_cart',
'checkout' => 'woocommerce_checkout',
'account' => 'woocommerce_my_account',
'tracking' => 'woocommerce_order_tracking',
);
$sc = $map[ self::v( $s, 'page', 'cart' ) ] ?? 'woocommerce_cart';
if ( $preview && 'woocommerce_checkout' === $sc ) {
return '' . esc_html__( 'Checkout', 'akram' ) . ''
. esc_html__( 'The checkout form renders on the live page.', 'akram' ) . '
';
}
return '' . do_shortcode( '[' . $sc . ']' ) . '
';
}
/** Apply Product Filter widget parameters (same names WooCommerce uses) to a product query. */
private static function apply_product_filters( array &$args, array &$tax, array &$meta ) {
// phpcs:disable WordPress.Security.NonceVerification.Recommended
if ( ! empty( $_GET['product_cat'] ) ) {
$tax[] = array(
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => array_map( 'sanitize_title', explode( ',', sanitize_text_field( wp_unslash( $_GET['product_cat'] ) ) ) ),
);
}
foreach ( $_GET as $key => $val ) {
if ( 0 !== strpos( (string) $key, 'filter_' ) || ! is_string( $val ) || '' === $val ) {
continue;
}
$taxonomy = 'pa_' . sanitize_title( substr( $key, 7 ) );
if ( taxonomy_exists( $taxonomy ) ) {
$tax[] = array(
'taxonomy' => $taxonomy,
'field' => 'slug',
'terms' => array_map( 'sanitize_title', explode( ',', sanitize_text_field( wp_unslash( $val ) ) ) ),
'operator' => 'IN',
);
}
}
$min = isset( $_GET['min_price'] ) && '' !== $_GET['min_price'] ? (float) $_GET['min_price'] : null;
$max = isset( $_GET['max_price'] ) && '' !== $_GET['max_price'] ? (float) $_GET['max_price'] : null;
if ( null !== $min || null !== $max ) {
$meta[] = array(
'key' => '_price',
'value' => array( null === $min ? 0 : $min, null === $max ? PHP_INT_MAX : $max ),
'compare' => 'BETWEEN',
'type' => 'DECIMAL(10,2)',
);
$args['meta_query'] = array_merge( (array) ( $args['meta_query'] ?? array() ), $meta ); // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- bounded query on a builder meta key.
}
if ( ! empty( $_GET['rating_filter'] ) ) {
$ratings = array_filter( array_map( 'absint', explode( ',', sanitize_text_field( wp_unslash( $_GET['rating_filter'] ) ) ) ) );
if ( $ratings ) {
$tax[] = array(
'taxonomy' => 'product_visibility',
'field' => 'name',
'terms' => array_map( static function ( $r ) { return 'rated-' . min( 5, $r ); }, $ratings ),
);
}
}
if ( ! empty( $_GET['nx_sale'] ) ) {
$args['post__in'] = array_merge( array( 0 ), isset( $args['post__in'] ) ? array_intersect( $args['post__in'], wc_get_product_ids_on_sale() ) : wc_get_product_ids_on_sale() );
}
if ( ! empty( $_GET['nx_stock'] ) ) {
$tax[] = array(
'taxonomy' => 'product_visibility',
'field' => 'name',
'terms' => 'outofstock',
'operator' => 'NOT IN',
);
}
if ( ! empty( $_GET['orderby'] ) && in_array( $_GET['orderby'], array( 'price', 'price-desc', 'popularity', 'rating', 'date' ), true ) ) {
$ob = sanitize_key( $_GET['orderby'] );
$ordering = WC()->query->get_catalog_ordering_args( 'price-desc' === $ob ? 'price' : $ob, 'price-desc' === $ob ? 'DESC' : ( 'price' === $ob ? 'ASC' : 'DESC' ) );
$args = array_merge( $args, array(
'orderby' => $ordering['orderby'],
'order' => $ordering['order'],
) );
if ( ! empty( $ordering['meta_key'] ) ) {
$args['meta_key'] = $ordering['meta_key']; // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- bounded query on a builder meta key.
}
}
// phpcs:enable
}
private static function w_product_filter( array $s, $id, $post_id, $preview ) {
if ( ! function_exists( 'wc_get_product' ) ) {
return $preview ? '' . esc_html__( 'WooCommerce is not active.', 'akram' ) . '
' : '';
}
// phpcs:disable WordPress.Security.NonceVerification.Recommended
$get = static function ( $k ) {
return isset( $_GET[ $k ] ) ? sanitize_text_field( wp_unslash( $_GET[ $k ] ) ) : '';
};
$parts = (array) self::v( $s, 'parts', array( 'cats', 'price', 'attrs', 'rating', 'sale', 'stock', 'sort' ) );
$open = self::v( $s, 'collapsed', false ) ? '' : ' open';
$groups = '';
if ( in_array( 'cats', $parts, true ) ) {
$sel = array_filter( explode( ',', $get( 'product_cat' ) ) );
$terms = get_terms( array(
'taxonomy' => 'product_cat',
'hide_empty' => true,
'number' => 40,
) );
$list = '';
foreach ( is_array( $terms ) ? $terms : array() as $t ) {
if ( 'uncategorized' === $t->slug ) {
continue;
}
$list .= '';
}
if ( $list ) {
$groups .= ''
. esc_html__( 'Categories', 'akram' ) . self::icon( 'chevron' )
. '
' . $list . '
';
}
}
if ( in_array( 'price', $parts, true ) ) {
global $wpdb;
// The store's price range in one query (no WordPress API aggregates meta); it takes no user input.
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$range = $wpdb->get_row(
"SELECT MIN(CAST(meta_value AS DECIMAL(10,2))) AS lo, MAX(CAST(meta_value AS DECIMAL(10,2))) AS hi
FROM {$wpdb->postmeta} WHERE meta_key = '_price' AND meta_value <> ''"
);
$lo = $range ? floor( (float) $range->lo ) : 0;
$hi = $range ? ceil( (float) $range->hi ) : 1000;
$cur = get_woocommerce_currency_symbol();
$groups .= '' . esc_html__( 'Price', 'akram' )
. self::icon( 'chevron' ) . '
';
}
if ( in_array( 'attrs', $parts, true ) && function_exists( 'wc_get_attribute_taxonomies' ) ) {
foreach ( wc_get_attribute_taxonomies() as $a ) {
$tx = wc_attribute_taxonomy_name( $a->attribute_name );
$terms = get_terms( array(
'taxonomy' => $tx,
'hide_empty' => true,
) );
if ( ! $terms || is_wp_error( $terms ) ) {
continue;
}
$key = 'filter_' . $a->attribute_name;
$sel = array_filter( explode( ',', $get( $key ) ) );
$color = in_array( strtolower( $a->attribute_name ), array( 'color', 'colour' ), true );
$list = '';
foreach ( $terms as $t ) {
$sw = $color ? '' : '';
$list .= '';
}
$groups .= ''
. esc_html( $a->attribute_label ) . self::icon( 'chevron' )
. '
' . $list
. '
';
}
}
if ( in_array( 'rating', $parts, true ) ) {
$sel = array_filter( explode( ',', $get( 'rating_filter' ) ) );
$list = '';
for ( $r = 5; $r >= 1; $r-- ) {
$list .= '';
}
$groups .= '' . esc_html__( 'Rating', 'akram' )
. self::icon( 'chevron' ) . '
' . $list . '
';
}
$toggles = '';
if ( in_array( 'sale', $parts, true ) ) {
$toggles .= '';
}
if ( in_array( 'stock', $parts, true ) ) {
$toggles .= '';
}
$sort = '';
if ( in_array( 'sort', $parts, true ) ) {
$opts = array(
'' => __( 'Default sorting', 'akram' ),
'popularity' => __( 'Popularity', 'akram' ),
'rating' => __( 'Average rating', 'akram' ),
'date' => __( 'Latest', 'akram' ),
'price' => __( 'Price: low to high', 'akram' ),
'price-desc' => __( 'Price: high to low', 'akram' ),
);
$sort = '';
}
// phpcs:enable
$cfg = array(
'ajax' => (bool) self::v( $s, 'ajax', true ),
'auto' => (bool) self::v( $s, 'auto', true ),
);
return '';
}
private static function w_news_ticker( array $s ) {
$items = array();
if ( 'posts' === self::v( $s, 'source', 'posts' ) ) {
$q = new \WP_Query( array(
'post_type' => post_type_exists( (string) self::v( $s, 'postType', 'post' ) ) ? self::v( $s, 'postType', 'post' ) : 'post',
'posts_per_page' => max( 1, min( 30, (int) self::v( $s, 'count', 8 ) ) ),
'post_status' => 'publish',
'ignore_sticky_posts' => true,
'no_found_rows' => true,
) );
foreach ( $q->posts as $p ) {
$items[] = ''
. esc_html( get_the_title( $p ) ) . ''
. ( self::v( $s, 'date', true ) ? ' ' : '' );
}
} else {
foreach ( preg_split( '/\r?\n/', (string) self::v( $s, 'lines', '' ) ) as $line ) {
$line = trim( $line );
if ( '' === $line ) {
continue;
}
$parts = array_map( 'trim', explode( '|', $line, 2 ) );
$items[] = ! empty( $parts[1] ) ? '' . esc_html( $parts[0] ) . '' : '' . esc_html( $parts[0] ) . '';
}
}
if ( ! $items ) {
return '';
}
$fx = self::v( $s, 'fx', 'marquee' );
$label = self::v( $s, 'label', __( 'Breaking', 'akram' ) );
$list = '' . implode( '', $items ) . '';
if ( 'marquee' === $fx ) {
$track = '';
} else {
Frontend::add_module( 'ticker' );
$track = '';
}
return ''
. ( $label ? '
' . esc_html( $label ) . '' : '' )
. '
' . $track . '
';
}
private static function w_sidebar( array $s ) {
$id = sanitize_key( self::v( $s, 'area', 'sidebar-1' ) );
if ( ! is_active_sidebar( $id ) ) {
return '';
}
ob_start();
dynamic_sidebar( $id );
return '';
}
private static function w_terms_list( array $s ) {
$tax = sanitize_key( self::v( $s, 'tax', 'category' ) );
if ( ! taxonomy_exists( $tax ) ) {
return '';
}
$terms = get_terms( array(
'taxonomy' => $tax,
'hide_empty' => (bool) self::v( $s, 'hideEmpty', true ),
'number' => max( 1, (int) self::v( $s, 'count', 20 ) ),
'orderby' => 'cloud' === self::v( $s, 'style', 'list' ) || 'count' === self::v( $s, 'orderby', 'name' ) ? 'count' : 'name',
'order' => 'count' === self::v( $s, 'orderby', 'name' ) ? 'DESC' : 'ASC',
'parent' => self::v( $s, 'top', false ) ? 0 : '',
) );
if ( ! $terms || is_wp_error( $terms ) ) {
return '';
}
$style = self::v( $s, 'style', 'list' );
$max = max( 1, max( wp_list_pluck( $terms, 'count' ) ) );
$cur = is_tax() || is_category() || is_tag() ? get_queried_object_id() : 0;
$out = '';
foreach ( $terms as $t ) {
$size = 'cloud' === $style ? ' style="font-size:' . round( 0.85 + ( $t->count / $max ) * 0.9, 2 ) . 'em"' : '';
$out .= 'term_id ? ' aria-current="page"' : '' ) . '>' . esc_html( $t->name )
. ''
. ( self::v( $s, 'counts', true ) && 'cloud' !== $style ? '' . (int) $t->count . '' : '' )
. '';
}
return '';
}
private static function w_social_feed( array $s, $id, $post_id, $preview ) {
$source = (string) self::v( $s, 'source', 'rss' );
$items = Feeds::items( $source, 'youtube' === $source ? self::v( $s, 'channel', '' ) : self::v( $s, 'url', '' ), (int) self::v( $s, 'count', 6 ) );
if ( is_wp_error( $items ) ) {
return $preview ? '' . esc_html__( 'Social feed', 'akram' )
. '' . esc_html( $items->get_error_message() ) . '
' : '';
}
$show = (array) self::v( $s, 'show', array( 'image', 'title', 'date' ) );
$blank = self::v( $s, 'newTab', true ) ? ' target="_blank" rel="noopener"' : '';
$out = '';
foreach ( $items as $it ) {
$play = 'youtube' === $source ? '' : '';
$img = in_array( 'image', $show, true ) && $it['image'] ? '
' . $play
. '' : '';
$title = in_array( 'title', $show, true ) && $it['title'] ? '' . esc_html( $it['title'] ) . '' : '';
$text = in_array( 'text', $show, true ) && $it['text'] ? '' . esc_html( $it['text'] ) . '' : '';
$date = in_array( 'date', $show, true ) && $it['date'] ? '' : '';
$out .= '' . $img
. ( $title || $text || $date ? '' . $title . $text . $date . '' : '' )
. '';
}
return '';
}
private static function w_google_reviews( array $s, $id, $post_id, $preview ) {
$d = Feeds::google_reviews( self::v( $s, 'place', '' ) );
if ( is_wp_error( $d ) ) {
return $preview ? '' . esc_html__( 'Google reviews', 'akram' )
. '' . esc_html( $d->get_error_message() ) . '
' : '';
}
$min = (int) self::v( $s, 'min', 4 );
$star = static function ( $n ) {
$o = '';
for ( $i = 1; $i <= 5; $i++ ) {
$o .= '★';
}
$label = sprintf( /* translators: %s: rating */ __( '%s out of 5 stars', 'akram' ), number_format_i18n( $n, 1 ) );
return '' . $o . '';
};
$cards = '';
foreach ( array_slice( $d['reviews'], 0, (int) self::v( $s, 'count', 5 ) ) as $r ) {
if ( $r['rating'] < $min || '' === trim( $r['text'] ) ) {
continue;
}
$cards .= ''
. ( $r['photo'] ? '
' : '' )
. '' . esc_html( $r['author'] ) . '' . esc_html( $r['time'] )
. '' . $star( $r['rating'] ) . ''
. esc_html( wp_trim_words( $r['text'], (int) self::v( $s, 'words', 45 ) ) )
. '
';
}
$head = self::v( $s, 'summary', true ) ? ''
. esc_html( number_format_i18n( $d['rating'], 1 ) ) . '' . $star( $d['rating'] ) . '
'
. esc_html( sprintf( /* translators: %s: count */ _n( '%s review on Google', '%s reviews on Google', $d['total'], 'akram' ), number_format_i18n( $d['total'] ) ) )
. ''
. ( $d['url'] ? '
' . esc_html__( 'Write a review', 'akram' ) . '' : '' )
. '
' : '';
$schema = '';
if ( self::v( $s, 'schema', false ) && $d['total'] ) {
$schema = wp_get_inline_script_tag( wp_json_encode( array(
'@context' => 'https://schema.org',
'@type' => 'LocalBusiness',
'name' => $d['name'],
'aggregateRating' => array(
'@type' => 'AggregateRating',
'ratingValue' => $d['rating'],
'reviewCount' => $d['total'],
),
), JSON_HEX_TAG | JSON_HEX_AMP | JSON_UNESCAPED_SLASHES ), array( 'type' => 'application/ld+json' ) );
}
return '' . $head . '
' . $cards . '
' . $schema . '
';
}
private static function w_wc_notices() {
if ( ! function_exists( 'wc_print_notices' ) ) {
return '';
}
ob_start();
wc_print_notices();
return '' . ob_get_clean() . '
';
}
}
/**
* Menu walker: submenu indicators and mega-menu panels.
*/
class Nav_Walker extends \Walker_Nav_Menu {
private $indicator;
public function __construct( $indicator = 'chevron' ) {
$this->indicator = $indicator;
}
public function start_el( &$output, $item, $depth = 0, $args = null, $id = 0 ) {
$mega = (int) get_post_meta( $item->ID, '_akram_mega', true );
if ( $mega && 0 === $depth ) {
$item->classes[] = 'nx-mega';
}
parent::start_el( $output, $item, $depth, $args, $id );
$has = in_array( 'menu-item-has-children', (array) $item->classes, true ) || ( $mega && 0 === $depth );
if ( $has && 'none' !== $this->indicator ) {
$icon = 'plus' === $this->indicator ? '' : '';
$output = preg_replace( '/<\/a>$/', '', $output );
}
if ( $mega && 0 === $depth ) {
$output .= '' . Runtime::template( $mega ) . '
';
}
}
}