array( 'post' ), 'selection_mode' => 'auto', 'manual_ids' => array(), 'relate_by' => array( 'category', 'post_tag' ), 'engine' => 'smart', 'weights' => srpp_default_weights(), 'recency_days' => 30, 'fallback' => 'recent', 'cross_match' => 1, 'order' => 'score', 'items' => 6, // --- 2. Placement ----------------------------------------------. 'placement' => 'after_content', 'placement_value' => 4, 'repeat_every' => 0, 'repeat_max' => 3, 'priority' => 10, // --- Display conditions ----------------------------------------. 'cond_types' => array( 'post' ), 'cond_logic' => 'and', 'cond_include' => array(), 'cond_exclude' => array(), 'cond_ids_include' => array(), 'cond_ids_exclude' => array(), 'cond_price_min' => '', 'cond_price_max' => '', 'cond_users' => 'all', 'cond_devices' => array( 'desktop', 'tablet', 'mobile' ), // --- 3. Layout -------------------------------------------------. 'layout' => 'grid', 'cols_d' => 3, 'cols_t' => 2, 'cols_m' => 1, 'gap' => 24, // --- 4. Design -------------------------------------------------. 'template' => 'tpl-03', 'heading' => __( 'You may also like', 'advanced-css3-related-posts-widget' ), 'heading_tag' => 'h3', 'heading_align' => 'left', 'fields' => array( 'image', 'title', 'excerpt' ), 'excerpt_length' => 16, 'image_ratio' => '16-9', 'link_target' => '_self', 'button_text' => __( 'Read more', 'advanced-css3-related-posts-widget' ), 'style' => srpp_default_style(), // --- Exclusions ------------------------------------------------. 'ex_current' => 1, 'ex_password' => 1, 'ex_private' => 1, 'ex_noindex' => 0, 'ex_outofstock' => 1, 'ex_terms' => array(), 'ex_authors' => array(), 'ex_ids' => array(), 'no_duplicates' => 1, // --- Performance -----------------------------------------------. 'cache_ttl' => DAY_IN_SECONDS, ); } /** * Default relation weights. * * @return array */ function srpp_default_weights() { return array( 'primary_term' => 10, 'category' => 5, 'post_tag' => 3, 'taxonomy' => 4, 'attribute' => 4, 'author' => 1, 'recency' => 1, ); } /** * Default style tokens. * * @return array */ function srpp_default_style() { return array( 'accent' => '#f0a02e', 'card_bg' => '#ffffff', 'title_color' => '#1b2138', 'text_color' => '#5c6478', 'meta_color' => '#949cae', 'border' => '#f0e7dc', 'radius' => 12, 'img_radius' => 10, 'shadow' => 'sm', 'title_size' => 16, 'text_size' => 14, 'padding' => 16, ); } /** * Layouts available. * * @return array */ function srpp_layouts() { return array( 'grid' => __( 'Grid', 'advanced-css3-related-posts-widget' ), 'list' => __( 'List', 'advanced-css3-related-posts-widget' ), 'inline' => __( 'Inline', 'advanced-css3-related-posts-widget' ), 'carousel' => __( 'Carousel', 'advanced-css3-related-posts-widget' ), 'masonry' => __( 'Masonry', 'advanced-css3-related-posts-widget' ), 'compact' => __( 'Compact', 'advanced-css3-related-posts-widget' ), 'single' => __( 'Single recommendation', 'advanced-css3-related-posts-widget' ), 'horizontal' => __( 'Horizontal cards', 'advanced-css3-related-posts-widget' ), ); } /** * Image aspect ratios. * * @return array */ function srpp_ratios() { return array( '16-9' => '16:9', '4-3' => '4:3', '3-2' => '3:2', '1-1' => '1:1', '3-4' => '3:4', '2-3' => '2:3', 'original' => __( 'Original', 'advanced-css3-related-posts-widget' ), ); } /** * Public post types the plugin can work with. * * @return array type => label */ function srpp_post_types() { $out = array(); $types = get_post_types( array( 'public' => true ), 'objects' ); foreach ( $types as $type ) { if ( in_array( $type->name, array( 'attachment', SRPP_CPT ), true ) ) { continue; } $out[ $type->name ] = $type->labels->singular_name ? $type->labels->singular_name : $type->name; } return apply_filters( 'srpp_post_types', $out ); } /** * Taxonomies usable for relation, optionally limited to given post types. * * @param array $post_types Post types. * @return array taxonomy => label */ function srpp_taxonomies( $post_types = array() ) { $out = array(); if ( empty( $post_types ) ) { $taxes = get_taxonomies( array( 'public' => true ), 'objects' ); } else { $taxes = array(); foreach ( (array) $post_types as $type ) { foreach ( get_object_taxonomies( $type, 'objects' ) as $key => $tax ) { if ( $tax->public ) { $taxes[ $key ] = $tax; } } } } foreach ( $taxes as $tax ) { $out[ $tax->name ] = $tax->labels->singular_name ? $tax->labels->singular_name : $tax->name; } return apply_filters( 'srpp_taxonomies', $out, $post_types ); } /** * Fields that a template may output, keyed by field => label. * * @return array */ function srpp_fields() { $fields = array( 'image' => __( 'Image', 'advanced-css3-related-posts-widget' ), 'title' => __( 'Title', 'advanced-css3-related-posts-widget' ), 'excerpt' => __( 'Excerpt', 'advanced-css3-related-posts-widget' ), 'category' => __( 'Category / term', 'advanced-css3-related-posts-widget' ), 'date' => __( 'Date', 'advanced-css3-related-posts-widget' ), 'author' => __( 'Author', 'advanced-css3-related-posts-widget' ), 'readtime' => __( 'Reading time', 'advanced-css3-related-posts-widget' ), 'button' => __( 'Read more button', 'advanced-css3-related-posts-widget' ), ); if ( srpp_is_woo_active() ) { $fields['price'] = __( 'Price', 'advanced-css3-related-posts-widget' ); $fields['rating'] = __( 'Rating', 'advanced-css3-related-posts-widget' ); $fields['cart'] = __( 'Add to cart', 'advanced-css3-related-posts-widget' ); $fields['badge'] = __( 'Sale badge', 'advanced-css3-related-posts-widget' ); } return apply_filters( 'srpp_fields', $fields ); } /** * Estimated reading time in minutes. * * @param int $post_id Post ID. * @return int */ function srpp_reading_time( $post_id ) { $post = get_post( $post_id ); if ( ! $post ) { return 1; } $words = srpp_word_count( wp_strip_all_tags( $post->post_content ) ); $wpm = (int) apply_filters( 'srpp_words_per_minute', 200 ); return max( 1, (int) ceil( $words / max( 1, $wpm ) ) ); } /** * UTF-8 safe word count. * * @param string $text Text. * @return int */ function srpp_word_count( $text ) { $text = trim( preg_replace( '/\s+/u', ' ', (string) $text ) ); if ( '' === $text ) { return 0; } return count( preg_split( '/\s+/u', $text ) ); } /** * Sanitize a list of integers. * * @param mixed $value Raw value. * @return array */ function srpp_int_list( $value ) { if ( is_string( $value ) ) { $value = preg_split( '/[\s,]+/', $value ); } $out = array(); foreach ( (array) $value as $item ) { if ( ! is_scalar( $item ) ) { continue; } $id = (int) $item; if ( $id > 0 && ! in_array( $id, $out, true ) ) { $out[] = $id; } } return $out; } /** * Read a plugin option. * * @param string $key Option key. * @param mixed $default Default value. * @return mixed */ function srpp_get_option( $key, $default = null ) { $options = get_option( 'srpp_settings', array() ); return isset( $options[ $key ] ) ? $options[ $key ] : $default; } /** * Render a Display anywhere in a theme. * * Example: srpp_the_related_content( 5 ); * * @param int|string $display_id Display ID or slug. * @param array $args Optional overrides (post_id, items, template...). * @return string */ function srpp_related_content( $display_id, $args = array() ) { $display = SRPP_Display::get( $display_id ); if ( ! $display ) { return ''; } return srpp()->render->render( $display, $args ); } /** * Echo (or return) a Display. Canonical helper for theme files. * * @param int|string $display_id Display ID or slug. * @param array $args Optional overrides. * @param bool $echo Echo or return. * @return string */ function srpp_the_related_content( $display_id, $args = array(), $echo = true ) { $html = srpp_related_content( $display_id, $args ); if ( $echo ) { echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Built from escaped template parts. } return $html; } if ( ! function_exists( 'smart_related_content' ) ) { /** * Back-compat alias for srpp_the_related_content(). * * Kept unprefixed because it is the call documented in earlier releases and * already sits in published theme files; renaming it would break those sites. * New code should call srpp_the_related_content() instead. * * @param int|string $display_id Display ID or slug. * @param array $args Optional overrides. * @param bool $echo Echo or return. * @return string */ function smart_related_content( $display_id, $args = array(), $echo = true ) { // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- Documented public API from earlier releases; see above. return srpp_the_related_content( $display_id, $args, $echo ); } } /* ------------------------------------------------------------------------- * Template helpers — used by the bundled templates and available to any * theme override placed in /your-theme/advanced-css3-related-posts-widget/. * ---------------------------------------------------------------------- */ /** * Output the item image inside its ratio box. * * @param array $item Item data. * @param SRPP_Display $display Display. * @param array $context Render context. */ function srpp_tpl_image( $item, $display, $context = array() ) { if ( ! $display->has_field( 'image' ) || '' === $item['image'] ) { return; } printf( ''; } /** * Output the item title as a link. * * @param array $item Item data. * @param SRPP_Display $display Display. * @param array $context Render context. * @param string $tag Wrapper tag. */ function srpp_tpl_title( $item, $display, $context = array(), $tag = 'h4' ) { if ( ! $display->has_field( 'title' ) ) { return; } printf( '<%1$s class="srpp-title">%3$s', esc_html( $tag ), SRPP_Render::link_atts( $item, $context, array( 'srpp-title-link' ) ), // phpcs:ignore WordPress.Security.EscapeOutput esc_html( $item['title'] ) ); } /** * Output the primary term chip. * * @param array $item Item data. * @param SRPP_Display $display Display. */ function srpp_tpl_term( $item, $display ) { if ( ! $display->has_field( 'category' ) || '' === $item['term'] ) { return; } echo '' . esc_html( $item['term'] ) . ''; } /** * Output the excerpt. * * @param array $item Item data. * @param SRPP_Display $display Display. */ function srpp_tpl_excerpt( $item, $display ) { if ( ! $display->has_field( 'excerpt' ) || '' === $item['excerpt'] ) { return; } echo '

' . esc_html( $item['excerpt'] ) . '

'; } /** * Output the meta row (date, author, reading time). * * @param array $item Item data. * @param SRPP_Display $display Display. */ function srpp_tpl_meta( $item, $display ) { $bits = array(); if ( $display->has_field( 'author' ) && $item['author'] ) { $bits[] = '' . esc_html( $item['author'] ) . ''; } if ( $display->has_field( 'date' ) ) { $bits[] = ''; } if ( $display->has_field( 'readtime' ) ) { $bits[] = '' . sprintf( /* translators: %d: minutes */ esc_html( _n( '%d min read', '%d min read', $item['readtime'], 'advanced-css3-related-posts-widget' ) ), (int) $item['readtime'] ) . ''; } if ( empty( $bits ) ) { return; } echo '
' . implode( '·', $bits ) . '
'; // phpcs:ignore WordPress.Security.EscapeOutput } /** * Output WooCommerce rating markup. * * @param array $item Item data. * @param SRPP_Display $display Display. */ function srpp_tpl_rating( $item, $display ) { if ( ! $display->has_field( 'rating' ) || '' === $item['rating'] ) { return; } echo '
' . wp_kses_post( $item['rating'] ) . '
'; } /** * Output the price. * * @param array $item Item data. * @param SRPP_Display $display Display. */ function srpp_tpl_price( $item, $display ) { if ( ! $display->has_field( 'price' ) || '' === $item['price'] ) { return; } echo '
' . wp_kses_post( $item['price'] ) . '
'; } /** * Output the add-to-cart control. * * @param array $item Item data. * @param SRPP_Display $display Display. */ function srpp_tpl_cart( $item, $display ) { if ( ! $display->has_field( 'cart' ) || '' === $item['cart'] ) { return; } echo '
' . wp_kses_post( $item['cart'] ) . '
'; } /** * Output the read-more button. * * @param array $item Item data. * @param SRPP_Display $display Display. * @param array $context Render context. */ function srpp_tpl_button( $item, $display, $context = array() ) { if ( ! $display->has_field( 'button' ) ) { return; } printf( '%s ', SRPP_Render::link_atts( $item, $context, array( 'srpp-button' ) ), // phpcs:ignore WordPress.Security.EscapeOutput esc_html( $display->opt( 'button_text' ) ) ); }