Commit 592c4759 authored by Sylvain's avatar Sylvain

Initial commit

parents
Pipeline #2 canceled with stages
MIT License
Copyright (c) 2020 Modulus / Services
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.
# Modulus Service Field
A helper to generate HTML form fields in Bootstrap very easily
## Required
- Composer
- PHP >= 7.2
- Laravel >= 5.8
## Installation
Require this package with composer.
```shell
composer require goldenscarab/modulus-service-field
```
Laravel 5.8 uses Package Auto-Discovery, so doesn't require you to manually add the ServiceProvider.
## Usage
```php
// Exemple sur une liste d'utilisateurs
{!! Template::list3([
'table_id' => null,
'table_class' => 'table-sortable',
'route_prefix' => $route_prefix,
'can_prefix' => $can_prefix,
'menu' => [
'display' => true,
'is_readable' => true,
'is_editable' => true,
'is_deletable' => true,
'is_duplicable' => false,
],
'source' => $items,
'columns' => array([
'label' => '#',
'value' => ['id'],
'sortable' => 'id'
],[
'label' => 'Dossier',
'value' => ['folder_html'],
'sortable' => 'ged_folders.title'
],[
'label' => 'Nom',
'value' => ['name'],
'sortable' => 'name',
],[
'label' => 'Version',
'value' => ['template' => 'v%s', 'key' => 'version'],
'sortable' => 'version',
'class' => 'text-center'
],[
'label' => 'Statut',
'value' => ['validation_html'],
'class' => 'text-center'
],[
'label' => 'Visibilité',
'class' => 'text-center',
'value' => ['key' => 'status', 'callback' => 'published_html'],
'sortable' => 'status',
],[
'label' => 'Date',
'value' => ['updated_at->diffForHumans()'],
'sortable' => 'updated_at'
]
)
]) !!}
```
Click [here](example.md) for more examples
## Security
If you discover any security related issues, please email contact@goldenscarab.fr instead of using the issue tracker.
## Credits
- [Sylvain CARRE](https://git.goldenscarab.fr/modulus)
## License
The MIT License (MIT). Please see [License File](LICENSE.md) for more information.
{
"name": "goldenscarab/modulus-service-template",
"description": "An helper to create html list easily",
"require": {
"php": ">=7.1.3"
},
"license": "MIT",
"authors": [
{
"name": "Goldenscarab",
"email": "web@goldenscarab.fr"
}
],
"autoload": {
"psr-4": {
"Goldenscarab\\Modulus\\Service\\Template\\": "src/"
},
"files": [
]
},
"minimum-stability": "dev",
"prefer-stable": true,
"extra": {
"laravel": {
"providers": [
"Goldenscarab\\Modulus\\Service\\Template\\TemplateServiceProvider"
],
"aliases": {
"Template": "Goldenscarab\\Modulus\\Service\\Template\\Facades\\Template"
}
}
},
"require-dev": {
"laravel/framework": "5.8.x"
}
}
# Templates
## Liste
### Utilisation minimale
```php
// Exemple sur liste utilisateurs
{!! Template::list3([
'table_id' => null,
'table_class' => 'table-sortable',
'route_prefix' => $route_prefix,
'can_prefix' => $can_prefix,
'menu' => [
'display' => true,
'is_readable' => true,
'is_editable' => true,
'is_deletable' => true,
'is_duplicable' => false,
],
'source' => $items,
'columns' => array([
'label' => '#',
'value' => ['id'],
'sortable' => 'id'
],[
'label' => 'Dossier',
'value' => ['folder_html'],
'sortable' => 'ged_folders.title'
],[
'label' => 'Nom',
'value' => ['name'],
'sortable' => 'name',
],[
'label' => 'Version',
'value' => ['template' => 'v%s', 'key' => 'version'],
'sortable' => 'version',
'class' => 'text-center'
],[
'label' => 'Statut',
'value' => ['validation_html'],
'class' => 'text-center'
],[
'label' => 'Visibilité',
'class' => 'text-center',
'value' => ['key' => 'status', 'callback' => 'published_html'],
'sortable' => 'status',
],[
'label' => 'Date',
'value' => ['updated_at->diffForHumans()'],
'sortable' => 'updated_at'
]
)
]) !!}
```
### Utilisation avancée
```php
// Exemple sur liste utilisateurs
{!! Template::list3([
'table_id' => null,
'table_class' => 'table-sortable',
'route_prefix' => $route_prefix,
'can_prefix' => $can_prefix,
'menu' => [
'display' => true,
'is_readable' => true,
'is_editable' => true,
'is_deletable' => true,
'is_duplicable' => false,
'tags' => array(
['template' => '[module|ged|document|%s]', 'key' => 'id']
),
'more' => array([
'label' => '<i class="fa fa-unlock mr-1"></i> RAZ validation',
'href' => [
'template' => url('backend/module/ged/file/status/%s/0?' . current_query_to_string()),
'key' => 'files->sortBy()->last()->id'
],
]
)
],
'source' => $items,
'rows' => array(
'class' => [
'value' => 'text-bold',
'condition' => [
'key' => 'file_current_version.status',
'operator' => '==',
'value' => -1
]
],
),
'columns' => array([
'label' => '',
'id' => 'mon-id',
'class' => 'ma-class',
'value' => [
'template' => '<img class="thumb-list" src="%s" alt="image" width=50 />',
'key' => 'image_type_url']
],[
'label' => '#',
'value' => ['id'],
'sortable' => 'id'
],[
'label' => 'Dossier',
'value' => ['key' => 'folder_html'],
'sortable' => 'ged_folders.title'
],[
'label' => 'Nom',
'value' => ['name'],
'sortable' => 'name',
],[
'label' => 'Version',
'value' => ['template' => 'v%s', 'key' => 'version'],
'sortable' => 'version',
'class' => 'text-center'
],[
'label' => 'Statut',
'value' => ['validation_html'],
'class' => 'text-center'
],[
'label' => 'Visibilité',
'class' => 'text-center',
'value' => ['key' => 'status', 'callback' => 'published_html'],
'sortable' => 'status',
],[
'label' => 'Date',
'value' => ['updated_at->diffForHumans()'],
'sortable' => 'updated_at'
],[
'value' => ['download_file_html'],
]
)
]) !!}
```
<?php
namespace Goldenscarab\Modulus\Service\Template\Compose;
use Illuminate\Support\Facades\Request;
use \Illuminate\Support\HtmlString;
class Template1Bt4
{
private $route_prefix;
private $route_param;
private $table_id;
private $table_class;
private $can_prefix;
private $has_menu;
private $is_editable;
private $is_deletable;
private $is_readable;
private $is_duplicable;
private $_add_row;
private $_datas;
private $_tags;
private $_menu_items;
public function __construct($attrs = [])
{
$this->setAttrs($attrs);
}
/**
* Retourne le rendu d'un tableau liste
* @return string le rendu du tableau liste
*/
public function renderList(): string
{
$template = '<div class="table-responsive-lg" style="min-height: 250px;">' . PHP_EOL;
$template .= ' <table id="%s" class="%s">' . PHP_EOL;
$template .= ' <thead>' . PHP_EOL;
$template .= ' <tr>' . PHP_EOL;
$template .= '%s';
$template .= ' </tr>' . PHP_EOL;
$template .= ' </thead>' . PHP_EOL;
$template .= ' <tbody>' . PHP_EOL;
$template .= '%s';
$template .= ' </tbody>' . PHP_EOL;
$template .= ' </table>';
$template .= '</div>';
$render = vsprintf($template, [
empty($this->table_id) ? 'table-' . str_slug($this->route_prefix) : $this->table_id,
trim('table table-sm table-hover table-striped ' . $this->table_class),
$this->renderIndent($this->renderListHead(), 3),
$this->renderIndent($this->renderListBody(), 2),
]);
return $render;
}
/**
* Retourne le rendu des entêtes de colonnes d'un tableau liste
* @return string Le rendu des entêtes de colonnes
*/
public function renderListHead(): string
{
$template = '<th scope="col"%s>%s%s</th>' . PHP_EOL;
$render = '';
$columns = $this->_datas['columns'];
// Colonne titre
if (is_iterable($columns)) {
foreach ($columns as $column) {
$sortable = data_get($column, 'sortable');
$class = data_get($column, 'class') . ' text-nowrap';
$render .= vsprintf($template, [
$this->renderClass($class),
data_get($column, 'label'),
is_null($sortable) ? '' : col_sort($sortable)
]);
}
}
// Colonne menu
$render .= vsprintf($template, ['','', '']);
return $render;
}
/**
* Retourne le rendu des lignes d'un tableau liste
* @return string Le rendu des lignes du tableau
*/
public function renderListBody(): string
{
$template_row = '<tr scope="row"%s>' . PHP_EOL;
$template_row .= '%s';
$template_row .= '</tr>' . PHP_EOL;
$template_cel = '<td%s%s>%s</td>' . PHP_EOL;
$render = '';
$collection = $this->_datas['collection'];
$columns = $this->_datas['columns'];
if (is_iterable($collection)) {
if (count($collection) == 0) {
$render_cels_row = vsprintf($template_cel, [
' colspan="' . (count($columns) + 1) .'"',
null,
'Aucun élément disponible'
]);
$render .= vsprintf($template_row, [
null,
$this->renderIndent($render_cels_row, 1)
]);
}
foreach ($collection as $item) {
$render_cels_row = '';
if (is_iterable($columns)) {
foreach ($columns as $column) {
$template = data_get($column, 'template');
$name = data_get($column, 'name');
$callback = data_get($column, 'callback');
$text = $this->objectToString($template, $name, $callback, $item);
$attributes = data_get($column, 'attributes');
$class = data_get($column, 'class');
// Création de la cellule
$render_cels_row .= vsprintf($template_cel, [
$this->renderAttributes($attributes, $item),
$this->renderClass($class),
$text
]);
}
// Ajout du menu en fin de ligne
$render_cels_row .= vsprintf($template_cel, [
null,
null,
$this->has_menu ? $this->renderListMenuItems($item) : ''
]);
}
$render .= vsprintf($template_row, [
$this->renderAddRow($item),
$this->renderIndent($render_cels_row, 1)
]);
}
}
return $render;
}
/**
* Retourne le rendu d'ajout à une ligne en fonction d'une condition
* @param Mix $item L'élément concerné par la condition
* @return string Le rendu à rajouter à la ligne
*/
private function renderAddRow($item): string
{
$render = '';
if (count($this->_add_row) > 0) {
$column = data_get($this->_add_row, 'condition.0');
$operator = data_get($this->_add_row, 'condition.1');
$value = data_get($this->_add_row, 'condition.2');
switch ($operator) {
case '==' :
$required_add = (data_get($item, $column) == $value ? true : false);
break;
case '>' :
$required_add = (data_get($item, $column) > $value ? true : false);
break;
case '<' :
$required_add = (data_get($item, $column) < $value ? true : false);
break;
case '!=' :
$required_add = (data_get($item, $column) != $value ? true : false);
break;
case '<=' :
$required_add = (data_get($item, $column) <= $value ? true : false);
break;
case '>=' :
$required_add = (data_get($item, $column) >= $value ? true : false);
break;
default :
$required_add = false;
}
if ($required_add) {
$render = sprintf(' class="%s"', data_get($this->_add_row, 'class'));
}
}
return $render;
}
private function renderListMenuItems($item): string
{
$template = '<div class="dropdown">' . PHP_EOL;
$template .= ' <button class="btn btn-default btn-xs dropdown-toggle no-caret square-to-circle item-option" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">' . PHP_EOL;
$template .= ' <i class="fa fa-cog" aria-hidden="true"></i>' . PHP_EOL;
$template .= ' </button>' . PHP_EOL;
$template .= ' <div class="dropdown-menu dropdown-menu-right">' . PHP_EOL;
$template .= '%s';
$template .= '%s';
$template .= '%s';
$template .= '%s';
$template .= '%s';
$template .= '%s';
$template .= ' </div>' . PHP_EOL;
$render = '';
$render = vsprintf($template, [
$this->renderIndent($this->renderListMenuItemRead($item), 2),
$this->renderIndent($this->renderListMenuItemUpdate($item), 2),
$this->renderIndent($this->renderListMenuItemTag($item), 2),
$this->renderIndent($this->renderListMenuItemMore($item), 2),
$this->renderIndent($this->renderListMenuItemDuplicate($item), 2),
$this->renderIndent($this->renderListMenuItemDelete($item), 2),
]);
return $render;
}
private function renderListMenuItemRead($item): string
{
$render = '';
if (auth()->user()->can($this->can_prefix . '-read')) {
if ($this->is_readable) {
$template = '<a class="dropdown-item" href="%s">' . PHP_EOL;
$template .= ' <i class="fa fa-eye mr-1"></i>Voir' . PHP_EOL;
$template .= '</a>' . PHP_EOL;
if (empty($this->route_param)) {
$render = sprintf($template, route($this->route_prefix . '.' . 'read', array_merge([$item->id], Request::query())));
} else {
$render = sprintf($template, route($this->route_prefix . '.' . 'read', array_merge([$this->route_param, $item->id ], Request::query())));
}
}
}
return $render;
}
private function renderListMenuItemUpdate($item): string
{
$render = '';
if (auth()->user()->can($this->can_prefix . '-update')) {
if ($this->is_editable) {
$template = '<a class="dropdown-item" href="%s">' . PHP_EOL;
$template .= ' <i class="fa fa-pencil-square-o mr-1"></i>Modifier' . PHP_EOL;
$template .= '</a>' . PHP_EOL;
if (empty($this->route_param)) {
$render = sprintf($template, route($this->route_prefix . '.' . 'update', array_merge([$item->id], Request::query())));
} else {
$render = sprintf($template, route($this->route_prefix . '.' . 'update', array_merge([$this->route_param, $item->id ], Request::query())));
}
}
}
return $render;
}
private function renderListMenuItemTag($item): string
{
$render = '';
if (auth()->user()->hasRole('admin')) {
if (count($this->_tags) > 0) {
$template = '<a class="dropdown-item clipboard-copy" href="#" title="Copier le Tag" data-clipboard-action="copy" data-clipboard-text="%s">' . PHP_EOL;
$template .= ' <i class="fa fa-clipboard mr-1"></i>%s' . PHP_EOL;
$template .= '</a>' . PHP_EOL;
foreach ($this->_tags as $attr => $template_tag) {
$render_tag = sprintf($template_tag, data_get($item, $attr));
$render .= vsprintf($template, [$render_tag, $render_tag]);
}
}
}
return $render;
}
private function renderListMenuItemMore($item): string
{
$render = '';
if (auth()->user()->can($this->can_prefix . '-read')) {
$menu_items = $this->_menu_items;
if (count($menu_items) > 0) {
$template = '<a class="dropdown-item" href="%s" target="%s">' . PHP_EOL;
$template .= ' %s' . PHP_EOL;
$template .= '</a>' . PHP_EOL;
foreach ($menu_items as $menu_item) {
$href = data_get($menu_item, 'href');
$name = data_get($menu_item, 'name');
$callback = data_get($menu_item, 'callback');
$url = $this->objectToString($href, $name, $callback, $item);
$render .= vsprintf($template, [
$url,
$menu_item['target'] ?? '_self',
$menu_item['label']
]);
}
}
}
return $render;
}
private function renderListMenuItemDuplicate($item): string
{
$render = '';
if (auth()->user()->can($this->can_prefix . '-create')) {
if ($this->is_duplicable) {
$template = '<a class="dropdown-item" href="%s">' . PHP_EOL;
$template .= ' <i class="fa fa-clone mr-1"></i>Dupliquer' . PHP_EOL;
$template .= '</a>' . PHP_EOL;
if (empty($this->route_param)) {
$render = sprintf($template, route($this->route_prefix . '.' . 'duplicate', array_merge([$item->id], Request::query())));
} else {
$render = sprintf($template, route($this->route_prefix . '.' . 'duplicate', array_merge([$this->route_param, $item->id], Request::query())));
}
}
}
return $render;
}
private function renderListMenuItemDelete($item): string
{
$render = '';
if (auth()->user()->can($this->can_prefix . '-delete')) {
if ($this->is_deletable) {
$template = '<div class="dropdown-divider"></div>' . PHP_EOL;
$template .= '<a class="dropdown-item delete" href="#" data-href="%s">' . PHP_EOL;
$template .= ' <i class="fa fa-trash mr-1"></i>Supprimer' . PHP_EOL;
$template .= '</a>' . PHP_EOL;
if (empty($this->route_param)) {
$render = sprintf($template, route($this->route_prefix . '.' . 'delete', array_merge([$item->id], Request::query())));
} else {
$render = sprintf($template, route($this->route_prefix . '.' . 'delete', array_merge([$this->route_param, $item->id], Request::query())));
}
}
}
return $render;
}
/**
* Retourne le rende d'un paramètre class
* @param string $class Le contenu du paramètre
* @return string Le rendu du paramètre class
*/
private function renderClass($class): string
{
$render = '';
$template = ' class="%s"';
if (!empty($class)) {
$render = sprintf($template, $class);
}
return $render;
}
/**
* Retourne le rendu d'attributs avec leur valeur
* @param array $attrs Les attributs avec la colonne de l'object conteant la valeur
* @param Object $item Object contenant la valeur de l'attribut
* @return string Le rendu des attributs avec leur valeur
*/
private function renderAttributes($attrs = [], $item): string
{
$render = '';
if (is_iterable($attrs)) {
$template = ' %s="%s"';
foreach ($attrs as $name => $value) {
$render .= vsprintf($template, [$name, $this->objectToString(null, $value, null, $item)]);
}
}
return $render;
}
/**
* Retourne le rendu d'un template avec une liste de noms de colonnes
* @param string $template Le template servant au rendu
* @param string|array $display Le ou les nom de colonnes
* @param string $eval Chaine de caractère à executer comme du php
* @param Mix $item Objet source des donnés à afficher
* @param boolean $strip Supprimer les balises HTML
* @return string Le rendu
*/
private function objectToString($template = null, $displays = null, $callback = null, $item, $strip = false)
{
// Création du texte à afficher
$datas = [];
// Convertion en tableau si besoin
if (!is_iterable($displays)) {
$displays = [$displays];
}
// Traitement du tableau de valeur à afficher
foreach ($displays as $key => $display) {
$data = mixte_get($item, $display);
// Callback array
if (is_array($callback) && isset($callback[$key]) && !is_null($callback[$key])) {
$data = $callback[$key]($data);
}
$datas[] = $strip ? strip_tags($data) : $data;
}
// Traitement des % seuls pour éviter les conflits
if (!empty($template)) {
$template = preg_replace('/(%)[^0-9sd.\']/i', '%%"', $template);
}
// Traitement template & callback
if (is_string($callback)) {
if (empty($template)) {
$string = call_user_func_array($callback, $datas);
} else {
$string = vsprintf($template, $datas);
$string = $callback($string);
}
} else if (!empty($template)) {
$string = vsprintf($template, $datas);
} else {
$string = $datas[0];
}
return $string;
}
/**
* Retourne le rendu d'une chaine de caractère en HTML
* @param String $string La chains de caractères à traiter
* @return String Le rendu HTML
*/
public function renderHTML($string): string
{
return new HtmlString($string);
}
/**
* Retourne le rendu avec indentation d'un texte
* @param string $text Le texte à traiter
* @param Integer $nb Le nombre d'indentation à appliquer
* @return string Le rendu avec indentation
*/
private function renderIndent($text, $nb): string
{
$indent = ' ';
$render = '';
$real_indent = '';
for ($i = 1; $i <= $nb; $i++) {
$real_indent .= $indent;
}
$lines = explode(PHP_EOL, $text);
foreach ($lines as $line) {
if (!empty($line)) {
$render .= $real_indent . $line . PHP_EOL;
}
}
return $render;
}
/**
* Mise à jour des attributs depuis le tableau passé en paramètre
* @param Array $attrs Liste des attributs à traiter
* @return void
*/
private function setAttrs($attrs)
{
$this->resetAttrs();
if (is_null($attrs)) {
return ;
}
// Liste des attributs autorisés
$attrs_available = array_map(function ($val) {
return trim($val, '_');
}, array_keys(get_object_vars($this)));
// Traitement des attributs
if (is_array($attrs)) {
foreach ($attrs as $attr => $value) {
if (in_array($attr, $attrs_available)) {
if (is_array($value)) {
$this->{'_' . $attr} = $value;
} else {
$this->{$attr} = $value;
}
} else {
throw new \InvalidArgumentException("Le paramètre [" . $attr . "] n'est pas pris en charge");
}
}
} else {
throw new \InvalidArgumentException("Type de paramètre invalide. Attendu : Tableau");
}
}
/**
* Réinitialisation des attributs de constructions
* @return void
*/
private function resetAttrs()
{
$attrs = array_keys(get_object_vars($this));
foreach ($attrs as $attr) {
if (preg_match('/^_.*/', $attr)) {
$this->{$attr} = [];
} else if (preg_match('/^is_.*/', $attr)) {
$this->{$attr} = false;
} else {
$this->{$attr} = null;
}
}
}
}
<?php
namespace Goldenscarab\Modulus\Service\Template\Compose;
use Illuminate\Support\Facades\Request;
use \Illuminate\Support\HtmlString;
use Illuminate\Support\FacadesRequest;
class Template2Bt4
{
private $route_prefix;
private $route_param;
private $table_id;
private $table_class;
private $can_prefix;
private $has_menu;
private $is_editable;
private $is_deletable;
private $is_readable;
private $is_duplicable;
private $_add_row;
private $_datas;
private $_tags;
private $_menu_items;
public function __construct($attrs = [])
{
$this->setAttrs($attrs);
}
/**
* Retourne le rendu d'un tableau liste
* @return string le rendu du tableau liste
*/
public function renderList(): string
{
$template = '<div class="table-responsive-lg" style="min-height: 250px;">' . PHP_EOL;
$template .= ' <table id="%s" class="%s">' . PHP_EOL;
$template .= ' <thead>' . PHP_EOL;
$template .= ' <tr>' . PHP_EOL;
$template .= '%s';
$template .= ' </tr>' . PHP_EOL;
$template .= ' </thead>' . PHP_EOL;
$template .= ' <tbody>' . PHP_EOL;
$template .= '%s';
$template .= ' </tbody>' . PHP_EOL;
$template .= ' </table>';
$template .= '</div>';
$render = vsprintf($template, [
empty($this->table_id) ? 'table-' . str_slug($this->route_prefix) : $this->table_id,
trim('table table-sm table-hover table-striped ' . $this->table_class),
$this->renderIndent($this->renderListHead(), 3),
$this->renderIndent($this->renderListBody(), 2),
]);
return $render;
}
/**
* Retourne le rendu des entêtes de colonnes d'un tableau liste
* @return string Le rendu des entêtes de colonnes
*/
public function renderListHead(): string
{
$template = '<th scope="col"%s>%s%s</th>' . PHP_EOL;
$render = '';
$columns = $this->_datas['columns'];
// Colonne titre
if (is_iterable($columns)) {
foreach ($columns as $column) {
$sortable = data_get($column, 'sortable');
$class = data_get($column, 'class') . ' text-nowrap';
$render .= vsprintf($template, [
$this->renderClass($class),
data_get($column, 'label'),
is_null($sortable) ? '' : col_sort($sortable)
]);
}
}
// Colonne menu
$render .= vsprintf($template, ['','', '']);
return $render;
}
/**
* Retourne le rendu des lignes d'un tableau liste
* @return string Le rendu des lignes du tableau
*/
public function renderListBody(): string
{
$template_row = '<tr scope="row"%s>' . PHP_EOL;
$template_row .= '%s';
$template_row .= '</tr>' . PHP_EOL;
$template_cel = '<td%s%s>%s</td>' . PHP_EOL;
$render = '';
$collection = $this->_datas['collection'];
$columns = $this->_datas['columns'];
if (is_iterable($collection)) {
if (count($collection) == 0) {
$render_cels_row = vsprintf($template_cel, [
' colspan="' . (count($columns) + 1) .'"',
null,
'Aucun élément disponible'
]);
$render .= vsprintf($template_row, [
null,
$this->renderIndent($render_cels_row, 1)
]);
}
foreach ($collection as $item) {
$render_cels_row = '';
if (is_iterable($columns)) {
foreach ($columns as $column) {
$template = data_get($column, 'template');
$name = data_get($column, 'name');
$callback = data_get($column, 'callback');
$text = $this->objectToString($template, $name, $callback, $item);
$attributes = data_get($column, 'attributes');
$class = data_get($column, 'class');
// Création de la cellule
$render_cels_row .= vsprintf($template_cel, [
$this->renderAttributes($attributes, $item),
$this->renderClass($class),
$text
]);
}
// Ajout du menu en fin de ligne
$render_cels_row .= vsprintf($template_cel, [
null,
null,
$this->has_menu ? $this->renderListMenuItems($item) : ''
]);
}
$render .= vsprintf($template_row, [
$this->renderAddRow($item),
$this->renderIndent($render_cels_row, 1)
]);
}
}
return $render;
}
/**
* Retourne le rendu d'ajout à une ligne en fonction d'une condition
* @param Mix $item L'élément concerné par la condition
* @return string Le rendu à rajouter à la ligne
*/
private function renderAddRow($item): string
{
$render = '';
if (count($this->_add_row) > 0) {
$column = data_get($this->_add_row, 'condition.0');
$operator = data_get($this->_add_row, 'condition.1');
$value = data_get($this->_add_row, 'condition.2');
switch ($operator) {
case '==' :
$required_add = (data_get($item, $column) == $value ? true : false);
break;
case '>' :
$required_add = (data_get($item, $column) > $value ? true : false);
break;
case '<' :
$required_add = (data_get($item, $column) < $value ? true : false);
break;
case '!=' :
$required_add = (data_get($item, $column) != $value ? true : false);
break;
case '<=' :
$required_add = (data_get($item, $column) <= $value ? true : false);
break;
case '>=' :
$required_add = (data_get($item, $column) >= $value ? true : false);
break;
default :
$required_add = false;
}
if ($required_add) {
$render = sprintf(' class="%s"', data_get($this->_add_row, 'class'));
}
}
return $render;
}
private function renderListMenuItems($item): string
{
$template = '<div class="dropdown">' . PHP_EOL;
$template .= ' <button class="btn btn-default btn-xs dropdown-toggle no-caret square-to-circle item-option" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">' . PHP_EOL;
$template .= ' <i class="fa fa-cog" aria-hidden="true"></i>' . PHP_EOL;
$template .= ' </button>' . PHP_EOL;
$template .= ' <div class="dropdown-menu dropdown-menu-right">' . PHP_EOL;
$template .= '%s';
$template .= '%s';
$template .= '%s';
$template .= '%s';
$template .= '%s';
$template .= '%s';
$template .= ' </div>' . PHP_EOL;
$render = '';
$render = vsprintf($template, [
$this->renderIndent($this->renderListMenuItemRead($item), 2),
$this->renderIndent($this->renderListMenuItemUpdate($item), 2),
$this->renderIndent($this->renderListMenuItemTag($item), 2),
$this->renderIndent($this->renderListMenuItemMore($item), 2),
$this->renderIndent($this->renderListMenuItemDuplicate($item), 2),
$this->renderIndent($this->renderListMenuItemDelete($item), 2),
]);
return $render;
}
private function renderListMenuItemRead($item): string
{
$render = '';
if (auth()->user()->can($this->can_prefix . '-read')) {
if ($this->is_readable) {
$template = '<a class="dropdown-item" href="%s">' . PHP_EOL;
$template .= ' <i class="fa fa-eye mr-1"></i>Voir' . PHP_EOL;
$template .= '</a>' . PHP_EOL;
if (empty($this->route_param)) {
$render = sprintf($template, route($this->route_prefix . '.' . 'read', array_merge([$item->id], Request::query())));
} else {
$render = sprintf($template, route($this->route_prefix . '.' . 'read', array_merge([$this->route_param, $item->id ], Request::query())));
}
}
}
return $render;
}
private function renderListMenuItemUpdate($item): string
{
$render = '';
if (auth()->user()->can($this->can_prefix . '-update')) {
if ($this->is_editable) {
$template = '<a class="dropdown-item" href="%s">' . PHP_EOL;
$template .= ' <i class="fa fa-pencil-square-o mr-1"></i>Modifier' . PHP_EOL;
$template .= '</a>' . PHP_EOL;
if (empty($this->route_param)) {
$render = sprintf($template, route($this->route_prefix . '.' . 'update', array_merge([$item->id], Request::query())));
} else {
$render = sprintf($template, route($this->route_prefix . '.' . 'update', array_merge([$this->route_param, $item->id ], Request::query())));
}
}
}
return $render;
}
private function renderListMenuItemTag($item): string
{
$render = '';
if (auth()->user()->hasRole('admin')) {
if (count($this->_tags) > 0) {
$template = '<a class="dropdown-item clipboard-copy" href="#" title="Copier le Tag" data-clipboard-action="copy" data-clipboard-text="%s">' . PHP_EOL;
$template .= ' <i class="fa fa-clipboard mr-1"></i>%s' . PHP_EOL;
$template .= '</a>' . PHP_EOL;
foreach ($this->_tags as $attr => $template_tag) {
$render_tag = sprintf($template_tag, data_get($item, $attr));
$render .= vsprintf($template, [$render_tag, $render_tag]);
}
}
}
return $render;
}
private function renderListMenuItemMore($item): string
{
$render = '';
if (auth()->user()->can($this->can_prefix . '-read')) {
$menu_items = $this->_menu_items;
if (count($menu_items) > 0) {
$template = '<a class="dropdown-item%s"%s>' . PHP_EOL;
$template .= ' %s' . PHP_EOL;
$template .= '</a>' . PHP_EOL;
foreach ($menu_items as $menu_item) {
$href = data_get($menu_item, 'href');
$name = data_get($menu_item, 'name');
$class = data_get($menu_item, 'class');
$attrs = collect($menu_item)->except(['label', 'name', 'class']);
// Traitement des attributs
foreach ($attrs as $name => $value) {
if (is_array($value)) {
$attrs[$name] = $this->objectToString(
mixte_get($value, 'template'),
mixte_get($value, 'value'),
mixte_get($value, 'callback'), $item
);
}
}
// Rendu de l'élément
$render .= vsprintf($template, [
empty($class) ? '' : ' ' . $class,
$this->renderAttributes($attrs),
$menu_item['label']
]);
}
}
}
return $render;
}
private function renderListMenuItemDuplicate($item): string
{
$render = '';
if (auth()->user()->can($this->can_prefix . '-create')) {
if ($this->is_duplicable) {
$template = '<a class="dropdown-item" href="%s">' . PHP_EOL;
$template .= ' <i class="fa fa-clone mr-1"></i>Dupliquer' . PHP_EOL;
$template .= '</a>' . PHP_EOL;
if (empty($this->route_param)) {
$render = sprintf($template, route($this->route_prefix . '.' . 'duplicate', array_merge([$item->id], Request::query())));
} else {
$render = sprintf($template, route($this->route_prefix . '.' . 'duplicate', array_merge([$this->route_param, $item->id], Request::query())));
}
}
}
return $render;
}
private function renderListMenuItemDelete($item): string
{
$render = '';
if (auth()->user()->can($this->can_prefix . '-delete')) {
if ($this->is_deletable) {
$template = '<div class="dropdown-divider"></div>' . PHP_EOL;
$template .= '<a class="dropdown-item delete" href="#" data-href="%s">' . PHP_EOL;
$template .= ' <i class="fa fa-trash mr-1"></i>Supprimer' . PHP_EOL;
$template .= '</a>' . PHP_EOL;
if (empty($this->route_param)) {
$render = sprintf($template, route($this->route_prefix . '.' . 'delete', array_merge([$item->id], Request::query())));
} else {
$render = sprintf($template, route($this->route_prefix . '.' . 'delete', array_merge([$this->route_param, $item->id], Request::query())));
}
}
}
return $render;
}
/**
* Retourne le rende d'un paramètre class
* @param string $class Le contenu du paramètre
* @return string Le rendu du paramètre class
*/
private function renderClass($class): string
{
$render = '';
$template = ' class="%s"';
if (!empty($class)) {
$render = sprintf($template, $class);
}
return $render;
}
/**
* Retourne le rendu d'attributs avec leur valeur
* @param array $attrs Les attributs avec la colonne de l'object conteant la valeur
* @param Object $item Object contenant la valeur de l'attribut
* @return string Le rendu des attributs avec leur valeur
*/
private function renderAttributes($attrs = [], $item = null): string
{
$render = '';
if (is_iterable($attrs)) {
$template = ' %s="%s"';
foreach ($attrs as $name => $value) {
if (is_null($item)) {
$render .= vsprintf($template, [$name, $value]);
} else {
$render .= vsprintf($template, [$name, $this->objectToString(null, $value, null, $item)]);
}
}
}
return $render;
}
/**
* Retourne le rendu d'un template avec une liste de noms de colonnes
* @param string $template Le template servant au rendu
* @param string|array $display Le ou les nom de colonnes
* @param string $eval Chaine de caractère à executer comme du php
* @param Mix $item Objet source des donnés à afficher
* @param boolean $strip Supprimer les balises HTML
* @return string Le rendu
*/
private function objectToString($template = null, $displays = null, $callback = null, $item, $strip = false)
{
// Création du texte à afficher
$datas = [];
// Convertion en tableau si besoin
if (!is_iterable($displays)) {
$displays = [$displays];
}
// Traitement du tableau de valeur à afficher
foreach ($displays as $key => $display) {
$data = mixte_get($item, $display);
// Callback array
if (is_array($callback) && isset($callback[$key]) && !is_null($callback[$key])) {
$data = $callback[$key]($data);
}
$datas[] = $strip ? strip_tags($data) : $data;
}
// Traitement des % seuls pour éviter les conflits
if (!empty($template)) {
$template = preg_replace('/(%)[^0-9sd.\']/i', '%%"', $template);
}
// Traitement template & callback
if (is_string($callback)) {
if (empty($template)) {
$string = call_user_func_array($callback, $datas);
} else {
$string = vsprintf($template, $datas);
$string = $callback($string);
}
} else if (!empty($template)) {
$string = vsprintf($template, $datas);
} else {
$string = $datas[0];
}
return $string;
}
/**
* Retourne le rendu d'une chaine de caractère en HTML
* @param String $string La chains de caractères à traiter
* @return String Le rendu HTML
*/
public function renderHTML($string): string
{
return new HtmlString($string);
}
/**
* Retourne le rendu avec indentation d'un texte
* @param string $text Le texte à traiter
* @param Integer $nb Le nombre d'indentation à appliquer
* @return string Le rendu avec indentation
*/
private function renderIndent($text, $nb): string
{
$indent = ' ';
$render = '';
$real_indent = '';
for ($i = 1; $i <= $nb; $i++) {
$real_indent .= $indent;
}
$lines = explode(PHP_EOL, $text);
foreach ($lines as $line) {
if (!empty($line)) {
$render .= $real_indent . $line . PHP_EOL;
}
}
return $render;
}
/**
* Mise à jour des attributs depuis le tableau passé en paramètre
* @param Array $attrs Liste des attributs à traiter
* @return void
*/
private function setAttrs($attrs)
{
$this->resetAttrs();
if (is_null($attrs)) {
return ;
}
// Liste des attributs autorisés
$attrs_available = array_map(function ($val) {
return trim($val, '_');
}, array_keys(get_object_vars($this)));
// Traitement des attributs
if (is_array($attrs)) {
foreach ($attrs as $attr => $value) {
if (in_array($attr, $attrs_available)) {
if (is_array($value)) {
$this->{'_' . $attr} = $value;
} else {
$this->{$attr} = $value;
}
} else {
throw new \InvalidArgumentException("Le paramètre [" . $attr . "] n'est pas pris en charge");
}
}
} else {
throw new \InvalidArgumentException("Type de paramètre invalide. Attendu : Tableau");
}
}
/**
* Réinitialisation des attributs de constructions
* @return void
*/
private function resetAttrs()
{
$attrs = array_keys(get_object_vars($this));
foreach ($attrs as $attr) {
if (preg_match('/^_.*/', $attr)) {
$this->{$attr} = [];
} else if (preg_match('/^is_.*/', $attr)) {
$this->{$attr} = false;
} else {
$this->{$attr} = null;
}
}
}
}
<?php
namespace Goldenscarab\Modulus\Service\Template\Compose;
use Illuminate\Support\Facades\Request;
use \Illuminate\Support\HtmlString;
use Illuminate\Support\FacadesRequest;
class Template3Bt4
{
private $route_prefix;
private $route_param;
private $table_id;
private $table_class;
private $can_prefix;
private $source;
private $_menu;
private $_rows;
private $_columns;
public function __construct($attrs = [])
{
$this->setAttrs($attrs);
}
/**
* Retourne le rendu d'un tableau liste
* @return string le rendu du tableau liste
*/
public function renderList(): string
{
$template = '<div class="table-responsive-lg" style="min-height: 250px;">' . PHP_EOL;
$template .= ' <table id="%s" class="%s">' . PHP_EOL;
$template .= ' <thead>' . PHP_EOL;
$template .= ' <tr>' . PHP_EOL;
$template .= '%s';
$template .= ' </tr>' . PHP_EOL;
$template .= ' </thead>' . PHP_EOL;
$template .= ' <tbody>' . PHP_EOL;
$template .= '%s';
$template .= ' </tbody>' . PHP_EOL;
$template .= ' </table>';
$template .= '</div>';
$render = vsprintf($template, [
empty($this->table_id) ? 'table-' . str_slug($this->route_prefix) : $this->table_id,
trim('table table-sm table-hover table-striped ' . $this->table_class),
$this->renderIndent($this->renderListHead(), 3),
$this->renderIndent($this->renderListBody(), 2),
]);
return $render;
}
/**
* Retourne le rendu des entêtes de colonnes d'un tableau liste
* @return string Le rendu des entêtes de colonnes
*/
public function renderListHead(): string
{
$template = '<th scope="col" class="text-nowrap">%s%s</th>' . PHP_EOL;
$render = '';
$columns = $this->_columns;
// Colonne titre
if (is_iterable($columns)) {
foreach ($columns as $column) {
$sortable = data_get($column, 'sortable');
$render .= vsprintf($template, [
data_get($column, 'label'),
is_null($sortable) ? '' : col_sort($sortable)
]);
}
}
// Colonne menu
$render .= vsprintf($template, ['','', '']);
return $render;
}
/**
* Retourne le rendu des lignes d'un tableau liste
* @return string Le rendu des lignes du tableau
*/
public function renderListBody(): string
{
$template_row = '<tr scope="row"%s>' . PHP_EOL;
$template_row .= '%s';
$template_row .= '</tr>' . PHP_EOL;
$template_cel = '<td%s>%s</td>' . PHP_EOL;
$render = '';
$collection = $this->source;
$columns = $this->_columns;
$rows = $this->_rows;
if (is_iterable($collection)) {
if (count($collection) == 0) {
$render_cels_row = vsprintf($template_cel, [
' colspan="' . (count($columns) + 1) .'"',
null,
'Aucun élément disponible'
]);
$render .= vsprintf($template_row, [
null,
$this->renderIndent($render_cels_row, 1)
]);
} else {
foreach ($collection as $item) {
$render_cels_row = '';
if (is_iterable($columns)) {
foreach ($columns as $column) {
$attrs = collect($column)->except(['label', 'row', 'value', 'sortable', 'id']);
$attributes = $this->renderAttributes($attrs, $item);
$value = $this->getValue(data_get($column, 'value'), $item);
// Création de la cellule
$render_cels_row .= vsprintf($template_cel, [
$attributes,
$value
]);
}
// Ajout du menu en fin de ligne
$render_cels_row .= vsprintf($template_cel, [
null,
data_get($this->_menu, 'display') ? $this->renderListMenuItems($item) : ''
]);
}
$render .= vsprintf($template_row, [
$this->renderAttributes($rows, $item),
$this->renderIndent($render_cels_row, 1)
]);
}
}
}
return $render;
}
/**
* Retourne le rendu du menu item
* @param Object $source Source des données
* @return string Le rendu
*/
private function renderListMenuItems($source): string
{
$template = '<div class="dropdown">' . PHP_EOL;
$template .= ' <button class="btn btn-default btn-xs dropdown-toggle no-caret square-to-circle item-option" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">' . PHP_EOL;
$template .= ' <i class="fa fa-cog" aria-hidden="true"></i>' . PHP_EOL;
$template .= ' </button>' . PHP_EOL;
$template .= ' <div class="dropdown-menu dropdown-menu-right">' . PHP_EOL;
$template .= '%s';
$template .= '%s';
$template .= '%s';
$template .= '%s';
$template .= '%s';
$template .= '%s';
$template .= ' </div>' . PHP_EOL;
$render = '';
$render = vsprintf($template, [
$this->renderIndent($this->renderListMenuItemRead($source), 2),
$this->renderIndent($this->renderListMenuItemUpdate($source), 2),
$this->renderIndent($this->renderListMenuItemTag($source), 2),
$this->renderIndent($this->renderListMenuItemMore($source), 2),
$this->renderIndent($this->renderListMenuItemDuplicate($source), 2),
$this->renderIndent($this->renderListMenuItemDelete($source), 2),
]);
return $render;
}
/**
* Retourne l'element voir du menu item
* @param Object $source Source des données
* @return string Le rendu
*/
private function renderListMenuItemRead($source): string
{
$render = '';
if (auth()->user()->can($this->can_prefix . '-read')) {
if (data_get($this->_menu, 'is_readable')) {
$template = '<a class="dropdown-item" href="%s">' . PHP_EOL;
$template .= ' <i class="fa fa-eye mr-1"></i>Voir' . PHP_EOL;
$template .= '</a>' . PHP_EOL;
if (empty($this->route_param)) {
$render = sprintf($template, route($this->route_prefix . '.' . 'read', array_merge([$source->id], Request::query())));
} else {
$render = sprintf($template, route($this->route_prefix . '.' . 'read', array_merge([$this->route_param, $source->id ], Request::query())));
}
}
}
return $render;
}
/**
* Retourne l'element modifier du menu item
* @param Object $source Source des données
* @return string Le rendu
*/
private function renderListMenuItemUpdate($source): string
{
$render = '';
if (auth()->user()->can($this->can_prefix . '-update')) {
if (data_get($this->_menu, 'is_editable')) {
$template = '<a class="dropdown-item" href="%s">' . PHP_EOL;
$template .= ' <i class="fa fa-pencil-square-o mr-1"></i>Modifier' . PHP_EOL;
$template .= '</a>' . PHP_EOL;
if (empty($this->route_param)) {
$render = sprintf($template, route($this->route_prefix . '.' . 'update', array_merge([$source->id], Request::query())));
} else {
$render = sprintf($template, route($this->route_prefix . '.' . 'update', array_merge([$this->route_param, $source->id ], Request::query())));
}
}
}
return $render;
}
/**
* Retourne l'element tag du menu item
* @param Object $source Source des données
* @return string Le rendu
*/
private function renderListMenuItemTag($source): string
{
$render = '';
if (auth()->user()->hasRole('admin')) {
if (count(data_get($this->_menu, 'tags')) > 0) {
$template = '<a class="dropdown-item clipboard-copy" href="#" title="Copier le Tag" data-clipboard-action="copy" data-clipboard-text="%s">' . PHP_EOL;
$template .= ' <i class="fa fa-clipboard mr-1"></i>%s' . PHP_EOL;
$template .= '</a>' . PHP_EOL;
foreach (data_get($this->_menu, 'tags') as $tag) {
$tag_value = $this->getValue($tag, $source);
$render .= vsprintf($template, [$tag_value, $tag_value]);
}
}
}
return $render;
}
/**
* Retourne les éléments supplémentaires du menu item
* @param Object $source Source des données
* @return string Le rendu
*/
private function renderListMenuItemMore($source): string
{
$render = '';
if (auth()->user()->can($this->can_prefix . '-read')) {
$menu_more = data_get($this->_menu, 'more');
if (count($menu_more) > 0) {
$template = '<a class="dropdown-item%s"%s>' . PHP_EOL;
$template .= ' %s' . PHP_EOL;
$template .= '</a>' . PHP_EOL;
foreach ($menu_more as $menu_item) {
$href = data_get($menu_item, 'href');
$name = data_get($menu_item, 'name');
$class = data_get($menu_item, 'class');
$attrs = collect($menu_item)->except(['label', 'name', 'class']);
// Rendu de l'élément
$render .= vsprintf($template, [
empty($class) ? '' : ' ' . $class,
$this->renderAttributes($attrs, $source),
$menu_item['label']
]);
}
}
}
return $render;
}
/**
* Retourne l'element dupliqué du menu item
* @param Object $source Source des données
* @return string Le rendu
*/
private function renderListMenuItemDuplicate($source): string
{
$render = '';
if (auth()->user()->can($this->can_prefix . '-create')) {
if (data_get($this->_menu, 'is_duplicable')) {
$template = '<a class="dropdown-item" href="%s">' . PHP_EOL;
$template .= ' <i class="fa fa-clone mr-1"></i>Dupliquer' . PHP_EOL;
$template .= '</a>' . PHP_EOL;
if (empty($this->route_param)) {
$render = sprintf($template, route($this->route_prefix . '.' . 'duplicate', array_merge([$source->id], Request::query())));
} else {
$render = sprintf($template, route($this->route_prefix . '.' . 'duplicate', array_merge([$this->route_param, $source->id], Request::query())));
}
}
}
return $render;
}
/**
* Retourne l'element supprimer du menu item
* @param Object $source Source des données
* @return string Le rendu
*/
private function renderListMenuItemDelete($source): string
{
$render = '';
if (auth()->user()->can($this->can_prefix . '-delete')) {
if (data_get($this->_menu, 'editable')) {
$template = '<div class="dropdown-divider"></div>' . PHP_EOL;
$template .= '<a class="dropdown-item delete" href="#" data-href="%s">' . PHP_EOL;
$template .= ' <i class="fa fa-trash mr-1"></i>Supprimer' . PHP_EOL;
$template .= '</a>' . PHP_EOL;
if (empty($this->route_param)) {
$render = sprintf($template, route($this->route_prefix . '.' . 'delete', array_merge([$source->id], Request::query())));
} else {
$render = sprintf($template, route($this->route_prefix . '.' . 'delete', array_merge([$this->route_param, $source->id], Request::query())));
}
}
}
return $render;
}
/**
* Retourne le rendu d'attributs avec leur valeur
* @param array $attrs Les attributs avec la colonne de l'object conteant la valeur
* @param Object $item Object contenant la valeur de l'attribut
* @return string Le rendu des attributs avec leur valeur
*/
private function renderAttributes($attrs = [], $source = null): string
{
$render = '';
if (is_iterable($attrs)) {
$template = ' %s="%s"';
foreach ($attrs as $name => $data) {
if (is_null($source) || !is_array($data)) {
$value = $data;
} else if (is_array($data)) {
$value = $this->getValue($data, $source);
}
$render .= vsprintf($template, [$name, $value]);
}
}
return $render;
}
/**
* Vérifier la validité d'un paramètre condition
* @param array|null $condition La condition si elle est disponible
* @param Objet $datas Les données dans lesquelles aller chercher la valeur à controler
* @return bollean True si la condition est valide, sinon false
*/
private function checkCondition($condition, $datas): string
{
$data = mixte_get($datas, mixte_get($condition, 'key'));
$value = mixte_get($condition, 'value');
$operator = mixte_get($condition, 'operator');
$default = true;
switch ($operator) {
case '==' :
$validated = $data == $value ? true : false;
break;
case '>' :
$validated = $data > $value ? true : false;
break;
case '<' :
$validated = $data < $value ? true : false;
break;
case '!=' :
$validated = $data != $value ? true : false;
break;
case '<=' :
$validated = $data <= $value ? true : false;
break;
case '>=' :
$validated = $data >= $value ? true : false;
break;
default :
$validated = $default;
}
return $validated;
}
/**
* Récupération d'une valeur en fonction de sa composition
* @param Mixed $value array pour une valeur dynamique ou string|int|float|bool pour une valeur statique
* @param Object $datas Objet dans lequel aller chercher la valeur si dynamique
* @param boolean $strip Supprimer les balises HTML dela valeur résultante
* @return Mixed La valeur
*/
private function getValue($value, $datas = null, $strip = false)
{
$_value = null;
if (is_array($value)) {
// Si le tableau n'est pas de type associatif ['my-key'] devient ['key' => 'my-key']
if(array_keys($value) === range(0, count($value) - 1) && count($value) == 1) {
$value = ['key' => $value[0]];
}
$condition = data_get($value, 'condition');
if ($this->checkCondition($condition, $datas)) {
$_value = $this->dynamicFormatedValue(
data_get($value, 'template'),
data_get($value, 'key'),
data_get($value, 'value'),
data_get($value, 'callback'),
$datas,
$strip,
);
}
} else {
$_value = $value;
}
return $_value;
}
/**
* Retourne le rendu formaté d'une valeur dynamique
* @param string $template Le template servant au formatage
* @param string|array $keys Le ou les nom de colonnes
* @param Mix $default Valeur par défaut
* @param string $callback Fonction callback à appeler pour traiter la valeur
* @param Mix $source Objet source pour récupérer la valeur dynamique
* @param boolean $strip Supprimer les balises HTML
* @return string Le rendu
*/
private function dynamicFormatedValue($template = null, $keys = null, $default = null, $callback = null, $source, $strip = false)
{
// Création du texte à afficher
$datas = [];
// Convertion en tableau si besoin
if (!is_iterable($keys)) {
$keys = [$keys];
}
// Traitement du tableau de valeur à afficher
foreach ($keys as $key => $column) {
if (is_null($column)) {
$data = $default;
} else {
$data = mixte_get($source, $column, $default);
}
// Callback array
if (is_array($callback) && isset($callback[$key]) && !is_null($callback[$key])) {
$data = $callback[$key]($data);
}
$datas[] = $strip ? strip_tags($data) : $data;
}
// Traitement des % seuls pour éviter les conflits
if (!empty($template)) {
$template = preg_replace('/(%)[^0-9sd.\']/i', '%%"', $template);
}
// Traitement template & callback
if (is_string($callback)) {
if (empty($template)) {
$string = call_user_func_array($callback, $datas);
} else {
$string = vsprintf($template, $datas);
$string = $callback($string);
}
} else if (!empty($template)) {
$string = vsprintf($template, $datas);
} else {
$string = $datas[0];
}
return $string;
}
/**
* Retourne le rendu d'une chaine de caractère en HTML
* @param String $string La chains de caractères à traiter
* @return String Le rendu HTML
*/
public function renderHTML($string): string
{
return new HtmlString($string);
}
/**
* Retourne le rendu avec indentation d'un texte
* @param string $text Le texte à traiter
* @param Integer $nb Le nombre d'indentation à appliquer
* @return string Le rendu avec indentation
*/
private function renderIndent($text, $nb): string
{
$indent = ' ';
$render = '';
$real_indent = '';
for ($i = 1; $i <= $nb; $i++) {
$real_indent .= $indent;
}
$lines = explode(PHP_EOL, $text);
foreach ($lines as $line) {
if (!empty($line)) {
$render .= $real_indent . $line . PHP_EOL;
}
}
return $render;
}
/**
* Mise à jour des attributs depuis le tableau passé en paramètre
* @param Array $attrs Liste des attributs à traiter
* @return void
*/
private function setAttrs($attrs)
{
$this->resetAttrs();
if (is_null($attrs)) {
return ;
}
// Liste des attributs autorisés
$attrs_available = array_map(function ($val) {
return trim($val, '_');
}, array_keys(get_object_vars($this)));
// Traitement des attributs
if (is_array($attrs)) {
foreach ($attrs as $attr => $value) {
if (in_array($attr, $attrs_available)) {
if (is_array($value)) {
$this->{'_' . $attr} = $value;
} else {
$this->{$attr} = $value;
}
} else {
throw new \InvalidArgumentException("Le paramètre [" . $attr . "] n'est pas pris en charge");
}
}
} else {
throw new \InvalidArgumentException("Type de paramètre invalide. Attendu : Tableau");
}
}
/**
* Réinitialisation des attributs de constructions
* @return void
*/
private function resetAttrs()
{
$attrs = array_keys(get_object_vars($this));
foreach ($attrs as $attr) {
if (preg_match('/^_.*/', $attr)) {
$this->{$attr} = [];
} else if (preg_match('/^is_.*/', $attr)) {
$this->{$attr} = false;
} else {
$this->{$attr} = null;
}
}
}
}
<?php
namespace Goldenscarab\Modulus\Service\Template\Facades;
use Illuminate\Support\Facades\Facade;
class Template extends Facade
{
protected static function getFacadeAccessor()
{
return 'Template';
}
}
<?php
namespace Goldenscarab\Modulus\Service\Template;
use Goldenscarab\Modulus\Service\Template\Compose\Template1Bt4;
use Goldenscarab\Modulus\Service\Template\Compose\Template2Bt4;
use Goldenscarab\Modulus\Service\Template\Compose\Template3Bt4;
class Template
{
public function list($attrs = []): string
{
$template = new Template1Bt4($attrs);
$render = $template->renderList();
return $template->renderHTML($render);
}
/**
* Modification sur les traitements d'un éléments complémentaire dans le menu
*/
public function list2($attrs = []): string
{
$template = new Template2Bt4($attrs);
$render = $template->renderList();
return $template->renderHTML($render);
}
/**
* Refonte complète des listes
*/
public function list3($attrs = []): string
{
$template = new Template3Bt4($attrs);
$render = $template->renderList();
return $template->renderHTML($render);
}
}
<?php
namespace Goldenscarab\Modulus\Service\Template;
use Illuminate\Support\ServiceProvider;
use Illuminate\Foundation\AliasLoader;
class TemplateServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
}
/**
* Register any application services.
*
* @return void
*/
public function register()
{
$this->app->bind('Template', function() {
return new \Goldenscarab\Modulus\Service\Template\Template;
});
}
}
<?php
namespace Tests\Unit;
use Tests\TestCase;
use Illuminate\Support\Facades\File;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Goldenscarab\Modulus\Service\Field\Facades\Field;
/**
* ./vendor/bin/phpunit ./vendor/goldenscarab/modulus-service-field/tests/FieldsTest.php
*/
class FieldsTest extends TestCase
{
private $data_source = [
'type' => [
'id' => 'mon-id',
'label' => 'mon-label',
'code' => 'mon-code'
]
];
private $options = [
1 => 'Option 1',
2 => 'Option 2',
3 => 'Option 3',
4 => 'Option 4',
5 => 'Option 5'
];
private $collection = [
['id' => 1, 'title' => 'Titre 1', 'value' => 'value-1', 'data' => ['data1' => 'data-value1.1', 'data2' => 'data-value1.2']],
['id' => 2, 'title' => 'Titre 2', 'value' => 'value-2', 'data' => ['data1' => 'data-value2.1', 'data2' => 'data-value2.2']],
['id' => 3, 'title' => 'Titre 3', 'value' => 'value-3', 'data' => ['data1' => 'data-value3.1', 'data2' => 'data-value3.2']],
['id' => 4, 'title' => 'Titre 4', 'value' => 'value-4', 'data' => ['data1' => 'data-value4.1', 'data2' => 'data-value4.2']]
];
private $lorem = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Laboriosam, rem esse itaque inventore provident reiciendis quo, asperiores dolorem voluptate nostrum quisquam similique commodi quam consequatur ad eligendi iusto aperiam quos?';
/**
* Test du fonctionnement de la classe en mode test unitaire
* @return void
*/
public function testTest()
{
$this->assertTrue(true);
}
public function testInputField()
{
$generated_string = Field::input([
'type' => 'text',
'label' => 'Total',
'name' => 'total',
'value' => 23.4,
]);
$desired_string = File::get(__DIR__ . '/html/fields/input.html');
$this->assertEquals($desired_string, $generated_string);
}
public function testInputAdvancedField()
{
$generated_string = Field::input([
'id' => 'total-final',
'type' => 'text',
'label' => 'Total',
'name' => 'total',
'value' => 23.4,
'class' => 'text-danger',
'prefix' => '<i class="fa fa-money"></i>',
'suffix' => '€',
'placeholder' => "123,30",
'help' => 'Taxe comprise',
'indice' => 1,
'style' => 'background-color: #c3c3c3;',
'attributes' => [
'onchange' => 'console.log("change")',
'title' => [
'source' => $this->data_source,
'template' => '%s ~ %s',
'attributes' => ['type.id', 'type.label'],
'callback' => 'ucfirst'
]
],
'datas' => [
'type' => 'column',
'reference' => [
'source' => $this->data_source,
'template' => '%s|%s',
'attributes' => ['type.id', 'type.code'],
'callback' => 'ucfirst'
]
],
'is_inline' => true,
'is_disabled' => true,
'is_readonly' => true,
'is_required' => true,
'is_autocomplete' => true,
'is_autofocus' => true,
'popover' => [
'placement' => 'right',
'title' => 'Information',
'content' => "Le montant est calculé selon les éléments communiqué. Il peux néanmoins variée suivant d'autre facteurs non pris en compte"
],
]);
$desired_string = File::get(__DIR__ . '/html/fields/input_advanced.html');
$this->assertEquals($desired_string, $generated_string);
}
public function testSelectSimpleField()
{
$generated_string = Field::select([
'label' => 'Collection',
'name' => 'collection',
'value' => 4,
'class' => 'select2',
'prefix' => '<i class="fa fa-list"></i>',
'suffix' => '<i class="fa fa-hand-paper-o"></i>',
'size' => 'sm',
'indice' => 34,
'is_required' => true,
'options' => $this->options
]);
$desired_string = File::get(__DIR__ . '/html/fields/select_simple.html');
$this->assertEquals($desired_string, $generated_string);
}
public function testSelectGroupField()
{
$generated_string = Field::select([
'label' => 'Menu déroulant',
'name' => 'my_field_name',
'value' => 23,
'placeholder' => 'Choisir ...',
'size' => 'sm',
'is_required' => true,
'options' => [
'Groupe 1' => [
23 => 'Élement 23',
24 => 'Élement 24',
25 => 'Élement 25',
],
'Groupe 2' => [
26 => 'Élement 26',
27 => 'Élement 27',
28 => 'Élement 28',
]
]
]);
$desired_string = File::get(__DIR__ . '/html/fields/select_group.html');
$this->assertEquals($desired_string, $generated_string);
}
public function testSelectMultipleField()
{
$generated_string = Field::select([
'label' => 'Collection',
'name' => 'collection',
'values' => [2, 4],
'class' => 'select2',
'prefix' => '<i class="fa fa-list"></i>',
'suffix' => '<i class="fa fa-hand-paper-o"></i>',
'indice' => 34,
'is_required' => true,
'is_multiple' => true,
'options' => [
'collect' => $this->collection,
'value' => 'id',
'template' => '%s - %s',
'callback' => 'strtoupper',
'text' => ['title', 'value'],
]
]);
$desired_string = File::get(__DIR__ . '/html/fields/select_multiple.html');
$this->assertEquals($desired_string, $generated_string);
}
public function testSelectDataField()
{
$generated_string = Field::select([
'label' => 'Ville',
'name' => 'city_id',
'value' => 2,
'placeholder' => "Choisir...",
'options' => [
'collect' => $this->collection,
'value' => 'id',
'text' => ['title', 'value'],
'template' => '%s - %s',
'datas' => [
'data1' => 'data.data1',
'data2' => 'data.data2',
]
]
]);
$desired_string = File::get(__DIR__ . '/html/fields/select_data.html');
$this->assertEquals($desired_string, $generated_string);
}
public function testTextareaField()
{
$generated_string = Field::textarea([
'label' => 'Contenu',
'name' => 'content',
'value' => $this->lorem,
'class' => 'text-editor',
'rows' => 15,
'popover' => [
'placement' => 'right',
'title' => 'Le contenu',
'content' => "Le contenu est le coeur de l'article. Grâce à l'éditeur vous pouvez formater le rendu selon votre goût."
]
]);
$desired_string = File::get(__DIR__ . '/html/fields/textarea.html');
$this->assertEquals($desired_string, $generated_string);
}
public function testFileField()
{
$generated_string = Field::file([
'label' => 'Uploader',
'name' => 'csv',
'prefix' => 'Fichier',
'placeholder' => 'Aucun fichier choisi'
]);
$desired_string = File::get(__DIR__ . '/html/fields/file.html');
$this->assertEquals($desired_string, $generated_string);
}
public function testPdfField()
{
$generated_string = Field::pdf([
'label' => 'Champs pdf',
'name' => 'my_field_pdf',
'value' => 'test.pdf',
'placeholder' => 'ex: /upload/folder/file.pdf',
'suffix' => '<i class="fa fa-file-pdf-o mr-2"></i> Choisir un PDF',
'is_required' => true,
]);
$desired_string = File::get(__DIR__ . '/html/fields/pdf.html');
$this->assertEquals($desired_string, $generated_string);
}
public function testVideoField()
{
$generated_string = Field::pdf([
'label' => 'Champs video',
'name' => 'my_field_video',
'value' => 'my-video.mp4',
'placeholder' => 'ex: /upload/folder/video.mp4',
'suffix' => '<i class="fa fa-file-video-o mr-2"></i> Choisir une vidéo',
'is_required' => true,
]);
$desired_string = File::get(__DIR__ . '/html/fields/video.html');
$this->assertEquals($desired_string, $generated_string);
}
public function testImageField()
{
$generated_string = Field::pdf([
'label' => 'Champs image',
'name' => 'my_field_image',
'value' => 'image.png',
'placeholder' => 'ex: /upload/folder/image.png',
'suffix' => '<i class="fa fa-file-image-o mr-2"></i> Choisir une image',
'is_required' => true,
]);
$desired_string = File::get(__DIR__ . '/html/fields/image.html');
$this->assertEquals($desired_string, $generated_string);
}
public function testToogleField()
{
$generated_string = Field::toggle([
'label' => 'Toggle',
'name' => 'toggle',
'value' => 1,
'datas' => [
'on' => 'Actif',
'off' => 'Inactif',
'onstyle' => 'success',
'offstyle' => 'danger',
'toggle' => 'toggle',
'width' => '75',
'size' => 'xs'
]
]);
$desired_string = File::get(__DIR__ . '/html/fields/toggle.html');
$this->assertEquals($desired_string, $generated_string);
}
public function testRangeField()
{
$generated_string = Field::range([
'label' => 'Zoom',
'name' => 'zoom',
'min' => 0,
'max' => 20,
'value' => 7
]);
$desired_string = File::get(__DIR__ . '/html/fields/range.html');
$this->assertEquals($desired_string, $generated_string);
}
public function testCodeField()
{
$generated_string = Field::code([
'label' => 'Contenu',
'name' => 'content',
'value' => 'function foo(items) {
var x = "All this is syntax highlighted";
return x;
}',
'style' => 'min-height: 400px;',
'is_required' => true,
'datas' => array(
'language' => 'javascript',
'readonly' => 'false',
'beautiful' => 'false',
)
]);
$desired_string = File::get(__DIR__ . '/html/fields/code.html');
$this->assertEquals($desired_string, $generated_string);
}
public function testRadioField()
{
$generated_string = Field::radio([
'label' => 'Choix unique',
'name' => 'my_field_name',
'value' => 2,
'is_inline' => true,
'options' => $this->options
]);
$desired_string = File::get(__DIR__ . '/html/fields/radio.html');
$this->assertEquals($desired_string, $generated_string);
}
public function testRadioIndiceTrueField()
{
$generated_string = Field::radio([
'label' => 'Choix unique',
'name' => 'my_field_name',
'value' => 2,
'indice' => true,
'is_inline' => true,
'options' => $this->options
]);
$desired_string = File::get(__DIR__ . '/html/fields/radio_indice_true.html');
$this->assertEquals($desired_string, $generated_string);
}
public function testRadioCollectField()
{
$generated_string = Field::radio([
'label' => 'Mon Champs',
'name' => 'mon-champs',
'value' => 'value-2',
'is_inline' => false,
'options' => [
'collect' => $this->collection,
'value' => 'value',
'template' => '%s - %s',
'text' => ['id', 'title'],
'callback' => 'strtoupper',
'datas' => [
'one' => 'data.data1',
'tow' => 'data.data2',
]
]
]);
$desired_string = File::get(__DIR__ . '/html/fields/radio_collect.html');
$this->assertEquals($desired_string, $generated_string);
}
public function testCheckboxField()
{
$generated_string = Field::checkbox([
'label' => 'Choix multiple',
'name' => 'my_field_name',
'values' => [2, 3],
'is_inline' => true,
'options' => $this->options
]);
$desired_string = File::get(__DIR__ . '/html/fields/checkbox.html');
$this->assertEquals($desired_string, $generated_string);
}
public function testCheckboxIndiceField()
{
$generated_string = Field::checkbox([
'label' => 'Choix multiple',
'name' => 'my_field_name',
'indice' => 12,
'values' => [2, 3],
'is_inline' => true,
'options' => $this->options
]);
$desired_string = File::get(__DIR__ . '/html/fields/checkbox_indice.html');
$this->assertEquals($desired_string, $generated_string);
}
public function testCheckboxCollectField()
{
$generated_string = Field::checkbox([
'label' => 'Mon Champs',
'name' => 'mon-champs',
'values' => ['value-2', 'value-3'],
'is_inline' => false,
'options' => [
'collect' => $this->collection,
'value' => 'value',
'template' => '%s - %s',
'text' => ['id', 'title'],
'callback' => 'strtoupper',
'datas' => [
'one' => 'data.data1',
'tow' => 'data.data2',
]
]
]);
$desired_string = File::get(__DIR__ . '/html/fields/checkbox_collect.html');
$this->assertEquals($desired_string, $generated_string);
}
}
<div class="form-group row">
<label for="my-field-name-5" class="col-sm-2">Choix multiple</label>
<div class="col-sm-10">
<div class="form-check form-check-inline">
<input type="checkbox" id="my-field-name-1" class="form-check-input" name="my_field_name[]" value="1"/>
<label class="form-check-label" for="my-field-name-1">Option 1</label>
</div>
<div class="form-check form-check-inline">
<input type="checkbox" id="my-field-name-2" class="form-check-input" name="my_field_name[]" value="2" checked/>
<label class="form-check-label" for="my-field-name-2">Option 2</label>
</div>
<div class="form-check form-check-inline">
<input type="checkbox" id="my-field-name-3" class="form-check-input" name="my_field_name[]" value="3" checked/>
<label class="form-check-label" for="my-field-name-3">Option 3</label>
</div>
<div class="form-check form-check-inline">
<input type="checkbox" id="my-field-name-4" class="form-check-input" name="my_field_name[]" value="4"/>
<label class="form-check-label" for="my-field-name-4">Option 4</label>
</div>
<div class="form-check form-check-inline">
<input type="checkbox" id="my-field-name-5" class="form-check-input" name="my_field_name[]" value="5"/>
<label class="form-check-label" for="my-field-name-5">Option 5</label>
</div>
</div>
</div>
<div class="form-group">
<label for="mon-champs-value-4">Mon Champs</label>
<div class="form-check">
<input type="checkbox" id="mon-champs-value-1" class="form-check-input" name="mon-champs[]" value="VALUE-1" data-one="data-value1.1" data-tow="data-value1.2" />
<label class="form-check-label" for="mon-champs-value-1">1 - TITRE 1</label>
</div>
<div class="form-check">
<input type="checkbox" id="mon-champs-value-2" class="form-check-input" name="mon-champs[]" value="VALUE-2" data-one="data-value2.1" data-tow="data-value2.2" />
<label class="form-check-label" for="mon-champs-value-2">2 - TITRE 2</label>
</div>
<div class="form-check">
<input type="checkbox" id="mon-champs-value-3" class="form-check-input" name="mon-champs[]" value="VALUE-3" data-one="data-value3.1" data-tow="data-value3.2" />
<label class="form-check-label" for="mon-champs-value-3">3 - TITRE 3</label>
</div>
<div class="form-check">
<input type="checkbox" id="mon-champs-value-4" class="form-check-input" name="mon-champs[]" value="VALUE-4" data-one="data-value4.1" data-tow="data-value4.2" />
<label class="form-check-label" for="mon-champs-value-4">4 - TITRE 4</label>
</div>
</div>
<div class="form-group row">
<label for="my-field-name-12-5" class="col-sm-2">Choix multiple</label>
<div class="col-sm-10">
<div class="form-check form-check-inline">
<input type="checkbox" id="my-field-name-12-1" class="form-check-input" name="my_field_name[12][]" value="1"/>
<label class="form-check-label" for="my-field-name-12-1">Option 1</label>
</div>
<div class="form-check form-check-inline">
<input type="checkbox" id="my-field-name-12-2" class="form-check-input" name="my_field_name[12][]" value="2" checked/>
<label class="form-check-label" for="my-field-name-12-2">Option 2</label>
</div>
<div class="form-check form-check-inline">
<input type="checkbox" id="my-field-name-12-3" class="form-check-input" name="my_field_name[12][]" value="3" checked/>
<label class="form-check-label" for="my-field-name-12-3">Option 3</label>
</div>
<div class="form-check form-check-inline">
<input type="checkbox" id="my-field-name-12-4" class="form-check-input" name="my_field_name[12][]" value="4"/>
<label class="form-check-label" for="my-field-name-12-4">Option 4</label>
</div>
<div class="form-check form-check-inline">
<input type="checkbox" id="my-field-name-12-5" class="form-check-input" name="my_field_name[12][]" value="5"/>
<label class="form-check-label" for="my-field-name-12-5">Option 5</label>
</div>
</div>
</div>
<div class="form-group">
<label for="field-content" class="required">Contenu</label>
<div id="editor-field-content" class="code-editor"style="min-height: 400px;" data-language="javascript" data-readonly="false" data-beautiful="false" data-target="#field-content">function foo(items) {
var x = &quot;All this is syntax highlighted&quot;;
return x;
}</div>
<textarea id="field-content" name="content" style="display: none;">function foo(items) {
var x = &quot;All this is syntax highlighted&quot;;
return x;
}</textarea>
</div>
<div class="form-group">
<label for="field-csv">Uploader</label>
<div class="input-group">
<div class="input-group-prepend">
<div class="input-group-text">Fichier</div>
</div>
<div class="custom-file">
<input type="file" id="field-csv" class="custom-file-input" name="csv" value="" placeholder="Aucun fichier choisi" />
<label class="custom-file-label" for="field-csv">Aucun fichier choisi</label>
<script type="text/javascript">
document.getElementById('field-csv').addEventListener('change', function(e) {
if (e.target.files[0]) {
var fileName = e.target.files[0].name;
var nextSibling = e.target.nextElementSibling;
nextSibling.innerText = fileName
}
});
</script>
</div>
</div>
</div>
<div class="form-group">
<label for="field-my-field-image" class="required">Champs image</label>
<div class="input-group">
<div class="input-group-prepend">
<div class="input-group-text text-danger">
<i class="fa fa-file-pdf-o" aria-hidden="true"></i>
</div>
</div>
<input type="text" id="field-my-field-image" class="form-control" name="my_field_image" value="image.png" placeholder="ex: /upload/folder/image.png" required="required" />
<div class="input-group-append">
<button class="btn btn-outline-secondary popupfinder" type="button" id="btn-field-my-field-image" data-field="#field-my-field-image" data-mimes="application/pdf">
<i class="fa fa-file-image-o mr-2"></i> Choisir une image
</button>
</div>
</div>
</div>
<div class="form-group">
<label for="field-total">Total</label>
<input type="text" id="field-total" class="form-control" name="total" value="23,4" />
</div>
<div class="form-group row">
<label for="total-final-1" class="requiredcol-sm-2">Total</label>
<span class="text-info popup-help" data-toggle="popover" data-placement="right" title="Information" data-content="Le montant est calculé selon les éléments communiqué. Il peux néanmoins variée suivant d'autre facteurs non pris en compte">
<i class="fa fa-info-circle"></i>
</span>
<div class="col-sm-10">
<div class="input-group">
<div class="input-group-prepend">
<div class="input-group-text"><i class="fa fa-money"></i></div>
</div>
<input type="text" id="total-final-1" class="form-control text-danger" name="total[1]" value="23,4" placeholder="123,30" style="background-color: #c3c3c3;" autocomplete="autocomplete" autofocus="autofocus" disabled="disabled" required="required" readonly="readonly" onchange="console.log("change")" title="Mon-id ~ mon-label" data-type="column" data-reference="Mon-id|mon-code" />
<div class="input-group-append">
<div class="input-group-text"></div>
</div>
</div>
<small class="form-text text-muted text-right mt-0">Taxe comprise</small>
</div>
</div>
<div class="form-group">
<label for="field-my-field-pdf" class="required">Champs pdf</label>
<div class="input-group">
<div class="input-group-prepend">
<div class="input-group-text text-danger">
<i class="fa fa-file-pdf-o" aria-hidden="true"></i>
</div>
</div>
<input type="text" id="field-my-field-pdf" class="form-control" name="my_field_pdf" value="test.pdf" placeholder="ex: /upload/folder/file.pdf" required="required" />
<div class="input-group-append">
<button class="btn btn-outline-secondary popupfinder" type="button" id="btn-field-my-field-pdf" data-field="#field-my-field-pdf" data-mimes="application/pdf">
<i class="fa fa-file-pdf-o mr-2"></i> Choisir un PDF
</button>
</div>
</div>
</div>
<div class="form-group row">
<label for="my-field-name-5" class="col-sm-2">Choix unique</label>
<div class="col-sm-10">
<div class="form-check form-check-inline">
<input type="radio" id="my-field-name-1" class="form-check-input" name="my_field_name" value="1"/>
<label class="form-check-label" for="my-field-name-1">Option 1</label>
</div>
<div class="form-check form-check-inline">
<input type="radio" id="my-field-name-2" class="form-check-input" name="my_field_name" value="2" checked/>
<label class="form-check-label" for="my-field-name-2">Option 2</label>
</div>
<div class="form-check form-check-inline">
<input type="radio" id="my-field-name-3" class="form-check-input" name="my_field_name" value="3"/>
<label class="form-check-label" for="my-field-name-3">Option 3</label>
</div>
<div class="form-check form-check-inline">
<input type="radio" id="my-field-name-4" class="form-check-input" name="my_field_name" value="4"/>
<label class="form-check-label" for="my-field-name-4">Option 4</label>
</div>
<div class="form-check form-check-inline">
<input type="radio" id="my-field-name-5" class="form-check-input" name="my_field_name" value="5"/>
<label class="form-check-label" for="my-field-name-5">Option 5</label>
</div>
</div>
</div>
<div class="form-group">
<label for="mon-champs-value-4">Mon Champs</label>
<div class="form-check">
<input type="radio" id="mon-champs-value-1" class="form-check-input" name="mon-champs" value="VALUE-1" data-one="data-value1.1" data-tow="data-value1.2" />
<label class="form-check-label" for="mon-champs-value-1">1 - TITRE 1</label>
</div>
<div class="form-check">
<input type="radio" id="mon-champs-value-2" class="form-check-input" name="mon-champs" value="VALUE-2" data-one="data-value2.1" data-tow="data-value2.2" />
<label class="form-check-label" for="mon-champs-value-2">2 - TITRE 2</label>
</div>
<div class="form-check">
<input type="radio" id="mon-champs-value-3" class="form-check-input" name="mon-champs" value="VALUE-3" data-one="data-value3.1" data-tow="data-value3.2" />
<label class="form-check-label" for="mon-champs-value-3">3 - TITRE 3</label>
</div>
<div class="form-check">
<input type="radio" id="mon-champs-value-4" class="form-check-input" name="mon-champs" value="VALUE-4" data-one="data-value4.1" data-tow="data-value4.2" />
<label class="form-check-label" for="mon-champs-value-4">4 - TITRE 4</label>
</div>
</div>
<div class="form-group row">
<label for="my-field-name-5" class="col-sm-2">Choix unique</label>
<div class="col-sm-10">
<div class="form-check form-check-inline">
<input type="radio" id="my-field-name-1" class="form-check-input" name="my_field_name[]" value="1"/>
<label class="form-check-label" for="my-field-name-1">Option 1</label>
</div>
<div class="form-check form-check-inline">
<input type="radio" id="my-field-name-2" class="form-check-input" name="my_field_name[]" value="2" checked/>
<label class="form-check-label" for="my-field-name-2">Option 2</label>
</div>
<div class="form-check form-check-inline">
<input type="radio" id="my-field-name-3" class="form-check-input" name="my_field_name[]" value="3"/>
<label class="form-check-label" for="my-field-name-3">Option 3</label>
</div>
<div class="form-check form-check-inline">
<input type="radio" id="my-field-name-4" class="form-check-input" name="my_field_name[]" value="4"/>
<label class="form-check-label" for="my-field-name-4">Option 4</label>
</div>
<div class="form-check form-check-inline">
<input type="radio" id="my-field-name-5" class="form-check-input" name="my_field_name[]" value="5"/>
<label class="form-check-label" for="my-field-name-5">Option 5</label>
</div>
</div>
</div>
<div class="form-group">
<label for="field-zoom">Zoom</label>
<input type="range" id="field-zoom" class="form-control" name="zoom" value="7" max="20" oninput="zoomShowValue(this.value)" />
<span id="field-zoom-value">7&nbsp;</span>
<script type="text/javascript">
function zoomShowValue(newValue) {
document.getElementById("field-zoom-value").innerHTML=newValue;
}
</script>
</div>
<div class="form-group">
<label for="field-city-id">Ville</label>
<select id="field-city-id" class="form-control" name="city_id">
<option value="" selected >Choisir...</option>
<option value="1" data-data1="data-value1.1" data-data2="data-value1.2">Titre 1 - value-1</option>
<option value="2" data-data1="data-value2.1" data-data2="data-value2.2" selected>Titre 2 - value-2</option>
<option value="3" data-data1="data-value3.1" data-data2="data-value3.2">Titre 3 - value-3</option>
<option value="4" data-data1="data-value4.1" data-data2="data-value4.2">Titre 4 - value-4</option>
</select>
</div>
<div class="form-group">
<label for="field-my-field-name" class="required">Menu déroulant</label>
<select id="field-my-field-name" class="form-control form-control-sm" name="my_field_name" required="required">
<option value="" disabled hidden selected >Choisir ...</option>
<optgroup label="Groupe 1"><option value="23" selected>Élement 23</option>
<option value="24">Élement 24</option>
<option value="25">Élement 25</option>
</optgroup>
<optgroup label="Groupe 2"><option value="26">Élement 26</option>
<option value="27">Élement 27</option>
<option value="28">Élement 28</option>
</optgroup>
</select>
</div>
<div class="form-group">
<label for="field-collection-34" class="required">Collection</label>
<div class="input-group">
<div class="input-group-prepend">
<div class="input-group-text"><i class="fa fa-list"></i></div>
</div>
<select id="field-collection-34" class="form-control select2" name="collection[34][]" multiple="multiple" required="required">
<option value="1">TITRE 1 - VALUE-1</option>
<option value="2" selected>TITRE 2 - VALUE-2</option>
<option value="3">TITRE 3 - VALUE-3</option>
<option value="4" selected>TITRE 4 - VALUE-4</option>
</select>
<div class="input-group-append">
<div class="input-group-text"><i class="fa fa-hand-paper-o"></i></div>
</div>
</div>
</div>
<div class="form-group">
<label for="field-collection-34" class="required">Collection</label>
<div class="input-group input-group-sm">
<div class="input-group-prepend">
<div class="input-group-text"><i class="fa fa-list"></i></div>
</div>
<select id="field-collection-34" class="form-control select2" name="collection[34]" required="required">
<option value="1">Option 1</option>
<option value="2">Option 2</option>
<option value="3">Option 3</option>
<option value="4" selected>Option 4</option>
<option value="5">Option 5</option>
</select>
<div class="input-group-append">
<div class="input-group-text"><i class="fa fa-hand-paper-o"></i></div>
</div>
</div>
</div>
<div class="form-group">
<label for="field-content">Contenu</label>
<span class="text-info popup-help" data-toggle="popover" data-placement="right" title="Le contenu" data-content="Le contenu est le coeur de l'article. Grâce à l'éditeur vous pouvez formater le rendu selon votre goût.">
<i class="fa fa-info-circle"></i>
</span>
<textarea id="field-content" class="form-control text-editor" name="content" rows="15">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Laboriosam, rem esse itaque inventore provident reiciendis quo, asperiores dolorem voluptate nostrum quisquam similique commodi quam consequatur ad eligendi iusto aperiam quos?</textarea>
</div>
<div class="form-group">
<label for="field-toggle">Toggle</label>
<div class="toogle">
<input type="checkbox" value="1" id="field-toggle" class="form-control" name="toggle" data-on="Actif" data-off="Inactif" data-onstyle="success" data-offstyle="danger" data-toggle="toggle" data-width="75" data-size="xs" checked />
</div>
</div>
<div class="form-group">
<label for="field-my-field-video" class="required">Champs video</label>
<div class="input-group">
<div class="input-group-prepend">
<div class="input-group-text text-danger">
<i class="fa fa-file-pdf-o" aria-hidden="true"></i>
</div>
</div>
<input type="text" id="field-my-field-video" class="form-control" name="my_field_video" value="my-video.mp4" placeholder="ex: /upload/folder/video.mp4" required="required" />
<div class="input-group-append">
<button class="btn btn-outline-secondary popupfinder" type="button" id="btn-field-my-field-video" data-field="#field-my-field-video" data-mimes="application/pdf">
<i class="fa fa-file-video-o mr-2"></i> Choisir une vidéo
</button>
</div>
</div>
</div>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment