Файл: cobisja/BootHelp/src/ListGroup.php
Строк: 353
<?php
/**
 * BootHelp - PHP Helpers for Bootstrap
 *
 * (The MIT License)
 *
 * Copyright (c) 2015 Jorge Cobis <jcobis@gmail.com / http://twitter.com/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;
/**
 * Generates an HTML block tag that follows the Bootstrap documentation
 * on how to display <strong>List group</strong> component.
 *
 * See {@link http://getbootstrap.com/components/#list-group} for more information.
 */
class ListGroup extends Base
{
    /**
     * Initializes the Carousel instance.
     *
     * @param mixed    $content_or_options_with_block the display options for List group.
     * @param Callable $block Block to generate customized List group 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);
            }
        }
        $list_group = $this->buildListGroup($content, $options);
        $this->setHtmlObject($list_group->getHtmlObject());
    }
    /**
     * Builds the List group component.
     * 
     * @param mixed $content List group's content
     * @param array $options List group's options to customize the component generation.
     * 
     * @return ContentTag a ContentTag instance that represents the List group.
     */
    private function buildListGroup($content, array $options)
    {
        !is_array($content) ? $content = [$content] : null;
        $items_options = Base::getAndUnset('items', $options);
        $linked = Base::getAndUnset('linked', $options);
        
        $list_group_items = $this->buildListGroupItems($content, $items_options, $linked);
        $list_group_main_tag = $linked ? 'div': 'ul';
        Base::appendClass($options, 'list-group');
        
        return new ContentTag($list_group_main_tag, $list_group_items, $options);
    }
    
    /**
     * Builds the List group content.
     * 
     * @param array  $content list group items.
     * @param array  $options list group options.
     * @param bolean $linked true if the list group items are linked, false otherwise.
     * 
     * @return array ContentTag array that represents the list group items.
     */
    private function buildListGroupItems(array $content, $options, $linked)
    {
        $list_group_items = [];
        is_null($options) ? $options = [] : null;
        $klass = Base::getAndUnset('class', $options);
        
        foreach ($content as $item) {
            $item_base_options = ['class'=>'list-group-item'];
            Base::appendClass($item_base_options, $klass);
            $item = $this->getRealContent($item);
            $item_content = $item['content'];
            Base::appendClass($item_base_options, Base::getAndUnset('class', $item['options']));
            $item_options = array_merge($item_base_options, $item['options']);
            
            $item_options = array_merge($options, $this->configItemClass($item_options));
            $item_type = $this->configItemType($linked, $item_options);
            
            $list_group_items[] = new ContentTag($item_type, $item_content, $item_options);
        }
        
        return $list_group_items;
    }
    
    /**
     * Parses a list group item to get its real content and associated options.
     * 
     * @param mixed $item list group item.
     * 
     * @return array list group item information.
     */
    private function getRealContent($item)
    {
        if (!is_array($item)) {
            $real_content = ['content'=>(is_callable($item) ? call_user_func($item) : $item), 'options'=>[]];
        } else {
            $item_title = $item_content = null;
            $title = Base::getAndUnset('title', $item);
            $content = Base::getAndUnset('content', $item);
            
            if (is_null($title) && is_null($content)) {
                $item_content = array_shift($item);
                $real_content =  ['content'=>$item_content, 'options'=>$item];
            } else {
                if (!is_null($title)) {
                    $item_title = is_callable($title) ? call_user_func($title) : new ContentTag('h4', $title);
                }
                if (!is_null($content)) {
                    $item_content = is_callable($content) ? call_user_func($content) : new ContentTag('p', $content);
                }
                
                $real_content = ['content'=>array_filter([$item_title, $item_content], 'strlen'), 'options'=>$item];
            }
        }
        
        return $real_content;
    }
    
    /**
     * Config the Item class according 'active', 'disabled' and 'context' options.
     * 
     * @param array $item_options item options.
     * 
     * @return array Item options with class attribute set.
     */
    private function configItemClass($item_options)
    {
        if (Base::getAndUnset('active', $item_options)) {
            Base::appendClass($item_options, 'active');
        }
        if (Base::getAndUnset('disabled', $item_options)) {
            Base::appendClass($item_options, 'disabled');
        }
        
        $context = Base::getAndUnset('context', $item_options);
        
        if ($context) {
            Base::appendClass($item_options, 'list-group-item-' . $context);
        }
        
        return $item_options;
    }
    
    /**
     * Config the tag should be used to generate the list group item.
     * 
     * @param boolean $linked true if list group items are linked, false otherwise.
     * @param string  $item_options item options.
     * 
     * @return string tag to be used to generate the list group item.
     */
    private function configItemType($linked, &$item_options)
    {
        if ($linked) {
            $type = 'a';
            !isset($item_options['href']) ? $item_options['href'] = '#' : null;
        } else {
            $type = 'li';
        }
        
        return $type;
    }
}