Вход Регистрация
Файл: 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;
    }
}
Онлайн: 4
Реклама