2020-12-04 16:08:11 +01:00
< ? php
2021-11-23 15:29:55 +01:00
2020-12-04 16:08:11 +01:00
/**
* 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
2022-11-24 12:50:11 +01:00
* - vertical - size : Specify how many bootstrap ' 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 ;
2022-11-24 12:50:11 +01:00
use App\View\AppView ;
2020-12-04 16:08:11 +01:00
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 ;
2022-11-24 12:50:11 +01:00
use Cake\Utility\Text ;
2020-12-04 16:08:11 +01:00
use InvalidArgumentException ;
2022-11-24 12:50:11 +01:00
use \App\View\Helper\BootstrapElements\BootstrapSwitch ;
use \App\View\Helper\BootstrapElements\BootstrapTabs ;
use \App\View\Helper\BootstrapElements\BootstrapAlert ;
use \App\View\Helper\BootstrapElements\BootstrapAccordion ;
use \App\View\Helper\BootstrapElements\BootstrapBadge ;
use \App\View\Helper\BootstrapElements\BootstrapButton ;
use \App\View\Helper\BootstrapElements\BootstrapCard ;
use \App\View\Helper\BootstrapElements\BootstrapCollapse ;
use \App\View\Helper\BootstrapElements\BootstrapDropdownMenu ;
use \App\View\Helper\BootstrapElements\BootstrapIcon ;
use \App\View\Helper\BootstrapElements\BootstrapListGroup ;
use \App\View\Helper\BootstrapElements\BootstrapListTable ;
use \App\View\Helper\BootstrapElements\BootstrapModal ;
use \App\View\Helper\BootstrapElements\BootstrapNotificationBubble ;
use \App\View\Helper\BootstrapElements\BootstrapProgress ;
use \App\View\Helper\BootstrapElements\BootstrapProgressTimeline ;
use \App\View\Helper\BootstrapElements\BootstrapTable ;
use \App\View\Helper\BootstrapElements\BootstrapToast ;
const COMPACT_ATTRIBUTES = [
'checked' => true ,
'default' => true ,
'disabled' => true ,
'enabled' => true ,
'hidden' => true ,
'multiple' => true ,
'novalidate' => true ,
'readonly' => true ,
'required' => true ,
'selected' => true ,
'visible' => true ,
];
2020-12-04 16:08:11 +01:00
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 )
{
2022-11-24 12:50:11 +01:00
$bsAlert = new BootstrapAlert ( $options );
2021-02-22 15:47:30 +01:00
return $bsAlert -> alert ();
}
2021-02-22 16:38:55 +01:00
public function table ( $options , $data )
{
2022-11-24 12:50:11 +01:00
$bsTable = new BootstrapTable ( $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 )
{
2022-11-24 12:50:11 +01:00
$bsListTable = new BootstrapListTable ( $options , $data , $this );
2021-07-06 12:34:53 +02:00
return $bsListTable -> table ();
}
2021-02-23 11:25:20 +01:00
public function button ( $options )
{
2022-11-24 12:50:11 +01:00
$bsButton = new BootstrapButton ( $options );
2021-02-23 11:25:20 +01:00
return $bsButton -> button ();
}
2021-03-10 09:28:33 +01:00
2021-11-23 15:29:55 +01:00
public function icon ( $icon , $options = [])
2021-09-03 10:48:18 +02:00
{
2022-11-24 12:50:11 +01:00
$bsIcon = new BootstrapIcon ( $icon , $options );
2021-09-03 10:48:18 +02:00
return $bsIcon -> icon ();
}
2021-03-10 09:28:33 +01:00
public function badge ( $options )
{
2022-11-24 12:50:11 +01:00
$bsBadge = new BootstrapBadge ( $options );
2021-03-10 09:28:33 +01:00
return $bsBadge -> badge ();
}
2021-03-10 09:32:18 +01:00
public function modal ( $options )
{
2022-11-24 12:50:11 +01:00
$bsModal = new BootstrapModal ( $options );
2021-06-12 11:57:49 +02:00
return $bsModal -> modal ();
}
2021-11-23 15:29:55 +01:00
2021-06-21 08:43:37 +02:00
public function card ( $options )
{
2022-11-24 12:50:11 +01:00
$bsCard = new BootstrapCard ( $options );
2021-06-21 08:43:37 +02:00
return $bsCard -> card ();
}
2021-06-12 11:57:49 +02:00
public function progress ( $options )
{
2022-11-24 12:50:11 +01:00
$bsProgress = new BootstrapProgress ( $options );
2021-06-12 11:57:49 +02:00
return $bsProgress -> progress ();
}
public function collapse ( $options , $content )
{
2022-11-24 12:50:11 +01:00
$bsCollapse = new BootstrapCollapse ( $options , $content , $this );
2021-06-12 11:57:49 +02:00
return $bsCollapse -> collapse ();
}
2021-10-28 09:27:30 +02:00
public function accordion ( $options , $content )
{
2022-11-24 12:50:11 +01:00
$bsAccordion = new BootstrapAccordion ( $options , $content , $this );
2021-10-28 09:27:30 +02:00
return $bsAccordion -> accordion ();
}
2021-06-12 11:57:49 +02:00
public function progressTimeline ( $options )
{
2022-11-24 12:50:11 +01:00
$bsProgressTimeline = new BootstrapProgressTimeline ( $options , $this );
2021-06-12 11:57:49 +02:00
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-09-13 13:02:33 +02:00
public function switch ( $options )
{
2022-11-24 12:50:11 +01:00
$bsSwitch = new BootstrapSwitch ( $options , $this );
2021-09-13 13:02:33 +02:00
return $bsSwitch -> switch ();
}
2021-10-20 09:36:32 +02:00
2022-02-08 17:57:20 +01:00
public function notificationBubble ( $options )
{
2022-11-24 12:50:11 +01:00
$bsNotificationBubble = new BootstrapNotificationBubble ( $options , $this );
2022-02-08 17:57:20 +01:00
return $bsNotificationBubble -> notificationBubble ();
}
2021-10-20 09:36:32 +02:00
public function dropdownMenu ( $options )
{
2022-11-24 12:50:11 +01:00
$bsDropdownMenu = new BootstrapDropdownMenu ( $options , $this );
2021-10-20 09:36:32 +02:00
return $bsDropdownMenu -> dropdownMenu ();
}
2022-11-24 12:50:11 +01:00
public function toast ( $options )
{
$bsToast = new BootstrapToast ( $options , $this );
return $bsToast -> toast ();
}
public function node ( $tag , $attrs = [], $content = '' , $options = []) : string
{
return BootstrapGeneric :: node ( $tag , $attrs , $content , $options );
}
public function render ( $template , $data = [], $options = [])
{
return BootstrapGeneric :: render ( $template , $data , $options );
}
2021-02-22 15:47:30 +01:00
}
2022-11-24 12:50:11 +01:00
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 )));
}
}
}
2022-11-24 12:50:11 +01:00
/**
* Replaces {{ placeholders }} inside a $template with the given $data
*
* Example :
* `` `
* render ( '{{name}} is {{age}} years old.' , [ 'name' => 'Bob' , 'age' => '65' ]);
* `` `
* Returns : Bob is 65 years old .
*
* @ param string $template The template containing the placeholders
* @ param array $data A K - V array where keys are placeholder name to be replaced by their value
* @ param array < string , mixed > $options Array of options passed to the Text :: insert function
* @ return string
*/
public static function render ( string $template , array $data , array $options = []) : string
{
$defaults = [
'before' => '{{' , 'after' => '}}' , 'escape' => '\\' , 'format' => null , 'clean' => false ,
2020-12-04 16:08:11 +01:00
];
2022-11-24 12:50:11 +01:00
$options += $defaults ;
return Text :: insert (
$template ,
$data ,
$options
);
2020-12-04 16:08:11 +01:00
}
2022-11-24 12:50:11 +01:00
/**
* Creates an HTML node
*
* ### Options
*
* - `escape` Set to false to disable escaping of attribute value .
*
* @ param string $tag The tag of the node . Example : 'div' , 'span'
* @ param array $attrs Attributes to be added to the node
* @ param string | array < string > $content Optional content to be added as innerHTML . If an array is given , it gets converted into string
* @ param array $options Array of options
* @ return string
*/
public static function node ( string $tag , array $attrs = [], $content = '' , array $options = []) : string
{
return self :: render (
'<{{tag}} {{attrs}}>{{content}}</{{tag}}>' ,
2021-11-23 15:29:55 +01:00
[
2022-11-24 12:50:11 +01:00
'tag' => $tag ,
'attrs' => self :: buildAttrs ( $attrs , $options ),
'content' => is_array ( $content ) ? implode ( '' , $content ) : $content ,
2021-11-23 15:29:55 +01:00
]
2022-11-24 12:50:11 +01:00
);
2020-12-04 16:08:11 +01:00
}
2022-11-24 12:50:11 +01:00
public static function nodeOpen ( string $tag , array $attrs = [], array $options = []) : string
2020-12-04 16:08:11 +01:00
{
2022-11-24 12:50:11 +01:00
return self :: render (
'<{{tag}} {{attrs}}>' ,
[
'tag' => $tag ,
'attrs' => self :: buildAttrs ( $attrs , $options ),
]
);
2020-12-04 16:08:11 +01:00
}
2022-11-24 12:50:11 +01:00
public static function nodeClose ( string $tag ) : string
2020-12-04 16:08:11 +01:00
{
2022-11-24 12:50:11 +01:00
return self :: render (
'</{{tag}}>' ,
[
'tag' => $tag ,
]
);
2020-12-04 16:08:11 +01:00
}
2021-02-22 15:47:30 +01:00
2022-11-24 12:50:11 +01:00
/**
* Build a space - delimited string with each HTML attribute generated .
*
* @ param array $attrs
* @ param array < string , mixed > $options Array of options
* @ return string
*/
public static function buildAttrs ( array $attrs , array $options ) : string
2021-11-23 15:29:55 +01:00
{
2022-11-24 12:50:11 +01:00
$defaults = [
'escape' => true ,
2021-02-22 15:47:30 +01:00
];
2022-11-24 12:50:11 +01:00
$options = $options + $defaults ;
2020-12-04 16:08:11 +01:00
2022-11-24 12:50:11 +01:00
$attributes = [];
foreach ( $attrs as $key => $value ) {
if ( ! empty ( $key ) && $value !== null ) {
$attributes [] = self :: __formatAttribute (( string ) $key , $value , $options [ 'escape' ]);
}
2020-12-04 16:08:11 +01:00
}
2022-11-24 12:50:11 +01:00
$html = trim ( implode ( ' ' , $attributes ));
2020-12-04 16:08:11 +01:00
return $html ;
}
2022-11-24 12:50:11 +01:00
/**
* Format an individual HTML attribute
* Support minimized attributes such as `selected` and `disabled`
*
* @ param string $key The name of the attribute
* @ param array < string >| string $value The value of the attribute
* @ param bool $escape Should the attribute value be escaped
* @ return string
*/
public static function __formatAttribute ( string $key , $value , bool $escape = true ) : string
{
$value = is_array ( $value ) ? implode ( ' ' , $value ) : $value ;
if ( is_numeric ( $key )) {
return sprintf ( '%s="%s"' , h ( $value ), ( ! empty ( $escape ) ? h ( $value ) : $value ));
}
$isMinimized = isset ( COMPACT_ATTRIBUTES [ $key ]);
if ( $isMinimized ) {
if ( ! empty ( $value )) {
return sprintf ( '%s="%s"' , h ( $key ), ( ! empty ( $escape ) ? h ( $value ) : $value ));
2021-02-22 16:38:55 +01:00
}
2022-11-24 12:50:11 +01:00
return '' ;
} else if ( empty ( $value )) {
return '' ;
2021-02-23 11:42:26 +01:00
}
2022-11-24 12:50:11 +01:00
return sprintf ( '%s="%s"' , h ( $key ), ( ! empty ( $escape ) ? h ( $value ) : $value ));
2021-02-23 11:42:26 +01:00
}
2022-11-24 12:50:11 +01:00
protected static function genHTMLParams ( $params )
2021-02-23 11:42:26 +01:00
{
2022-11-24 12:50:11 +01:00
$html = '' ;
foreach ( $params as $k => $v ) {
if ( ! empty ( $k ) && ( isset ( $v ) && $v !== '' )) {
$html .= BootstrapGeneric :: genHTMLParam ( $k , $v ) . ' ' ;
2021-02-22 16:38:55 +01:00
}
}
2021-02-23 11:42:26 +01:00
return $html ;
}
2022-11-24 12:50:11 +01:00
protected static function genHTMLParam ( $paramName , $values )
2021-02-23 11:42:26 +01:00
{
2022-11-24 12:50:11 +01:00
if ( ! is_array ( $values )) {
$values = [ $values ];
2021-02-23 11:42:26 +01:00
}
2022-11-24 12:50:11 +01:00
return sprintf ( '%s="%s"' , $paramName , implode ( ' ' , $values ));
2021-07-06 12:34:53 +02:00
}
2022-11-24 12:50:11 +01:00
protected static function convertToArrayIfNeeded ( $data ) : array
2021-07-06 12:34:53 +02:00
{
2022-11-24 12:50:11 +01:00
return is_array ( $data ) ? $data : [ $data ];
2021-07-06 12:34:53 +02:00
}
2022-11-24 12:50:11 +01:00
protected static function genericCloseButton ( $dismissTarget )
2021-07-06 12:34:53 +02:00
{
2022-11-24 12:50:11 +01:00
return self :: node ( 'button' , [
'type' => 'button' ,
'class' => 'btn-close' ,
'data-bs-dismiss' => $dismissTarget ,
'arial-label' => __ ( 'Close' )
2021-07-06 12:34:53 +02:00
]);
}
2022-11-24 12:50:11 +01:00
protected static function getTextClassForVariant ( string $variant ) : string
2021-07-06 12:34:53 +02:00
{
2022-11-24 12:50:11 +01:00
return ! empty ( self :: $textClassByVariants [ $variant ]) ? self :: $textClassByVariants [ $variant ] : 'text-black' ;
2021-07-06 12:34:53 +02:00
}
2022-11-24 12:50:11 +01:00
protected static function getBGAndTextClassForVariant ( string $variant ) : string
2021-07-06 12:34:53 +02:00
{
2022-11-24 12:50:11 +01:00
return sprintf ( 'bg-%s %s' , $variant , self :: getTextClassForVariant ( $variant ));
2021-10-20 09:36:32 +02:00
}
2021-11-23 15:29:55 +01:00
}