2024-03-30 21:40:17 +01:00
< ? php
/**
* This file is part of Zwii .
*
* For full copyright and license information , please see the LICENSE
* file that was distributed with this source code .
*
* @ author Rémi Jean < remi . jean @ outlook . com >
* @ copyright Copyright ( C ) 2008 - 2018 , Rémi Jean
* @ author Frédéric Tempez < frederic . tempez @ outlook . com >
* @ copyright Copyright ( C ) 2018 - 2024 , Frédéric Tempez
* @ license CC Attribution - NonCommercial - NoDerivatives 4.0 International
* @ link http :// zwiicms . fr /
*/
class geogallery extends common
{
const VERSION = '0.1' ;
const REALNAME = 'Géo galerie' ;
const DATADIRECTORY = self :: DATA_DIR . 'geogallery/' ;
const SORT_ASC = 'SORT_ASC' ;
const SORT_DSC = 'SORT_DSC' ;
const SORT_HAND = 'SORT_HAND' ;
public static $directories = [];
public static $firstPictures = [];
public static $galleries = [];
public static $galleriesId = [];
public static $pictures = [];
public static $picturesId = [];
public static $thumbs = [];
public static $config = [];
public static $actions = [
'config' => self :: GROUP_EDITOR ,
'delete' => self :: GROUP_EDITOR ,
'dirs' => self :: GROUP_EDITOR ,
'sortGalleries' => self :: GROUP_EDITOR ,
'sortPictures' => self :: GROUP_EDITOR ,
'edit' => self :: GROUP_EDITOR ,
'add' => self :: GROUP_EDITOR ,
'theme' => self :: GROUP_EDITOR ,
'option' => self :: GROUP_EDITOR ,
'index' => self :: GROUP_VISITOR
];
public static $sort = [
self :: SORT_ASC => 'Alphabétique ' ,
self :: SORT_DSC => 'Alphabétique inverse' ,
self :: SORT_HAND => 'Manuel'
];
public static $galleryThemeFlexAlign = [
'flex-start' => 'À gauche' ,
'center' => 'Au centre' ,
'flex-end' => 'À droite' ,
'space-around' => 'Distribué avec marges' ,
'space-between' => 'Distribué sans marge' ,
];
public static $galleryThemeAlign = [
'left' => 'À gauche' ,
'center' => 'Au centre' ,
'right' => 'À droite'
];
public static $galleryThemeSizeWidth = [
'9em' => 'Très petite' ,
'12em' => 'Petite' ,
'15em' => 'Moyenne' ,
'18em' => 'Grande' ,
'21em' => 'Très grande' ,
'100%' => 'Proportionnelle'
];
public static $galleryThemeSizeHeight = [
'9em' => 'Très petite' ,
'12em' => 'Petite' ,
'15em' => 'Moyenne' ,
'18em' => 'Grande' ,
'21em' => 'Très grande'
];
public static $galleryThemeLegendHeight = [
'.125em' => 'Très petite' ,
'.25em' => 'Petite' ,
'.375em' => 'Moyenne' ,
'.5em' => 'Grande' ,
'.625em' => 'Très grande'
];
public static $galleryThemeBorder = [
'0em' => 'Aucune' ,
'.1em' => 'Très fine' ,
'.3em' => 'Fine' ,
'.5em' => 'Moyenne' ,
'.7em' => 'Epaisse' ,
'.9em' => 'Très épaisse'
];
public static $galleryThemeOpacity = [
'1' => 'Aucun ' ,
'.9' => 'Très Discrète' ,
'.8' => 'Discrète' ,
'.7' => 'Moyenne' ,
'.6' => 'Forte' ,
'.5' => 'Très forte'
];
public static $galleryThemeMargin = [
'0em' => 'Aucune' ,
'.1em' => 'Très petite' ,
'.3em' => 'Petite' ,
'.5em' => 'Moyenne' ,
'.7em' => 'Grande' ,
'.9em' => 'Très grande'
];
public static $galleryThemeRadius = [
'0em' => 'Aucun' ,
'.3em' => 'Très léger' ,
'.6em' => 'Léger' ,
'.9em' => 'Moyen' ,
'1.2em' => 'Important' ,
'1.5em' => 'Très important'
];
public static $galleryThemeShadows = [
'0px' => 'Aucune' ,
'1px 1px 5px' => 'Très légère' ,
'1px 1px 10px' => 'Légère' ,
'1px 1px 15px' => 'Moyenne' ,
'1px 1px 25px' => 'Importante' ,
'1px 1px 50px' => 'Très importante'
];
public static $galleryOptionBackPosition = [
'none' => 'Masqué' ,
'top' => 'Au-dessus' ,
'both' => 'Au-dessus et en dessous' ,
'bottom' => 'En dessous' ,
];
public static $galleryOptionBackAlign = [
'left' => 'A gauche' ,
'center' => 'Au centre' ,
'right' => 'A droite' ,
];
public static $formOptionSelect = '' ;
/**
* Mise à jour du module
* Appelée par les fonctions index et config
*/
private function update ()
{
$versionData = $this -> getData ([ 'module' , $this -> getUrl ( 0 ), 'config' , 'versionData' ]);
}
/**
* Configuration
*/
public function config ()
{
// Mise à jour des données de module
$this -> update ();
//Affichage de la galerie triée
2024-08-07 18:11:24 +02:00
$galleries = $this -> getData ([ 'module' , $this -> getUrl ( 0 ), 'content' ]);
2024-04-18 13:43:21 +02:00
2024-03-30 21:40:17 +01:00
// Traitement de l'affichage
if ( $galleries ) {
foreach ( $galleries as $galleryId => $gallery ) {
// Erreur dossier vide
if ( is_dir ( $gallery [ 'config' ][ 'directory' ])) {
if ( count ( scandir ( $gallery [ 'config' ][ 'directory' ])) === 2 ) {
$gallery [ 'config' ][ 'directory' ] = '<span class="galleryConfigError">' . $gallery [ 'config' ][ 'directory' ] . ' (dossier vide)</span>' ;
}
}
// Erreur dossier supprimé
else {
$gallery [ 'config' ][ 'directory' ] = '<span class="galleryConfigError">' . $gallery [ 'config' ][ 'directory' ] . ' (dossier introuvable)</span>' ;
}
// Met en forme le tableau
self :: $galleries [] = [
$gallery [ 'config' ][ 'name' ],
$gallery [ 'config' ][ 'directory' ],
template :: button ( 'galleryConfigEdit' . $galleryId , [
'href' => helper :: baseUrl () . $this -> getUrl ( 0 ) . '/edit/' . $galleryId ,
'value' => template :: ico ( 'pencil' ),
'help' => 'Configuration de la galerie '
]),
template :: button ( 'galleryConfigDelete' . $galleryId , [
'class' => 'galleryConfigDelete buttonRed' ,
'href' => helper :: baseUrl () . $this -> getUrl ( 0 ) . '/delete/' . $galleryId ,
'value' => template :: ico ( 'trash' ),
'help' => 'Supprimer cette galerie'
])
];
// Tableau des id des galleries pour le drag and drop
self :: $galleriesId [] = $galleryId ;
}
}
// Valeurs en sortie
$this -> addOutput ([
'title' => helper :: translate ( 'Configuration des galeries' ),
2024-08-07 17:24:57 +02:00
'view' => 'config'
2024-03-30 21:40:17 +01:00
]);
}
/**
* Ajout d ' une galerie
*/
public function add ()
{
// Soumission du formulaire d'ajout d'une galerie
if (
$this -> getUser ( 'permission' , __CLASS__ , __FUNCTION__ ) === true &&
$this -> isPost ()
) {
$galleryId = $this -> getInput ( 'galleryAddName' , null , true );
$success = false ;
if ( $galleryId ) {
$galleryId = helper :: increment ( $this -> getInput ( 'galleryAddName' , helper :: FILTER_ID , true ), ( array ) $this -> getData ([ 'module' , $this -> getUrl ( 0 ), 'content' ]));
// définir une vignette par défaut
$directory = $this -> getInput ( 'galleryAddDirectory' , helper :: FILTER_STRING_SHORT , true );
$iterator = new DirectoryIterator ( $directory );
$i = 0 ;
foreach ( $iterator as $fileInfos ) {
if ( $fileInfos -> isDot () === false and $fileInfos -> isFile () and @ getimagesize ( $fileInfos -> getPathname ())) {
$i += 1 ;
// Créer la miniature si manquante
if ( ! file_exists ( str_replace ( 'source' , 'thumb' , $fileInfos -> getPath ()) . '/' . self :: THUMBS_SEPARATOR . strtolower ( $fileInfos -> getFilename ()))) {
$this -> makeThumb (
$fileInfos -> getPathname (),
str_replace ( 'source' , 'thumb' , $fileInfos -> getPath ()) . '/' . self :: THUMBS_SEPARATOR . strtolower ( $fileInfos -> getFilename ()),
self :: THUMBS_WIDTH
);
}
break ;
}
}
// Le dossier de la galerie est vide
if ( $i > 0 ) {
$this -> setData ([
'module' ,
$this -> getUrl ( 0 ),
'content' ,
$galleryId ,
[
'config' => [
'name' => $this -> getInput ( 'galleryAddName' ),
'directory' => $this -> getInput ( 'galleryAddDirectory' , helper :: FILTER_STRING_SHORT , true ),
],
'legend' => [],
'positions' => []
]
]);
$success = true ;
} else {
self :: $inputNotices [ 'galleryAddDirectory' ] = " Le dossier sélectionné ne contient aucune image " ;
$success = false ;
}
}
2024-08-07 18:11:24 +02:00
// Valeurs en sortie
$this -> addOutput ([
'redirect' => helper :: baseUrl () . $this -> getUrl ( 0 ) . '/edit/' . $galleryId ,
'notification' => helper :: translate ( 'Paramétrage de la galerie' ),
'state' => true
]);
2024-03-30 21:40:17 +01:00
} else {
// Valeurs en sortie
$this -> addOutput ([
'title' => helper :: translate ( 'Création d\'une galerie' ),
'view' => 'add'
]);
}
}
/**
* Suppression
*/
public function delete ()
{
// La galerie n'existe pas
if (
$this -> getUser ( 'permission' , __CLASS__ , __FUNCTION__ ) !== true ||
$this -> getData ([ 'module' , $this -> getUrl ( 0 ), 'content' , $this -> getUrl ( 2 )]) === null
) {
// Valeurs en sortie
$this -> addOutput ([
'access' => false
]);
}
// Suppression
else {
$this -> deleteData ([ 'module' , $this -> getUrl ( 0 ), 'content' , $this -> getUrl ( 2 )]);
// Valeurs en sortie
$this -> addOutput ([
'redirect' => helper :: baseUrl () . $this -> getUrl ( 0 ) . '/config' ,
'notification' => helper :: translate ( 'Galerie effacée' ),
'state' => true
]);
}
}
/**
* Liste des dossiers
*/
public function dirs ()
{
// Valeurs en sortie
$this -> addOutput ([
'display' => self :: DISPLAY_JSON ,
'content' => geogalleriesHelper :: scanDir ( self :: FILE_DIR . 'source' )
]);
}
/**
* Édition
*/
public function edit ()
{
// Soumission du formulaire
if (
$this -> getUser ( 'permission' , __CLASS__ , __FUNCTION__ ) === true &&
$this -> isPost ()
) {
// légendes
foreach (( array ) $this -> getInput ( 'legend' , null ) as $file => $legend ) {
// Image de couverture par défaut si non définie
2024-08-07 17:24:57 +02:00
$legends [ str_replace ( '.' , '' , $file )] = helper :: filter ( $legend , helper :: FILTER_STRING_SHORT );
2024-03-30 21:40:17 +01:00
}
2024-04-01 22:25:23 +02:00
// Données géographiques
foreach (( array ) $this -> getInput ( 'legend' , null ) as $file => $data ) {
2024-08-07 17:24:57 +02:00
$geo [ str_replace ( '.' , '' , $file )] = [
2024-04-18 13:43:21 +02:00
'long' => $this -> getInput ( 'gpslong[' . $file . ']' ),
'lat' => $this -> getInput ( 'gpslat[' . $file . ']' )
2024-04-01 22:25:23 +02:00
];
}
2024-03-30 21:40:17 +01:00
// Sauvegarder
$this -> setData ([
'module' ,
$this -> getUrl ( 0 ),
'content' ,
$this -> getUrl ( 2 ),
[
'config' => [
// Données mises à jour par les options
'name' => $this -> getData ([ 'module' , $this -> getUrl ( 0 ), 'content' , $this -> getUrl ( 2 ), 'config' , 'name' ]),
'directory' => $this -> getData ([ 'module' , $this -> getUrl ( 0 ), 'content' , $this -> getUrl ( 2 ), 'config' , 'directory' ]),
],
'legend' => $legends ,
2024-04-18 13:43:21 +02:00
//'geo' => $geo,
2024-08-07 17:24:57 +02:00
'positions' => $geo
2024-03-30 21:40:17 +01:00
]
]);
// Valeurs en sortie
$this -> addOutput ([
'redirect' => helper :: baseUrl () . $this -> getUrl ( 0 ) . '/edit/' . $this -> getUrl ( 2 ),
'notification' => helper :: translate ( 'Modifications enregistrées' ),
'state' => true
]);
}
// La galerie n'existe pas
if ( $this -> getData ([ 'module' , $this -> getUrl ( 0 ), 'content' , $this -> getUrl ( 2 )]) === null ) {
// Valeurs en sortie
$this -> addOutput ([
'access' => false
]);
}
// La galerie existe
else {
// Met en forme le tableau
$directory = $this -> getData ([ 'module' , $this -> getUrl ( 0 ), 'content' , $this -> getUrl ( 2 ), 'config' , 'directory' ]);
if ( is_dir ( $directory )) {
$iterator = new DirectoryIterator ( $directory );
foreach ( $iterator as $fileInfos ) {
if ( $fileInfos -> isDot () === false and $fileInfos -> isFile () and @ getimagesize ( $fileInfos -> getPathname ())) {
// Créer la miniature RFM si manquante
if ( ! file_exists ( str_replace ( 'source' , 'thumb' , $fileInfos -> getPath ()) . '/' . strtolower ( $fileInfos -> getFilename ()))) {
$this -> makeThumb (
$fileInfos -> getPathname (),
str_replace ( 'source' , 'thumb' , $fileInfos -> getPath ()) . '/' . strtolower ( $fileInfos -> getFilename ()),
122
);
}
// Obtenir les métadonnées EXIF de l'image
$exif = exif_read_data ( $fileInfos -> getPath () . '/' . $fileInfos -> getFilename ());
2024-04-18 13:43:21 +02:00
$latitude = 'Donnée absente' ;
$longitude = 'Donnée absente' ;
2024-03-30 21:40:17 +01:00
// Vérifier si les données EXIF contiennent des informations de géolocalisation
if ( ! empty ( $exif [ 'GPSLatitude' ]) && ! empty ( $exif [ 'GPSLongitude' ])) {
// Coordonnées de latitude
$latitude = $this -> gps_decimal ( $exif [ 'GPSLatitude' ], $exif [ 'GPSLatitudeRef' ]);
// Coordonnées de longitude
$longitude = $this -> gps_decimal ( $exif [ 'GPSLongitude' ], $exif [ 'GPSLongitudeRef' ]);
}
self :: $pictures [ str_replace ( '.' , '' , $fileInfos -> getFilename ())] = [
2024-08-07 17:24:57 +02:00
//$this->getData(['module', $this->getUrl(0), 'content', $this->getUrl(2), 'positions', str_replace('.', '', $fileInfos->getFilename())]) + 1,
2024-03-30 21:40:17 +01:00
$fileInfos -> getFilename (),
template :: text ( 'legend[' . $fileInfos -> getFilename () . ']' , [
'value' => $this -> getData ([ 'module' , $this -> getUrl ( 0 ), 'content' , $this -> getUrl ( 2 ), 'legend' , str_replace ( '.' , '' , $fileInfos -> getFilename ())])
]),
2024-04-01 22:25:23 +02:00
template :: text ( 'gpslong[' . $fileInfos -> getFilename () . ']' , [
2024-04-18 13:43:21 +02:00
'value' => $longitude ,
'readonly' => true ,
2024-08-07 17:24:57 +02:00
]),
2024-04-01 22:25:23 +02:00
template :: text ( 'gpslat[' . $fileInfos -> getFilename () . ']' , [
2024-04-18 13:43:21 +02:00
'value' => $latitude ,
'readonly' => true ,
2024-04-01 22:25:23 +02:00
]),
2024-03-30 21:40:17 +01:00
'<a href="' . str_replace ( 'source' , 'thumb' , $directory ) . '/' . self :: THUMBS_SEPARATOR . $fileInfos -> getFilename () . '" rel="data-lity" data-lity=""><img src="' . str_replace ( 'source' , 'thumb' , $directory ) . '/' . $fileInfos -> getFilename () . '"></a>' ,
];
self :: $picturesId [] = str_replace ( '.' , '' , $fileInfos -> getFilename ());
}
}
// Tri des images
switch ( $this -> getData ([ 'module' , $this -> getUrl ( 0 ), 'content' , $this -> getUrl ( 2 ), 'config' , 'sort' ])) {
case self :: SORT_HAND :
$positions = $this -> getData ([ 'module' , $this -> getUrl ( 0 ), 'content' , $this -> getUrl ( 2 ), 'positions' ]);
if ( $positions ) {
foreach ( $positions as $key => $value ) {
if ( array_key_exists ( $key , self :: $pictures )) {
$tempPictures [ $key ] = self :: $pictures [ $key ];
$tempPicturesId [] = $key ;
}
}
// Images ayant été ajoutées dans le dossier mais non triées
foreach ( self :: $pictures as $key => $value ) {
if ( ! array_key_exists ( $key , $tempPictures )) {
$tempPictures [ $key ] = self :: $pictures [ $key ];
$tempPicturesId [] = $key ;
}
}
self :: $pictures = $tempPictures ;
self :: $picturesId = $tempPicturesId ;
}
break ;
case self :: SORT_ASC :
ksort ( self :: $pictures , SORT_NATURAL );
sort ( self :: $picturesId , SORT_NATURAL );
break ;
case self :: SORT_DSC :
krsort ( self :: $pictures , SORT_NATURAL );
rsort ( self :: $picturesId , SORT_NATURAL );
break ;
}
}
// Valeurs en sortie
$this -> addOutput ([
'title' => sprintf ( helper :: translate ( 'Configuration de la galerie %s ' ), $this -> getData ([ 'module' , $this -> getUrl ( 0 ), 'content' , $this -> getUrl ( 2 ), 'config' , 'name' ])),
2024-08-07 17:24:57 +02:00
'view' => 'edit'
2024-03-30 21:40:17 +01:00
]);
}
}
/**
* Accueil ( deux affichages en un pour éviter une url à rallonge )
*/
public function index ()
{
// Mise à jour des données de module
$this -> update ();
2024-04-01 22:25:23 +02:00
2024-08-07 18:11:24 +02:00
// Liste des galeries
$galleries = array_keys ( $this -> getData ([ 'module' , $this -> getUrl ( 0 ), 'content' ]));
foreach ( $galleries as $key => $gallery ) {
$directory = $this -> getData ([ 'module' , $this -> getUrl ( 0 ), 'content' , $gallery , 'config' , 'directory' ]);
if ( is_dir ( $directory )) {
$iterator = new DirectoryIterator ( $directory );
foreach ( $iterator as $fileInfos ) {
if ( $fileInfos -> isDot () === false and $fileInfos -> isFile () and @ getimagesize ( $fileInfos -> getPathname ())) {
self :: $galleries [ $directory . '/' . $fileInfos -> getFilename ()] = $this -> getData ([ 'module' , $this -> getUrl ( 0 ), 'content' , $gallery , 'legend' , str_replace ( '.' , '' , $fileInfos -> getFilename ())]);
// Créer la miniature si manquante
if ( ! file_exists ( str_replace ( 'source' , 'thumb' , $fileInfos -> getPath ()) . '/' . self :: THUMBS_SEPARATOR . strtolower ( $fileInfos -> getFilename ()))) {
$this -> makeThumb (
$fileInfos -> getPathname (),
str_replace ( 'source' , 'thumb' , $fileInfos -> getPath ()) . '/' . self :: THUMBS_SEPARATOR . strtolower ( $fileInfos -> getFilename ()),
self :: THUMBS_WIDTH
);
2024-03-30 21:40:17 +01:00
}
2024-08-07 18:11:24 +02:00
$exif = exif_read_data ( $fileInfos -> getPath () . '/' . $fileInfos -> getFilename ());
// Vérifier si les données EXIF contiennent des informations de géolocalisation
if ( ! empty ( $exif [ 'GPSLatitude' ]) && ! empty ( $exif [ 'GPSLongitude' ])) {
// Coordonnées
self :: $galleries [ $directory . '/' . $fileInfos -> getFilename ()] = [
'lat' => $this -> gps_decimal ( $exif [ 'GPSLatitude' ], $exif [ 'GPSLatitudeRef' ]),
'long' => $this -> gps_decimal ( $exif [ 'GPSLongitude' ], $exif [ 'GPSLatitudeRef' ])
];
}
2024-03-30 21:40:17 +01:00
}
}
}
}
2024-08-07 18:11:24 +02:00
// Affichage du template
if ( self :: $galleries ) {
2024-03-30 21:40:17 +01:00
// Valeurs en sortie
$this -> addOutput ([
'showBarEditButton' => true ,
'view' => 'index' ,
2024-04-01 22:25:23 +02:00
'vendor' => [
'leaflet'
],
2024-03-30 21:40:17 +01:00
]);
}
}
/**
* Thème de la galerie
*/
public function theme ()
{
// Soumission du formulaire
if (
$this -> getUser ( 'permission' , __CLASS__ , __FUNCTION__ ) === true &&
$this -> isPost ()
) {
// Dossier de l'instance
if ( ! is_dir ( self :: DATADIRECTORY . $this -> getUrl ( 0 ))) {
mkdir ( self :: DATADIRECTORY . $this -> getUrl ( 0 ), 0755 , true );
}
$this -> setData ([
'module' ,
$this -> getUrl ( 0 ),
'theme' ,
[
]
]);
2024-08-07 17:24:57 +02:00
$success = true ;
2024-03-30 21:40:17 +01:00
// Valeurs en sortie
$this -> addOutput ([
'redirect' => helper :: baseUrl () . $this -> getUrl () . '/theme' ,
'notification' => $success ? 'Modifications enregistrées' : 'Modifications non enregistrées !' ,
'state' => $success
]);
}
// Valeurs en sortie
$this -> addOutput ([
'title' => helper :: translate ( 'Thème' ),
'view' => 'theme' ,
'vendor' => [
'tinycolorpicker'
]
]);
}
// Fonction pour convertir les coordonnées GPS au format décimal
private function gps_decimal ( $coordinate , $hemisphere )
{
// Extrait les degrés, minutes et secondes
2024-04-01 22:25:23 +02:00
$degrees = count ( $coordinate ) > 0 ? $this -> gps2Num ( $coordinate [ 0 ]) : 0 ;
$minutes = count ( $coordinate ) > 1 ? $this -> gps2Num ( $coordinate [ 1 ]) : 0 ;
$seconds = count ( $coordinate ) > 2 ? $this -> gps2Num ( $coordinate [ 2 ]) : 0 ;
2024-03-30 21:40:17 +01:00
// Convertit les degrés, minutes et secondes en décimal
$decimal = $degrees + ( $minutes / 60 ) + ( $seconds / 3600 );
// Si l'hémisphère est au Sud ou à l'Ouest, les coordonnées sont négatives
$decimal *= ( $hemisphere == 'S' || $hemisphere == 'W' ) ? - 1 : 1 ;
return $decimal ;
}
// Fonction pour convertir les coordonnées GPS en nombre
private function gps2Num ( $coordPart )
{
$parts = explode ( '/' , $coordPart );
if ( count ( $parts ) <= 0 )
return 0 ;
if ( count ( $parts ) == 1 )
return $parts [ 0 ];
return floatval ( $parts [ 0 ]) / floatval ( $parts [ 1 ]);
}
}
class geogalleriesHelper extends helper
{
/**
* Scan le contenu d ' un dossier et de ses sous - dossiers
* @ param string $dir Dossier à scanner
* @ return array
*/
public static function scanDir ( $dir )
{
$dirContent = [];
$iterator = new DirectoryIterator ( $dir );
foreach ( $iterator as $fileInfos ) {
if ( $fileInfos -> isDot () === false and $fileInfos -> isDir ()) {
$dirContent [] = $dir . '/' . $fileInfos -> getBasename ();
$dirContent = array_merge ( $dirContent , self :: scanDir ( $dir . '/' . $fileInfos -> getBasename ()));
}
}
return $dirContent ;
}
}