Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | |
100.00% |
1 / 1 |
|
100.00% |
5 / 5 |
CRAP | |
100.00% |
100 / 100 |
TwbBundleDropDown | |
100.00% |
1 / 1 |
|
100.00% |
5 / 5 |
58 | |
100.00% |
100 / 100 |
__invoke(array $aDropdownOptions = null) | |
100.00% |
1 / 1 |
2 | |
100.00% |
1 / 1 |
|||
render(array $aDropdownOptions) | |
100.00% |
1 / 1 |
5 | |
100.00% |
10 / 10 |
|||
renderToggle(array $aDropdownOptions) | |
100.00% |
1 / 1 |
13 | |
100.00% |
21 / 21 |
|||
renderListItems(array $aDropdownOptions) | |
100.00% |
1 / 1 |
17 | |
100.00% |
27 / 27 |
|||
renderItem($aItemOptions) | |
100.00% |
1 / 1 |
21 | |
100.00% |
41 / 41 |
<?php | |
namespace TwbBundle\View\Helper; | |
class TwbBundleDropDown extends \Zend\Form\View\Helper\AbstractHelper{ | |
const TYPE_ITEM_HEADER = 'header'; | |
const TYPE_ITEM_DIVIDER = '---'; | |
const TYPE_ITEM_LINK = 'link'; | |
/** | |
* @var string | |
*/ | |
private static $dropdownContainerFormat = '<div %s>%s</div>'; | |
/** | |
* @var string | |
*/ | |
private static $dropdownToggleFormat = '<a %s>%s <b class="caret"></b></a>'; | |
/** | |
* @var string | |
*/ | |
private static $dropdownListFormat = '<ul %s>%s</ul>'; | |
/** | |
* @var string | |
*/ | |
private static $dropdownItemContainerFormat = '<li %s>%s</li>'; | |
/** | |
* @var string | |
*/ | |
private static $dropdownItemFormats = array( | |
self::TYPE_ITEM_LINK => '<a %s>%s</a>' | |
); | |
/** | |
* @param array $aDropdownOptions | |
* @return \TwbBundle\View\Helper\TwbBundleDropDown|string | |
*/ | |
public function __invoke(array $aDropdownOptions = null){ | |
return $aDropdownOptions?$this->render($aDropdownOptions):$this; | |
} | |
/** | |
* Render dropdown markup | |
* @param array $aDropdownOptions | |
* @throws \LogicException | |
* @return string | |
*/ | |
public function render(array $aDropdownOptions){ | |
// ### Dropdown container attributes ### | |
if(empty($aDropdownOptions['attributes']))$aDropdownOptions['attributes'] = array('class' => 'dropdown'); | |
else{ | |
if(!is_array($aDropdownOptions['attributes']))throw new \LogicException('"attributes" option expects an array, "'.gettype($aDropdownOptions['attributes']).'" given'); | |
if(empty($aDropdownOptions['attributes']['class']))$aDropdownOptions['attributes']['class'] = 'dropdown'; | |
elseif(!preg_match('/(\s|^)dropdown(\s|$)/',$aDropdownOptions['attributes']['class']))$aDropdownOptions['attributes']['class'] .= ' dropdown'; | |
} | |
// ### Render dropdown ### | |
return sprintf( | |
self::$dropdownContainerFormat, | |
//Container attributes | |
$this->createAttributesString($aDropdownOptions['attributes']), | |
//Toggle | |
$this->renderToggle($aDropdownOptions). | |
//List items | |
$this->renderListItems($aDropdownOptions) | |
); | |
} | |
/** | |
* Render dropdown toggle markup | |
* @param array $aDropdownOptions | |
* @throws \LogicException | |
* @return string | |
*/ | |
public function renderToggle(array $aDropdownOptions){ | |
// ### Dropdown toggle ### | |
if(empty($aDropdownOptions['label']))$aDropdownOptions['label'] = ''; | |
elseif(!is_scalar($aDropdownOptions['label']))throw new \InvalidArgumentException('"label" option expects a scalar value, "'.gettype($aDropdownOptions['label']).'" given'); | |
elseif(($oTranslator = $this->getTranslator()))$aDropdownOptions['label'] = $oTranslator->translate($aDropdownOptions['label'],$this->getTranslatorTextDomain()); | |
//Dropdown toggle attributes | |
//Class | |
if(empty($aDropdownOptions['toggle_attributes']))$aDropdownOptions['toggle_attributes'] = array('class' => 'sr-only dropdown-toggle'); | |
else{ | |
if(!is_array($aDropdownOptions['toggle_attributes']))throw new \InvalidArgumentException('"toggle_attributes" option expects an array, "'.gettype($aDropdownOptions['toggle_attributes']).'" given'); | |
if(empty($aDropdownOptions['toggle_attributes']['class']))$aDropdownOptions['toggle_attributes']['class'] = 'sr-only dropdown-toggle'; | |
else{ | |
if(!preg_match('/(\s|^)sr-only(\s|$)/',$aDropdownOptions['toggle_attributes']['class']))$aDropdownOptions['toggle_attributes']['class'] .= ' sr-only'; | |
if(!preg_match('/(\s|^)dropdown-toggle(\s|$)/',$aDropdownOptions['toggle_attributes']['class']))$aDropdownOptions['toggle_attributes']['class'] .= ' dropdown-toggle'; | |
} | |
} | |
//data-toggle | |
if(empty($aDropdownOptions['toggle_attributes']['data-toggle']))$aDropdownOptions['toggle_attributes']['data-toggle'] = 'dropdown'; | |
//Role | |
if(empty($aDropdownOptions['toggle_attributes']['role']))$aDropdownOptions['toggle_attributes']['role'] = 'button'; | |
//Href | |
if(empty($aDropdownOptions['toggle_attributes']['href']))$aDropdownOptions['toggle_attributes']['href'] = '#'; | |
//Id | |
if(!empty($aDropdownOptions['name']))$aDropdownOptions['toggle_attributes']['id'] = $aDropdownOptions['name']; | |
$aValidTagAttributes = $this->validTagAttributes; | |
$this->validTagAttributes = array('href' => true); | |
$sAttributeString = $this->createAttributesString($aDropdownOptions['toggle_attributes']); | |
$this->validTagAttributes = $aValidTagAttributes; | |
return sprintf( | |
self::$dropdownToggleFormat, | |
//Toggle attributes | |
$sAttributeString, | |
//Toggle label | |
$this->getEscapeHtmlHelper()->__invoke($aDropdownOptions['label']) | |
); | |
} | |
/** | |
* Render dropdown list items markup | |
* @param array $aDropdownOptions | |
* @throws \LogicException | |
* @return string | |
*/ | |
public function renderListItems(array $aDropdownOptions){ | |
if(!isset($aDropdownOptions['items']))throw new \LogicException(__METHOD__.' expects "items" option'); | |
if(!is_array($aDropdownOptions['items']))throw new \LogicException('"items" option expects an array, "'.gettype($aDropdownOptions['items']).'" given'); | |
// ### Dropdown list attributes ### | |
//Class | |
if(empty($aDropdownOptions['list_attributes']))$aDropdownOptions['list_attributes'] = array('class' => 'dropdown-menu'); | |
else{ | |
if(!is_array($aDropdownOptions['list_attributes']))throw new \LogicException('"list_attributes" option expects an array, "'.gettype($aDropdownOptions['list_attributes']).'" given'); | |
if(empty($aDropdownOptions['list_attributes']['class']))$aDropdownOptions['list_attributes']['class'] = 'dropdown-menu'; | |
elseif(!preg_match('/(\s|^)dropdown-menu(\s|$)/',$aDropdownOptions['list_attributes']['class']))$aDropdownOptions['list_attributes']['class'] .= ' dropdown-menu'; | |
} | |
//Role | |
if(empty($aDropdownOptions['list_attributes']['role']))$aDropdownOptions['list_attributes']['role'] = 'menu'; | |
//Id | |
if(!empty($aDropdownOptions['name']))$aDropdownOptions['list_attributes']['aria-labelledby'] = $aDropdownOptions['name']; | |
// ### Items ### | |
$sItems = ''; | |
foreach($aDropdownOptions['items'] as $sKey => $aItemOptions){ | |
if(!is_array($aItemOptions)){ | |
if(!is_scalar($aItemOptions))throw new \LogicException('item option expects an array or a scalar value, "'.gettype($aItemOptions).'" given'); | |
$aItemOptions = $aItemOptions === self::TYPE_ITEM_DIVIDER | |
//Divider | |
?array('type' => self::TYPE_ITEM_DIVIDER) | |
//Link | |
:array( | |
'label' => $aItemOptions, | |
'type' => self::TYPE_ITEM_LINK, | |
'item_attributes' => array('href' => is_string($sKey)?$sKey:null) | |
); | |
} | |
else{ | |
if(!isset($aItemOptions['label']))$aItemOptions['label'] = is_string($sKey)?$sKey:null; | |
if(!isset($aItemOptions['type']))$aItemOptions['type'] = self::TYPE_ITEM_LINK; | |
} | |
$sItems .= $this->renderItem($aItemOptions).PHP_EOL; | |
} | |
return sprintf( | |
self::$dropdownListFormat, | |
//List attributes | |
$this->createAttributesString($aDropdownOptions['list_attributes']), | |
//Items | |
$sItems | |
); | |
} | |
/** | |
* Render dropdown list item markup | |
* @param array $aItemOptions | |
* @throws \LogicException | |
* @return string | |
*/ | |
protected function renderItem($aItemOptions){ | |
if(empty($aItemOptions['type']))throw new \LogicException(__METHOD__.' expects "type" option'); | |
//Item container attributes | |
if(empty($aItemOptions['attributes']))$aItemOptions['attributes'] = array(); | |
elseif(!is_array($aItemOptions['attributes']))throw new \LogicException('"attributes" option expects an array, "'.gettype($aItemOptions['attributes']).'" given'); | |
//Role | |
if(empty($aItemOptions['attributes']['role']))$aItemOptions['attributes']['role'] = 'presentation'; | |
$sItemContent = ''; | |
switch($aItemOptions['type']){ | |
case self::TYPE_ITEM_HEADER: | |
//Define item container "header" class | |
if(empty($aItemOptions['attributes']['class']))$aItemOptions['attributes']['class'] = 'dropdown-header'; | |
elseif(!preg_match('/(\s|^)dropdown-header(\s|$)/',$aItemOptions['attributes']['class']))$aItemOptions['attributes']['class'] .= ' dropdown-header'; | |
//Header label | |
if(empty($aItemOptions['label']))throw new \LogicException('"'.$aItemOptions['type'].'" item expects "label" option'); | |
if(!is_scalar($aItemOptions['label']))throw new \LogicException('"label" option expect scalar value, "'.gettype($aItemOptions['label']).'" given'); | |
elseif(($oTranslator = $this->getTranslator()))$aItemOptions['label'] = $oTranslator->translate($aItemOptions['label'],$this->getTranslatorTextDomain()); | |
$sItemContent = $this->getEscapeHtmlHelper()->__invoke($aItemOptions['label']); | |
break; | |
case self::TYPE_ITEM_DIVIDER: | |
//Define item container "divider" class | |
if(empty($aItemOptions['attributes']['class']))$aItemOptions['attributes']['class'] = 'divider'; | |
elseif(!preg_match('/(\s|^)divider(\s|$)/',$aItemOptions['attributes']['class']))$aItemOptions['attributes']['class'] .= ' divider'; | |
$sItemContent = ''; | |
break; | |
case self::TYPE_ITEM_LINK: | |
if(empty($aItemOptions['label']))throw new \LogicException('"'.$aItemOptions['type'].'" item expects "label" option'); | |
if(!is_scalar($aItemOptions['label']))throw new \LogicException('"label" option expect scalar value, "'.gettype($aItemOptions['label']).'" given'); | |
elseif(($oTranslator = $this->getTranslator()))$aItemOptions['label'] = $oTranslator->translate($aItemOptions['label'],$this->getTranslatorTextDomain()); | |
//Item attributes | |
//Role | |
if(empty($aItemOptions['item_attributes']['role']))$aItemOptions['item_attributes']['role'] = 'menuitem'; | |
//Tab index | |
if(!isset($aItemOptions['item_attributes']['tabindex']))$aItemOptions['item_attributes']['tabindex'] = '-1'; | |
//Href | |
if(!isset($aItemOptions['item_attributes']['href']))$aItemOptions['item_attributes']['href'] = '#'; | |
$aValidTagAttributes = $this->validTagAttributes; | |
$this->validTagAttributes = array('href' => true); | |
$sAttributeString = $this->createAttributesString($aItemOptions['item_attributes']); | |
$this->validTagAttributes = $aValidTagAttributes; | |
$sItemContent = sprintf( | |
self::$dropdownItemFormats[self::TYPE_ITEM_LINK], | |
$sAttributeString, | |
$this->getEscapeHtmlHelper()->__invoke($aItemOptions['label']) | |
); | |
break; | |
} | |
return sprintf( | |
self::$dropdownItemContainerFormat, | |
$this->createAttributesString($aItemOptions['attributes']), | |
$sItemContent | |
); | |
} | |
} |