2020-12-04 16:08:11 +01:00
< ? php
/**
* Bootstrap Tabs helper
* Options :
* [ style ]
2021-01-13 14:16:52 +01:00
* - fill : Should the navigation items occupy all available space
2020-12-11 08:52:11 +01:00
* - justify : Should the navigation items be justified ( accept : [ 'center' , 'end' ])
* - pills : Should the navigation items be pills
* - vertical : Should the navigation bar be placed on the left side of the content
* - vertical - size : Specify how many boostrap ' s `cols` should be used for the navigation ( only used when `vertical` is true )
2020-12-04 16:08:11 +01:00
* - card : Should the navigation be placed in a bootstrap card
2021-01-13 14:16:52 +01:00
* - header - variant : The bootstrap variant to be used for the card header
* - body - variant : The bootstrap variant to be used for the card body
2020-12-04 16:08:11 +01:00
* - nav - class : additional class to add to the nav container
* - content - class : additional class to add to the content container
* [ data ]
* - data : contains the data for the tabs and content
* {
* 'navs' : [{ nav - item }, { nav - item }, ... ],
* 'content' : [{ nav - content }, { nav - content }, ... ]
* }
*
* # Usage:
* echo $this -> Bootstrap -> Tabs ([
* 'pills' => true ,
* 'card' => true ,
* 'data' => [
* 'navs' => [
* 'tab1' ,
* [ 'text' => 'tab2' , 'active' => true ],
* [ 'html' => '<b>tab3</b>' , 'disabled' => true ],
* ],
* 'content' => [
* 'body1' ,
* '<i>body2</i>' ,
* '~body3~'
* ]
* ]
* ]);
*/
namespace App\View\Helper ;
use Cake\View\Helper ;
2021-06-12 11:57:49 +02:00
use Cake\Utility\Hash ;
2021-03-10 09:27:17 +01:00
use Cake\Utility\Inflector ;
2020-12-04 16:08:11 +01:00
use Cake\Utility\Security ;
use InvalidArgumentException ;
class BootstrapHelper extends Helper
{
2021-06-12 11:57:49 +02:00
public $helpers = [ 'FontAwesome' ];
2020-12-04 16:08:11 +01:00
public function tabs ( $options )
{
$bsTabs = new BootstrapTabs ( $options );
return $bsTabs -> tabs ();
}
2021-02-22 15:47:30 +01:00
public function alert ( $options )
{
$bsAlert = new BoostrapAlert ( $options );
return $bsAlert -> alert ();
}
2021-02-22 16:38:55 +01:00
public function table ( $options , $data )
{
2021-07-06 12:34:53 +02:00
$bsTable = new BoostrapTable ( $options , $data , $this );
2021-02-22 16:38:55 +01:00
return $bsTable -> table ();
}
2021-02-23 11:25:20 +01:00
2021-07-06 12:34:53 +02:00
public function listTable ( $options , $data )
{
$bsListTable = new BoostrapListTable ( $options , $data , $this );
return $bsListTable -> table ();
}
2021-02-23 11:25:20 +01:00
public function button ( $options )
{
$bsButton = new BoostrapButton ( $options );
return $bsButton -> button ();
}
2021-03-10 09:28:33 +01:00
2021-09-03 10:48:18 +02:00
public function icon ( $icon , $options = [])
{
$bsIcon = new BoostrapIcon ( $icon , $options );
return $bsIcon -> icon ();
}
2021-03-10 09:28:33 +01:00
public function badge ( $options )
{
$bsBadge = new BoostrapBadge ( $options );
return $bsBadge -> badge ();
}
2021-03-10 09:32:18 +01:00
public function modal ( $options )
{
2021-06-12 11:57:49 +02:00
$bsModal = new BoostrapModal ( $options );
return $bsModal -> modal ();
}
2021-06-21 08:43:37 +02:00
public function card ( $options )
{
$bsCard = new BoostrapCard ( $options );
return $bsCard -> card ();
}
2021-06-12 11:57:49 +02:00
public function progress ( $options )
{
$bsProgress = new BoostrapProgress ( $options );
return $bsProgress -> progress ();
}
public function collapse ( $options , $content )
{
$bsCollapse = new BoostrapCollapse ( $options , $content , $this );
return $bsCollapse -> collapse ();
}
public function progressTimeline ( $options )
{
$bsProgressTimeline = new BoostrapProgressTimeline ( $options , $this );
return $bsProgressTimeline -> progressTimeline ();
2021-03-10 09:32:18 +01:00
}
2021-07-19 14:58:54 +02:00
2021-07-20 11:24:37 +02:00
public function listGroup ( $options , $data )
{
$bsListGroup = new BootstrapListGroup ( $options , $data , $this );
return $bsListGroup -> listGroup ();
}
2021-07-19 14:58:54 +02:00
public function genNode ( $node , $params = [], $content = '' )
{
return BootstrapGeneric :: genNode ( $node , $params , $content );
}
2021-09-17 17:12:33 +02:00
2021-09-13 13:02:33 +02:00
public function switch ( $options )
{
$bsSwitch = new BoostrapSwitch ( $options , $this );
return $bsSwitch -> switch ();
}
2021-02-22 15:47:30 +01:00
}
class BootstrapGeneric
{
2021-03-10 09:27:17 +01:00
public static $variants = [ 'primary' , 'secondary' , 'success' , 'danger' , 'warning' , 'info' , 'light' , 'dark' , 'white' , 'transparent' ];
2021-06-12 11:57:49 +02:00
public static $textClassByVariants = [
2021-09-17 18:12:24 +02:00
'primary' => 'text-light' ,
'secondary' => 'text-light' ,
'success' => 'text-light' ,
'danger' => 'text-light' ,
'warning' => 'text-dark' ,
'info' => 'text-light' ,
'light' => 'text-dark' ,
'dark' => 'text-light' ,
'white' => 'text-dark' ,
'transparent' => 'text-dark'
2021-06-12 11:57:49 +02:00
];
2021-02-22 15:47:30 +01:00
protected $allowedOptionValues = [];
protected $options = [];
protected function checkOptionValidity ()
{
foreach ( $this -> allowedOptionValues as $option => $values ) {
if ( ! isset ( $this -> options [ $option ])) {
throw new InvalidArgumentException ( __ ( 'Option `{0}` should have a value' , $option ));
}
if ( ! in_array ( $this -> options [ $option ], $values )) {
throw new InvalidArgumentException ( __ ( 'Option `{0}` is not a valid option for `{1}`. Accepted values: {2}' , json_encode ( $this -> options [ $option ]), $option , json_encode ( $values )));
}
}
}
2021-07-19 14:58:54 +02:00
public static function genNode ( $node , $params = [], $content = " " )
2021-02-23 08:45:35 +01:00
{
return sprintf ( '<%s %s>%s</%s>' , $node , BootstrapGeneric :: genHTMLParams ( $params ), $content , $node );
}
protected static function openNode ( $node , $params = [])
2021-02-22 15:47:30 +01:00
{
return sprintf ( '<%s %s>' , $node , BootstrapGeneric :: genHTMLParams ( $params ));
}
2021-02-23 08:45:35 +01:00
protected static function closeNode ( $node )
{
return sprintf ( '</%s>' , $node );
}
2021-02-22 15:47:30 +01:00
protected static function genHTMLParams ( $params )
{
$html = '' ;
foreach ( $params as $k => $v ) {
2021-09-18 11:21:50 +02:00
if ( ! empty ( $k ) && ! empty ( $v )) {
$html .= BootstrapGeneric :: genHTMLParam ( $k , $v ) . ' ' ;
}
2021-02-22 15:47:30 +01:00
}
return $html ;
}
protected static function genHTMLParam ( $paramName , $values )
{
if ( ! is_array ( $values )) {
$values = [ $values ];
}
return sprintf ( '%s="%s"' , $paramName , implode ( ' ' , $values ));
}
2021-03-10 09:27:17 +01:00
protected static function genericCloseButton ( $dismissTarget )
{
return BootstrapGeneric :: genNode ( 'button' , [
'type' => 'button' ,
2021-09-17 13:04:37 +02:00
'class' => 'btn-close' ,
'data-bs-dismiss' => $dismissTarget ,
2021-03-10 09:27:17 +01:00
'arial-label' => __ ( 'Close' )
2021-09-17 13:04:37 +02:00
]);
2021-03-10 09:27:17 +01:00
}
2021-06-12 11:57:49 +02:00
protected static function getTextClassForVariant ( $variant )
{
return ! empty ( self :: $textClassByVariants [ $variant ]) ? self :: $textClassByVariants [ $variant ] : 'text-black' ;
}
2020-12-04 16:08:11 +01:00
}
2021-02-22 15:47:30 +01:00
class BootstrapTabs extends BootstrapGeneric
2020-12-04 16:08:11 +01:00
{
private $defaultOptions = [
2020-12-11 08:52:11 +01:00
'fill' => false ,
'justify' => false ,
2020-12-04 16:08:11 +01:00
'pills' => false ,
'vertical' => false ,
'vertical-size' => 3 ,
'card' => false ,
2021-09-28 10:59:57 +02:00
'header-variant' => '' ,
2021-01-13 14:16:52 +01:00
'body-variant' => '' ,
2021-07-06 12:34:53 +02:00
'body-class' => [],
2020-12-04 16:08:11 +01:00
'nav-class' => [],
'nav-item-class' => [],
'content-class' => [],
'data' => [
'navs' => [],
'content' => [],
],
];
private $bsClasses = null ;
function __construct ( $options ) {
2021-02-22 15:47:30 +01:00
$this -> allowedOptionValues = [
'justify' => [ false , 'center' , 'end' ],
'body-variant' => array_merge ( BootstrapGeneric :: $variants , [ '' ]),
2021-09-28 10:59:57 +02:00
'header-variant' => array_merge ( BootstrapGeneric :: $variants , [ '' ]),
2021-02-22 15:47:30 +01:00
];
2020-12-04 16:08:11 +01:00
$this -> processOptions ( $options );
}
public function tabs ()
{
return $this -> genTabs ();
}
private function processOptions ( $options )
{
$this -> options = array_merge ( $this -> defaultOptions , $options );
$this -> data = $this -> options [ 'data' ];
$this -> checkOptionValidity ();
2021-02-22 15:47:30 +01:00
if ( empty ( $this -> data [ 'navs' ])) {
throw new InvalidArgumentException ( __ ( 'No navigation data provided' ));
}
2020-12-04 16:08:11 +01:00
$this -> bsClasses = [
'nav' => [],
'nav-item' => $this -> options [ 'nav-item-class' ],
];
2020-12-11 08:52:11 +01:00
if ( ! empty ( $this -> options [ 'justify' ])) {
$this -> bsClasses [ 'nav' ][] = 'justify-content-' . $this -> options [ 'justify' ];
2020-12-04 16:08:11 +01:00
}
2021-01-13 14:16:52 +01:00
if ( $this -> options [ 'vertical' ] && ! isset ( $options [ 'pills' ]) && ! isset ( $options [ 'card' ])) {
$this -> options [ 'pills' ] = true ;
$this -> options [ 'card' ] = true ;
}
2020-12-04 16:08:11 +01:00
if ( $this -> options [ 'pills' ]) {
$this -> bsClasses [ 'nav' ][] = 'nav-pills' ;
if ( $this -> options [ 'vertical' ]) {
$this -> bsClasses [ 'nav' ][] = 'flex-column' ;
}
if ( $this -> options [ 'card' ]) {
$this -> bsClasses [ 'nav' ][] = 'card-header-pills' ;
}
} else {
$this -> bsClasses [ 'nav' ][] = 'nav-tabs' ;
if ( $this -> options [ 'card' ]) {
$this -> bsClasses [ 'nav' ][] = 'card-header-tabs' ;
}
}
2020-12-11 08:52:11 +01:00
if ( $this -> options [ 'fill' ]) {
2020-12-04 16:08:11 +01:00
$this -> bsClasses [ 'nav' ][] = 'nav-fill' ;
}
2020-12-11 08:52:11 +01:00
if ( $this -> options [ 'justify' ]) {
2020-12-04 16:08:11 +01:00
$this -> bsClasses [ 'nav' ][] = 'nav-justify' ;
}
$activeTab = 0 ;
foreach ( $this -> data [ 'navs' ] as $i => $nav ) {
if ( ! is_array ( $nav )) {
$this -> data [ 'navs' ][ $i ] = [ 'text' => $nav ];
}
if ( ! isset ( $this -> data [ 'navs' ][ $i ][ 'id' ])) {
$this -> data [ 'navs' ][ $i ][ 'id' ] = 't-' . Security :: randomString ( 8 );
}
if ( ! empty ( $nav [ 'active' ])) {
$activeTab = $i ;
}
}
$this -> data [ 'navs' ][ $activeTab ][ 'active' ] = true ;
2021-07-19 14:58:54 +02:00
if ( ! empty ( $this -> options [ 'vertical-size' ]) && $this -> options [ 'vertical-size' ] != 'auto' ) {
$this -> options [ 'vertical-size' ] = $this -> options [ 'vertical-size' ] < 0 || $this -> options [ 'vertical-size' ] > 11 ? 3 : $this -> options [ 'vertical-size' ];
}
2020-12-07 09:52:35 +01:00
2021-01-13 14:16:52 +01:00
$this -> options [ 'header-text-variant' ] = $this -> options [ 'header-variant' ] == 'light' ? 'body' : 'white' ;
$this -> options [ 'header-border-variant' ] = $this -> options [ 'header-variant' ] == 'light' ? '' : $this -> options [ 'header-variant' ];
$this -> options [ 'body-text-variant' ] = $this -> options [ 'body-variant' ] == '' ? 'body' : 'white' ;
2020-12-07 09:52:35 +01:00
if ( ! is_array ( $this -> options [ 'nav-class' ])) {
$this -> options [ 'nav-class' ] = [ $this -> options [ 'nav-class' ]];
}
if ( ! is_array ( $this -> options [ 'content-class' ])) {
$this -> options [ 'content-class' ] = [ $this -> options [ 'content-class' ]];
}
2020-12-04 16:08:11 +01:00
}
private function genTabs ()
{
$html = '' ;
if ( $this -> options [ 'vertical' ]) {
$html .= $this -> genVerticalTabs ();
} else {
$html .= $this -> genHorizontalTabs ();
}
return $html ;
}
private function genHorizontalTabs ()
{
$html = '' ;
if ( $this -> options [ 'card' ]) {
2021-02-23 08:45:35 +01:00
$html .= $this -> openNode ( 'div' , [ 'class' => array_merge ([ 'card' ], [ " border- { $this -> options [ 'header-border-variant' ] } " ])]);
$html .= $this -> openNode ( 'div' , [ 'class' => array_merge ([ 'card-header' ], [ " bg- { $this -> options [ 'header-variant' ] } " , " text- { $this -> options [ 'header-text-variant' ] } " ])]);
2020-12-04 16:08:11 +01:00
}
$html .= $this -> genNav ();
if ( $this -> options [ 'card' ]) {
2021-02-23 08:45:35 +01:00
$html .= $this -> closeNode ( 'div' );
2021-07-06 12:34:53 +02:00
$html .= $this -> openNode ( 'div' , [
'class' => array_merge (
[ 'card-body' ],
$this -> options [ 'body-class' ] ? ? [],
[ " bg- { $this -> options [ 'body-variant' ] } " , " text- { $this -> options [ 'body-text-variant' ] } " ]
)
]);
2020-12-04 16:08:11 +01:00
}
$html .= $this -> genContent ();
if ( $this -> options [ 'card' ]) {
2021-02-23 08:45:35 +01:00
$html .= $this -> closeNode ( 'div' );
$html .= $this -> closeNode ( 'div' );
2020-12-04 16:08:11 +01:00
}
return $html ;
}
private function genVerticalTabs ()
{
2021-07-19 14:58:54 +02:00
$html = $this -> openNode ( 'div' , [ 'class' => array_merge (
[
'row' ,
( $this -> options [ 'card' ] ? 'card flex-row' : '' ),
( $this -> options [ 'vertical-size' ] == 'auto' ? 'flex-nowrap' : '' )
],
[
" border- { $this -> options [ 'header-border-variant' ] } "
]
)]);
$html .= $this -> openNode ( 'div' , [ 'class' => array_merge (
[
( $this -> options [ 'vertical-size' ] != 'auto' ? 'col-' . $this -> options [ 'vertical-size' ] : '' ),
2021-09-17 17:12:33 +02:00
( $this -> options [ 'card' ] ? 'card-header border-end' : '' )
2021-07-19 14:58:54 +02:00
],
[
" bg- { $this -> options [ 'header-variant' ] } " ,
" text- { $this -> options [ 'header-text-variant' ] } " ,
" border- { $this -> options [ 'header-border-variant' ] } "
])]);
2020-12-04 16:08:11 +01:00
$html .= $this -> genNav ();
2021-02-23 08:45:35 +01:00
$html .= $this -> closeNode ( 'div' );
2021-07-19 14:58:54 +02:00
$html .= $this -> openNode ( 'div' , [ 'class' => array_merge (
[
( $this -> options [ 'vertical-size' ] != 'auto' ? 'col-' . ( 12 - $this -> options [ 'vertical-size' ]) : '' ),
( $this -> options [ 'card' ] ? 'card-body2' : '' )
],
[
" bg- { $this -> options [ 'body-variant' ] } " ,
" text- { $this -> options [ 'body-text-variant' ] } "
])]);
2020-12-04 16:08:11 +01:00
$html .= $this -> genContent ();
2021-02-23 08:45:35 +01:00
$html .= $this -> closeNode ( 'div' );
$html .= $this -> closeNode ( 'div' );
2020-12-04 16:08:11 +01:00
return $html ;
}
private function genNav ()
{
2021-02-23 08:45:35 +01:00
$html = $this -> openNode ( 'ul' , [
2020-12-04 16:08:11 +01:00
'class' => array_merge ([ 'nav' ], $this -> bsClasses [ 'nav' ], $this -> options [ 'nav-class' ]),
'role' => 'tablist' ,
2020-12-08 09:24:25 +01:00
]);
2020-12-04 16:08:11 +01:00
foreach ( $this -> data [ 'navs' ] as $navItem ) {
$html .= $this -> genNavItem ( $navItem );
}
2021-02-23 08:45:35 +01:00
$html .= $this -> closeNode ( 'ul' );
2020-12-04 16:08:11 +01:00
return $html ;
}
private function genNavItem ( $navItem )
{
2021-02-23 08:45:35 +01:00
$html = $this -> openNode ( 'li' , [
2020-12-04 16:08:11 +01:00
'class' => array_merge ([ 'nav-item' ], $this -> bsClasses [ 'nav-item' ], $this -> options [ 'nav-item-class' ]),
'role' => 'presentation' ,
2020-12-08 09:24:25 +01:00
]);
2021-02-23 08:45:35 +01:00
$html .= $this -> openNode ( 'a' , [
2020-12-04 16:08:11 +01:00
'class' => array_merge (
[ 'nav-link' ],
[ ! empty ( $navItem [ 'active' ]) ? 'active' : '' ],
[ ! empty ( $navItem [ 'disabled' ]) ? 'disabled' : '' ]
),
2021-09-17 13:04:37 +02:00
'data-bs-toggle' => $this -> options [ 'pills' ] ? 'pill' : 'tab' ,
2020-12-04 16:08:11 +01:00
'id' => $navItem [ 'id' ] . '-tab' ,
'href' => '#' . $navItem [ 'id' ],
'aria-controls' => $navItem [ 'id' ],
'aria-selected' => ! empty ( $navItem [ 'active' ]),
'role' => 'tab' ,
2020-12-08 09:24:25 +01:00
]);
2020-12-04 16:08:11 +01:00
if ( ! empty ( $navItem [ 'html' ])) {
$html .= $navItem [ 'html' ];
} else {
$html .= h ( $navItem [ 'text' ]);
}
2021-02-23 08:45:35 +01:00
$html .= $this -> closeNode ( 'a' );
$html .= $this -> closeNode ( 'li' );
2020-12-04 16:08:11 +01:00
return $html ;
}
private function genContent ()
{
2021-02-23 08:45:35 +01:00
$html = $this -> openNode ( 'div' , [
2020-12-04 16:08:11 +01:00
'class' => array_merge ([ 'tab-content' ], $this -> options [ 'content-class' ]),
2020-12-08 09:24:25 +01:00
]);
2020-12-04 16:08:11 +01:00
foreach ( $this -> data [ 'content' ] as $i => $content ) {
$navItem = $this -> data [ 'navs' ][ $i ];
$html .= $this -> genContentItem ( $navItem , $content );
}
2021-02-23 08:45:35 +01:00
$html .= $this -> closeNode ( 'div' );
2020-12-04 16:08:11 +01:00
return $html ;
}
private function genContentItem ( $navItem , $content )
{
2021-02-23 08:45:35 +01:00
return $this -> genNode ( 'div' , [
2020-12-04 16:08:11 +01:00
'class' => array_merge ([ 'tab-pane' , 'fade' ], [ ! empty ( $navItem [ 'active' ]) ? 'show active' : '' ]),
'role' => 'tabpanel' ,
'id' => $navItem [ 'id' ],
'aria-labelledby' => $navItem [ 'id' ] . '-tab'
2021-02-23 08:45:35 +01:00
], $content );
2020-12-04 16:08:11 +01:00
}
2021-02-22 15:47:30 +01:00
}
class BoostrapAlert extends BootstrapGeneric {
private $defaultOptions = [
'text' => '' ,
'html' => null ,
'dismissible' => true ,
'variant' => 'primary' ,
'fade' => true
];
private $bsClasses = null ;
function __construct ( $options ) {
$this -> allowedOptionValues = [
'variant' => BootstrapGeneric :: $variants ,
];
$this -> processOptions ( $options );
}
2020-12-04 16:08:11 +01:00
2021-02-22 15:47:30 +01:00
private function processOptions ( $options )
{
$this -> options = array_merge ( $this -> defaultOptions , $options );
$this -> checkOptionValidity ();
}
public function alert ()
2020-12-04 16:08:11 +01:00
{
2021-02-22 15:47:30 +01:00
return $this -> genAlert ();
}
private function genAlert ()
{
2021-02-23 08:45:35 +01:00
$html = $this -> openNode ( 'div' , [
2021-02-22 15:47:30 +01:00
'class' => [
'alert' ,
" alert- { $this -> options [ 'variant' ] } " ,
$this -> options [ 'dismissible' ] ? 'alert-dismissible' : '' ,
$this -> options [ 'fade' ] ? 'fade show' : '' ,
],
'role' => " alert "
]);
$html .= $this -> genContent ();
$html .= $this -> genCloseButton ();
2021-02-23 08:45:35 +01:00
$html .= $this -> closeNode ( 'div' );
2021-02-22 15:47:30 +01:00
return $html ;
2020-12-04 16:08:11 +01:00
}
2021-02-22 15:47:30 +01:00
private function genCloseButton ()
2020-12-04 16:08:11 +01:00
{
$html = '' ;
2021-02-22 15:47:30 +01:00
if ( $this -> options [ 'dismissible' ]) {
2021-03-10 09:27:17 +01:00
$html .= $this -> genericCloseButton ( 'alert' );
2020-12-04 16:08:11 +01:00
}
return $html ;
}
2021-02-22 15:47:30 +01:00
private function genContent ()
2020-12-04 16:08:11 +01:00
{
2021-02-23 08:45:35 +01:00
return ! is_null ( $this -> options [ 'html' ]) ? $this -> options [ 'html' ] : $this -> options [ 'text' ];
2020-12-04 16:08:11 +01:00
}
}
2021-02-22 16:38:55 +01:00
class BoostrapTable extends BootstrapGeneric {
private $defaultOptions = [
'striped' => true ,
'bordered' => true ,
'borderless' => false ,
'hover' => true ,
'small' => false ,
'variant' => '' ,
'tableClass' => [],
'headerClass' => [],
'bodyClass' => [],
];
private $bsClasses = null ;
2021-07-06 12:34:53 +02:00
function __construct ( $options , $data , $btHelper ) {
2021-02-22 16:38:55 +01:00
$this -> allowedOptionValues = [
'variant' => array_merge ( BootstrapGeneric :: $variants , [ '' ])
];
$this -> processOptions ( $options );
$this -> fields = $data [ 'fields' ];
$this -> items = $data [ 'items' ];
$this -> caption = ! empty ( $data [ 'caption' ]) ? $data [ 'caption' ] : '' ;
2021-07-06 12:34:53 +02:00
$this -> btHelper = $btHelper ;
2021-02-22 16:38:55 +01:00
}
private function processOptions ( $options )
{
$this -> options = array_merge ( $this -> defaultOptions , $options );
$this -> checkOptionValidity ();
}
public function table ()
{
return $this -> genTable ();
}
private function genTable ()
{
2021-02-23 08:45:35 +01:00
$html = $this -> openNode ( 'table' , [
2021-02-22 16:38:55 +01:00
'class' => [
'table' ,
" table- { $this -> options [ 'variant' ] } " ,
$this -> options [ 'striped' ] ? 'table-striped' : '' ,
$this -> options [ 'bordered' ] ? 'table-bordered' : '' ,
$this -> options [ 'borderless' ] ? 'table-borderless' : '' ,
$this -> options [ 'hover' ] ? 'table-hover' : '' ,
$this -> options [ 'small' ] ? 'table-sm' : '' ,
! empty ( $this -> options [ 'variant' ]) ? " table- { $this -> options [ 'variant' ] } " : '' ,
2021-03-10 09:27:17 +01:00
! empty ( $this -> options [ 'tableClass' ]) ? ( is_array ( $this -> options [ 'tableClass' ]) ? implode ( ' ' , $this -> options [ 'tableClass' ]) : $this -> options [ 'tableClass' ]) : ''
2021-02-22 16:38:55 +01:00
],
]);
$html .= $this -> genCaption ();
$html .= $this -> genHeader ();
$html .= $this -> genBody ();
2021-02-23 08:45:35 +01:00
$html .= $this -> closeNode ( 'table' );
2021-02-22 16:38:55 +01:00
return $html ;
}
private function genHeader ()
{
2021-02-23 08:45:35 +01:00
$head = $this -> openNode ( 'thead' , [
2021-02-22 16:38:55 +01:00
'class' => [
! empty ( $this -> options [ 'headerClass' ]) ? $this -> options [ 'headerClass' ] : ''
],
]);
2021-02-23 08:45:35 +01:00
$head .= $this -> openNode ( 'tr' );
2021-02-22 16:38:55 +01:00
foreach ( $this -> fields as $i => $field ) {
if ( is_array ( $field )) {
2021-03-10 09:27:17 +01:00
if ( ! empty ( $field [ 'labelHtml' ])) {
$label = $field [ 'labelHtml' ];
} else {
$label = ! empty ( $field [ 'label' ]) ? $field [ 'label' ] : Inflector :: humanize ( $field [ 'key' ]);
$label = h ( $label );
}
2021-02-22 16:38:55 +01:00
} else {
$label = Inflector :: humanize ( $field );
2021-03-10 09:27:17 +01:00
$label = h ( $label );
2021-02-22 16:38:55 +01:00
}
2021-03-10 09:27:17 +01:00
$head .= $this -> genNode ( 'th' , [], $label );
2021-02-22 16:38:55 +01:00
}
2021-02-23 08:45:35 +01:00
$head .= $this -> closeNode ( 'tr' );
$head .= $this -> closeNode ( 'thead' );
2021-02-22 16:38:55 +01:00
return $head ;
}
private function genBody ()
{
2021-02-23 08:45:35 +01:00
$body = $this -> openNode ( 'tbody' , [
2021-02-22 16:38:55 +01:00
'class' => [
2021-03-10 09:27:17 +01:00
! empty ( $this -> options [ 'bodyClass' ]) ? ( is_array ( $this -> options [ 'bodyClass' ]) ? implode ( ' ' , $this -> options [ 'bodyClass' ]) : $this -> options [ 'bodyClass' ]) : ''
2021-02-22 16:38:55 +01:00
],
]);
foreach ( $this -> items as $i => $row ) {
2021-02-23 11:42:26 +01:00
$body .= $this -> genRow ( $row );
}
$body .= $this -> closeNode ( 'tbody' );
return $body ;
}
private function genRow ( $row )
{
$html = $this -> openNode ( 'tr' ,[
'class' => [
! empty ( $row [ '_rowVariant' ]) ? " table- { $row [ '_rowVariant' ] } " : ''
]
]);
if ( array_keys ( $row ) !== range ( 0 , count ( $row ) - 1 )) { // associative array
foreach ( $this -> fields as $i => $field ) {
if ( is_array ( $field )) {
$key = $field [ 'key' ];
} else {
$key = $field ;
2021-02-22 16:38:55 +01:00
}
2021-06-12 11:57:49 +02:00
$cellValue = Hash :: get ( $row , $key );
2021-10-18 13:28:26 +02:00
$html .= $this -> genCell ( $cellValue , $field , $row , $i );
2021-02-23 11:42:26 +01:00
}
} else { // indexed array
foreach ( $row as $cellValue ) {
2021-10-18 13:28:26 +02:00
$html .= $this -> genCell ( $cellValue , $field , $row , $i );
2021-02-22 16:38:55 +01:00
}
}
2021-02-23 11:42:26 +01:00
$html .= $this -> closeNode ( 'tr' );
return $html ;
}
2021-10-18 13:28:26 +02:00
private function genCell ( $value , $field = [], $row = [], $i = 0 )
2021-02-23 11:42:26 +01:00
{
if ( isset ( $field [ 'formatter' ])) {
2021-10-18 13:28:26 +02:00
$cellContent = $field [ 'formatter' ]( $value , $row , $i );
2021-07-06 12:34:53 +02:00
} else if ( isset ( $field [ 'element' ])) {
$cellContent = $this -> btHelper -> getView () -> element ( $field [ 'element' ], [
'data' => [ $value ],
'field' => [ 'path' => '0' ]
]);
2021-02-23 11:42:26 +01:00
} else {
$cellContent = h ( $value );
}
return $this -> genNode ( 'td' , [
'class' => [
! empty ( $row [ '_cellVariant' ]) ? " bg- { $row [ '_cellVariant' ] } " : ''
]
], $cellContent );
2021-02-22 16:38:55 +01:00
}
private function genCaption ()
{
2021-06-21 08:43:37 +02:00
return ! empty ( $this -> caption ) ? $this -> genNode ( 'caption' , [], h ( $this -> caption )) : '' ;
2021-02-22 16:38:55 +01:00
}
2021-02-23 08:45:35 +01:00
}
2021-02-23 11:25:20 +01:00
2021-07-06 12:34:53 +02:00
class BoostrapListTable extends BootstrapGeneric {
private $defaultOptions = [
'striped' => true ,
'bordered' => false ,
'borderless' => false ,
'hover' => true ,
'small' => false ,
'variant' => '' ,
'tableClass' => [],
'bodyClass' => [],
];
private $bsClasses = null ;
function __construct ( $options , $data , $btHelper ) {
$this -> allowedOptionValues = [
'variant' => array_merge ( BootstrapGeneric :: $variants , [ '' ])
];
$this -> processOptions ( $options );
$this -> fields = $data [ 'fields' ];
$this -> item = $data [ 'item' ];
$this -> caption = ! empty ( $data [ 'caption' ]) ? $data [ 'caption' ] : '' ;
$this -> btHelper = $btHelper ;
}
private function processOptions ( $options )
{
$this -> options = array_merge ( $this -> defaultOptions , $options );
$this -> checkOptionValidity ();
}
public function table ()
{
return $this -> genTable ();
}
private function genTable ()
{
$html = $this -> openNode ( 'table' , [
'class' => [
'table' ,
" table- { $this -> options [ 'variant' ] } " ,
$this -> options [ 'striped' ] ? 'table-striped' : '' ,
$this -> options [ 'bordered' ] ? 'table-bordered' : '' ,
$this -> options [ 'borderless' ] ? 'table-borderless' : '' ,
$this -> options [ 'hover' ] ? 'table-hover' : '' ,
$this -> options [ 'small' ] ? 'table-sm' : '' ,
! empty ( $this -> options [ 'variant' ]) ? " table- { $this -> options [ 'variant' ] } " : '' ,
! empty ( $this -> options [ 'tableClass' ]) ? ( is_array ( $this -> options [ 'tableClass' ]) ? implode ( ' ' , $this -> options [ 'tableClass' ]) : $this -> options [ 'tableClass' ]) : ''
],
'id' => $this -> options [ 'id' ] ? ? ''
]);
$html .= $this -> genCaption ();
$html .= $this -> genBody ();
$html .= $this -> closeNode ( 'table' );
return $html ;
}
private function genBody ()
{
$body = $this -> openNode ( 'tbody' , [
'class' => [
! empty ( $this -> options [ 'bodyClass' ]) ? ( is_array ( $this -> options [ 'bodyClass' ]) ? implode ( ' ' , $this -> options [ 'bodyClass' ]) : $this -> options [ 'bodyClass' ]) : ''
],
]);
foreach ( $this -> fields as $i => $field ) {
$body .= $this -> genRow ( $field );
}
$body .= $this -> closeNode ( 'tbody' );
return $body ;
}
private function genRow ( $field )
{
$rowValue = $this -> genCell ( $field );
$rowKey = $this -> genNode ( 'th' , [
'class' => [
'col-sm-2'
],
'scope' => 'row'
], h ( $field [ 'key' ]));
$row = $this -> genNode ( 'tr' ,[
'class' => [
'd-flex' ,
! empty ( $field [ '_rowVariant' ]) ? " table- { $field [ '_rowVariant' ] } " : ''
]
], implode ( '' , [ $rowKey , $rowValue ]));
return $row ;
}
private function genCell ( $field = [])
{
if ( isset ( $field [ 'raw' ])) {
$cellContent = h ( $field [ 'raw' ]);
} else if ( isset ( $field [ 'formatter' ])) {
$cellContent = $field [ 'formatter' ]( $this -> getValueFromObject ( $field ), $this -> item );
} else if ( isset ( $field [ 'type' ])) {
$cellContent = $this -> btHelper -> getView () -> element ( $this -> getElementPath ( $field [ 'type' ]), [
'data' => $this -> item ,
'field' => $field
]);
} else {
$cellContent = h ( $this -> getValueFromObject ( $field ));
}
return $this -> genNode ( 'td' , [
'class' => [
'col-sm-10' ,
! empty ( $row [ '_cellVariant' ]) ? " bg- { $row [ '_cellVariant' ] } " : ''
]
], $cellContent );
}
private function getValueFromObject ( $field )
{
if ( is_array ( $field )) {
$key = $field [ 'path' ];
} else {
$key = $field ;
}
$cellValue = Hash :: get ( $this -> item , $key );
return $cellValue ;
}
private function getElementPath ( $type )
{
return sprintf ( '%s%sField' ,
$this -> options [ 'elementsRootPath' ] ? ? '' ,
$type
);
}
private function genCaption ()
{
return ! empty ( $this -> caption ) ? $this -> genNode ( 'caption' , [], h ( $this -> caption )) : '' ;
}
}
2021-02-23 11:25:20 +01:00
class BoostrapButton extends BootstrapGeneric {
private $defaultOptions = [
'id' => '' ,
'text' => '' ,
'html' => null ,
'variant' => 'primary' ,
'outline' => false ,
'size' => '' ,
'icon' => null ,
2021-10-04 13:06:41 +02:00
'image' => null ,
2021-02-23 11:25:20 +01:00
'class' => [],
'type' => 'button' ,
'nodeType' => 'button' ,
2021-08-24 10:48:53 +02:00
'title' => '' ,
2021-03-10 09:32:00 +01:00
'params' => [],
'badge' => false
2021-02-23 11:25:20 +01:00
];
private $bsClasses = [];
function __construct ( $options ) {
$this -> allowedOptionValues = [
2021-08-24 10:48:53 +02:00
'variant' => array_merge ( BootstrapGeneric :: $variants , [ 'link' , 'text' ]),
2021-02-23 11:25:20 +01:00
'size' => [ '' , 'sm' , 'lg' ],
'type' => [ 'button' , 'submit' , 'reset' ]
];
2021-03-10 09:27:17 +01:00
if ( empty ( $options [ 'class' ])) {
$options [ 'class' ] = '' ;
}
2021-02-23 11:25:20 +01:00
$options [ 'class' ] = ! is_array ( $options [ 'class' ]) ? [ $options [ 'class' ]] : $options [ 'class' ];
$this -> processOptions ( $options );
}
private function processOptions ( $options )
{
$this -> options = array_merge ( $this -> defaultOptions , $options );
$this -> checkOptionValidity ();
$this -> bsClasses [] = 'btn' ;
if ( $this -> options [ 'outline' ]) {
$this -> bsClasses [] = " btn-outline- { $this -> options [ 'variant' ] } " ;
} else {
$this -> bsClasses [] = " btn- { $this -> options [ 'variant' ] } " ;
}
if ( ! empty ( $this -> options [ 'size' ])) {
2021-08-24 10:48:53 +02:00
$this -> bsClasses [] = " btn- { $this -> options [ 'size' ] } " ;
2021-02-23 11:25:20 +01:00
}
2021-08-24 10:48:53 +02:00
if ( $this -> options [ 'variant' ] == 'text' ) {
$this -> bsClasses [] = 'p-0' ;
$this -> bsClasses [] = 'lh-1' ;
}
2021-02-23 11:25:20 +01:00
}
public function button ()
{
return $this -> genButton ();
}
private function genButton ()
{
$html = $this -> openNode ( $this -> options [ 'nodeType' ], array_merge ( $this -> options [ 'params' ], [
'class' => array_merge ( $this -> options [ 'class' ], $this -> bsClasses ),
'role' => " alert " ,
2021-08-24 10:48:53 +02:00
'type' => $this -> options [ 'type' ],
'title' => h ( $this -> options [ 'title' ]),
2021-02-23 11:25:20 +01:00
]));
$html .= $this -> genIcon ();
2021-10-04 13:06:41 +02:00
$html .= $this -> genImage ();
2021-02-23 11:25:20 +01:00
$html .= $this -> genContent ();
2021-03-10 09:32:00 +01:00
if ( ! empty ( $this -> options [ 'badge' ])) {
$bsBadge = new BoostrapBadge ( $this -> options [ 'badge' ]);
$html .= $bsBadge -> badge ();
}
2021-02-23 11:25:20 +01:00
$html .= $this -> closeNode ( $this -> options [ 'nodeType' ]);
return $html ;
}
private function genIcon ()
{
2021-10-04 13:06:41 +02:00
if ( ! empty ( $this -> options [ 'icon' ])) {
$bsIcon = new BoostrapIcon ( $this -> options [ 'icon' ], [
2021-10-08 16:53:00 +02:00
'class' => [( ! empty ( $this -> options [ 'text' ]) ? 'me-1' : '' )]
2021-10-04 13:06:41 +02:00
]);
return $bsIcon -> icon ();
}
return '' ;
}
private function genImage ()
{
if ( ! empty ( $this -> options [ 'image' ])) {
return $this -> genNode ( 'img' , [
'src' => $this -> options [ 'image' ][ 'path' ] ? ? '' ,
'class' => [ 'img-fluid' , 'me-1' ],
'width' => '26' ,
'height' => '26' ,
'alt' => $this -> options [ 'image' ][ 'alt' ] ? ? ''
]);
}
return '' ;
2021-02-23 11:25:20 +01:00
}
private function genContent ()
{
return ! is_null ( $this -> options [ 'html' ]) ? $this -> options [ 'html' ] : $this -> options [ 'text' ];
}
2021-03-10 09:28:33 +01:00
}
class BoostrapBadge extends BootstrapGeneric {
private $defaultOptions = [
'text' => '' ,
'variant' => 'primary' ,
'pill' => false ,
2021-08-24 10:48:53 +02:00
'title' => '' ,
'class' => [],
2021-03-10 09:28:33 +01:00
];
function __construct ( $options ) {
$this -> allowedOptionValues = [
'variant' => BootstrapGeneric :: $variants ,
];
$this -> processOptions ( $options );
}
private function processOptions ( $options )
{
$this -> options = array_merge ( $this -> defaultOptions , $options );
$this -> checkOptionValidity ();
}
public function badge ()
{
return $this -> genBadge ();
}
private function genBadge ()
{
$html = $this -> genNode ( 'span' , [
2021-08-24 10:48:53 +02:00
'class' => array_merge ( $this -> options [ 'class' ], [
2021-09-17 18:12:24 +02:00
'ms-1' ,
2021-03-10 09:28:33 +01:00
'badge' ,
2021-09-17 13:04:37 +02:00
" bg- { $this -> options [ 'variant' ] } " ,
2021-09-17 18:12:24 +02:00
$this -> getTextClassForVariant ( $this -> options [ 'variant' ]),
2021-09-17 13:04:37 +02:00
$this -> options [ 'pill' ] ? 'rounded-pill' : '' ,
2021-08-24 10:48:53 +02:00
]),
2021-03-10 09:28:33 +01:00
'title' => $this -> options [ 'title' ]
], h ( $this -> options [ 'text' ]));
return $html ;
}
}
2021-03-10 09:32:18 +01:00
2021-09-03 10:48:18 +02:00
class BoostrapIcon extends BootstrapGeneric {
private $icon = '' ;
private $defaultOptions = [
'class' => [],
];
function __construct ( $icon , $options = []) {
$this -> icon = $icon ;
$this -> processOptions ( $options );
}
private function processOptions ( $options )
{
$this -> options = array_merge ( $this -> defaultOptions , $options );
$this -> checkOptionValidity ();
}
public function icon ()
{
return $this -> genIcon ();
}
private function genIcon ()
{
$html = $this -> genNode ( 'span' , [
'class' => array_merge (
is_array ( $this -> options [ 'class' ]) ? $this -> options [ 'class' ] : [ $this -> options [ 'class' ]],
[ " fa fa- { $this -> icon } " ]
),
]);
return $html ;
}
}
2021-03-10 09:32:18 +01:00
class BoostrapModal extends BootstrapGeneric {
private $defaultOptions = [
'size' => '' ,
'centered' => true ,
'scrollable' => true ,
'backdropStatic' => false ,
'title' => '' ,
'titleHtml' => false ,
'body' => '' ,
'bodyHtml' => false ,
'footerHtml' => false ,
'confirmText' => 'Confirm' ,
'cancelText' => 'Cancel' ,
'modalClass' => [ '' ],
'headerClass' => [ '' ],
'bodyClass' => [ '' ],
'footerClass' => [ '' ],
'type' => 'ok-only' ,
'variant' => '' ,
2021-03-18 14:01:14 +01:00
'confirmFunction' => '' , // Will be called with the following arguments confirmFunction(modalObject, tmpApi)
2021-03-10 09:32:18 +01:00
'cancelFunction' => ''
];
private $bsClasses = null ;
function __construct ( $options ) {
$this -> allowedOptionValues = [
'size' => [ 'sm' , 'lg' , 'xl' , '' ],
2021-06-14 13:03:58 +02:00
'type' => [ 'ok-only' , 'confirm' , 'confirm-success' , 'confirm-warning' , 'confirm-danger' , 'custom' ],
2021-03-10 09:32:18 +01:00
'variant' => array_merge ( BootstrapGeneric :: $variants , [ '' ]),
];
$this -> processOptions ( $options );
}
private function processOptions ( $options )
{
$this -> options = array_merge ( $this -> defaultOptions , $options );
$this -> checkOptionValidity ();
}
public function modal ()
{
return $this -> genModal ();
}
private function genModal ()
{
$dialog = $this -> openNode ( 'div' , [
'class' => array_merge (
[ 'modal-dialog' , ( ! empty ( $this -> options [ 'size' ])) ? " modal- { $this -> options [ 'size' ] } " : '' ],
$this -> options [ 'modalClass' ]
),
]);
$content = $this -> openNode ( 'div' , [
'class' => [ 'modal-content' ],
]);
$header = $this -> genHeader ();
$body = $this -> genBody ();
$footer = $this -> genFooter ();
$closedDiv = $this -> closeNode ( 'div' );
$html = " { $dialog } { $content } { $header } { $body } { $footer } { $closedDiv } { $closedDiv } " ;
return $html ;
}
private function genHeader ()
{
$header = $this -> openNode ( 'div' , [ 'class' => array_merge ([ 'modal-header' ], $this -> options [ 'headerClass' ])]);
if ( ! empty ( $this -> options [ 'titleHtml' ])) {
$header .= $this -> options [ 'titleHtml' ];
} else {
$header .= $this -> genNode ( 'h5' , [ 'class' => [ 'modal-title' ]], h ( $this -> options [ 'title' ]));
}
if ( empty ( $this -> options [ 'backdropStatic' ])) {
$header .= $this -> genericCloseButton ( 'modal' );
}
$header .= $this -> closeNode ( 'div' );
return $header ;
}
private function genBody ()
{
$body = $this -> openNode ( 'div' , [ 'class' => array_merge ([ 'modal-body' ], $this -> options [ 'bodyClass' ])]);
if ( ! empty ( $this -> options [ 'bodyHtml' ])) {
$body .= $this -> options [ 'bodyHtml' ];
} else {
$body .= h ( $this -> options [ 'body' ]);
}
$body .= $this -> closeNode ( 'div' );
return $body ;
}
private function genFooter ()
{
2021-06-14 13:03:58 +02:00
$footer = $this -> openNode ( 'div' , [
'class' => array_merge ([ 'modal-footer' ], $this -> options [ 'footerClass' ]),
'data-custom-footer' => $this -> options [ 'type' ] == 'custom'
]);
2021-03-10 09:32:18 +01:00
if ( ! empty ( $this -> options [ 'footerHtml' ])) {
$footer .= $this -> options [ 'footerHtml' ];
} else {
$footer .= $this -> getFooterBasedOnType ();
}
$footer .= $this -> closeNode ( 'div' );
return $footer ;
}
private function getFooterBasedOnType () {
if ( $this -> options [ 'type' ] == 'ok-only' ) {
return $this -> getFooterOkOnly ();
} else if ( str_contains ( $this -> options [ 'type' ], 'confirm' )) {
return $this -> getFooterConfirm ();
2021-06-14 13:03:58 +02:00
} else if ( $this -> options [ 'type' ] == 'custom' ) {
return $this -> getFooterCustom ();
2021-03-10 09:32:18 +01:00
} else {
return $this -> getFooterOkOnly ();
}
}
private function getFooterOkOnly ()
{
return ( new BoostrapButton ([
'variant' => 'primary' ,
'text' => __ ( 'Ok' ),
'params' => [
2021-09-17 13:04:37 +02:00
'data-bs-dismiss' => $this -> options [ 'confirmFunction' ] ? '' : 'modal' ,
2021-03-10 09:32:18 +01:00
'onclick' => $this -> options [ 'confirmFunction' ]
]
])) -> button ();
}
private function getFooterConfirm ()
{
if ( $this -> options [ 'type' ] == 'confirm' ) {
$variant = 'primary' ;
} else {
$variant = explode ( '-' , $this -> options [ 'type' ])[ 1 ];
}
$buttonCancel = ( new BoostrapButton ([
'variant' => 'secondary' ,
'text' => h ( $this -> options [ 'cancelText' ]),
'params' => [
2021-09-17 13:04:37 +02:00
'data-bs-dismiss' => 'modal' ,
2021-03-10 09:32:18 +01:00
'onclick' => $this -> options [ 'cancelFunction' ]
]
])) -> button ();
$buttonConfirm = ( new BoostrapButton ([
'variant' => $variant ,
'text' => h ( $this -> options [ 'confirmText' ]),
2021-03-18 14:01:14 +01:00
'class' => 'modal-confirm-button' ,
2021-03-10 09:32:18 +01:00
'params' => [
2021-09-17 13:04:37 +02:00
// 'data-bs-dismiss' => $this->options['confirmFunction'] ? '' : 'modal',
2021-03-18 14:01:14 +01:00
'data-confirmFunction' => sprintf ( '%s' , $this -> options [ 'confirmFunction' ])
2021-03-10 09:32:18 +01:00
]
])) -> button ();
return $buttonCancel . $buttonConfirm ;
}
2021-06-14 13:03:58 +02:00
private function getFooterCustom ()
{
$buttons = [];
foreach ( $this -> options [ 'footerButtons' ] as $buttonConfig ) {
$buttons [] = ( new BoostrapButton ([
'variant' => h ( $buttonConfig [ 'variant' ] ? ? 'primary' ),
'text' => h ( $buttonConfig [ 'text' ]),
'class' => 'modal-confirm-button' ,
'params' => [
2021-09-17 13:04:37 +02:00
'data-bs-dismiss' => ! empty ( $buttonConfig [ 'clickFunction' ]) ? '' : 'modal' ,
2021-06-14 13:03:58 +02:00
'data-clickFunction' => sprintf ( '%s' , $buttonConfig [ 'clickFunction' ])
]
])) -> button ();
}
return implode ( '' , $buttons );
}
2021-03-10 09:32:18 +01:00
}
2021-06-12 11:57:49 +02:00
2021-06-21 08:43:37 +02:00
class BoostrapCard extends BootstrapGeneric
{
private $defaultOptions = [
'variant' => '' ,
'headerText' => '' ,
'footerText' => '' ,
'bodyText' => '' ,
'headerHTML' => '' ,
'footerHTML' => '' ,
'bodyHTML' => '' ,
2021-09-06 11:17:25 +02:00
'class' => '' ,
2021-06-21 08:43:37 +02:00
'headerClass' => '' ,
'bodyClass' => '' ,
'footerClass' => '' ,
];
public function __construct ( $options )
{
$this -> allowedOptionValues = [
'variant' => array_merge ( BootstrapGeneric :: $variants , [ '' ]),
];
$this -> processOptions ( $options );
}
private function processOptions ( $options )
{
$this -> options = array_merge ( $this -> defaultOptions , $options );
$this -> checkOptionValidity ();
}
public function card ()
{
return $this -> genCard ();
}
private function genCard ()
{
$card = $this -> genNode ( 'div' , [
'class' => [
'card' ,
! empty ( $this -> options [ 'variant' ]) ? " bg- { $this -> options [ 'variant' ] } " : '' ,
! empty ( $this -> options [ 'variant' ]) ? $this -> getTextClassForVariant ( $this -> options [ 'variant' ]) : '' ,
2021-09-06 11:17:25 +02:00
h ( $this -> options [ 'class' ]),
2021-06-21 08:43:37 +02:00
],
], implode ( '' , [ $this -> genHeader (), $this -> genBody (), $this -> genFooter ()]));
return $card ;
}
private function genHeader ()
{
if ( empty ( $this -> options [ 'headerHTML' ]) && empty ( $this -> options [ 'headerText' ])) {
return '' ;
}
$content = ! empty ( $this -> options [ 'headerHTML' ]) ? $this -> options [ 'headerHTML' ] : h ( $this -> options [ 'headerText' ]);
$header = $this -> genNode ( 'div' , [
'class' => [
'card-header' ,
h ( $this -> options [ 'headerClass' ]),
],
], $content );
return $header ;
}
private function genBody ()
{
if ( empty ( $this -> options [ 'bodyHTML' ]) && empty ( $this -> options [ 'bodyText' ])) {
return '' ;
}
$content = ! empty ( $this -> options [ 'bodyHTML' ]) ? $this -> options [ 'bodyHTML' ] : h ( $this -> options [ 'bodyText' ]);
$body = $this -> genNode ( 'div' , [
'class' => [
'card-body' ,
h ( $this -> options [ 'bodyClass' ]),
],
], $content );
return $body ;
}
private function genFooter ()
{
if ( empty ( $this -> options [ 'footerHTML' ]) && empty ( $this -> options [ 'footerText' ])) {
return '' ;
}
$content = ! empty ( $this -> options [ 'footerHTML' ]) ? $this -> options [ 'footerHTML' ] : h ( $this -> options [ 'footerText' ]);
$footer = $this -> genNode ( 'div' , [
'class' => [
'card-footer' ,
h ( $this -> options [ 'footerClass' ]),
],
], $content );
return $footer ;
}
}
2021-09-13 13:02:33 +02:00
class BoostrapSwitch extends BootstrapGeneric {
private $defaultOptions = [
'label' => '' ,
'variant' => 'primary' ,
'disabled' => false ,
'checked' => false ,
2021-09-18 11:21:50 +02:00
'title' => '' ,
'class' => [],
'attrs' => [],
2021-09-13 13:02:33 +02:00
];
function __construct ( $options ) {
$this -> allowedOptionValues = [
'variant' => BootstrapGeneric :: $variants ,
];
$this -> processOptions ( $options );
}
private function processOptions ( $options )
{
$this -> options = array_merge ( $this -> defaultOptions , $options );
$this -> checkOptionValidity ();
}
public function switch ()
{
return $this -> genSwitch ();
}
private function genSwitch ()
{
$tmpId = 'tmp-' . mt_rand ();
$html = $this -> genNode ( 'div' , [
'class' => [
2021-09-17 13:04:37 +02:00
'form-check form-switch' ,
2021-09-13 13:02:33 +02:00
],
'title' => $this -> options [ 'title' ]
], implode ( '' , [
2021-09-18 11:21:50 +02:00
$this -> genNode ( 'input' , array_merge ([
2021-09-13 13:02:33 +02:00
'type' => " checkbox " ,
2021-09-18 11:21:50 +02:00
'class' => 'form-check-input' ,
2021-09-13 13:02:33 +02:00
'id' => $tmpId ,
( $this -> options [ 'disabled' ] ? 'disabled' : '' ) => '' ,
2021-09-18 11:21:50 +02:00
( $this -> options [ 'checked' ] ? 'checked' : '' ) => $this -> options [ 'checked' ] ? 'checked' : '' ,
], $this -> options [ 'attrs' ])),
2021-09-13 13:02:33 +02:00
$this -> genNode ( 'label' , [
2021-09-18 11:21:50 +02:00
'class' => 'form-check-label' ,
2021-09-13 13:02:33 +02:00
'for' => $tmpId ,
], h ( $this -> options [ 'label' ]))
]));
return $html ;
}
}
2021-06-12 11:57:49 +02:00
class BoostrapProgress extends BootstrapGeneric {
private $defaultOptions = [
'value' => 0 ,
'total' => 100 ,
'text' => '' ,
'title' => '' ,
'variant' => 'primary' ,
'height' => '' ,
'striped' => false ,
'animated' => false ,
'label' => true
];
function __construct ( $options ) {
$this -> allowedOptionValues = [
'variant' => BootstrapGeneric :: $variants ,
];
$this -> processOptions ( $options );
}
private function processOptions ( $options )
{
$this -> options = array_merge ( $this -> defaultOptions , $options );
$this -> checkOptionValidity ();
}
public function progress ()
{
return $this -> genProgress ();
}
private function genProgress ()
{
$percentage = round ( 100 * $this -> options [ 'value' ] / $this -> options [ 'total' ]);
$heightStyle = ! empty ( $this -> options [ 'height' ]) ? sprintf ( 'height: %s;' , h ( $this -> options [ 'height' ])) : '' ;
$widthStyle = sprintf ( 'width: %s%%;' , $percentage );
$label = $this -> options [ 'label' ] ? " { $percentage } % " : '' ;
$pb = $this -> genNode ( 'div' , [
'class' => [
'progress-bar' ,
" bg- { $this -> options [ 'variant' ] } " ,
$this -> options [ 'striped' ] ? 'progress-bar-striped' : '' ,
$this -> options [ 'animated' ] ? 'progress-bar-animated' : '' ,
],
'role' => " progressbar " ,
'aria-valuemin' => " 0 " , 'aria-valuemax' => " 100 " , 'aria-valuenow' => $percentage ,
'style' => " ${ widthStyle } " ,
'title' => $this -> options [ 'title' ]
], $label );
$container = $this -> genNode ( 'div' , [
'class' => [
'progress' ,
],
'style' => " ${ heightStyle } " ,
'title' => h ( $this -> options [ 'title' ]),
], $pb );
return $container ;
}
}
class BoostrapCollapse extends BootstrapGeneric {
private $defaultOptions = [
'text' => '' ,
'open' => false ,
];
function __construct ( $options , $content , $btHelper ) {
$this -> allowedOptionValues = [];
$this -> processOptions ( $options );
$this -> content = $content ;
$this -> btHelper = $btHelper ;
}
private function processOptions ( $options )
{
$this -> options = array_merge ( $this -> defaultOptions , $options );
$this -> checkOptionValidity ();
}
public function collapse ()
{
return $this -> genCollapse ();
}
private function genControl ()
{
$html = $this -> genNode ( 'a' , [
'class' => [ 'text-decoration-none' ],
2021-09-17 13:04:37 +02:00
'data-bs-toggle' => 'collapse' ,
2021-06-12 11:57:49 +02:00
'href' => '#collapseExample' ,
'role' => 'button' ,
'aria-expanded' => 'false' ,
'aria-controls' => 'collapseExample' ,
], h ( $this -> options [ 'title' ]));
return $html ;
}
private function genContent ()
{
$content = $this -> genNode ( 'div' , [
'class' => 'card' ,
], $this -> content );
$container = $this -> genNode ( 'div' , [
'class' => [ 'collapse' , $this -> options [ 'open' ] ? 'show' : '' ],
'id' => 'collapseExample' ,
], $content );
return $container ;
}
private function genCollapse ()
{
$html = $this -> genControl ();
$html .= $this -> genContent ();
return $html ;
}
}
class BoostrapProgressTimeline extends BootstrapGeneric {
private $defaultOptions = [
'steps' => [],
'selected' => 0 ,
'variant' => 'info' ,
'variantInactive' => 'secondary' ,
];
function __construct ( $options , $btHelper ) {
$this -> allowedOptionValues = [
'variant' => BootstrapGeneric :: $variants ,
'variantInactive' => BootstrapGeneric :: $variants ,
];
$this -> processOptions ( $options );
$this -> btHelper = $btHelper ;
}
private function processOptions ( $options )
{
$this -> options = array_merge ( $this -> defaultOptions , $options );
$this -> checkOptionValidity ();
}
public function progressTimeline ()
{
return $this -> genProgressTimeline ();
}
private function getStepIcon ( $step , $i , $nodeActive , $lineActive )
{
$icon = $this -> genNode ( 'b' , [
'class' => [
! empty ( $step [ 'icon' ]) ? h ( $this -> btHelper -> FontAwesome -> getClass ( $step [ 'icon' ])) : '' ,
$this -> getTextClassForVariant ( $this -> options [ 'variant' ])
],
], empty ( $step [ 'icon' ]) ? h ( $i + 1 ) : '' );
$iconContainer = $this -> genNode ( 'span' , [
'class' => [
'd-flex' , 'align-items-center' , 'justify-content-center' ,
'rounded-circle' ,
$nodeActive ? " bg- { $this -> options [ 'variant' ] } " : " bg- { $this -> options [ 'variantInactive' ] } "
],
'style' => 'width:50px; height:50px'
], $icon );
$li = $this -> genNode ( 'li' , [
'class' => [
'd-flex' , 'flex-column' ,
$nodeActive ? 'progress-active' : 'progress-inactive' ,
],
], $iconContainer );
$html = $li . $this -> getHorizontalLine ( $i , $nodeActive , $lineActive );
return $html ;
}
private function getHorizontalLine ( $i , $nodeActive , $lineActive )
{
$stepCount = count ( $this -> options [ 'steps' ]);
if ( $i == $stepCount - 1 ) {
return '' ;
}
$progressBar = ( new BoostrapProgress ([
'label' => false ,
'value' => $nodeActive ? ( $lineActive ? 100 : 50 ) : 0 ,
'height' => '2px' ,
'variant' => $this -> options [ 'variant' ]
])) -> progress ();
$line = $this -> genNode ( 'span' , [
'class' => [
'progress-line' ,
'flex-grow-1' , 'align-self-center' ,
$lineActive ? " bg- { $this -> options [ 'variant' ] } " : ''
],
], $progressBar );
return $line ;
}
private function getStepText ( $step , $isActive )
{
return $this -> genNode ( 'li' , [
'class' => [
'text-center' ,
2021-09-17 13:04:37 +02:00
'fw-bold' ,
2021-06-12 11:57:49 +02:00
$isActive ? 'progress-active' : 'progress-inactive' ,
],
], h ( $step [ 'text' ] ? ? '' ));
}
private function genProgressTimeline ()
{
$iconLis = '' ;
$textLis = '' ;
foreach ( $this -> options [ 'steps' ] as $i => $step ) {
$nodeActive = $i <= $this -> options [ 'selected' ];
$lineActive = $i < $this -> options [ 'selected' ];
$iconLis .= $this -> getStepIcon ( $step , $i , $nodeActive , $lineActive );
$textLis .= $this -> getStepText ( $step , $nodeActive );
}
$ulIcons = $this -> genNode ( 'ul' , [
'class' => [
'd-flex' , 'justify-content-around' ,
],
], $iconLis );
$ulText = $this -> genNode ( 'ul' , [
'class' => [
'd-flex' , 'justify-content-between' ,
],
], $textLis );
$html = $this -> genNode ( 'div' , [
2021-06-18 09:22:04 +02:00
'class' => [ 'progress-timeline' , 'mw-75' , 'mx-auto' ]
2021-06-12 11:57:49 +02:00
], $ulIcons . $ulText );
return $html ;
}
2021-07-20 11:24:37 +02:00
}
class BootstrapListGroup extends BootstrapGeneric
{
private $defaultOptions = [
'hover' => false ,
];
private $bsClasses = null ;
function __construct ( $options , $data , $btHelper ) {
$this -> data = $data ;
$this -> processOptions ( $options );
$this -> btHelper = $btHelper ;
}
private function processOptions ( $options )
{
$this -> options = array_merge ( $this -> defaultOptions , $options );
}
public function listGroup ()
{
return $this -> genListGroup ();
}
private function genListGroup ()
{
$html = $this -> openNode ( 'div' , [
'class' => [ 'list-group' ,],
]);
foreach ( $this -> data as $item ) {
$html .= $this -> genItem ( $item );
}
$html .= $this -> closeNode ( 'div' );
return $html ;
}
private function genItem ( $item )
{
if ( ! empty ( $item [ 'heading' ])) { // complex layout with heading, badge and body
$html = $this -> genNode ( 'a' , [
'class' => [ 'list-group-item' , ( ! empty ( $this -> options [ 'hover' ]) ? 'list-group-item-action' : '' ),],
], implode ( '' , [
$this -> genHeadingGroup ( $item ),
$this -> genBody ( $item ),
]));
} else { // simple layout with just <li>-like elements
$html = $this -> genNode ( 'a' , [
'class' => [ 'list-group-item' , 'd-flex' , 'align-items-center' , 'justify-content-between' ],
], implode ( '' , [
h ( $item [ 'text' ]),
$this -> genBadge ( $item )
]));
}
return $html ;
}
private function genHeadingGroup ( $item )
{
$html = $this -> genNode ( 'div' , [
'class' => [ 'd-flex' , 'w-100' , 'justify-content-between' ,],
], implode ( '' , [
$this -> genHeading ( $item ),
$this -> genBadge ( $item )
]));
return $html ;
}
private function genHeading ( $item )
{
if ( empty ( $item [ 'heading' ])) {
return '' ;
}
return $this -> genNode ( 'h5' , [
'class' => [ 'mb-1' ],
], h ( $item [ 'heading' ]));
}
private function genBadge ( $item )
{
if ( empty ( $item [ 'badge' ])) {
return '' ;
}
return $this -> genNode ( 'span' , [
2021-09-17 17:51:45 +02:00
'class' => [ 'badge rounded-pill' , ( ! empty ( $item [ 'badge-variant' ]) ? " bg- { $item [ 'badge-variant' ] } " : 'bg-primary' )],
2021-07-20 11:24:37 +02:00
], h ( $item [ 'badge' ]));
}
private function genBody ( $item )
{
if ( ! empty ( $item [ 'bodyHTML' ])) {
return $item [ 'bodyHTML' ];
}
return ! empty ( $item [ 'body' ]) ? h ( $item [ 'body' ]) : '' ;
}
2021-06-12 11:57:49 +02:00
}