Your IP : 3.143.17.175


Current Path : /home/ncdcgo/public_html/wp-content/plugins backup/wp-grid-builder/frontend/
Upload File :
Current File : /home/ncdcgo/public_html/wp-content/plugins backup/wp-grid-builder/frontend/class-cards.php

<?php
/**
 * Cards
 *
 * @package   WP Grid Builder
 * @author    Loïc Blascos
 * @copyright 2019-2023 Loïc Blascos
 */

namespace WP_Grid_Builder\FrontEnd;

use WP_Grid_Builder\Includes\Helpers;
use WP_Grid_Builder\Includes\Database;

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Build card class
 *
 * @class WP_Grid_Builder\FrontEnd\Cards
 * @since 1.0.0
 */
final class Cards implements Models\Cards_Interface {

	/**
	 * Holds settings properties
	 *
	 * @since 1.0.0
	 * @access protected
	 *
	 * @var WP_Grid_Builder\FrontEnd\Settings instance
	 */
	protected $settings;

	/**
	 * Holds cards
	 *
	 * @since 1.0.0
	 * @access protected
	 *
	 * @var array
	 */
	protected static $cards = [];

	/**
	 * Holds card attributes
	 *
	 * @since 1.0.0
	 * @access protected
	 *
	 * @var array
	 */
	protected $atts = [];

	/**
	 * Default card layout
	 *
	 * @since 1.0.0
	 * @access protected
	 *
	 * @var array
	 */
	protected $layout = [
		'layers' => [
			'inner' => [
				'media' => [
					'media-thumbnail' => true,
				],
			],
		],
	];

	/**
	 * Holds allowed layer names
	 *
	 * @since 1.0.0
	 * @access protected
	 *
	 * @var array
	 */
	protected $layers = [
		'inner'                => true,
		'header'               => true,
		'media'                => true,
		'media-thumbnail'      => true,
		'media-overlay'        => true,
		'media-content'        => true,
		'media-content-top'    => true,
		'media-content-center' => true,
		'media-content-bottom' => true,
		'content'              => true,
		'body'                 => true,
		'footer'               => true,
	];

	/**
	 * Holds allowed blocks and associated default HTML tags.
	 *
	 * @since 1.0.0
	 * @access protected
	 *
	 * @var array
	 */
	protected $blocks = [
		// Post blocks.
		'the_id'                 => 'div',
		'the_title'              => 'h3',
		'the_name'               => 'div',
		'the_content'            => 'div',
		'the_excerpt'            => 'p',
		'the_post_type'          => 'div',
		'the_post_format'        => 'div',
		'the_post_status'        => 'div',
		'the_date'               => 'time',
		'the_modified_date'      => 'time',
		'the_terms'              => 'div',
		'the_author'             => 'div',
		'the_avatar'             => 'div',
		'comments_number'        => 'div',
		// Product/Download blocks.
		'the_full_price'         => 'div',
		'the_price'              => 'div',
		'the_regular_price'      => 'div',
		'the_sale_price'         => 'div',
		'the_cart_button'        => 'a',
		'the_star_rating'        => 'div',
		'the_text_rating'        => 'div',
		'the_on_sale_badge'      => 'div',
		'the_in_stock_badge'     => 'div',
		'the_out_of_stock_badge' => 'div',
		// User blocks.
		'the_user_id'            => 'div',
		'the_user_display_name'  => 'h3',
		'the_user_first_name'    => 'div',
		'the_user_last_name'     => 'div',
		'the_user_nickname'      => 'div',
		'the_user_login'         => 'div',
		'the_user_description'   => 'p',
		'the_user_email'         => 'div',
		'the_user_url'           => 'div',
		'the_user_roles'         => 'div',
		'the_user_post_count'    => 'div',
		// term blocks.
		'the_term_id'            => 'div',
		'the_term_name'          => 'h3',
		'the_term_slug'          => 'div',
		'the_term_taxonomy'      => 'div',
		'the_term_parent'        => 'div',
		'the_term_description'   => 'p',
		'the_term_count'         => 'div',
		// General blocks.
		'metadata'               => 'div',
		'raw_content_block'      => 'div',
		'media_button_block'     => 'div',
		'social_share_block'     => 'a',
		'svg_icon_block'         => 'div',
		'custom_block'           => 'div',
	];

	/**
	 * Constructor
	 *
	 * @since 1.0.0
	 * @access public
	 *
	 * @param object Settings $settings Settings class instance.
	 */
	public function __construct( Settings $settings ) {

		$this->settings = $settings;

	}

	/**
	 * Get cards
	 *
	 * @since 1.0.0
	 * @access public
	 */
	public function get() {

		return self::$cards;

	}

	/**
	 * Get card params
	 *
	 * @since 1.0.0
	 * @access public
	 */
	public function query() {

		$cards = (array) $this->settings->cards;
		$cards = array_values( $cards );
		$cards = array_filter( $cards, 'is_numeric' );
		$cards = array_unique( $cards );
		// Check if there are new card(s) to query.
		$cards = array_diff( $cards, array_keys( self::$cards ) );

		if ( empty( $cards ) ) {
			return;
		}

		$type = 'masonry' !== $this->settings->type ? 'metro' : null;

		$cards = Database::query_results(
			[
				'select' => 'id, type, layout, css',
				'from'   => 'cards',
				'type'   => $type,
				'id'     => $cards,
			]
		);

		foreach ( $cards as $card ) {

			$layout = json_decode( $card['layout'], true );
			$layout = apply_filters( 'wp_grid_builder/card/settings', $layout );

			self::$cards[ $card['id'] ] = $layout;
			self::$cards[ $card['id'] ]['css'] = $card['css'];

		}

		return $this;

	}

	/**
	 * Build card
	 *
	 * @since 1.0.0
	 * @access public
	 *
	 * @param array  $atts Post attributes.
	 * @param string $type Layout type.
	 */
	public function render( $atts, $type = 'masonry' ) {

		$this->atts = $atts;

		$card = $this->check( $type );
		$card = $this->prepare( $card, $type );

		$this->normalize( $card );
		$this->process( $card );

	}

	/**
	 * Check card
	 *
	 * @since 1.0.0
	 * @access public
	 *
	 * @param string $type Layout type.
	 * @return array Card layout.
	 */
	protected function check( $type ) {

		// Allow to override card.
		$this->atts['card'] = apply_filters( 'wp_grid_builder/card/id', $this->atts['card'] );

		$card = $this->atts['card'];
		$type = 'masonry' !== $type ? 'metro' : null;

		// If card exists.
		if ( isset( self::$cards[ $card ] ) ) {
			return self::$cards[ $card ];
		}

		$customs   = apply_filters( 'wp_grid_builder/cards', [] );
		$card_type = isset( $customs[ $card ]['type'] ) ? $customs[ $card ]['type'] : '';
		$is_valid  = ! $type || ( $type && 'masonry' !== $card_type );

		if ( isset( $customs[ $card ]['render_callback'] ) && $is_valid ) {
			return $customs[ $card ];
		}

		// Set card name to default.
		$this->atts['card'] = 'default';
		// Return default card layout.
		return $this->layout;

	}

	/**
	 * Prepare card layout
	 *
	 * @since 1.0.0
	 * @access protected
	 *
	 * @param array  $card Holds card layers.
	 * @param string $type Layout type.
	 * @return array Card layout.
	 */
	protected function prepare( $card, $type ) {

		$this->atts['format'] = wpgb_get_media_format();

		if ( isset( $card['settings']['responsive'] ) && $card['settings']['responsive'] ) {
			$this->atts['fluid'] = ' data-fluid';
		}

		if ( ! isset( $card['layers']['inner'] ) ) {
			return $card;
		}

		// Metro/Justified card does not support content holders.
		if ( 'masonry' !== $type ) {

			unset(
				$card['layers']['inner']['header'],
				$card['layers']['inner']['content']
			);

		} elseif ( ! wpgb_has_post_media() ) {

			unset( $card['layers']['inner']['media'] );
			return $card;

		}

		if ( wpgb_has_post_thumbnail() ) {
			return $card;
		}

		$this->atts['nothumb'] = ' data-nothumb';

		// Exception: Audio format without poster.
		if ( 'masonry' === $type && 'audio' === $this->atts['format'] ) {

			unset(
				$card['layers']['inner']['media']['media-overlay'],
				$card['layers']['inner']['media']['media-content']
			);

		}

		return $card;

	}

	/**
	 * Normalize card attributes
	 *
	 * @since 1.0.0
	 * @access public
	 *
	 * @param array $card Holds card layers and blocks.
	 */
	protected function normalize( $card ) {

		$this->atts = apply_filters( 'wp_grid_builder/card/attributes', $this->atts, $card );
		$this->atts = wp_parse_args(
			$this->atts,
			[
				'class'                => '',
				'columns'              => 1,
				'rows'                 => 1,
				'format'               => 'standard',
				'nothumb'              => '',
				'fluid'                => '',
				'content_color_scheme' => 'dark',
				'overlay_color_scheme' => 'light',
				'content_background'   => '',
				'overlay_background'   => '',
			]
		);

		$this->atts['class']   = Helpers::sanitize_html_classes( $this->atts['class'] );
		$this->atts['columns'] = max( 1, (int) $this->atts['columns'] );
		$this->atts['rows']    = max( 1, (int) $this->atts['rows'] );

	}

	/**
	 * Precess card
	 *
	 * @since 1.0.0
	 * @access protected
	 *
	 * @param array $card Holds card layers and blocks.
	 */
	protected function process( $card ) {

		$tag_name = apply_filters( 'wp_grid_builder/card/tag', 'article', $card, $this->settings );

		printf(
			'<%s class="wpgb-card wpgb-card-%s %s" data-col="%d" data-row="%d" data-format="%s"%s%s>',
			tag_escape( $tag_name ),
			esc_attr( $this->atts['card'] ),
			esc_attr( $this->atts['class'] ),
			esc_attr( $this->atts['columns'] ),
			esc_attr( $this->atts['rows'] ),
			esc_attr( $this->atts['format'] ),
			esc_attr( $this->atts['fluid'] ),
			esc_attr( $this->atts['nothumb'] )
		);

			do_action( 'wp_grid_builder/card/wrapper_start', $card );

			echo '<div class="wpgb-card-wrapper">';
				$this->do_card( $card );
				$this->do_action( $card );
			echo '</div>';

			do_action( 'wp_grid_builder/card/wrapper_end', $card );

		echo '</' . tag_escape( $tag_name ) . '>';

	}


	/**
	 * Do card
	 *
	 * @since 1.0.0
	 * @access protected
	 *
	 * @param array $card Holds card layers and blocks.
	 */
	protected function do_card( $card ) {

		$native = ! isset( $card['layers'] ) ?: $card['layers'];
		$custom = ! isset( $card['render_callback'] ) ?: $card['render_callback'];

		if ( $native && is_array( $native ) ) {
			$this->do_layers( $native );
		} elseif ( $custom && is_callable( $custom ) ) {
			call_user_func( $custom );
		}
	}

	/**
	 * Do card layers
	 *
	 * @since 1.0.3 Added layer action argument to wpgb_the_post_media().
	 * @since 1.0.0
	 * @access protected
	 *
	 * @param array $layers Holds card layers.
	 */
	protected function do_layers( $layers ) {

		foreach ( (array) $layers as $layer => $args ) {

			// If layer name does not exist.
			if ( ! isset( $this->layers[ $layer ] ) ) {
				continue;
			}

			// Exception for thumbnail.
			if ( 'media-thumbnail' === $layer ) {

				$layer  = $layers[ $layer ];
				$action = empty( $layer['action'] ) ?: $layer['action'];

				wpgb_the_post_media( $action );
				continue;

			}

			$this->do_layer( $layers, $layer );

		}
	}

	/**
	 * Do card layer
	 *
	 * @since 1.0.0
	 * @access protected
	 *
	 * @param array  $layers Holds layers.
	 * @param string $layer Layer name.
	 */
	protected function do_layer( $layers, $layer ) {

		$layers = $layers[ $layer ];

		printf(
			'<div class="%s"%s%s>',
			$this->get_layer_classes( $layers, $layer ),
			$this->get_layer_background( $layers, $layer ),
			$this->has_action( $layers ) ? ' data-action' : ''
		);

			$this->do_layers( $layers );
			$this->do_blocks( $layers );
			$this->do_action( $layers );

		echo '</div>';

	}

	/**
	 * Do blocks
	 *
	 * @since 1.0.0
	 * @access protected
	 *
	 * @param array $layer Holds layer properties.
	 */
	protected function do_blocks( $layer ) {

		if ( ! isset( $layer['blocks'] ) ) {
			return;
		}

		foreach ( (array) $layer['blocks'] as $block ) {

			$source   = $this->get_block( $block );
			$function = WPGB_SLUG . '_' . $source;

			// If block has no content.
			if ( empty( $block['content'] ) ) {
				continue;
			}

			// If not a native block.
			if ( empty( $source ) || ! function_exists( $function ) ) {
				$function = 'wpgb_custom_block';
			}

			// Get default block tag if not set.
			if ( empty( $block['content']['tag'] ) && isset( $this->blocks[ $source ] ) ) {
				$block['content']['tag'] = $this->blocks[ $source ];
			}

			$function( $block['content'], $block['action'] );

		}
	}

	/**
	 * Do layer action
	 *
	 * @since 1.0.0
	 * @access protected
	 *
	 * @param array $layer Holds layer properties.
	 */
	protected function do_action( $layer ) {

		if ( ! $this->has_action( $layer ) ) {
			return;
		}

		$link = wpgb_get_block_link( $layer['action'] );

		if ( empty( $link ) ) {
			return;
		}

		// Add layer action class.
		$layer['action']['class'] = 'wpgb-card-layer-link';

		wpgb_block_action( $layer['action'], $link );
		wpgb_block_end( $layer, $layer['action'] );

	}

	/**
	 * Check if layer has action (link only)
	 *
	 * @since 1.0.0
	 * @access protected
	 *
	 * @param array $layer Holds layer properties.
	 * @return boolean
	 */
	protected function has_action( $layer ) {

		if ( isset( $layer['action']['action_type'] ) && 'link' === $layer['action']['action_type'] ) {
			return true;
		}

		return false;

	}

	/**
	 * Get block
	 *
	 * @since 1.0.0
	 * @access protected
	 *
	 * @param array $block Holds block properties.
	 * @return string
	 */
	protected function get_block( $block ) {

		if ( empty( $block['content'] ) ) {
			return '';
		}

		$content = $block['content'];
		$source  = isset( $content['source'] ) ? $content['source'] : 'post_field';
		$source  = isset( $content[ $source ] ) ? $content[ $source ] : $source;

		// If block source does not exist.
		if ( ! isset( $this->blocks[ $source ] ) ) {
			return '';
		}

		return $source;

	}

	/**
	 * Get layer background color
	 *
	 * @since 1.0.0
	 * @access protected
	 *
	 * @param string $layer Layer arguments.
	 * @param string $name  Layer name.
	 * @return string
	 */
	protected function get_layer_background( $layer, $name ) {

		$background = '';

		if ( 'media-overlay' === $name ) {
			$background .= $this->atts['overlay_background'];
		} elseif ( 'header' === $name || 'body' === $name || 'footer' === $name ) {
			$background .= $this->atts['content_background'];
		}

		if ( empty( $background ) ) {
			return '';
		}

		return ' style="background:' . esc_attr( $background ) . '"';

	}

	/**
	 * Get layer classes
	 *
	 * @since 1.0.0
	 * @access protected
	 *
	 * @param string $layer Layer arguments.
	 * @param string $name  Layer name.
	 * @return string
	 */
	protected function get_layer_classes( $layer, $name ) {

		$class = 'wpgb-card-' . $name;

		if ( isset( $layer['action']['action_type'] ) && 'open_media' === $layer['action']['action_type'] ) {
			$class .= ' wpgb-card-media-button';
		}

		if ( 'media' === $name ) {
			$class .= ' wpgb-scheme-' . $this->atts['overlay_color_scheme'];
		} elseif ( 'header' === $name || 'content' === $name ) {
			$class .= ' wpgb-scheme-' . $this->atts['content_color_scheme'];
		}

		$class = Helpers::sanitize_html_classes( $class );

		return $class;

	}
}