Current File : /home/aventura/www/site/wp-content/plugins/victheme_core/wordpress/element/wpcarousel.php |
<?php
/**
* Class for extending WpLoop to build a carousel element
* using slick carousel javascript instead of an isotope element.
*
* WP_QUERY OBJECT
* ===============
* 1. Direct WP_Query object injection via context
* with key query
*
* 2. Fallback to global $wp_query on non single page
* if no Direct WP Query Object defined and no
* queryArgs defined
*
* 3. Build a new WP_Query Object if it cannot use
* Direct or Global WP_Query object, provided
* user specify the WP_Query object args via
* queryArgs context.
*
* Without valid object, the class will not produce any markups
*
* AJAX (not yet implemented)
* ====
* This class is compatible with wp-ajax.js to invoke the integration
* witht wp-ajax, it will need the :
*
* $context['ajax'] = true;
*
* GRIDS
* =====
*
* The class will provide columns object for processing
* bootstrap object grids defined in context into a valid
* css class for the bootstrap grids.
*
* The object can be accessed via $this->getContext('object.columns')->getClass()
* when in template or directly injected to object when template is specified
* as a valid VTCore_Html_Base object (or its children).
*
*
* SLICK CAROUSEL
* ==============
*
* This class is capable to invoking slick carousel js directly if user
* specifies the correct carousel options via context['slick']
*
* TEMPLATING
* ==========
*
* This class supports :
* 1. Pure php file as template
* 2. VTCore_Html_Base child objects as template
* 3. class name for valid VTCore_Html_Base as template
*
* user should define the template in the context :
*
* $context['template']['items'] = the template for items inside the loop
* $context['template']['empty'] = the template when loop found no posts.
*
*
* @author jason.xie@victheme.com
*
*/
class VTCore_Wordpress_Element_WpCarousel
extends VTCore_Wordpress_Element_WpLoop {
protected $context = array(
'type' => 'div',
'attributes' => array(
'class' => array(
'wp-carousel',
//'slick-carousel', // Autoload via js
),
),
// Slick options
'slick' => array(
'accessibility' => true,
'autoplay' => false,
'autoplaySpeed' => 3000,
'arrows' => true,
'dots' => true,
'centerMode' => false,
'centerPadding' => '50px',
'cssEase' => 'ease',
'draggable' => true,
'fade' => false,
'easing' => 'linear',
'infinite' => true,
//'lazyLoad' => 'ondemand',
'pauseOnHover' => true,
//'slidesToShow' => 1, // disabling this will invoke auto format based on grid
'slidesToScroll' => 1,
'speed' => 300,
'swipe' => true,
'touchMove' => true,
'touchThreshold' => 5,
'vertical' => false,
'variableWidth' => false,
'adaptiveHeight' => false,
'lazyloader' => false,
),
'breakpoints' => array(
'mobile' => 768,
'tablet' => 990,
'small' => 1199,
),
// Direct markup inject via markup context
'contents' => array(),
'content_element' => array(
'type' => 'div',
'attributes' => array(
'class' => array('slick-items'),
),
),
// WpLoop Contexts
'id' => false,
'query' => false,
'queryMain' => false,
'queryArgs' => array(),
// @todo Implement Slick carousel ajax to wploop integration
'ajax' => false,
'ajaxData' => array(
'ajax-mode' => 'selfData',
'ajax-object' => 'carousel',
'ajax-loading-text' => 'Loading...',
'ajax-target' => false,
'ajax-action' => 'vtcore_ajax_framework',
'ajax-value' => 'carousel',
'ajax-queue' => array(
'replace',
),
),
'grids' => array(
'columns' => array(
'mobile' => 12,
'tablet' => 6,
'small' => 4,
'large' => 3,
),
),
'template' => array(
'items' => false,
'empty' => false,
),
'custom' => array(),
'loopQuery' => array(),
// Build data-filter with related taxonomy terms as value
'filters' => false,
// Allow user to disable the automated build
// process items via context args.
'process' => array(
'query' => true,
'filter' => true,
'isotope' => true,
'ajax' => true,
'loop' => true,
'queryform' => false,
),
'convert_grids' => true,
);
protected $booleans = array(
'slick.accessibility',
'slick.autoplay',
'slick.arrows',
'slick.dots',
'slick.centerMode',
'slick.draggable',
'slick.fade',
'slick.infinite',
'slick.pauseOnHover',
'slick.swipe',
'slick.touchMove',
'slick.vertical',
'slick.variableWidth',
'slick.adaptiveHeight',
'slick.lazyloader',
);
protected $int = array(
'slick.slidesToShow',
'slick.slidesToScroll',
'slick.speed',
'slick.touchTreshold',
'slick.autoplaySpeed',
);
/**
* Overriding parent
* @param array $context
*/
public function buildObject($context) {
$object = new VTCore_Wordpress_Objects_Array($context);
// Convert to booleans
foreach ($this->booleans as $key) {
if ($object->get($key)) {
$object->mutate($key, filter_var($object->get($key), FILTER_VALIDATE_BOOLEAN));
}
}
foreach ($this->int as $key) {
if ($object->get($key)) {
$object->mutate($key, (int) $object->get($key));
}
}
$context = $object->extract();
// Populate $this->context
parent::buildObject($context);
$this->processBooleans();
}
/**
* Preparing for slick carousel
*/
protected function prepareSlick() {
VTCore_Wordpress_Utility::loadAsset('jquery-slick');
$this->addClass('slick-carousel');
// Fade mode can only slide a single items and not compatible
// with centerMode, variable width and the grid system!
if ($this->getContext('slick.fade')) {
$this->addContext('slick.slidesToScroll', 1);
$this->addContext('slick.slidesToShow', 1);
$this->addContext('slick.centerMode', false);
$this->removeContext('grids');
$this->addContext('slick.variableWidth', false);
}
// Adaptive height can only show a single slide
if ($this->getContext('slick.adaptiveHeight')) {
$this->addContext('slick.slidesToShow', 1);
$this->addContext('slick.slidesToScroll', 1);
}
// Auto format slides to show
if ($this->getContext('grids.columns.large')
&& !$this->getContext('slick.slidesToShow')
&& !$this->getContext('slick.fade')) {
if ($this->getContext('convert_grids')) {
$this->addContext('slick.slidesToShow', (int) 12 / $this->getContext('grids.columns.large'));
}
else {
$this->addContext('slick.slidesToShow', (int) $this->getContext('grids.columns.large'));
}
// Automated grid cannot use variable width!
$this->addContext('slick.variableWidth', false);
}
// Auto format responsiveness
if (!$this->getContext('slick.resposive')
&& !$this->getContext('slick.fade')
&& $this->getContext('grids.columns')) {
$responsive = array();
foreach ($this->getContext('grids.columns') as $mediaSize => $size) {
if (!$this->getContext('breakpoints.' . $mediaSize)) {
continue;
}
$object = new stdClass();
$object->breakpoint = $this->getContext('breakpoints.' . $mediaSize);
$object->settings = new stdClass();
if ($this->getContext('convert_grids')) {
$object->settings->slidesToShow = (int) 12 / $size;
}
else {
$object->settings->slidesToShow = (int) $size;
}
// Don't use center mode on small screen
if ($size == 12 && $mediaSize == 'mobile') {
$object->settings->centerMode = false;
}
$responsive[] = $object;
}
if (!empty($responsive)) {
$this->addContext('slick.responsive', $responsive);
}
}
if ($this->getContext('convert_grids')) {
$this->addContext('content_element.grids', $this->getContext('grids'));
}
$this->removeContext('grids');
$this->addData('settings', $this->getContext('slick'));
if ($this->getContext('ajax')) {
$this->addData('ajax-marker', array(
'slick' => true,
'id' => $this->getContext('id'),
'mode' => 'wp-loop',
));
}
$this->addAdditionalStylingClass();
return $this;
}
/**
* Overriding parent method
*
* This is where the main logic invocation
* for building the loop object.
*
* It is advisable to extends other method
* when trying to customize this object and
* leave this main logic intact if possible.
*
* @see VTCore_Html_Base::buildElement()
*/
public function buildElement() {
parent::buildElement();
$this->prepareSlick();
foreach ($this->getContext('contents') as $content) {
$this->addSlide($content);
}
return $this;
}
/**
* Helper function for detecting template.
* Detection sequence :
* 1. Valid PHP file - include the file
* 2. Valid HTML Object - direct include
* 3. Valid HTML class - build new object and direct include
*
* Overriding parent method to use addSlide instead of addChildren
* method for injecting the carousel slide.
*/
protected function buildTemplate($template) {
global $post;
if (is_string($template)
&& strpos($template, '.php') !== false) {
// Template can access $this for retrieiving context
// and information.
ob_start();
include VTCore_Wordpress_Utility::locateTemplate($template);
$content = ob_get_clean();
if ($this->getContext('slick.lazyloader')) {
$content = str_replace(' srcset="', ' data-srcset="', $content);
$content = str_replace(' src="', ' data-lazy="', $content);
}
$this->addSlide($content, $post);
}
// Direct inject if template is VTCore object
elseif (is_object($template)
&& $template instanceof VTCore_Html_Base) {
$this->addSlide($template, $post);
}
// Try to build a new object if the template
// is a class name.
elseif (class_exists($template, true)) {
$this->addSlide(new $template(array('grids' => $this->getContext('grids'))), $post);
}
return $this;
}
/**
* Allow user to inject slide object or context array
* after the object created
*
* @param $object
* @return $this
*/
public function addSlide($object, $post = false) {
if (is_array($object)) {
$object = new VTCore_VTCore_Bootstrap_Element_BsElement($object);
}
$arguments = new VTCore_Wordpress_Objects_Array($this->getContext('content_element'));
$filters = (array) $this->getContext('filters');
if (!empty($filters) && isset($post->ID)) {
$filterTax = new VTCore_Wordpress_Objects_Array();
foreach ($filters as $taxonomy) {
$terms = wp_get_post_terms((int) $post->ID, trim($taxonomy));
if (!is_wp_error($terms)) {
foreach ($terms as $term) {
$filterTax->add('terms.' . $term->term_id, $term->term_id);
}
}
}
if ($filterTax->get('terms')) {
$arguments->add('data.filter', implode(', ',$filterTax->get('terms')));
}
}
$this
->addChildren(new VTCore_Bootstrap_Element_BsElement($arguments->extract()))
->lastChild()
->addChildren($object);
$arguments = null;
unset($arguments);
return $this;
}
/**
* Additional class for styling purposes only.
*/
protected function addAdditionalStylingClass() {
if ($this->getContext('slick.centerMode')) {
$this->addClass('slick-centermode');
}
if ($this->getContext('slick.variableWidth')) {
$this->addClass('slick-variablewidth');
}
}
}