This commit is contained in:
nguyen dung
2022-02-18 16:43:41 +07:00
commit 39b8cb3612
4470 changed files with 1378320 additions and 0 deletions

View File

@@ -0,0 +1,40 @@
<?php
global $extensions_url;
global $extensions_uri;
$extensions_url = get_template_directory() . '/inc/extensions';
$extensions_uri = get_template_directory_uri() . '/inc/extensions';
// Shortcode Inserter
if(is_admin()){ require $extensions_url.'/flatsome-shortcode-insert/tinymce.php'; }
// Lazy load
if((!is_admin() && !is_customize_preview() ) && get_theme_mod('lazy_load_images')){ require $extensions_url.'/flatsome-lazy-load/flatsome-lazy-load.php'; }
if ( get_theme_mod( 'perf_instant_page', 0 ) ) {
require $extensions_url.'/flatsome-instant-page/flatsome-instant-page.php';
}
if(get_theme_mod('live_search', 1)){
require $extensions_url.'/flatsome-live-search/flatsome-live-search.php';
}
if ( get_theme_mod( 'cookie_notice' ) || is_customize_preview() ) {
require $extensions_url . '/flatsome-cookie-notice/flatsome-cookie-notice.php';
}
if(is_woocommerce_activated()){
if(!get_theme_mod('disable_quick_view', 0)){
require $extensions_url.'/flatsome-wc-quick-view/flatsome-quick-view.php';
}
if ( get_theme_mod( 'flatsome_infinite_scroll' ) ) {
require $extensions_url . '/flatsome-infinite-scroll/class-flatsome-infinite-scroll.php';
}
if ( get_theme_mod( 'cart_auto_refresh' ) ) {
require $extensions_url . '/flatsome-cart-refresh/flatsome-cart-refresh.php';
}
if ( get_theme_mod( 'swatches' ) ) {
require $extensions_url . '/flatsome-swatches/index.php';
}
}

View File

@@ -0,0 +1,18 @@
Flatsome.behavior('cart-refresh', {
attach: function () {
if (!jQuery('.cart-auto-refresh').length) {
return
}
var updateCartButton = jQuery('button[name=\'update_cart\']')
var updateCart = null
jQuery('.woocommerce-cart-form').find('.cart_item .qty').on('change', function () {
if (updateCart != null) {
clearTimeout(updateCart)
}
updateCart = setTimeout(function () {
updateCartButton.trigger('click')
}, 1200)
})
}
})

View File

@@ -0,0 +1,31 @@
<?php
/**
* Flatsome Cart refresh extension
*
* @author UX Themes
* @category Extension
* @package Flatsome/Extensions
* @since 3.6.0
*/
/**
* To be enqueued refresh script.
*/
function flatsome_cart_refresh_script() {
global $extensions_uri;
$theme = wp_get_theme( get_template() );
$version = $theme->get( 'Version' );
wp_enqueue_script( 'flatsome-cart-refresh', $extensions_uri . '/flatsome-cart-refresh/flatsome-cart-refresh.js', array( 'jquery', 'flatsome-js' ), $version, true );
}
/**
* Add extension script if on cart page.
*/
function flatsome_add_cart_refresh_script() {
if ( is_cart() ) {
add_action( 'wp_enqueue_scripts', 'flatsome_cart_refresh_script' );
}
}
add_action( 'wp', 'flatsome_add_cart_refresh_script' );

View File

@@ -0,0 +1,20 @@
/* global flatsomeVars, cookie */
jQuery(document).ready(function () {
'use strict'
var $notice = jQuery('.flatsome-cookies')
var cookieId = 'flatsome_cookie_notice'
var cookieValue = flatsomeVars.options.cookie_notice_version
if (cookie(cookieId) !== cookieValue) {
setTimeout(function () {
$notice.addClass('flatsome-cookies--active')
$notice.on('click', '.flatsome-cookies__accept-btn', function (e) {
e.preventDefault()
$notice.removeClass('flatsome-cookies--active').addClass('flatsome-cookies--inactive')
// set cookie
cookie(cookieId, cookieValue, 365)
})
}, 2500)
}
})

View File

@@ -0,0 +1,73 @@
<?php
/**
* Flatsome Cookie notice extension
*
* @author UX Themes
* @category Extension
* @package Flatsome/Extensions
* @since 3.12.0
*/
defined( 'ABSPATH' ) || exit;
/**
* Enqueue extensions scripts.
*/
function flatsome_cookie_notice_scripts() {
global $extensions_uri;
wp_enqueue_script( 'flatsome-cookie-notice', $extensions_uri . '/flatsome-cookie-notice/flatsome-cookie-notice.js', array( 'jquery', 'flatsome-js' ), '3.12.0', true );
}
add_action( 'wp_enqueue_scripts', 'flatsome_cookie_notice_scripts' );
/**
* Html template for cookie notice.
*/
function flatsome_cookie_notice_template() {
if ( ! get_theme_mod( 'cookie_notice' ) ) {
return;
}
$classes = array( 'flatsome-cookies' );
if ( get_theme_mod( 'cookie_notice_text_color' ) === 'dark' ) {
$classes[] = 'dark';
}
$text = get_theme_mod( 'cookie_notice_text' );
$id = get_theme_mod( 'privacy_policy_page' );
$page = $id ? get_post( $id ) : false;
$text = $text ? $text : __( 'This site uses cookies to offer you a better browsing experience. By browsing this website, you agree to our use of cookies.', 'flatsome' );
?>
<div class="<?php echo esc_attr( implode( ' ', $classes ) ); ?>">
<div class="flatsome-cookies__inner">
<div class="flatsome-cookies__text">
<?php echo do_shortcode( $text ); ?>
</div>
<div class="flatsome-cookies__buttons">
<?php
if ( $page ) {
echo flatsome_apply_shortcode( 'button', array(
'text' => _x( 'More info', 'cookie notice', 'flatsome' ),
'style' => get_theme_mod( 'cookie_notice_button_style', '' ),
'link' => get_permalink( $page->ID ),
'color' => 'secondary',
'class' => 'flatsome-cookies__more-btn',
) );
}
?>
<?php
echo flatsome_apply_shortcode( 'button', array(
'text' => _x( 'Accept', 'cookie notice', 'flatsome' ),
'style' => get_theme_mod( 'cookie_notice_button_style', '' ),
'link' => '#',
'color' => 'primary',
'class' => 'flatsome-cookies__accept-btn',
) );
?>
</div>
</div>
</div>
<?php
}
add_action( 'wp_footer', 'flatsome_cookie_notice_template' );

View File

@@ -0,0 +1,147 @@
<?php
/**
* Flatsome Infinite scroll extension
*
* @author UX Themes
* @category Extension
* @package Flatsome/Extensions
* @since 3.5.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Class Flatsome_Infinite_Scroll
*/
class Flatsome_Infinite_Scroll {
/**
* Version number
*
* @var string
*/
private $version;
/**
* Holds loader type selected from theme settings.
* ex. button, spinner, image, etc.
*
* @var string
*/
private $loader_type;
/**
* Holds category list style from theme settings.
* ex. grid, list, masonry
*
* @var string
*/
private $list_style;
/**
* Static instance
*
* @var object
*/
private static $instance;
/**
* Flatsome_Infinite_Scroll constructor.
*/
private function __construct() {
$theme = wp_get_theme( get_template() );
$this->version = $theme->get( 'Version' );
add_action( 'init', array( $this, 'init' ) );
}
/**
* Initializes the extension object and returns its instance
*
* @return object The extension object instance
*/
public static function get_instance() {
if ( ! isset( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Initialize extension
*/
public function init() {
if ( is_admin() ) {
return;
} // Disable for admin
$this->loader_type = get_theme_mod( 'infinite_scroll_loader_type', 'spinner' );
$this->list_style = get_theme_mod( 'category_grid_style', 'grid' );
add_action( 'wp_enqueue_scripts', array( $this, 'add_scripts' ), 99 );
add_action( 'woocommerce_after_shop_loop', array( $this, 'add_page_loader' ), 20 );
add_action( 'wp_head', array( $this, 'add_css' ), 110 );
}
/**
* Add extension scripts
*/
public function add_scripts() {
global $extensions_uri;
wp_enqueue_script( 'flatsome-infinite-scroll-js', get_template_directory_uri() . '/assets/libs/infinite-scroll.pkgd.min.js', array( 'jquery', 'flatsome-js' ), '4.0.1', true );
wp_enqueue_script( 'flatsome-infinite-scroll', $extensions_uri . '/flatsome-infinite-scroll/flatsome-infinite-scroll.js', array( 'jquery', 'flatsome-js' ), $this->version, true );
$params = array(
'scroll_threshold' => 400,
'fade_in_duration' => 300,
'type' => $this->loader_type,
'list_style' => $this->list_style,
'history' => 'push',
);
wp_localize_script( 'flatsome-infinite-scroll', 'flatsome_infinite_scroll', apply_filters( 'flatsome_infinite_scroll_params', $params ) );
}
/**
* Adds page loader template
*/
public function add_page_loader() {
$this->get_template( $this->loader_type );
}
/**
* Add extension CSS
*/
public function add_css() {
ob_start();
?>
<style id="infinite-scroll-css" type="text/css">
.page-load-status,
.archive .woocommerce-pagination {
display: none;
}
</style>
<?php
$css = ob_get_clean();
echo flatsome_minify_css( $css ); // @codingStandardsIgnoreLine
}
/**
* Gets and includes loader template file specified by name.
*
* @param string $name Name of the template.
*/
private function get_template( $name ) {
global $extensions_url;
$template = $extensions_url . "/flatsome-infinite-scroll/templates/{$name}.php";
include $template;
}
}
/**
* Init Flatsome_Infinite_Scroll
*/
Flatsome_Infinite_Scroll::get_instance();

View File

@@ -0,0 +1,90 @@
/* global flatsome_infinite_scroll, Packery, ga */
jQuery(document).ready(function () {
var container = jQuery('.shop-container .products')
var paginationNext = '.woocommerce-pagination li a.next'
if (container.length === 0 || jQuery(paginationNext).length === 0) {
return
}
var viewMoreButton = jQuery('button.view-more-button.products-archive')
var byButton = flatsome_infinite_scroll.type === 'button'
var isMasonry = flatsome_infinite_scroll.list_style === 'masonry'
// Set packery instance as outlayer when masonry is set.
var outlayer = isMasonry ? Packery.data(container[0]) : false
var $container = container.infiniteScroll({
path: paginationNext,
append: '.shop-container .product',
checkLastPage: true,
status: '.page-load-status',
hideNav: '.archive .woocommerce-pagination',
button: '.view-more-button',
history: flatsome_infinite_scroll.history,
historyTitle: true,
debug: false,
outlayer: outlayer,
scrollThreshold: parseInt(flatsome_infinite_scroll.scroll_threshold)
})
if (byButton) {
viewMoreButton.removeClass('hidden')
$container.infiniteScroll('option', {
scrollThreshold: false,
loadOnScroll: false
})
}
$container.on('load.infiniteScroll', function (event, response, path) {
flatsomeInfiniteScroll.attachBehaviors(response)
})
$container.on('request.infiniteScroll', function (event, path) {
if (byButton) viewMoreButton.addClass('loading')
})
$container.on('append.infiniteScroll', function (event, response, path, items) {
jQuery(document).trigger('flatsome-infiniteScroll-append', [response, path, items])
if (byButton) viewMoreButton.removeClass('loading')
// Fix Safari bug
jQuery(items).find('img').each(function (index, img) {
img.outerHTML = img.outerHTML
})
// Load fragments and init_handling_after_ajax for new items.
jQuery(document).trigger('yith_wcwl_reload_fragments')
jQuery(document).trigger('flatsome-equalize-box')
Flatsome.attach('lazy-load-images', container)
flatsomeInfiniteScroll.animateNewItems(items)
if (isMasonry) {
setTimeout(function () {
$container.imagesLoaded(function () {
$container.packery('layout')
})
}, 500)
}
if (window.ga && ga.loaded && typeof ga === 'function') {
var link = document.createElement('a')
link.href = path
ga('set', 'page', link.pathname)
ga('send', 'pageview')
}
})
var flatsomeInfiniteScroll = {
attachBehaviors: function (response) {
Flatsome.attach('quick-view', response)
Flatsome.attach('tooltips', response)
Flatsome.attach('add-qty', response)
Flatsome.attach('wishlist', response)
},
animateNewItems: function (items) {
if (isMasonry) return
jQuery(items).hide().fadeIn(parseInt(flatsome_infinite_scroll.fade_in_duration))
}
}
})

View File

@@ -0,0 +1,3 @@
<p class="text-center">
<button class="view-more-button products-archive button primary hidden"><?php esc_html_e( 'View more', 'flatsome' ); ?></button>
</p>

View File

@@ -0,0 +1,9 @@
<div class="page-load-status">
<div class="loader-image infinite-scroll-request text-center">
<?php if ( get_theme_mod( 'infinite_scroll_loader_img' ) ) : ?>
<img class="archive-img-loader" alt="" src="<?php echo set_url_scheme( get_theme_mod( 'infinite_scroll_loader_img' ) ) ?>"/>
<?php else : ?>
<p>No custom loader image set.</p>
<?php endif ?>
</div>
</div>

View File

@@ -0,0 +1,5 @@
<div class="page-load-status">
<div class="loader-spinner infinite-scroll-request text-center">
<div class="loading-spin"></div>
</div>
</div>

View File

@@ -0,0 +1,131 @@
// modified to work without type="module"
;(function () {
/*! instant.page v1.2.2 - (C) 2019 Alexandre Dieulot - https://instant.page/license */
var urlToPreload
var mouseoverTimer
var lastTouchTimestamp
var prefetcher = document.createElement('link')
var isSupported = prefetcher.relList && prefetcher.relList.supports && prefetcher.relList.supports('prefetch')
var isDataSaverEnabled = navigator.connection && navigator.connection.saveData
var allowQueryString = 'instantAllowQueryString' in document.body.dataset
var allowExternalLinks = 'instantAllowExternalLinks' in document.body.dataset
if (isSupported && !isDataSaverEnabled) {
prefetcher.rel = 'prefetch'
document.head.appendChild(prefetcher)
var eventListenersOptions = {
capture: true,
passive: true
}
document.addEventListener('touchstart', touchstartListener, eventListenersOptions)
document.addEventListener('mouseover', mouseoverListener, eventListenersOptions)
}
function touchstartListener (event) {
/* Chrome on Android calls mouseover before touchcancel so `lastTouchTimestamp`
* must be assigned on touchstart to be measured on mouseover. */
lastTouchTimestamp = performance.now()
var linkElement = event.target.closest('a')
if (!isPreloadable(linkElement)) {
return
}
linkElement.addEventListener('touchcancel', touchendAndTouchcancelListener, { passive: true })
linkElement.addEventListener('touchend', touchendAndTouchcancelListener, { passive: true })
urlToPreload = linkElement.href
preload(linkElement.href)
}
function touchendAndTouchcancelListener () {
urlToPreload = undefined
stopPreloading()
}
function mouseoverListener (event) {
if (performance.now() - lastTouchTimestamp < 1100) {
return
}
var linkElement = event.target.closest('a')
if (!isPreloadable(linkElement)) {
return
}
linkElement.addEventListener('mouseout', mouseoutListener, { passive: true })
urlToPreload = linkElement.href
mouseoverTimer = setTimeout(function () {
preload(linkElement.href)
mouseoverTimer = undefined
}, 65)
}
function mouseoutListener (event) {
if (event.relatedTarget && event.target.closest('a') === event.relatedTarget.closest('a')) {
return
}
if (mouseoverTimer) {
clearTimeout(mouseoverTimer)
mouseoverTimer = undefined
} else {
urlToPreload = undefined
stopPreloading()
}
}
function isPreloadable (linkElement) {
if (!linkElement || !linkElement.href) {
return
}
if (urlToPreload === linkElement.href) {
return
}
var preloadLocation = new URL(linkElement.href)
if (!allowExternalLinks && preloadLocation.origin !== location.origin && !('instant' in linkElement.dataset)) {
return
}
if (!['http:', 'https:'].includes(preloadLocation.protocol)) {
return
}
if (preloadLocation.protocol === 'http:' && location.protocol === 'https:') {
return
}
if (!allowQueryString && preloadLocation.search && !('instant' in linkElement.dataset)) {
return
}
if (preloadLocation.hash && preloadLocation.pathname + preloadLocation.search === location.pathname + location.search) {
return
}
if ('noInstant' in linkElement.dataset) {
return
}
return true
}
function preload (url) {
prefetcher.href = url
}
function stopPreloading () {
prefetcher.removeAttribute('href')
}
})()

View File

@@ -0,0 +1,31 @@
<?php
/**
* Flatsome Instant Page extension
*
* @author UX Themes
* @category Extension
* @package Flatsome/Extensions
* @since 3.9.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
add_action( 'wp_enqueue_scripts', 'flatsome_instant_page' );
if ( ! function_exists( 'flatsome_instant_page' ) ) :
function flatsome_instant_page() {
global $extensions_uri;
wp_enqueue_script(
'flatsome-instant-page',
$extensions_uri . '/flatsome-instant-page/flatsome-instant-page.js',
array(),
'1.2.1',
true
);
}
endif;

View File

@@ -0,0 +1,89 @@
/* global objectFitImages */
;(function () {
function createObserver (handler) {
return new IntersectionObserver(function (entries) {
for (var i = 0; i < entries.length; i++) {
handler(entries[i])
}
}, {
rootMargin: '0px',
threshold: 0.1
})
}
Flatsome.behavior('lazy-load-images', {
attach: function (context) {
var observer = createObserver(function (entry) {
if (entry.intersectionRatio > 0) {
observer.unobserve(entry.target)
var $el = jQuery(entry.target)
var src = $el.data('src')
var srcset = $el.data('srcset')
if ($el.hasClass('lazy-load-active')) return
else $el.addClass('lazy-load-active')
if (src) $el.attr('src', src)
if (srcset) $el.attr('srcset', srcset)
$el.imagesLoaded(function () {
$el.removeClass('lazy-load')
if (typeof objectFitImages !== 'undefined') {
objectFitImages($el)
}
})
}
})
jQuery('.lazy-load', context).each(function (i, el) {
observer.observe(el)
})
}
})
Flatsome.behavior('lazy-load-sliders', {
attach: function (context) {
var observer = createObserver(function (entry) {
if (entry.intersectionRatio > 0) {
observer.unobserve(entry.target)
var $el = jQuery(entry.target)
if ($el.hasClass('slider-lazy-load-active')) return
else $el.addClass('slider-lazy-load-active')
$el.imagesLoaded(function () {
if ($el.hasClass('flickity-enabled')) {
$el.flickity('resize')
}
})
}
})
jQuery('.slider', context).each(function (i, el) {
observer.observe(el)
})
}
})
Flatsome.behavior('lazy-load-packery', {
attach: function (context) {
var observer = createObserver(function (entry) {
if (entry.intersectionRatio > 0) {
observer.unobserve(entry.target)
var $el = jQuery(entry.target)
$el.imagesLoaded(function () {
jQuery('.has-packery').packery('layout') // why global selector?
})
}
})
jQuery('.has-packery .lazy-load', context).each(function (i, el) {
observer.observe(el)
})
}
})
})()

View File

@@ -0,0 +1,147 @@
<?php
if ( ! class_exists( 'FL_LazyLoad_Images' ) ) :
class FL_LazyLoad_Images {
protected static $enabled = true;
static function init() {
if ( is_admin() ) return; // Disable for admin
add_action( 'wp_enqueue_scripts', array( __CLASS__, 'add_scripts' ), 99 );
add_action( 'wp_head', array( __CLASS__, 'setup_filters' ), 99 );
}
static function setup_filters() {
add_filter( 'the_content', array( __CLASS__, 'add_image_placeholders' ), 9999 );
add_filter( 'post_thumbnail_html', array( __CLASS__, 'add_image_placeholders' ), 11 );
add_filter( 'get_avatar', array( __CLASS__, 'add_image_placeholders' ), 11 );
add_filter( 'flatsome_woocommerce_get_alt_product_thumbnail', array( __CLASS__, 'add_image_placeholders' ), 11 );
add_filter( 'flatsome_lazy_load_images', array( __CLASS__, 'add_image_placeholders' ), 9999 );
add_filter( 'flatsome_woocommerce_single_product_extra_images', array( __CLASS__, 'add_image_placeholders' ), 9999 );
add_filter( 'woocommerce_single_product_image_thumbnail_html', array( __CLASS__, 'add_image_placeholders' ), 9999 );
add_filter( 'woocommerce_product_get_image', array( __CLASS__, 'add_image_placeholders' ), 9999 );
}
static function add_scripts() {
global $extensions_uri;
$theme = wp_get_theme( get_template() );
$version = $theme->get( 'Version' );
wp_enqueue_script(
'flatsome-lazy',
$extensions_uri . '/flatsome-lazy-load/flatsome-lazy-load.js',
array( 'flatsome-js' ),
$version,
true
);
}
static function add_image_placeholders( $content ) {
if ( ! self::is_enabled() )
return $content;
// Don't lazyload for feeds, previews, mobile
if ( is_feed() || is_preview() )
return $content;
$matches = array();
preg_match_all( '/<img[\s\r\n]+.*?>/is', $content, $matches );
$search = array();
$replace = array();
$i = 0;
foreach ( $matches[0] as $imgHTML ) {
// don't do the replacement if the image is a data-uri
if ( ! preg_match( "/src=['\"]data:image/is", $imgHTML ) ) {
$i++;
// generate a base64 image string
$src = self::create_base64_string( $imgHTML );
// replace the src and add the data-src attribute
$replaceHTML = '';
if ( false === strpos( $imgHTML, 'data-src' ) ) {
$replaceHTML = preg_replace( '/<img(.*?)src=/is', '<img$1src="' . $src . '" data-src=', $imgHTML );
} else {
$replaceHTML = preg_replace( '/<img(.*?)src=(["\'](.*?)["\'])/is', '<img$1src="' . $src . '"', $imgHTML );
}
$replaceHTML = preg_replace( '/<img(.*?)srcset=/is', '<img$1srcset="" data-srcset=', $replaceHTML );
// add the lazy class to the img element
$classes = 'lazy-load';
if ( preg_match( '/class=["\']/i', $replaceHTML ) ) {
$replaceHTML = preg_replace( '/class=(["\'])(.*?)["\']/is', 'class=$1' . $classes . ' $2$1', $replaceHTML );
} else {
$replaceHTML = preg_replace( '/<img/is', '<img class="' . $classes . '"', $replaceHTML );
}
array_push( $search, $imgHTML );
array_push( $replace, $replaceHTML );
}
}
$search = array_unique( $search );
$replace = array_unique( $replace );
$content = str_replace( $search, $replace, $content );
return $content;
}
static function is_enabled() {
return self::$enabled;
}
static function get_image_size( $html ) {
preg_match_all( '/(height|width)=["\'](.*?)["\']/is', $html, $matches, PREG_PATTERN_ORDER );
$size = array( 100, 100 );
foreach ( $matches[1] as $key => $attr ) {
$value = intval( $matches[2][ $key ] );
if ( $attr === 'width' ) $size[0] = $value;
if ( $attr === 'height' ) $size[1] = $value;
}
return $size;
}
static function create_base64_string( $imgHTML ) {
list( $width, $height ) = self::get_image_size( $imgHTML );
$svg = '<svg';
$svg .= ' viewBox="0 0 ' . $width . ' ' . $height . '"';
$svg .= ' xmlns="http://www.w3.org/2000/svg"';
$svg .= '></svg>';
// For base64 string:
// return 'data:image/svg+xml;base64,' . base64_encode( $svg );
return 'data:image/svg+xml,' . rawurlencode( $svg );
}
}
add_action( 'init', array( 'FL_LazyLoad_Images', 'init' ) );
/**
* WooCommerce category thumbnails don't have a filter.
* Remove the original action and add a custom.
*/
function flatsome_woocommerce_subcategory_thumbnail( $category ) {
ob_start();
woocommerce_subcategory_thumbnail( $category );
$thumbnail = ob_get_clean();
echo FL_LazyLoad_Images::add_image_placeholders( $thumbnail );
}
remove_action( 'woocommerce_before_subcategory_title', 'woocommerce_subcategory_thumbnail', 10 );
add_action( 'woocommerce_before_subcategory_title', 'flatsome_woocommerce_subcategory_thumbnail', 10 );
endif;

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,233 @@
<?php
function flatsome_live_search_script() {
global $extensions_uri;
$theme = wp_get_theme( get_template() );
$version = $theme->get( 'Version' );
wp_enqueue_script( 'flatsome-live-search', $extensions_uri . '/flatsome-live-search/flatsome-live-search.js', false, $version, true );
}
add_action( 'wp_enqueue_scripts', 'flatsome_live_search_script' );
/**
* Search for posts and pages.
*
* @param array $args Query args.
*
* @return array Posts.
*/
function flatsome_ajax_search_posts( $args ) {
$defaults = $args;
$args['s'] = apply_filters( 'flatsome_ajax_search_query', $_REQUEST['query'] );
$args['post_type'] = apply_filters( 'flatsome_ajax_search_post_type', array( 'post', 'page' ) );
$search_query = http_build_query( $args );
$query_function = apply_filters( 'flatsome_ajax_search_function', 'get_posts', $search_query, $args, $defaults );
return ( ( $query_function == 'get_posts' ) || ! function_exists( $query_function ) ) ? get_posts( $args ) : $query_function( $search_query, $args, $defaults );
}
/**
* Gets products based on the search type specified.
*
* @param string $search_type Type of search.
* @param array $args Default query args.
*
* @return array Products.
*/
function flatsome_ajax_search_get_products( $search_type, array $args ) {
$order_by = get_theme_mod( 'search_products_order_by', 'relevance' );
$ordering_args = WC()->query->get_catalog_ordering_args( $order_by, 'ASC' );
$defaults = $args;
$args['post_type'] = 'product';
$args['orderby'] = $ordering_args['orderby'];
$args['order'] = $ordering_args['order'];
$args['meta_query'] = WC()->query->get_meta_query(); // WPCS: slow query ok.
$args['tax_query'] = array(); // WPCS: slow query ok.
$args = flatsome_ajax_search_catalog_visibility( $args );
$args = flatsome_ajax_search_query_by_category( $args );
switch ( $search_type ) {
case 'product':
$args['s'] = apply_filters( 'flatsome_ajax_search_products_search_query', $_REQUEST['query'] );
break;
case 'tag':
$args['s'] = '';
$args['product_tag'] = apply_filters( 'flatsome_ajax_search_products_by_tag_search_query', $_REQUEST['query'] );
break;
case 'sku':
$query = apply_filters( 'flatsome_ajax_search_products_by_sku_search_query', $_REQUEST['query'] );
$args['s'] = '';
$args['post_type'] = array( 'product', 'product_variation' );
$args['meta_query'][] = array(
'key' => '_sku',
'value' => $query,
);
break;
}
$search_query = http_build_query( $args );
$query_function = apply_filters( 'flatsome_ajax_search_function', 'get_posts', $search_query, $args, $defaults );
return ( ( $query_function === 'get_posts' ) || ! function_exists( $query_function ) ) ? get_posts( $args ) : $query_function( $search_query, $args, $defaults );
}
/**
* Checks product catalog visibility with custom tax_query. (only queries the exclude-from-search term) and checks WC hide out of stock option.
*
* @param array $args Query args.
*
* @return array Query args with addition.
*/
function flatsome_ajax_search_catalog_visibility( $args ) {
$product_visibility_term_ids = wc_get_product_visibility_term_ids();
// Catalog visibility.
$args['tax_query'][] = array(
'taxonomy' => 'product_visibility',
'field' => 'term_taxonomy_id',
'terms' => $product_visibility_term_ids['exclude-from-search'],
'operator' => 'NOT IN',
);
// Hide out of stock.
if ( 'yes' === get_option( 'woocommerce_hide_out_of_stock_items' ) ) {
$args['tax_query'][] = array(
'taxonomy' => 'product_visibility',
'field' => 'term_taxonomy_id',
'terms' => $product_visibility_term_ids['outofstock'],
'operator' => 'NOT IN',
);
}
return $args;
}
/**
* Query products by category if 'product_cat' is in request.
*
* @param array $args Query args.
*
* @return array Query args with or without addition.
*/
function flatsome_ajax_search_query_by_category( $args ) {
if ( isset( $_REQUEST['product_cat'] ) ) {
$args['tax_query'][] = array(
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => esc_attr( $_REQUEST['product_cat'] ),
);
}
return $args;
}
/**
* Search AJAX handler.
*/
function flatsome_ajax_search() {
// The string from search text field.
$query = apply_filters( 'flatsome_ajax_search_query', $_REQUEST['query'] );
$wc_activated = is_woocommerce_activated();
$products = array();
$posts = array();
$sku_products = array();
$tag_products = array();
$suggestions = array();
$args = array(
's' => $query,
'orderby' => '',
'post_type' => array(),
'post_status' => 'publish',
'posts_per_page' => 100,
'ignore_sticky_posts' => 1,
'post_password' => '',
'suppress_filters' => false,
);
if ( $wc_activated ) {
$products = flatsome_ajax_search_get_products( 'product', $args );
$sku_products = get_theme_mod( 'search_by_sku', 0 ) ? flatsome_ajax_search_get_products( 'sku', $args ) : array();
$tag_products = get_theme_mod( 'search_by_product_tag', 0 ) ? flatsome_ajax_search_get_products( 'tag', $args ) : array();
}
if ( ( ! $wc_activated || get_theme_mod( 'search_result', 1 ) ) && ! isset( $_REQUEST['product_cat'] ) ) {
$posts = flatsome_ajax_search_posts( $args );
}
$results = array_merge( $products, $sku_products, $tag_products, $posts );
foreach ( $results as $key => $post ) {
if ( $wc_activated && ( $post->post_type === 'product' || $post->post_type === 'product_variation' ) ) {
$product = wc_get_product( $post );
if ( $product->get_parent_id() ) {
$parent_product = wc_get_product( $product->get_parent_id() );
$visible = $parent_product->get_catalog_visibility() === 'visible' || $parent_product->get_catalog_visibility() === 'search';
if ( $parent_product->get_status() !== 'publish' || ! $visible ) {
unset( $results[ $key ] );
continue;
}
}
$product_image = wp_get_attachment_image_src( get_post_thumbnail_id( $product->get_id() ) );
$suggestions[] = array(
'type' => 'Product',
'id' => $product->get_id(),
'value' => $product->get_title(),
'url' => $product->get_permalink(),
'img' => $product_image ? $product_image[0] : '',
'price' => $product->get_price_html(),
);
} else {
$suggestions[] = array(
'type' => 'Page',
'id' => $post->ID,
'value' => get_the_title( $post->ID ),
'url' => get_the_permalink( $post->ID ),
'img' => get_the_post_thumbnail_url( $post->ID, 'thumbnail' ),
'price' => '',
);
}
}
if ( empty( $results ) ) {
$no_results = $wc_activated ? __( 'No products found.', 'woocommerce' ) : __( 'No matches found', 'flatsome' );
$suggestions[] = array(
'id' => -1,
'value' => $no_results,
'url' => '',
);
}
$suggestions = flatsome_unique_suggestions( array( $products, $sku_products, $tag_products ), $suggestions );
wp_send_json( array( 'suggestions' => $suggestions ) );
}
add_action( 'wp_ajax_flatsome_ajax_search_products', 'flatsome_ajax_search' );
add_action( 'wp_ajax_nopriv_flatsome_ajax_search_products', 'flatsome_ajax_search' );
/**
* Makes search suggestions unique if multiple raw_results have values.
*
* @param array $raw_results Raw search results supplied unmerged.
* @param array $suggestions Suggestions that may or may not be unique.
*
* @return array Unique suggestions.
*/
function flatsome_unique_suggestions( array $raw_results, array $suggestions ) {
$results = array_map( function ( $n ) { return $n ? true : false; }, $raw_results );
$needs_filtering = count( array_filter( $results ) ) > 1;
if ( $needs_filtering ) {
$suggestions = array_map( 'unserialize', array_unique( array_map( 'serialize', $suggestions ) ) );
}
return $suggestions;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,15 @@
i.mce-i-icon {
font: 400 20px/1 dashicons!important;
padding: 0;
vertical-align: top;
speak: none;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
margin-left: -2px;
padding-right: 2px;
}
.mce-tooltip-inner{overflow: hidden!important;}
.image-bg-button{text-align: left!important; background-repeat: no-repeat!important;background-size: auto 100%!important; background-position: right!important;}
div[aria-label="Add Shortcodes"]{border:1px solid #627f9a!important;}
div[aria-label="Add Shortcodes"] > button > span{color:#627f9a!important;}

View File

@@ -0,0 +1,36 @@
<?php
/* NEW */
add_action('admin_head', 'ux_shortcode_button');
function ux_shortcode_button() {
global $typenow;
// check user permissions
if ( !current_user_can('edit_posts') && !current_user_can('edit_pages') ) {
return;
}
// verify the post type
if( ! in_array( $typenow, array( 'post', 'page', 'blocks', 'product' ) ) )
return;
// check if WYSIWYG is enabled
if ( get_user_option('rich_editing') == 'true') {
add_filter("mce_external_plugins", "ux_shortcode_add_tinymce_plugin");
add_filter('mce_buttons', 'ux_shortcode_insert_button');
}
}
function ux_shortcode_add_tinymce_plugin($plugin_array) {
$plugin_array['ux_shortcode_insert'] = get_template_directory_uri().'/inc/extensions/flatsome-shortcode-insert/shortcode_insert.js';
return $plugin_array;
}
function ux_shortcode_insert_button($buttons) {
array_push($buttons, "ux_shortcode_insert");
return $buttons;
}
function ux_shortcode_css() {
// TODO: Only Load on Edit Page
wp_enqueue_style('ux_shortcode_insert_css', get_template_directory_uri().'/inc/extensions/flatsome-shortcode-insert/style.css');
}
add_action('admin_enqueue_scripts', 'ux_shortcode_css');

View File

@@ -0,0 +1,67 @@
<?php
/**
* Swatches product admin class.
*
* @package Flatsome\Extensions
*/
namespace Flatsome\Extensions;
defined( 'ABSPATH' ) || exit;
/**
* Class Swatches_Admin_Product
*
* @package Flatsome\Extensions
*/
class Swatches_Admin_Product {
/**
* Swatches_Admin_Product constructor.
*/
public function __construct() {
add_action( 'woocommerce_product_option_terms', array( $this, 'product_option_terms' ), 10, 3 );
}
/**
* Add selector for extra attribute types.
* html-product-attribute.php template
*
* @param object $attribute_taxonomy Taxonomy.
* @param string|int $i Index.
* @param object $attribute Attribute.
*/
public function product_option_terms( $attribute_taxonomy, $i, $attribute ) {
if ( ! array_key_exists( $attribute_taxonomy->attribute_type, flatsome_swatches()->get_attribute_types() ) ) {
return;
}
global $thepostid;
$taxonomy_name = wc_attribute_taxonomy_name( $attribute_taxonomy->attribute_name );
$product_id = isset( $_POST['post_id'] ) ? absint( $_POST['post_id'] ) : $thepostid; // phpcs:ignore WordPress.Security.NonceVerification
?>
<select multiple="multiple" data-placeholder="<?php esc_attr_e( 'Select terms', 'woocommerce' ); ?>" class="multiselect attribute_values wc-enhanced-select" name="attribute_values[<?php echo esc_attr( $i ); ?>][]">
<?php
$args = array(
'orderby' => ! empty( $attribute_taxonomy->attribute_orderby ) ? $attribute_taxonomy->attribute_orderby : 'name',
'hide_empty' => 0,
);
$all_terms = get_terms( $taxonomy_name, apply_filters( 'woocommerce_product_attribute_terms', $args ) );
if ( $all_terms ) {
foreach ( $all_terms as $term ) {
echo '<option value="' . esc_attr( $term->term_id ) . '" ' . selected( has_term( absint( $term->term_id ), $taxonomy_name, $product_id ), true, false ) . '>' . esc_html( apply_filters( 'woocommerce_product_attribute_term_name', $term->name, $term ) ) . '</option>';
}
}
?>
</select>
<button class="button plus select_all_attributes"><?php esc_html_e( 'Select all', 'woocommerce' ); ?></button>
<button class="button minus select_no_attributes"><?php esc_html_e( 'Select none', 'woocommerce' ); ?></button>
<button class="button fr plus add_new_attribute" data-type="<?php echo esc_attr( $attribute_taxonomy->attribute_type ); ?>"><?php esc_html_e( 'Add new', 'woocommerce' ); ?></button>
<?php
}
}
new Swatches_Admin_Product();

View File

@@ -0,0 +1,391 @@
<?php
/**
* Swatches admin class.
*
* @package Flatsome\Extensions
*/
namespace Flatsome\Extensions;
defined( 'ABSPATH' ) || exit;
/**
* Class Swatches_Admin
*
* @package Flatsome\Extensions
*/
class Swatches_Admin {
/**
* The single instance of the class
*
* @var Swatches_Admin
*/
protected static $instance = null;
/**
* Main instance
*
* @return Swatches_Admin
*/
public static function instance() {
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Swatches_Admin constructor.
*/
public function __construct() {
add_action( 'admin_init', array( $this, 'includes' ) );
add_action( 'admin_init', array( $this, 'init_attribute_hooks' ) );
add_action( 'admin_print_scripts', array( $this, 'enqueue_scripts' ) );
// Add option fields.
add_action( 'flatsome_product_attribute_term_fields', array( $this, 'attribute_term_field' ), 10, 3 );
add_action( 'woocommerce_after_add_attribute_fields', array( $this, 'attribute_fields' ) );
add_action( 'woocommerce_after_edit_attribute_fields', array( $this, 'attribute_fields' ) );
// Add attribute option fields.
add_action( 'woocommerce_attribute_added', array( $this, 'add_attribute_options' ), 10, 2 );
add_action( 'woocommerce_attribute_updated', array( $this, 'update_attribute_options' ), 10, 3 );
add_action( 'woocommerce_attribute_updated', array( flatsome_swatches(), 'cache_clear' ), 10, 3 );
add_action( 'woocommerce_attribute_deleted', array( $this, 'delete_attribute_option' ), 10 );
}
/**
* Render attribute fields for add/edit screen.
*/
public function attribute_fields() {
$id = isset( $_GET['edit'] ) ? absint( $_GET['edit'] ) : false; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$options = $id ? get_option( "flatsome_product_attribute-{$id}" ) : '';
$swatch_size = isset( $options['swatch_size'] ) ? $options['swatch_size'] : '';
$swatch_shape = isset( $options['swatch_shape'] ) ? $options['swatch_shape'] : '';
$variation_images = isset( $options['swatch_variation_images'] ) ? $options['swatch_variation_images'] : '';
$table = doing_action( 'woocommerce_after_edit_attribute_fields' ); // Edit screen requires table markup.
?>
<?php echo $table ? '<tr class="form-field"><th scope="row" valign="top">' : '<div class="form-field">'; ?>
<label for="attribute_swatch_size"><?php esc_html_e( 'Swatch size', 'flatsome' ); ?></label>
<?php if ( $table ) echo '</th><td>'; ?>
<select name="attribute_swatch_size" id="attribute_swatch_size">
<option value="x-small" <?php selected( $swatch_size, 'x-small' ); ?>><?php esc_html_e( 'X Small', 'flatsome' ); ?></option>
<option value="small" <?php selected( $swatch_size, 'small' ); ?>><?php esc_html_e( 'Small', 'flatsome' ); ?></option>
<option value="" <?php selected( $swatch_size, '' ); ?>><?php esc_html_e( 'Medium', 'flatsome' ); ?></option>
<option value="large" <?php selected( $swatch_size, 'large' ); ?>><?php esc_html_e( 'Large', 'flatsome' ); ?></option>
<option value="x-large" <?php selected( $swatch_size, 'x-large' ); ?>><?php esc_html_e( 'X Large', 'flatsome' ); ?></option>
</select>
<p class="description"><?php esc_html_e( 'Determines the size of the swatches.', 'flatsome' ); ?></p>
<?php echo $table ? '</td></tr>' : '</div>'; ?>
<?php echo $table ? '<tr class="form-field"><th scope="row" valign="top">' : '<div class="form-field">'; ?>
<label for="attribute_swatch_shape"><?php esc_html_e( 'Swatch shape', 'flatsome' ); ?></label>
<?php if ( $table ) echo '</th><td>'; ?>
<select name="attribute_swatch_shape" id="attribute_swatch_shape">
<option value=""><?php esc_html_e( 'Square', 'flatsome' ); ?></option>
<option value="rounded" <?php selected( $swatch_shape, 'rounded' ); ?>><?php esc_html_e( 'Rounded', 'flatsome' ); ?></option>
<option value="circle" <?php selected( $swatch_shape, 'circle' ); ?>><?php esc_html_e( 'Circle', 'flatsome' ); ?></option>
</select>
<p class="description"><?php esc_html_e( 'Determines the shape of the swatches.', 'flatsome' ); ?></p>
<?php echo $table ? '</td></tr>' : '</div>'; ?>
<?php echo $table ? '<tr class="form-field"><th scope="row" valign="top">' : '<div class="form-field">'; ?>
<?php echo $table ? '<label for="attribute_swatch_variation_images">' . esc_html__( 'Use variation images?', 'flatsome' ) . '</label></th><td>' : '<label for="attribute_swatch_variation_images">'; ?>
<input name="attribute_swatch_variation_images" id="attribute_swatch_variation_images" type="checkbox" value="1" <?php checked( $variation_images ); ?>><?php if ( ! $table ) echo esc_html__( 'Use variation images?', 'flatsome' ) . '</label>'; ?>
<p class="description"><?php esc_html_e( 'Enable this if you want swatches for this attribute to be auto filled with variation images.', 'flatsome' ); ?></p>
<?php echo $table ? '</td></tr>' : '</div>'; ?>
<?php
}
/**
* Include files we need in product admin.
*/
public function includes() {
include_once dirname( __FILE__ ) . '/class-swatches-admin-product.php';
}
/**
* Add fields to attribute screen.
* Add swatch preview column per attribute term.
* Save new term meta.
*/
public function init_attribute_hooks() {
$attribute_taxonomies = wc_get_attribute_taxonomies();
if ( empty( $attribute_taxonomies ) ) {
return;
}
foreach ( $attribute_taxonomies as $tax ) {
add_action( 'pa_' . $tax->attribute_name . '_add_form_fields', array( $this, 'add_attribute_term_fields' ) );
add_action( 'pa_' . $tax->attribute_name . '_edit_form_fields', array( $this, 'edit_attribute_term_fields' ), 10, 2 );
add_filter( 'manage_edit-pa_' . $tax->attribute_name . '_columns', array( $this, 'add_attribute_columns' ) );
add_filter( 'manage_pa_' . $tax->attribute_name . '_custom_column', array( $this, 'add_attribute_column_content' ), 10, 3 );
}
add_action( 'created_term', array( $this, 'save_term_meta' ), 10, 3 );
add_action( 'edit_term', array( $this, 'save_term_meta' ), 10, 3 );
add_action( 'edit_term', array( flatsome_swatches(), 'cache_clear' ), 10, 3 );
}
/**
* Load scripts in edit product attribute screen.
*/
public function enqueue_scripts() {
$screen = get_current_screen();
if ( $screen && strpos( $screen->id, 'edit-pa_' ) === false && strpos( $screen->id, 'product' ) === false ) {
return;
}
wp_enqueue_media();
wp_enqueue_style( 'flatsome-swatches-admin', get_template_directory_uri() . '/assets/css/extensions/flatsome-swatches-admin.css', array( 'wp-color-picker' ), flatsome_swatches()->version );
wp_enqueue_script( 'flatsome-swatches-admin', get_template_directory_uri() . '/assets/js/extensions/flatsome-swatches-admin.js', array(
'jquery',
'wp-color-picker',
'wp-util',
), flatsome_swatches()->version, true );
wp_localize_script(
'flatsome-swatches-admin',
'flatsome_swatches',
array(
'placeholder' => WC()->plugin_url() . '/assets/images/placeholder.png',
)
);
}
/**
* Create hook to add fields to add attribute term screen.
*
* @param string $taxonomy Taxonomy.
*/
public function add_attribute_term_fields( $taxonomy ) {
$attr = flatsome_swatches()->get_attribute( $taxonomy );
do_action( 'flatsome_product_attribute_term_fields', $attr->attribute_type, '', 'add' );
}
/**
* Create hook to fields to edit attribute term screen.
*
* @param object $term Term.
* @param string $taxonomy Taxonomy.
*/
public function edit_attribute_term_fields( $term, $taxonomy ) {
$attr = flatsome_swatches()->get_attribute( $taxonomy );
$value = get_term_meta( $term->term_id, $attr->attribute_type, true );
do_action( 'flatsome_product_attribute_term_fields', $attr->attribute_type, $value, 'edit' );
}
/**
* Print HTML of custom field on attribute term add/edit screens.
*
* @param string $type Attribute type.
* @param string $value Field value.
* @param string $form The form kind.
*/
public function attribute_term_field( $type, $value, $form ) {
// Return if this is a default attribute type.
if ( in_array( $type, array( 'select', 'text' ), true ) ) {
return;
}
$name = $type;
// phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped
printf( '<%s class="form-field term-%s-wrap">%s<label for="term-%s">%s</label>%s',
'edit' == $form ? 'tr' : 'div',
esc_attr( $type ),
'edit' == $form ? '<th>' : '',
esc_attr( $type ),
esc_html( flatsome_swatches()->get_attribute_types()[ $type ] ),
'edit' == $form ? '</th><td>' : ''
);
// phpcs:enable WordPress.Security.EscapeOutput.OutputNotEscaped
switch ( $type ) {
case 'ux_image':
$image = $value ? wp_get_attachment_image_src( $value ) : '';
$image = $image ? $image[0] : WC()->plugin_url() . '/assets/images/placeholder.png';
?>
<div class="ux-swatches-term-image-thumbnail" style="margin: 8px 0;">
<img src="<?php echo esc_url( $image ); ?>" width="60px" height="60px" alt=""/>
</div>
<div style="line-height:35px;">
<input type="hidden" class="ux-swatches-term-image" name="<?php echo esc_attr( $name ); ?>" value="<?php echo esc_attr( $value ); ?>" />
<button type="button" class="ux-swatches-upload-image-button button"><?php esc_html_e( 'Select image', 'flatsome' ); ?></button>
<button type="button" class="ux-swatches-remove-image-button button <?php echo $value ? '' : 'hidden'; ?>"><?php esc_html_e( 'Remove', 'flatsome' ); ?></button>
</div>
<p>The swatch image.</p>
<?php
break;
case 'ux_color':
$color = flatsome_swatches()->parse_ux_color_term_meta( $value );
$value = $color['color'];
$value_2 = '';
$name .= '[]';
if ( $color['color_2'] ) $value_2 = $color['color_2'];
?>
<input type="text" id="term-<?php echo esc_attr( $type ); ?>" class="ux-color-field" name="<?php echo esc_attr( $name ); ?>" value="<?php echo esc_attr( $value ); ?>" />
<span class="ux-swatches-add-color button" data-content="<?php echo $value_2 ? '+' : '-'; ?>"><?php echo $value_2 ? '-' : '+'; ?></span><br>
<input type="text" id="term-<?php echo esc_attr( $type ); ?>_2" class="ux-swatches-bicolor-picker ux-color-field" name="<?php echo esc_attr( $name ); ?>" value="<?php echo esc_attr( $value_2 ); ?>"/>
<p>The swatch color.</p>
<?php
break;
case 'ux_label':
?>
<input type="text" id="term-<?php echo esc_attr( $type ); ?>" name="<?php echo esc_attr( $name ); ?>" value="<?php echo esc_attr( $value ); ?>" />
<p>The swatch text.</p>
<?php
break;
}
echo 'edit' == $form ? '</td></tr>' : '</div>';
}
/**
* Save term meta.
*
* @param int $term_id Term ID.
* @param int $tt_id Term taxonomy ID.
* @param string $taxonomy Taxonomy slug.
*/
public function save_term_meta( $term_id, $tt_id, $taxonomy ) {
foreach ( flatsome_swatches()->get_attribute_types() as $type => $label ) {
if ( isset( $_POST[ $type ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
$value = wp_unslash( $_POST[ $type ] ); // phpcs:ignore WordPress.Security.NonceVerification, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
if ( is_array( $value ) ) {
$array_values = array_filter( $value );
if ( empty( $array_values ) ) {
$value = '';
} else {
$value = implode( ',', $array_values );
}
}
update_term_meta( $term_id, $type, sanitize_text_field( $value ) );
}
}
}
/**
* Attribute added.
*
* @param int $id Added attribute ID.
* @param array $data Attribute data.
*/
public function add_attribute_options( $id, $data ) {
// phpcs:disable WordPress.Security.NonceVerification
$values = array(
'swatch_size' => isset( $_POST['attribute_swatch_size'] ) ? sanitize_text_field( wp_unslash( $_POST['attribute_swatch_size'] ) ) : '',
'swatch_shape' => isset( $_POST['attribute_swatch_shape'] ) ? sanitize_text_field( wp_unslash( $_POST['attribute_swatch_shape'] ) ) : '',
'swatch_variation_images' => isset( $_POST['attribute_swatch_variation_images'] ) ? isset( $_POST['attribute_swatch_variation_images'] ) : '',
);
// phpcs:enable WordPress.Security.NonceVerification
add_option( "flatsome_product_attribute-{$id}", $values );
}
/**
* Attribute updated.
*
* @param int $id Added attribute ID.
* @param array $data Attribute data.
* @param string $old_slug Attribute old name.
*/
public function update_attribute_options( $id, $data, $old_slug ) {
// phpcs:disable WordPress.Security.NonceVerification
$values = array(
'swatch_size' => isset( $_POST['attribute_swatch_size'] ) ? sanitize_text_field( wp_unslash( $_POST['attribute_swatch_size'] ) ) : '',
'swatch_shape' => isset( $_POST['attribute_swatch_shape'] ) ? sanitize_text_field( wp_unslash( $_POST['attribute_swatch_shape'] ) ) : '',
'swatch_variation_images' => isset( $_POST['attribute_swatch_variation_images'] ) ? isset( $_POST['attribute_swatch_variation_images'] ) : '',
);
// phpcs:enable WordPress.Security.NonceVerification
update_option( "flatsome_product_attribute-{$id}", $values );
}
/**
* Attribute deleted.
*
* @param int $id Added attribute ID.
*/
public function delete_attribute_option( $id ) {
delete_option( "flatsome_product_attribute-{$id}" );
}
/**
* Add thumbnail column to column list
*
* @param array $columns Columns.
*
* @return array
*/
public function add_attribute_columns( $columns ) {
if ( empty( $columns ) ) {
return $columns;
}
$new_columns = array();
$new_columns['cb'] = $columns['cb'];
$new_columns['ux_swatch_preview'] = __( 'Value', 'flatsome' );
unset( $columns['cb'] );
return array_merge( $new_columns, $columns );
}
/**
* Render thumbnail HTML depend on attribute type
*
* @param string $content Current content.
* @param string $column Column name.
* @param string|int $term_id Term ID.
*/
public function add_attribute_column_content( $content, $column, $term_id ) {
if ( 'ux_swatch_preview' === $column ) {
$classes = array( 'ux-swatch-preview' );
$attr = flatsome_swatches()->get_attribute( $_REQUEST['taxonomy'] ); // phpcs:ignore
$value = get_term_meta( $term_id, $attr->attribute_type, true );
switch ( $attr->attribute_type ) {
case 'ux_color':
$color_classes = array( 'ux-swatch__color' );
$color = flatsome_swatches()->parse_ux_color_term_meta( $value );
$classes[] = 'ux-swatch--color';
$color_classes[] = $color['class'];
printf( '<div class="%s"><span class="%s" style="%s"></span></div>',
esc_attr( implode( ' ', $classes ) ),
esc_attr( implode( ' ', $color_classes ) ),
$color['style'] // phpcs:ignore WordPress.Security.EscapeOutput
);
break;
case 'ux_image':
$image = $value ? wp_get_attachment_image_src( $value ) : '';
$image = $image ? $image[0] : WC()->plugin_url() . '/assets/images/placeholder.png';
$classes[] = 'ux-swatch--image';
printf( '<div class="%s"><img class="ux-swatch__img" src="%s" width="30px" height="30px" alt=""></div>',
esc_attr( implode( ' ', $classes ) ),
esc_url( $image )
);
break;
case 'ux_label':
$classes[] = 'ux-swatch--label';
printf( '<div class="%s"><span class="ux-swatch__text">%s</span></div>',
esc_attr( implode( ' ', $classes ) ),
esc_html( $value )
);
break;
}
}
}
}

View File

@@ -0,0 +1,762 @@
<?php
/**
* Swatches frontend class.
*
* @package Flatsome\Extensions
*/
namespace Flatsome\Extensions;
defined( 'ABSPATH' ) || exit;
/**
* Class Swatches_Frontend
*
* @package Flatsome\Extensions
*/
class Swatches_Frontend {
/**
* The single instance of the class
*
* @var Swatches_Frontend
*/
protected static $instance = null;
/**
* Main instance
*
* @return Swatches_Frontend
*/
public static function instance() {
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Swatches_Frontend constructor.
*/
public function __construct() {
add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
add_action( 'wp_head', array( $this, 'add_css' ), 110 );
add_filter( 'woocommerce_dropdown_variation_attribute_options_html', array( $this, 'get_swatch_html' ), 100, 2 );
add_filter( 'flatsome_swatch_html', array( $this, 'swatch_html' ), 5, 4 );
// Add swatches in loop.
add_action( 'woocommerce_before_shop_loop_item_title', array( $this, 'box_swatch_list' ) );
// Layered nav.
add_filter( 'woocommerce_layered_nav_term_html', array( $this, 'layered_nav_term_html' ), 10, 4 );
// Handle cache.
add_action( 'save_post', array( $this, 'cache_clear_save_post' ) );
add_action( 'woocommerce_before_product_object_save', array( $this, 'cache_clear_product_object_save' ) );
add_filter( 'pre_set_theme_mod_swatches', array( $this, 'cache_clear_all' ), 10, 2 );
add_filter( 'pre_set_theme_mod_swatches_box_attribute', array( $this, 'cache_clear_all' ), 10, 2 );
add_filter( 'pre_update_option_woocommerce_thumbnail_image_width', array( $this, 'cache_clear_all' ), 10, 2 );
add_filter( 'pre_update_option_woocommerce_thumbnail_cropping', array( $this, 'cache_clear_all' ), 10, 2 );
}
/**
* Enqueue scripts and stylesheets
*/
public function enqueue_scripts() {
wp_enqueue_style( 'flatsome-swatches-frontend', get_template_directory_uri() . '/assets/css/extensions/flatsome-swatches-frontend.css', array(), flatsome_swatches()->version );
wp_style_add_data( 'flatsome-swatches-frontend', 'rtl', 'replace' );
wp_enqueue_script( 'flatsome-swatches-frontend', get_template_directory_uri() . '/assets/js/extensions/flatsome-swatches-frontend.js', array(
'jquery',
'flatsome-js',
), flatsome_swatches()->version, true );
}
/**
* Add extension CSS.
*/
public function add_css() {
ob_start();
?>
<?php if ( get_theme_mod( 'swatches_layout' ) === 'stacked' ) : ?>
.variations th,
.variations td {
display: block;
}
.variations .label {
display: flex;
align-items: center;
}
.variations .label label {
margin: .5em 0;
}
.ux-swatch-selected-value {
font-weight: normal;
font-size: .9em;
}
<?php endif; ?>
<?php if ( get_theme_mod( 'swatches_color_selected', \Flatsome_Default::COLOR_SECONDARY ) !== \Flatsome_Default::COLOR_SECONDARY ) : ?>
.variations_form .ux-swatch.selected {
box-shadow: 0 0 0 0.1rem <?php echo get_theme_mod( 'swatches_color_selected' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>;
}
<?php endif; ?>
<?php if ( get_theme_mod( 'swatches_box_color_selected', \Flatsome_Default::COLOR_SECONDARY ) !== \Flatsome_Default::COLOR_SECONDARY ) : ?>
.ux-swatches-in-loop .ux-swatch.selected {
box-shadow: 0 0 0 0.1rem <?php echo get_theme_mod( 'swatches_box_color_selected' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>;
}
<?php endif; ?>
<?php
$output = ob_get_clean();
if ( ! $output ) {
return;
}
$css = '<style id="flatsome-swatches-css" type="text/css">';
$css .= $output;
$css .= '</style>';
echo flatsome_minify_css( $css ); // phpcs:ignore WordPress.Security.EscapeOutput
}
/**
* The swatches HTML for an attribute.
*
* @param string $html The dropdown variation attribute options html.
* @param array $args Args.
*
* @return string
* @uses swatch_html()
*/
public function get_swatch_html( $html, $args ) {
$swatch_types = flatsome_swatches()->get_attribute_types();
$attr = flatsome_swatches()->get_attribute( $args['attribute'] );
// Abort if this is normal attribute.
if ( empty( $attr ) || ! array_key_exists( $attr->attribute_type, $swatch_types ) ) {
return $html;
}
$swatches = '';
$options = $args['options'];
$product = $args['product'];
$attribute = $args['attribute'];
$classes = array( 'ux-swatches', "ux-swatches-attribute-{$attr->attribute_type}" );
$selector_classes = array( 'variation-selector', "variation-select-{$attr->attribute_type}" );
$args['tooltip'] = get_theme_mod( 'swatches_tooltip', 1 );
$attr_options = flatsome_swatches()->get_attribute_option_by_name( $args['attribute'] );
$available_variations = $product->get_available_variations();
$args['swatches'] = $this->get_swatches( $attribute, $options, $available_variations, $this->use_variation_images( $attr_options ) );
$args['swatches']['use_variation_image'] = $this->use_variation_images( $attr_options );
if ( isset( $attr_options['swatch_size'] ) && ! empty( $attr_options['swatch_size'] ) ) {
$classes[] = 'ux-swatches--' . $attr_options['swatch_size'];
}
if ( isset( $attr_options['swatch_shape'] ) && ! empty( $attr_options['swatch_shape'] ) ) {
$classes[] = 'ux-swatches--' . $attr_options['swatch_shape'];
}
if ( empty( $options ) && ! empty( $product ) && ! empty( $attribute ) ) {
$attributes = $product->get_variation_attributes();
$options = $attributes[ $attribute ];
}
if ( array_key_exists( $attr->attribute_type, $swatch_types ) ) {
if ( ! empty( $options ) && $product && taxonomy_exists( $attribute ) ) {
$terms = wc_get_product_terms( $product->get_id(), $attribute, array( 'fields' => 'all' ) );
foreach ( $terms as $term ) {
if ( ! in_array( $term->slug, $options, true ) ) {
continue;
}
$swatches .= apply_filters( 'flatsome_swatch_html', '', $term, $attr->attribute_type, $args );
}
}
if ( ! empty( $swatches ) ) {
$selector_classes[] = 'hidden';
$swatches = '<div class="' . esc_attr( implode( ' ', $classes ) ) . '" data-attribute_name="attribute_' . esc_attr( $attribute ) . '">' . $swatches . '</div>';
$html = '<div class="' . esc_attr( implode( ' ', $selector_classes ) ) . '">' . $html . '</div>' . $swatches;
}
}
return $html;
}
/**
* Single swatch HTML.
*
* @param string $html HTML.
* @param \WP_Term $term WP Term object.
* @param string $type Attribute type.
* @param array $args Args.
*
* @return string
*/
public function swatch_html( $html, $term, $type, $args ) {
$selected = sanitize_title( $args['selected'] ) == $term->slug ? 'selected' : '';
$name = esc_html( apply_filters( 'woocommerce_variation_option_name', $term->name ) );
$img_size = apply_filters( 'flatsome_swatch_image_size', 'woocommerce_gallery_thumbnail', $term );
$classes = array( 'ux-swatch' );
$thumb = '';
$tooltip = '';
if ( ! empty( $args['tooltip'] ) ) {
$classes[] = 'tooltip';
$tooltip = $term->description ? $term->description : $name;
}
// Gather variation image if one is available.
if ( $args['swatches']['use_variation_image'] ) {
$options_flipped = array_flip( $args['options'] );
$key = $options_flipped[ $term->slug ];
if ( isset( $args['swatches'][ $key ]['variation_id'] ) && $args['swatches'][ $key ]['variation_id'] ) {
$thumb_id = get_post_thumbnail_id( $args['swatches'][ $key ]['variation_id'] );
if ( $thumb_id ) {
$thumb = wp_get_attachment_image( $thumb_id, $img_size, false, array(
'class' => "ux-swatch__img attachment-$img_size size-$img_size",
'alt' => $name,
) );
$type = 'variation-image';
}
}
}
switch ( $type ) {
case 'ux_color':
$color_classes = array( 'ux-swatch__color' );
$value = get_term_meta( $term->term_id, 'ux_color', true );
$color = flatsome_swatches()->parse_ux_color_term_meta( $value );
if ( $color['class'] ) $color_classes[] = $color['class'];
$html = sprintf( '<div class="%s ux-swatch--color swatch-%s %s" data-value="%s" data-name="%s" title="%s"><span class="%s" style="%s"></span><span class="ux-swatch__text">%s</span></div>',
implode( ' ', $classes ),
esc_attr( $term->slug ),
$selected,
esc_attr( $term->slug ),
$name,
esc_attr( $tooltip ),
implode( ' ', $color_classes ),
$color['style'],
$name
);
break;
case 'ux_image':
$image_id = get_term_meta( $term->term_id, 'ux_image', true );
$image = '';
if ( $image_id ) {
$image = wp_get_attachment_image( $image_id, $img_size, false, array(
'class' => "ux-swatch__img attachment-$img_size size-$img_size",
'alt' => $name,
) );
}
$html = sprintf( '<div class="%s ux-swatch--image %s" data-value="%s" data-name="%s" title="%s">%s<span class="ux-swatch__text">%s</span></div>',
implode( ' ', $classes ),
$selected,
esc_attr( $term->slug ),
$name,
esc_attr( $tooltip ),
$image ? $image : wc_placeholder_img( $img_size ),
$name
);
break;
case 'variation-image':
$html = sprintf(
'<div class="%s ux-swatch--image %s" data-value="%s" data-name="%s" title="%s">%s<span class="ux-swatch__text">%s</span></div>',
implode( ' ', $classes ),
$selected,
esc_attr( $term->slug ),
$name,
esc_attr( $tooltip ),
$thumb ? $thumb : wc_placeholder_img( $img_size ),
$name
);
break;
case 'ux_label':
$label = get_term_meta( $term->term_id, 'ux_label', true );
$label = $label ? $label : $name;
$html = sprintf(
'<div class="%s ux-swatch--label %s" data-value="%s" data-name="%s" title="%s"><span class="ux-swatch__text">%s</span></div>',
implode( ' ', $classes ),
$selected,
esc_attr( $term->slug ),
$name,
esc_attr( $tooltip ),
esc_html( $label )
);
break;
}
return $html;
}
/**
* Get an array of types and values for each attribute.
*
* @param array $attributes Attributes.
*
* @return array
*/
public function get_variation_attributes_types( $attributes ) {
global $wc_product_attributes;
$types = array();
$defined_attr = flatsome_swatches()->get_attribute_types();
if ( ! empty( $attributes ) ) {
foreach ( $attributes as $name => $options ) {
$current = isset( $wc_product_attributes[ $name ] ) ? $wc_product_attributes[ $name ] : false;
if ( $current && array_key_exists( $current->attribute_type, $defined_attr ) ) {
$types[ $name ] = $current->attribute_type;
}
}
}
return $types;
}
/**
* Create a list of swatches on product boxes.
*
* @return string
*/
public function box_swatch_list() {
global $product;
$attribute = apply_filters( 'flatsome_swatches_box_attribute', $this->get_swatches_box_attribute(), $product );
if ( ! $attribute ) {
return;
}
$attribute_name = $attribute->slug;
if ( ! $attribute_name || empty( $attribute_name ) ) {
return;
}
$id = $product->get_id();
if ( empty( $id ) || ! $product->is_type( 'variable' ) ) {
return;
}
$attr_options = flatsome_swatches()->get_attribute_option_by_name( $attribute_name );
$cache_enabled = apply_filters( 'flatsome_swatches_cache_enabled', true );
$transient = 'flatsome_swatches_cache_' . $id;
$classes = array( 'ux-swatches', 'ux-swatches-in-loop' );
if ( $cache_enabled ) {
$available_variations = get_transient( $transient );
} else {
$available_variations = array();
}
if ( ! $available_variations ) {
/** @var $product \WC_Product_Variable */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort
$available_variations = $product->get_available_variations();
if ( $cache_enabled ) {
set_transient( $transient, $available_variations, apply_filters( 'flatsome_swatches_cache_time', WEEK_IN_SECONDS ) );
}
}
if ( empty( $available_variations ) ) {
return;
}
$swatches_to_show = $this->get_option_variations( $attribute_name, $available_variations );
if ( empty( $swatches_to_show ) ) {
return;
}
$html = '';
if ( get_theme_mod( 'swatches_box_shape' ) ) {
$classes[] = 'ux-swatches--' . get_theme_mod( 'swatches_box_shape' );
}
if ( get_theme_mod( 'swatches_box_size' ) ) $classes[] = 'ux-swatches--' . get_theme_mod( 'swatches_box_size' );
// Start ux-swatches.
$html .= '<div class="' . implode( ' ', $classes ) . '">';
// Order.
$terms = wc_get_product_terms( $product->get_id(), $attribute_name, array( 'fields' => 'slugs' ) );
$swatches_to_show_tmp = $swatches_to_show;
$swatches_to_show = array();
foreach ( $terms as $id => $slug ) {
if ( ! isset( $swatches_to_show_tmp[ $slug ] ) ) {
continue;
}
$swatches_to_show[ $slug ] = $swatches_to_show_tmp[ $slug ];
}
$index = 0;
$swatch_count = count( $swatches_to_show );
$swatch_limit = (int) get_theme_mod( 'swatches_box_limit', 5 );
$swatch_layout = get_theme_mod( 'swatches_box_layout' );
foreach ( $swatches_to_show as $key => $swatch ) {
$swatch_classes = array( 'ux-swatch' );
$color_classes = array( 'ux-swatch__color' );
$term = get_term_by( 'slug', $key, $attribute_name );
$name = esc_html( apply_filters( 'woocommerce_variation_option_name', $term->name ) );
$img_size = apply_filters( 'flatsome_swatch_image_size', 'woocommerce_gallery_thumbnail', $term );
$data = array();
$type_tmp = $attribute->type;
$swatch_inner_html = '';
if ( $this->use_variation_images( $attr_options ) && isset( $swatch['image_src'] ) ) {
$thumb_id = get_post_thumbnail_id( $swatch['variation_id'] );
if ( $thumb_id ) {
$type_tmp = 'variation-image';
$swatch_classes[] = 'ux-swatch--image';
$swatch_inner_html = wp_get_attachment_image( $thumb_id, $img_size, false, array(
'class' => "ux-swatch__img attachment-$img_size size-$img_size",
'alt' => $name,
) );
}
}
switch ( $type_tmp ) {
case 'ux_color':
$color = flatsome_swatches()->parse_ux_color_term_meta( $swatch['ux_color'] );
if ( $color['class'] ) $color_classes[] = $color['class'];
$swatch_classes[] = 'ux-swatch--color';
$swatch_inner_html = '<span class="' . implode( ' ', $color_classes ) . '" style="' . $color['style'] . '"></span>';
break;
case 'ux_image':
$swatch_classes[] = 'ux-swatch--image';
$swatch_inner_html = wp_get_attachment_image( $swatch['ux_image'], $img_size, false, array(
'class' => "ux-swatch__img attachment-$img_size size-$img_size",
'alt' => $name,
) );
break;
case 'ux_label':
$swatch_classes[] = 'ux-swatch--label';
break;
}
if ( isset( $swatch['image_src'] ) ) {
$data['data-image-src'] = $swatch['image_src'];
$data['data-image-srcset'] = $swatch['image_srcset'];
$data['data-image-sizes'] = $swatch['image_sizes'];
if ( ! $swatch['is_in_stock'] ) {
$swatch_classes[] = 'out-of-stock';
}
}
$data['data-attribute_name'] = 'attribute_' . $attribute_name;
$data['data-value'] = $term->slug;
if ( $swatch_layout === 'limit' && $swatch_count > $swatch_limit ) {
if ( $index >= $swatch_limit ) {
$swatch_classes[] = 'hidden';
}
if ( $index === $swatch_limit ) {
$html .= '<span class="ux-swatches__limiter">+' . ( $swatch_count - $swatch_limit ) . '</span>';
}
}
$html .= '<div class="' . esc_attr( implode( ' ', $swatch_classes ) ) . '" ' . flatsome_html_atts( $data ) . '>' . $swatch_inner_html . '<span class="ux-swatch__text">' . $name . '</span></div>';
$index ++;
}
$html .= '</div>';
echo $html; // phpcs:ignore WordPress.Security.EscapeOutput
}
/**
* Get the attribute to show in loops by user preference.
*
* @return \stdClass|null The attribute object.
*/
private function get_swatches_box_attribute() {
if ( ! get_theme_mod( 'swatches_box_attribute' ) ) {
return null;
}
$attr = wc_get_attribute( get_theme_mod( 'swatches_box_attribute' ) );
if ( $attr ) {
return $attr;
}
return null;
}
/**
* Get custom variation option data.
*
* @param string $attribute_name Attribute name.
* @param array $available_variations The available variation.
* @param mixed $option Whether or not to get only one variation by attribute option value.
*
* @return array|null
*/
private function get_option_variations( $attribute_name, $available_variations, $option = false ) {
$swatches_to_show = array();
foreach ( $available_variations as $key => $variation ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
$option_variation = array();
$attr_key = 'attribute_' . $attribute_name;
if ( ! isset( $variation['attributes'][ $attr_key ] ) ) {
return null;
}
$val = $variation['attributes'][ $attr_key ];
if ( ! empty( $variation['image']['src'] ) ) {
$option_variation = array(
'variation_id' => $variation['variation_id'],
'is_in_stock' => $variation['is_in_stock'],
'image_src' => $variation['image']['thumb_src'],
'image_srcset' => wp_get_attachment_image_srcset( $variation['image_id'], 'woocommerce_thumbnail' ),
'image_sizes' => wp_get_attachment_image_sizes( $variation['image_id'], 'woocommerce_thumbnail' ),
);
}
// Get only one variation by attribute option value.
if ( $option ) {
if ( $val != $option ) {
continue;
} else {
return $option_variation;
}
} else {
// Or get all variations with swatches to show by attribute name.
$swatch = $this->get_swatch( $attribute_name, $val );
// If key already exist don't replace existing with sequential match.
if ( ! array_key_exists( $val, $swatches_to_show ) ) {
$swatches_to_show[ $val ] = array_merge( $swatch, $option_variation );
}
}
}
return $swatches_to_show;
}
/**
* Get single swatch values.
*
* @param string $attr_name Attribute name.
* @param string|int $value Search for this term value.
*
* @return array
*/
private function get_swatch( $attr_name, $value ) {
$swatches = array();
$color = '';
$image = '';
$label = '';
$term = get_term_by( 'slug', $value, $attr_name );
if ( is_object( $term ) ) {
$color = get_term_meta( $term->term_id, 'ux_color', true );
$image = get_term_meta( $term->term_id, 'ux_image', true );
$label = get_term_meta( $term->term_id, 'ux_label', true );
}
if ( $color != '' ) {
$swatches['ux_color'] = $color;
}
if ( $image != '' ) {
$swatches['ux_image'] = $image;
}
if ( $label != '' ) {
$swatches['ux_label'] = $label;
}
return $swatches;
}
/**
* Get swatches.
*
* @param string $attr_name Attribute name.
* @param array $options Attribute options.
* @param array $available_variations Available variations.
* @param bool $use_variation_images Whether or not to search and collect the variation image. Default false.
*
* @return array
*/
private function get_swatches( $attr_name, $options, $available_variations, $use_variation_images = false ) {
$swatches = array();
foreach ( $options as $key => $value ) {
$swatch = $this->get_swatch( $attr_name, $value );
if ( ! empty( $swatch ) ) {
if ( $available_variations && $use_variation_images ) {
$variation = $this->get_option_variations( $attr_name, $available_variations, $value );
if ( $variation ) {
$swatch = array_merge( $swatch, $variation );
}
}
$swatches[ $key ] = $swatch;
}
if ( empty( $swatch ) && $available_variations && $use_variation_images ) {
$variation = $this->get_option_variations( $attr_name, $available_variations, $value );
if ( $variation ) {
$swatch = array_merge( $swatch, $variation );
$swatches[ $key ] = $swatch;
}
}
}
return $swatches;
}
/**
* Check if given attribute options wants to display variation images.
*
* @param array $options The attribute options array.
*
* @return bool Whether or not to us variation images.
*/
private function use_variation_images( $options ) {
if ( ! $options ) {
return false;
}
if ( isset( $options['swatch_variation_images'] ) && $options['swatch_variation_images'] ) {
return true;
}
return false;
}
/**
* Render swatch value in layered nav.
*
* @param string $term_html Term HTML.
* @param object $term Term.
* @param string $link Link.
* @param string|int $count Count.
*
* @return string
*/
public function layered_nav_term_html( $term_html, $term, $link, $count ) {
$swatch_types = flatsome_swatches()->get_attribute_types();
$attr = flatsome_swatches()->get_attribute( $term->taxonomy );
// Abort if this is normal attribute.
if ( empty( $attr ) || ! array_key_exists( $attr->attribute_type, $swatch_types ) ) {
return $term_html;
}
$classes = array( 'ux-swatch-widget-layered-nav-list__graphic' );
$img_size = apply_filters( 'flatsome_swatch_image_size', 'woocommerce_gallery_thumbnail', $term );
if ( get_theme_mod( 'swatches_box_shape' ) ) {
$classes[] = 'ux-swatches--' . get_theme_mod( 'swatches_box_shape' );
}
switch ( $attr->attribute_type ) {
case 'ux_image':
$image_id = get_term_meta( $term->term_id, 'ux_image', true );
$image = '';
$classes[] = 'ux-swatch--image';
if ( $image_id ) {
$image = wp_get_attachment_image( $image_id, $img_size, false, array(
'class' => "ux-swatch__img attachment-$img_size size-$img_size",
'alt' => $term->name,
) );
}
$swatch = sprintf( '<div class="' . implode( ' ', $classes ) . '">%s</div>',
$image ? $image : wc_placeholder_img( 'woocommerce_gallery_thumbnail' )
);
break;
case 'ux_color':
$color_classes = array( 'ux-swatch__color' );
$value = get_term_meta( $term->term_id, 'ux_color', true );
$color = flatsome_swatches()->parse_ux_color_term_meta( $value );
$classes[] = 'ux-swatch--color';
if ( $color['class'] ) $color_classes[] = $color['class'];
$swatch = sprintf( '<div class="' . implode( ' ', $classes ) . '"><span class="%s" style="%s"></span></div>',
implode( ' ', $color_classes ),
$color['style']
);
break;
default:
return $term_html;
}
return $swatch . $term_html;
}
/**
* Clear cache on save post by ID.
*
* @param int $post_id Post ID.
*/
public function cache_clear_save_post( $post_id ) {
if ( ! apply_filters( 'flatsome_swatches_cache_enabled', true ) ) {
return;
}
$transient = 'flatsome_swatches_cache_' . $post_id;
delete_transient( $transient );
}
/**
* Clear cache on product object save by ID.
*
* @param \WC_Product $product Product object.
*/
public function cache_clear_product_object_save( $product ) {
if ( ! apply_filters( 'flatsome_swatches_cache_enabled', true ) ) {
return;
}
$post_id = $product->get_id();
$transient = 'flatsome_swatches_cache_' . $post_id;
delete_transient( $transient );
}
/**
* Clear all cache.
*
* @param string $new_value The new value of the theme modification.
* @param string $old_value The current value of the theme modification.
*
* @return mixed
*/
public function cache_clear_all( $new_value, $old_value ) {
if ( $new_value !== $old_value ) {
flatsome_swatches()->cache_clear();
}
return $new_value;
}
}

View File

@@ -0,0 +1,227 @@
<?php
/**
* Swatches main class.
*
* @package Flatsome\Extensions
*/
namespace Flatsome\Extensions;
defined( 'ABSPATH' ) || exit;
/**
* Class Swatches
*
* @package Flatsome\Extensions
*/
final class Swatches {
/**
* The single instance of the class.
*
* @var Swatches
*/
protected static $instance = null;
/**
* Custom attribute types.
*
* @var array
*/
private $types;
/**
* Holds extension version.
*
* @var string
*/
public $version;
/**
* Swatches constructor.
*/
public function __construct() {
$this->types = array(
'ux_color' => esc_html__( 'UX Color', 'flatsome' ),
'ux_image' => esc_html__( 'UX Image', 'flatsome' ),
'ux_label' => esc_html__( 'UX Label', 'flatsome' ),
);
$theme = wp_get_theme( get_template() );
$this->version = $theme->get( 'Version' );
$this->includes();
add_action( 'init', array( $this, 'init' ) );
}
/**
* Include core files.
*/
public function includes() {
if ( is_admin() ) {
require_once dirname( __FILE__ ) . '/class-swatches-admin.php';
}
require_once dirname( __FILE__ ) . '/class-swatches-frontend.php';
}
/**
* Initialize.
*/
public function init() {
add_filter( 'product_attributes_type_selector', array( $this, 'add_attribute_types' ) );
if ( is_admin() ) {
$this->admin();
}
if ( ! is_admin() || ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ) {
$this->frontend();
}
}
/**
* Add extra custom attribute types.
*
* @param array $types The default types.
*
* @return array
*/
public function add_attribute_types( $types ) {
$types = array_merge( $types, $this->types );
return $types;
}
/**
* Get custom attribute types.
*
* @return array
*/
public function get_attribute_types() {
return $this->types;
}
/**
* Get product attribute option data by ID.
*
* @param string|int $id The ID.
*
* @return false|mixed
*/
public function get_attribute_option( $id ) {
return get_option( "flatsome_product_attribute-{$id}" );
}
/**
* Get product attribute option data by name.
*
* @param string $attribute The attribute name.
*
* @return false|mixed
*/
public function get_attribute_option_by_name( $attribute ) {
$id = wc_attribute_taxonomy_id_by_name( $attribute );
return get_option( "flatsome_product_attribute-{$id}" );
}
/**
* Get attribute's properties.
*
* @param string $taxonomy Taxonomy.
*
* @return object
*/
public function get_attribute( $taxonomy ) {
global $wpdb;
$attr = substr( $taxonomy, 3 );
$attr = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}woocommerce_attribute_taxonomies WHERE attribute_name = %s;", $attr ) );
return $attr;
}
/**
* Parses the term value specifically for ux_color. Checks and
* returns parsed data for single and dual color value(s).
*
* @param string $value The term meta value.
*
* @return string[]
*/
public function parse_ux_color_term_meta( $value ) {
$data = array(
'color' => '',
'color_2' => '',
'class' => '',
'style' => '',
);
$colors = explode( ',', $value );
$data['color'] = $colors[0];
if ( count( $colors ) > 1 ) {
$data['color_2'] = $colors[1];
$data['style'] = "--swatch-color: $colors[0]; --swatch-color-secondary: $colors[1];";
$data['class'] = 'ux-swatch__color--dual-color';
} else {
$data['style'] = "--swatch-color: $colors[0]";
$data['class'] = 'ux-swatch__color--single-color';
}
return $data;
}
/**
* Clears all cache.
*/
public function cache_clear() {
global $wpdb;
$wpdb->query( "DELETE FROM {$wpdb->options} WHERE `option_name` LIKE ('%\_transient\_flatsome\_swatches%');" );
$wpdb->query( "DELETE FROM {$wpdb->options} WHERE `option_name` LIKE ('%\_transient\_timeout\_flatsome\_swatches%');" );
}
/**
* Main instance.
*
* @return Swatches
*/
public static function instance() {
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Instance of admin.
*
* @return Swatches_Admin
*/
public function admin() {
return Swatches_Admin::instance();
}
/**
* Instance of frontend.
*
* @return Swatches_Frontend
*/
public function frontend() {
return Swatches_Frontend::instance();
}
}
/**
* Main instance.
*
* @return Swatches
*/
function flatsome_swatches() {
return Swatches::instance();
}

View File

@@ -0,0 +1,13 @@
<?php // @codingStandardsIgnoreLine
namespace Flatsome\Extensions;
defined( 'ABSPATH' ) || exit;
global $extensions_url;
require $extensions_url . '/flatsome-swatches/includes/class-swatches.php';
flatsome_swatches();

View File

@@ -0,0 +1,51 @@
<?php
/**
* Add Button to Grid Tools
*/
function flatsome_lightbox_button() {
if ( get_theme_mod( 'disable_quick_view', 0 ) ) {
return;
}
// Run Quick View Script.
wp_enqueue_script( 'wc-add-to-cart-variation' );
global $product;
echo ' <a class="quick-view" data-prod="' . $product->get_id() . '" href="#quick-view">' . __( 'Quick View', 'flatsome' ) . '</a>';
}
add_action( 'flatsome_product_box_actions', 'flatsome_lightbox_button', 50 );
/* Add stuff to lightbox */
add_action( 'woocommerce_single_product_lightbox_summary', 'woocommerce_template_single_price', 10 );
add_action( 'woocommerce_single_product_lightbox_summary', 'woocommerce_template_single_excerpt', 20 );
add_action( 'woocommerce_single_product_lightbox_summary', 'woocommerce_template_single_add_to_cart', 30 );
add_action( 'woocommerce_before_single_product_lightbox_summary', 'woocommerce_show_product_sale_flash', 20 );
if ( get_theme_mod( 'product_info_meta', 1 ) ) {
add_action( 'woocommerce_single_product_lightbox_summary', 'woocommerce_template_single_meta', 40 );
}
/**
* Quick View Output
*/
function flatsome_quickview() {
global $post, $product;
$prod_id = $_POST["product"];
$post = get_post( $prod_id );
$product = wc_get_product( $prod_id );
ob_start();
add_filter( 'woocommerce_add_to_cart_form_action', '__return_empty_string' ); // Disable form action that causes redirect.
wc_get_template( 'content-single-product-lightbox.php' );
remove_filter( 'woocommerce_add_to_cart_form_action', '__return_empty_string' );
$output = ob_get_contents();
ob_end_clean();
echo $output;
die();
}
add_action( 'wp_ajax_flatsome_quickview', 'flatsome_quickview' );
add_action( 'wp_ajax_nopriv_flatsome_quickview', 'flatsome_quickview' );