Файл: cobisja/BootHelp/src/Carousel.php
Строк: 541
<?php
/**
* The MIT License
*
* Copyright 2015 cobisja.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
namespace cobisjaBootHelp;
use cobisjaBootHelpBase;
use cobisjaBootHelpHelpersContentTag;
use cobisjaBootHelpIcon;
/**
* Generates an HTML block tag that follows the Bootstrap documentation
* on how to display <strong>Carousel</strong> component.
*
* See {@link http://getbootstrap.com/javascript/#carousel} for more information.
*/
class Carousel extends Base
{
/**
* Initializes the Carousel instance.
*
* @param mixed $content_or_options_with_block the display options for the carousel.
* @param Callable $block Block to generate customized carousel content.
*/
public function __construct($content_or_options_with_block, $block = null)
{
$num_args = $this->getFunctionNumArgs(func_get_args());
$content_block = is_callable(func_get_arg($num_args-1)) ? func_get_arg($num_args-1) : null;
if (1 === $num_args) {
$options = [];
$content = is_null($content_block) ? $content_or_options_with_block : call_user_func($content_block);
} else {
if (is_array($content_or_options_with_block) && is_array($block)) {
$content = $content_or_options_with_block;
$options = $block;
} else {
$options = $content_or_options_with_block;
$content = call_user_func($content_block);
}
}
Base::setCarouselId(
isset($options['id']) ? Base::getAndUnset('id', $options) : ('carousel-' . (string)(mt_rand(1, pow(10, 7))))
);
$carousel = $this->buildCarousel($content, $options);
Base::setCarouselId('');
$this->setHtmlObject($carousel->getHtmlObject());
}
/**
* Builds the Carousel component.
*
* @param mixed $content Carousel's content
* @param array $options Carousel's options to customize the component generation.
*
* @return ContentTag a ContentTag instance that represents the Carousel.
*/
private function buildCarousel($content, array $options)
{
$indicators = null;
$controls = [];
$active_item = isset($options['active_item']) ? Base::getAndUnset('active_item', $options) : 0;
$indicators_options = Base::getAndUnset('indicators_options', $options);
$content_options = Base::getAndUnset('content_options', $options);
$controls_options = Base::getAndUnset('controls_options', $options);
$show_indicators = Base::getAndUnset('show_indicators', $options);
$show_controls = Base::getAndUnset('show_controls', $options);
$items_number = count($content);
Base::appendClass($content_options, 'carousel-inner');
$content_options['role'] = 'listbox';
(is_null($show_indicators) || !is_null($show_indicators) && $show_indicators)
&& ($indicators = $this->buildCarouselIndicators($items_number, $indicators_options, $active_item));
(is_null($show_controls) || !is_null($show_controls) && $show_controls)
&& ($controls = $this->buildCarouselControls($controls_options));
$content = $this->buildCarouselItems($content, $content_options, $active_item);
Base::appendClass($options, 'carousel slide');
$options['id'] = Base::getCarouselId();
$options['data-ride'] = 'carousel';
$carousel = new ContentTag('div', $options, function () use ($indicators, $content, $controls) {
return array_filter(array_merge([$indicators, $content], $controls), 'strlen');
});
return $carousel;
}
/**
* Builds the Carousel's controls.
*
* @param int $quantity number of controls that must be generated.
* @param array $options options to be passed to the control's html tags.
* @param int $active_control control that will be initially active.
*
* @return ContentTag ContenTag instance that represents the Carousel's controls.
*/
private function buildCarouselIndicators($quantity, $options, $active_control)
{
Base::appendClass($options, 'carousel-indicators');
$indicators_object = new ContentTag('ol', $options, function () use ($quantity, $active_control) {
$indicators = [];
for ($idx=0; $idx < $quantity; $idx++) {
$indicator = new ContentTag(
'li',
'',
[
'data-target'=>'#' . Base::getCarouselId(),
'data-slide-to'=>(string)$idx,
'class'=> $idx === $active_control ? 'active' : null
]
);
array_push($indicators, $indicator);
}
return $indicators;
});
return $indicators_object;
}
/**
* Builds the Carousel's content
*
* @param array $content array of items associates to the Carousel's content.
* @param array $options options to be passed to the html tags associated with Carousel's content.
* @param int $active_item_id active item that wiil be initially active.
*
* @return ContentTag ContentTag instance that represents the Carousel's content.
*/
private function buildCarouselItems(array $content, array $options, $active_item_id)
{
$carousel_items = [];
for ($item_id = 0; $item_id < count($content); $item_id++) {
$element = $this->getItemAndCaption($content[$item_id]);
$item = $element['item'];
$caption = $element['caption'];
$item_class = 'item' . ($item_id === $active_item_id ? ' active' : '');
!is_null($caption) ? $caption = new ContentTag('div', $caption, ['class'=>'carousel-caption']) : null;
$carousel_items[] = new ContentTag(
'div',
(!is_null($caption) ? [$item, $caption] : $item),
['class'=>$item_class]
);
}
$carousel_content = new ContentTag('div', $carousel_items, $options);
return $carousel_content;
}
/**
* Builds the Carouse's nav controls.
*
* @param array $options options to be passed to the html tags associated with Carousel's nav controls.
*
* @return array Left and Right navigation controls.
*/
private function buildCarouselControls($options)
{
$href = '#' . Base::getCarouselId();
$default_left_control_options = [
'caption'=>'Previous',
'icon'=>'chevron-left',
'href'=>$href,
'role'=>'button',
'data-slide'=>'prev'
];
$default_right_control_options = [
'caption'=>'Next',
'icon'=>'chevron-right',
'href'=>$href,
'role'=>'button',
'data-slide'=>'next'
];
$left_control_options = isset($options['left']) ? Base::getAndUnset('left', $options) : [];
$right_control_options = isset($options['right']) ? Base::getAndUnset('right', $options) : [];
Base::appendClass($left_control_options, 'left carousel-control');
Base::appendClass($right_control_options, 'right carousel-control');
Base::setOptions($default_left_control_options, $left_control_options);
Base::setOptions($default_right_control_options, $right_control_options);
return [
$this->buildControl($left_control_options),
$this->buildControl($right_control_options)
];
}
/**
* Helper method to build icon associated with the Carousel's nav control.
*
* @param array $options options that allows to customized the nav control generation.
*
* @return ContentTag ContenTag instance that represents the Carousel's nav control.
*/
private function buildControl(array $options)
{
$icon = Base::getAndUnset('icon', $options);
$caption = Base::getAndUnset('caption', $options);
$control = new ContentTag(
'a',
$options,
function () use ($icon, $caption) {
return [
new Icon($icon, ['aria-hidden'=>true]),
new ContentTag('span', $caption, ['class'=>'sr-only'])
];
}
);
return $control;
}
/**
* Helper method to get an Carousel's item and its possible caption.
*
* @param mixed $item_object item data.
*
* @return array associativa array with the Carousel's item and its caption information.
*/
private function getItemAndCaption($item_object)
{
$element=[];
if (!is_array($item_object)) {
$element = [
'item'=> is_callable($item_object) ? call_user_func($item_object) : $item_object,
'caption'=>null
];
} else {
$item = is_callable($item_object[0]) ? call_user_func($item_object[0]) : $item_object[0];
if (!isset($item_object['caption'])) {
$caption = null;
} else {
if (is_callable($item_object['caption'])) {
$caption = call_user_func($item_object['caption']);
} else {
if (is_array($item_object['caption'])) {
$title = Base::getAndUnset('title', $item_object['caption']);
$content = Base::getAndUnset('content', $item_object['caption']);
} else {
$title = null;
$content = $item_object['caption'];
}
$caption = array_filter(
[
!is_null($title) ? new ContentTag('h3', $title) : null,
!is_null($content) ? new ContentTag('p', $content) : null
],
'strlen'
);
}
}
$element = ['item'=>$item, 'caption'=>$caption];
}
return $element;
}
}