diff --git a/core/class/helper.class.php b/core/class/helper.class.php index accf7132..fc623eab 100644 --- a/core/class/helper.class.php +++ b/core/class/helper.class.php @@ -86,7 +86,7 @@ class helper { * @param string $sort Type de tri à appliquer au tableau (SORT_ASC, SORT_DESC, ou null) * @return array */ - public static function arrayCollumn($array, $column, $sort = null) { + public static function arrayColumn($array, $column, $sort = null) { $newArray = []; if(empty($array) === false) { $newArray = array_map(function($element) use($column) { diff --git a/core/class/template.class.php b/core/class/template.class.php index ac510b31..5522201e 100644 --- a/core/class/template.class.php +++ b/core/class/template.class.php @@ -620,13 +620,6 @@ class template { if($attributes['before'] AND array_key_exists($attributes['id'], common::$inputBefore)) { $attributes['selected'] = common::$inputBefore[$attributes['id']]; } - // Liste des polices à intégrer - //var_dump(core::$fonts); - if ($attributes['fonts'] === true) { - foreach (core::$fonts as $fontId => $font) { - echo "\n"; - } - } // Début du wrapper $html = '
'; // Label diff --git a/core/core.php b/core/core.php index 02cb8806..142c587b 100644 --- a/core/core.php +++ b/core/core.php @@ -179,22 +179,18 @@ class common { ]; - // Fontes - public static $fonts = [ - ]; - public static $fontsWebSafe = [ 'arial' => 'Arial, Helvetica, sans-serif;', - 'arial-black' => 'Arial Black, Gadget, sans-serif;', - 'courrier' => 'Courier, Liberation Mono, monospace;', - 'courrier-new' => 'Courier New, Courier, monospace', + 'arial-black' => '"Arial Black", Gadget, sans-serif;', + 'courrier' => 'Courier, "Liberation Mono", monospace;', + 'courrier-new' => '"Courier New", Courier, monospace', 'garamond' => 'Garamond, serif', 'georgia' => 'Georgia, serif;', 'impact' => 'Impact, Charcoal, sans-serif;', - 'lucida' => 'Lucida Sans Unicode, Lucida Grande, sans-serif', + 'lucida' => '"Lucida Sans Unicode", "Lucida Grande", sans-serif', 'tahoma' => 'Tahoma, Geneva, sans-serif;', - 'times-new-roman' => 'Times New Roman, Liberation Serif, serif;', - 'trebuchet' => 'Trebuchet MS, Arial, Helvetica, sans-serif;', + 'times-new-roman' => '"Times New Roman", "Liberation Serif", serif;', + 'trebuchet' => '"Trebuchet MS", Arial, Helvetica, sans-serif;', 'tahoma' => 'Tahoma, Geneva, sans-serif;', 'verdana' => 'Verdana, Geneva, sans-serif;', ]; @@ -294,7 +290,7 @@ class common { // Construit la liste des pages parents/enfants if($this->hierarchy['all'] === []) { - $pages = helper::arrayCollumn($this->getData(['page']), 'position', 'SORT_ASC'); + $pages = helper::arrayColumn($this->getData(['page']), 'position', 'SORT_ASC'); // Parents foreach($pages as $pageId => $pagePosition) { if( @@ -407,6 +403,48 @@ class common { } } + /** + * Construit la liste des fontes dans un tableau + * @return array @fonts + * + */ + public function getFonts() { + + // Fusionne la liste des fontes avec les webSafe + foreach (self::$fontsWebSafe as $fontId => $fontValue) { + $fontName = explode (',', $fontValue); + $f ['websafe'] [$fontId] = [ + 'name' => str_replace('"', '', $fontName[0]), + 'font-family'=> $fontValue + ]; + } + // Ajoute les polices importées + $fontsImported = $this->getData(['fonts', 'imported']); + if (is_array($fontsImported) + ) { + foreach ($fontsImported as $fontId => $fontValue) { + $f ['imported'] [$fontId] = [ + 'name' => $fontValue ['name'], + 'font-family'=> $fontValue ['font-family'], + 'ressource' => $fontValue ['ressource'] + ]; + } + } + // Ajoute les polices locales + $fontsFiles = $this->getData(['fonts', 'files']); + if (is_array($fontsFiles) + ) { + foreach ($fontsFiles as $fontId => $fontValue) { + $f ['files'] [$fontId] = [ + 'name' => $fontValue ['name'], + 'font-family'=> $fontValue ['font-family'], + 'ressource' => $fontValue ['ressource'] + ]; + } + } + return $f; + } + /** * Check du token CSRF (true = bo */ @@ -2232,27 +2270,6 @@ class core extends common { } } - /** - * Traitement des polices de caractères - */ - - // Fusionne la liste des fontes avec les webSafe - foreach (self::$fontsWebSafe as $fontId => $fontValue) { - $fontName = explode (',', $fontValue); - self::$fonts [$fontId] = $fontName[0]; - } - // Importe les polices personnalisées - $fontsImported = $this->getData(['fonts', 'imported']); - if (is_array($fontsImported) && - !empty ($fontsImported) - ) { - // Fusionner avec les fontes installées - self::$fonts = array_merge(self::$fonts, $fontsImported); - - } - // Tri Alphabétique - asort(self::$fonts); - // Crée le fichier de personnalisation avancée if(file_exists(self::DATA_DIR.'custom.css') === false) { file_put_contents(self::DATA_DIR.'custom.css', file_get_contents('core/module/theme/resource/custom.css')); @@ -2268,18 +2285,24 @@ class core extends common { file_put_contents(self::DATA_DIR.'admin.css', ''); chmod(self::DATA_DIR.'admin.css', 0755); } + // Check la version rafraichissement du theme $cssVersion = preg_split('/\*+/', file_get_contents(self::DATA_DIR.'theme.css')); if(empty($cssVersion[1]) OR $cssVersion[1] !== md5(json_encode($this->getData(['theme'])))) { // Version $css = '/*' . md5(json_encode($this->getData(['theme']))) . '*/'; + /** * Import des polices de caractères * A partir du CDN * ou dans le dossier site/file/source/fonts * ou pas du tout si fonte webSafe */ + + // Fonts disponibles + $fontsAvailable = $this->getFonts(); + // Fontes installées $fonts = [ $this->getData(['theme', 'text', 'font']), $this->getData(['theme', 'title', 'font']), $this->getData(['theme', 'header', 'font']), @@ -2290,51 +2313,50 @@ class core extends common { $fonts = array_unique($fonts); /** - * Fontes Web Safe, ne sont pas chargées. + * Charge les fontes websafe */ + $fontFile = ''; foreach ($fonts as $fontId) { - if (array_key_exists($fontId, self::$fontsWebSafe) ) { - unset($fonts[$fontId]); + if ( isset($fontsAvailable['websafe'][$fontId])) { + $fonts [$fontId] = $fontsAvailable['websafe'][$fontId]['font-family']; } } /** - * Chargement des polices en ligne dans un fichier séparé + * Chargement des polices en ligne dans un fichier fonts.html inclus dans main.php */ - // Lire le fichier des fontes locales - $localFonts = $this->getData(['fonts', 'files']); $fontFile = ''; foreach ($fonts as $fontId) { - if (!array_key_exists($fontId, $localFonts) ) { - $fontFile .= ''; - // Supprimer l'élément des fontes chargées en ligne - unset($fonts[$fontId]); + if ( isset($fontsAvailable['imported'][$fontId])) { + $fontFile .= ''; + // Tableau pour la construction de la feuille de style + $fonts [$fontId] = $fontsAvailable['imported'][$fontId]['font-family']; } } + // Enregistre la personnalisation + file_put_contents(self::DATA_DIR.'fonts/fonts.html', $fontFile); /** * Fontes installées localement */ - // Validité du format - if ( !empty($localFonts) - ) { - foreach ($localFonts as $fontId => $fontName) { - // Validité du tableau : - if ( array_key_exists($fontId, self::$fonts) && - file_exists(self::DATA_DIR . 'fonts/' . $fontName) ) { - // Chargement de la police - //$formatFont = explode('.', self::DATA_DIR . 'fonts/' . $fontName); - $css .= '@font-face {font-family:"' . self::$fonts[$fontId] . '";'; - $css .= 'src: url("' . helper::baseUrl(false) . self::DATA_DIR . 'fonts/' . $fontName . '");}'; - } - + foreach ($fonts as $fontId) { + // Validité du tableau : + if ( isset($fontsAvailable['files'][$fontId]) && + file_exists(self::DATA_DIR . 'fonts/' . $f) ) { + // Chargement de la police + //$formatFont = explode('.', self::DATA_DIR . 'fonts/' . $fontName); + $css .= '@font-face {font-family:"' . $fontsAvailable['files'][$fontId]['font-family'] . '";'; + $css .= 'src: url("' . helper::baseUrl(false) . self::DATA_DIR . 'fonts/' .$fontsAvailable['files'][$fontId]['ressource'] . '");}'; + // Tableau pour la construction de la feuille de style + $fonts [$fontId] = $fontsAvailable['files'][$fontId]['font-family']; } + } // Fond du body $colors = helper::colorVariants($this->getData(['theme', 'body', 'backgroundColor'])); // Body - $css .= 'body{font-family:"' . self::$fonts[$this->getData(['theme', 'text', 'font'])] . '",sans-serif}'; + $css .= 'body{font-family:' . $fonts[$this->getData(['theme', 'text', 'font'])] . ';}'; if($themeBodyImage = $this->getData(['theme', 'body', 'image'])) { // Image dans html pour éviter les déformations. $css .= 'html {background-image:url("../file/source/' . $themeBodyImage . '");background-position:' . $this->getData(['theme', 'body', 'imagePosition']) . ';background-attachment:' . $this->getData(['theme', 'body', 'imageAttachment']) . ';background-size:' . $this->getData(['theme', 'body', 'imageSize']) . ';background-repeat:' . $this->getData(['theme', 'body', 'imageRepeat']) . '}'; @@ -2352,7 +2374,7 @@ class core extends common { $colors = helper::colorVariants($this->getData(['theme', 'text', 'linkColor'])); $css .= 'a{color:' . $colors['normal'] . '}'; // Couleurs de site dans TinyMCe - $css .= 'div.mce-edit-area {font-family:"' . self::$fonts[$this->getData(['theme', 'text', 'font'])] . '",sans-serif}'; + $css .= 'div.mce-edit-area {font-family:' . $fonts[$this->getData(['theme', 'text', 'font'])] . ';}'; // Site dans TinyMCE $css .= '.editorWysiwyg {background-color:' . $this->getData(['theme', 'site', 'backgroundColor']) . ';}'; $css .= 'span.mce-text{background-color: unset !important;}'; @@ -2393,7 +2415,7 @@ class core extends common { $css .= '.helpButton span:hover{color:' . $colors['darken'] . '}'; $css .= '.button:active,button[type=\'submit\']:active,.pagination a:active{background-color:' . $colors['veryDarken'] . '}'; $colors = helper::colorVariants($this->getData(['theme', 'title', 'textColor'])); - $css .= 'h1,h2,h3,h4,h5,h6,h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{color:' . $colors['normal'] . ';font-family:"' . self::$fonts[$this->getData(['theme', 'title', 'font'])] . '",sans-serif;font-weight:' . $this->getData(['theme', 'title', 'fontWeight']) . ';text-transform:' . $this->getData(['theme', 'title', 'textTransform']) . '}'; + $css .= 'h1,h2,h3,h4,h5,h6,h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{color:' . $colors['normal'] . ';font-family:' . $fonts[$this->getData(['theme', 'title', 'font'])] . ';font-weight:' . $this->getData(['theme', 'title', 'fontWeight']) . ';text-transform:' . $this->getData(['theme', 'title', 'textTransform']) . '}'; $css .= 'h1 a:hover,h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover,h6 a:hover{color:' . $colors['darken'] . '}'; // Les blocs $colors = helper::colorVariants($this->getData(['theme', 'block', 'backgroundColor'])); @@ -2427,7 +2449,7 @@ class core extends common { $css .= 'header{background-image:url("../file/source/' . $themeHeaderImage . '");background-position:' . $this->getData(['theme', 'header', 'imagePosition']) . ';background-repeat:' . $this->getData(['theme', 'header', 'imageRepeat']) . '}'; } $colors = helper::colorVariants($this->getData(['theme', 'header', 'textColor'])); - $css .= 'header span{color:' . $colors['normal'] . ';font-family:"' . self::$fonts[$this->getData(['theme', 'header', 'font'])] . '",sans-serif;font-weight:' . $this->getData(['theme', 'header', 'fontWeight']) . ';font-size:' . $this->getData(['theme', 'header', 'fontSize']) . ';text-transform:' . $this->getData(['theme', 'header', 'textTransform']) . '}'; + $css .= 'header span{color:' . $colors['normal'] . ';font-family:' . $fonts[$this->getData(['theme', 'header', 'font'])] . ';font-weight:' . $this->getData(['theme', 'header', 'fontWeight']) . ';font-size:' . $this->getData(['theme', 'header', 'fontSize']) . ';text-transform:' . $this->getData(['theme', 'header', 'textTransform']) . '}'; } // Bannière au contenu personnalisé @@ -2476,7 +2498,7 @@ class core extends common { $css .= 'nav{padding:0 10px;}'; } - $css .= '#toggle span,#menu a{padding:' . $this->getData(['theme', 'menu', 'height']) .';font-family:"' . self::$fonts[$this->getData(['theme', 'menu', 'font'])] . '",sans-serif;font-weight:' . $this->getData(['theme', 'menu', 'fontWeight']) . ';font-size:' . $this->getData(['theme', 'menu', 'fontSize']) . ';text-transform:' . $this->getData(['theme', 'menu', 'textTransform']) . '}'; + $css .= '#toggle span,#menu a{padding:' . $this->getData(['theme', 'menu', 'height']) .';font-family:' . $fonts[$this->getData(['theme', 'menu', 'font'])] . ';font-weight:' . $this->getData(['theme', 'menu', 'fontWeight']) . ';font-size:' . $this->getData(['theme', 'menu', 'fontSize']) . ';text-transform:' . $this->getData(['theme', 'menu', 'textTransform']) . '}'; // Pied de page $colors = helper::colorVariants($this->getData(['theme', 'footer', 'backgroundColor'])); @@ -2486,7 +2508,7 @@ class core extends common { $css .= 'footer{padding:0}'; } - $css .= 'footer span, #footerText > p {color:' . $this->getData(['theme', 'footer', 'textColor']) . ';font-family:"' . self::$fonts[$this->getData(['theme', 'footer', 'font'])] . '",sans-serif;font-weight:' . $this->getData(['theme', 'footer', 'fontWeight']) . ';font-size:' . $this->getData(['theme', 'footer', 'fontSize']) . ';text-transform:' . $this->getData(['theme', 'footer', 'textTransform']) . '}'; + $css .= 'footer span, #footerText > p {color:' . $this->getData(['theme', 'footer', 'textColor']) . ';font-family:' . $fonts[$this->getData(['theme', 'footer', 'font'])] . ';font-weight:' . $this->getData(['theme', 'footer', 'fontWeight']) . ';font-size:' . $this->getData(['theme', 'footer', 'fontSize']) . ';text-transform:' . $this->getData(['theme', 'footer', 'textTransform']) . '}'; $css .= 'footer {background-color:' . $colors['normal'] . ';color:' . $this->getData(['theme', 'footer', 'textColor']) . '}'; $css .= 'footer a{color:' . $this->getData(['theme', 'footer', 'textColor']) . '}'; $css .= 'footer #footersite > div {margin:' . $this->getData(['theme', 'footer', 'height']) . ' 0}'; @@ -2497,10 +2519,8 @@ class core extends common { $css .= '#footerText > p {text-align:' . $this->getData(['theme', 'footer', 'textAlign']) . '}'; $css .= '#footerCopyright{text-align:' . $this->getData(['theme', 'footer', 'copyrightAlign']) . '}'; - // Enregistre la personnalisation file_put_contents(self::DATA_DIR.'theme.css', $css); - file_put_contents(self::DATA_DIR.'fonts/fonts.html', $fontFile); // Effacer le cache pour tenir compte de la couleur de fond TinyMCE header("Expires: Tue, 01 Jan 2000 00:00:00 GMT"); header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); @@ -2527,52 +2547,51 @@ class core extends common { $fonts = array_unique($fonts); /** - * Fontes Web Safe, ne sont pas chargées. + * Charge les fontes websafe */ + $fontFile = ''; foreach ($fonts as $fontId) { - if (array_key_exists($fontId, self::$fontsWebSafe) ) { - unset($fonts[$fontId]); + if ( isset($fontsAvailable['websafe'][$fontId])) { + $fonts [$fontId] = $fontsAvailable['websafe'][$fontId]['font-family']; } } - // Lire le fichier des fontes locales - $localFonts = $this->getData(['fonts', 'files']); - /** - * Chargement des polices en ligne + * Chargement des polices en ligne dans un fichier fonts.html inclus dans main.php */ + $fontFile = ''; foreach ($fonts as $fontId) { - if (!array_key_exists($fontId, $localFonts) ) { - $css .= '@import url("http://fonts.cdnfonts.com/css/' . $fontId . '");'; - // Supprimer l'élément des fontes chargées en ligne - unset($fonts[$fontId]); + if ( isset($fontsAvailable['imported'][$fontId])) { + $fontFile .= ''; + // Tableau pour la construction de la feuille de style + $fonts [$fontId] = $fontsAvailable['imported'][$fontId]['font-family']; } } + // Enregistre la personnalisation + file_put_contents(self::DATA_DIR.'fonts/fonts.html', $fontFile); /** * Fontes installées localement */ - // Validité du format - if ( !empty($localFonts) - ) { - foreach ($localFonts as $fontId => $fontName) { - // Validité du tableau : - if ( array_key_exists($fontId, self::$fonts) && - file_exists(self::DATA_DIR . 'fonts/' . $fontName) ) { - // Chargement de la police - //$formatFont = explode('.', self::DATA_DIR . 'fonts/' . $fontName); - $css .= '@font-face {font-family:"' . self::$fonts[$fontId] . '";'; - $css .= 'src: url("' . helper::baseUrl(false) . self::DATA_DIR . 'fonts/' . $fontName . '");}'; - } - + foreach ($fonts as $fontId) { + // Validité du tableau : + if ( isset($fontsAvailable['files'][$fontId]) && + file_exists(self::DATA_DIR . 'fonts/' . $f) ) { + // Chargement de la police + //$formatFont = explode('.', self::DATA_DIR . 'fonts/' . $fontName); + $css .= '@font-face {font-family:"' . $fontsAvailable['files'][$fontId]['font-family'] . '";'; + $css .= 'src: url("' . helper::baseUrl(false) . self::DATA_DIR . 'fonts/' .$fontsAvailable['files'][$fontId]['ressource'] . '");}'; + // Tableau pour la construction de la feuille de style + $fonts [$fontId] = $fontsAvailable['files'][$fontId]['font-family']; } + } // Thème Administration $colors = helper::colorVariants($this->getData(['admin','backgroundColor'])); $css .= '#site{background-color:' . $colors['normal']. ';}'; - $css .= '.row > div {font:' . $this->getData(['admin','fontSize']) . ' "' . self::$fonts[$this->getData(['admin','fontText'])] . '", sans-serif;}'; - $css .= 'body h1, h2, h3, h4 a, h5, h6 {font-family:"' . self::$fonts[$this->getData(['admin','fontTitle'])] . '", sans-serif;color:' . $this->getData(['admin','colorTitle' ]) . ';}'; + $css .= '.row > div {font:' . $fonts[$this->getData(['admin','fontText'])] . ';font-size:' . $this->getData(['admin','fontSize']) .'}'; + $css .= 'body h1, h2, h3, h4 a, h5, h6 {font-family:' . $fonts[$this->getData(['admin','fontTitle'])] . ';color:' . $this->getData(['admin','colorTitle' ]) . ';}'; // TinyMCE $css .= 'body:not(.editorWysiwyg),span .zwiico-help {color:' . $this->getData(['admin','colorText']) . ';}'; diff --git a/core/include/update.inc.php b/core/include/update.inc.php index ceabc026..9badca7c 100644 --- a/core/include/update.inc.php +++ b/core/include/update.inc.php @@ -481,7 +481,7 @@ if ($this->getData(['core', 'dataVersion']) < 10400) { foreach ($pageList as $parentKey => $parent) { //La page est un blog if ($this->getData(['page',$parent,'moduleId']) === 'blog' ) { - $articleIds = array_keys(helper::arrayCollumn($this->getData(['module', $parent, 'posts']), 'publishedOn', 'SORT_DESC')); + $articleIds = array_keys(helper::arrayColumn($this->getData(['module', $parent, 'posts']), 'publishedOn', 'SORT_DESC')); foreach ($articleIds as $key => $article) { // Droits les deux groupes $this->setData(['module', $parent, 'posts', $article,'editConsent', 3]); @@ -874,26 +874,106 @@ if ($this->getData(['core', 'dataVersion']) < 11400) { // Version 12.0.00 if ($this->getData(['core', 'dataVersion']) < 12000) { $fonts = [ - 'arimo' => 'Arimo', - 'arvo' => 'Arvo', - 'dancing-script' => 'Dancing Script', - 'droid-sans-2' => 'Droid Sans', - 'droid-serif-2' => 'Droid Serif', - 'indie-flower' => 'Indie Flower', - 'liberation-sans' => 'Liberation Sans', - 'liberation-serif' => 'Liberation Serif', - 'lobster-2' => 'Lobster', - 'lora' => 'Lora', - 'lato' => 'Lato', - 'old-standard-tt-3' => 'Old Standard TT', - 'open-sans' => 'Open Sans', - 'oswald-4' => 'Oswald', - 'pt-mono' => 'PT Mono', - 'pt-serif' => 'PT Serif', - 'rancho' => 'Rancho', - 'roboto' => 'Roboto', - 'ubuntu' => 'Ubuntu', - 'vollkorn' => 'Vollkorn' + 'arimo'=> [ + 'name' => 'Arimo', + 'font-family' => 'Arimo, sans-serif', + 'url' => 'https://fonts.cdnfonts.com/css/arimo' + ], + 'arvo'=> [ + 'name' => 'Arvo', + 'font-family' => 'Arvo, sans-serif', + 'url' => 'https://fonts.cdnfonts.com/css/arvo' + ], + 'dancing-script' => [ + 'name' => 'Dancing Script', + 'font-family' => '"Dancing Script", sans-serif', + 'url' => 'https://fonts.cdnfonts.com/css/dancing-script' + ], + 'droid-sans-2'=> [ + 'name' => 'Droid Sans', + 'font-family' => '"Droid Sans", sans-serif', + 'url' => 'https://fonts.cdnfonts.com/css/droid-sans-2' + ], + 'droid-serif-2'=> [ + 'name' => 'Droid Serif', + 'font-family' => '"Droid Serif", serif', + 'url' => 'https://fonts.cdnfonts.com/css/droid-serif-2' + ], + 'indie-flower'=> [ + 'name' => 'Indie Flower', + 'font-family' => '"Indie Flower", sans-serif', + 'url' => 'https://fonts.cdnfonts.com/css/indie-flower' + ], + 'liberation-sans'=> [ + 'name' => 'Liberation Sans', + 'font-family' => '"Liberation Sans", sans-serif', + 'url' => 'https://fonts.cdnfonts.com/css/liberation-sans' + ], + 'liberation-serif'=> [ + 'name' => 'Liberation Serif', + 'font-family' => '"Liberation Serif", serif', + 'url' => 'https://fonts.cdnfonts.com/css/liberation-serif' + ], + 'lobster-2'=> [ + 'name' => 'Lobster', + 'font-family' => 'Lobster, sans-serif', + 'url' => 'https://fonts.cdnfonts.com/css/lobster-2' + ], + 'lato'=> [ + 'name' => 'lato', + 'font-family' => 'Lato, sans-serif', + 'url' => 'https://fonts.cdnfonts.com/css/lato' + ], + 'lora'=> [ + 'name' => 'Lora', + 'font-family' => 'Lora, serif', + 'url' => 'https://fonts.cdnfonts.com/css/lora' + ], + 'old-standard-tt-3'=> [ + 'name' => 'Old Standard TT', + 'font-family' => '"Old Standard TT", serif', + 'url' => 'https://fonts.cdnfonts.com/css/old-standard-tt-3' + ], + 'open-sans' => [ + 'name' => 'Open Sans', + 'font-family' => '"Open Sans", sans-serif', + 'url' => 'https://fonts.cdnfonts.com/css/open-sans' + ], + 'oswald-4'=> [ + 'name' => 'Oswald', + 'font-family' => 'Oswald, sans-serif', + 'url' => 'https://fonts.cdnfonts.com/css/oswald-4' + ], + 'pt-mono'=> [ + 'name' => 'PT Mono', + 'font-family' => '"PT Mono", monospace', + 'url' => 'https://fonts.cdnfonts.com/css/pt-mono' + ], + 'pt-serif'=> [ + 'name' => "PR Serif", + 'font-family' => '"PT Serif", serif', + 'url' => 'https://fonts.cdnfonts.com/css/pt-serif' + ], + 'rancho'=> [ + 'name' => 'Rancho', + 'font-family' => 'Rancho, sans-serif', + 'url' => 'https://fonts.cdnfonts.com/css/rancho' + ], + 'roboto'=> [ + 'name' => 'Roboto', + 'font-family' => 'Roboto, sans-serif', + 'url' => 'https://fonts.cdnfonts.com/css/roboto' + ], + 'ubuntu'=> [ + 'name' => 'Ubuntu', + 'font-family' => 'Ubuntu, sans-serif', + 'url' => 'https://fonts.cdnfonts.com/css/ubuntu' + ], + 'vollkorn'=> [ + 'name' => 'Vollkorn', + 'font-family' => 'Vollkorn, serif', + 'url' => 'https://fonts.cdnfonts.com/css/vollkorn' + ] ]; $this->setData(['fonts', 'imported', $fonts]); diff --git a/core/module/config/view/connect/connect.php b/core/module/config/view/connect/connect.php index e8528c2b..8e7f44b0 100644 --- a/core/module/config/view/connect/connect.php +++ b/core/module/config/view/connect/connect.php @@ -9,27 +9,15 @@ +
-
- $this->getData(['config', 'connect','captcha']) - ]); ?> - $this->getData(['config', 'connect', 'captchaStrong']), - 'help' => 'Option recommandée pour sécuriser la connexion. S\'applique à tous les captchas du site. Le captcha simple se limite à une addition de nombres de 0 à 10. Le captcha complexe utilise quatre opérations de nombres de 0 à 20. Activation recommandée.' - ]); ?> -
-
- 'Type de captcha', - 'selected' => $this->getData(['config', 'connect', 'captchaType']) - ]); ?> -
$this->getData(['config', 'connect', 'autoDisconnect']), 'help' => 'Déconnecte les sessions ouvertes précédemment sur d\'autres navigateurs ou terminaux. Activation recommandée.' ]); ?> +
+
$this->getData(['config', 'connect', 'showPassword']), 'help' => 'Dans l\'écran de connexion, active une icône dont le survol affiche temporairement le mot de passe.' @@ -39,7 +27,7 @@
'Connexions successives', + 'label' => 'Limitation des tentatives', 'selected' => $this->getData(['config', 'connect', 'attempt']) ]); ?>
@@ -71,6 +59,25 @@ ]); ?>
+
+
+ $this->getData(['config', 'connect','captcha']) + ]); ?> +
+
+ $this->getData(['config', 'connect', 'captchaStrong']), + 'help' => 'Option recommandée pour sécuriser la connexion. S\'applique à tous les captchas du site. Le captcha simple se limite à une addition de nombres de 0 à 10. Le captcha complexe utilise quatre opérations de nombres de 0 à 20. Activation recommandée.' + ]); ?> +
+
+ 'Type de captcha', + 'selected' => $this->getData(['config', 'connect', 'captchaType']) + ]); ?> +
+
diff --git a/core/module/config/view/locale/locale.php b/core/module/config/view/locale/locale.php index d6aa0d54..5e099c1a 100644 --- a/core/module/config/view/locale/locale.php +++ b/core/module/config/view/locale/locale.php @@ -57,21 +57,21 @@
- 'Accueil du site', 'selected' =>$this->getData(['locale', 'homePageId']), 'help' => 'La première page que vos visiteurs verront.' ]); ?>
- 'Page par défaut'],helper::arrayCollumn($module::$orphansList, 'title', 'SORT_ASC')), [ + 'Page par défaut'],helper::arrayColumn($module::$orphansList, 'title', 'SORT_ASC')), [ 'label' => 'Accès interdit, erreur 403', 'selected' =>$this->getData(['locale', 'page403']), 'help' => 'Cette page ne doit pas apparaître dans l\'arborescence du menu. Créez une page orpheline.' ]); ?>
- 'Page par défaut'],helper::arrayCollumn($module::$orphansList, 'title', 'SORT_ASC')), [ + 'Page par défaut'],helper::arrayColumn($module::$orphansList, 'title', 'SORT_ASC')), [ 'label' => 'Page inexistante, erreur 404', 'selected' =>$this->getData(['locale', 'page404']), 'help' => 'Cette page ne doit pas apparaître dans l\'arborescence du menu. Créez une page orpheline.' @@ -80,14 +80,14 @@
- 'Aucune'] , helper::arrayCollumn($module::$pagesList, 'title', 'SORT_ASC') ) , [ + 'Aucune'] , helper::arrayColumn($module::$pagesList, 'title', 'SORT_ASC') ) , [ 'label' => 'Mentions légales', 'selected' => $this->getData(['locale', 'legalPageId']), 'help' => 'Les mentions légales sont obligatoires en France. Une option du pied de page ajoute un lien discret vers cette page.' ]); ?>
- 'Aucune'] , helper::arrayCollumn($module::$pagesList, 'title', 'SORT_ASC') ) , [ + 'Aucune'] , helper::arrayColumn($module::$pagesList, 'title', 'SORT_ASC') ) , [ 'label' => 'Recherche dans le site', 'selected' => $this->getData(['locale', 'searchPageId']), 'help' => 'Sélectionnez une page contenant le module \'Recherche\'. Une option du pied de page ajoute un lien discret vers cette page.' @@ -95,7 +95,7 @@
'Page par défaut'],helper::arrayCollumn($module::$orphansList, 'title', 'SORT_ASC')), [ + echo template::select('localePage302', array_merge(['none' => 'Page par défaut'],helper::arrayColumn($module::$orphansList, 'title', 'SORT_ASC')), [ 'label' => 'Site en maintenance', 'selected' =>$this->getData(['locale', 'page302']), 'help' => 'Cette page ne doit pas apparaître dans l\'arborescence du menu. Créez une page orpheline.' diff --git a/core/module/install/install.php b/core/module/install/install.php index 48652ed6..afa59bd7 100644 --- a/core/module/install/install.php +++ b/core/module/install/install.php @@ -153,7 +153,7 @@ class install extends common { // Récupération de la liste des thèmes $dataThemes = file_get_contents('core/module/install/ressource/themes/themes.json'); $dataThemes = json_decode($dataThemes, true); - self::$themes = helper::arrayCollumn($dataThemes, 'name'); + self::$themes = helper::arrayColumn($dataThemes, 'name'); // Valeurs en sortie $this->addOutput([ diff --git a/core/module/install/ressource/defaultdata.php b/core/module/install/ressource/defaultdata.php index e696a7ca..e53171d1 100644 --- a/core/module/install/ressource/defaultdata.php +++ b/core/module/install/ressource/defaultdata.php @@ -88,26 +88,106 @@ class init extends common { 'fonts' => [ 'files' => [], 'imported'=> [ - 'arimo'=> 'Arimo', - 'arvo'=> 'Arvo', - 'dancing-script' => 'Dancing Script', - 'droid-sans-2'=> 'Droid Sans', - 'droid-serif-2'=> 'Droid Serif', - 'indie-flower'=> 'Indie Flower', - 'liberation-sans'=> 'Liberation Sans', - 'liberation-serif'=> 'Liberation Serif', - 'lobster-2'=> 'Lobster', - 'lora'=> 'Lora', - 'lato'=> 'Lato', - 'old-standard-tt-3'=> 'Old Standard TT', - 'open-sans'=> 'Open Sans', - 'oswald-4'=> 'Oswald', - 'pt-mono'=> 'PT Mono', - 'pt-serif'=> 'PT Serif', - 'rancho'=> 'Rancho', - 'roboto'=> 'Roboto', - 'ubuntu'=> 'Ubuntu', - 'vollkorn'=> 'Vollkorn' + 'arimo'=> [ + 'name' => 'Arimo', + 'font-family' => 'Arimo, sans-serif', + 'ressource' => 'https://fonts.cdnfonts.com/css/arimo' + ], + 'arvo'=> [ + 'name' => 'Arvo', + 'font-family' => 'Arvo, sans-serif', + 'ressource' => 'https://fonts.cdnfonts.com/css/arvo' + ], + 'dancing-script' => [ + 'name' => 'Dancing Script', + 'font-family' => '"Dancing Script", sans-serif', + 'ressource' => 'https://fonts.cdnfonts.com/css/dancing-script' + ], + 'droid-sans-2'=> [ + 'name' => 'Droid Sans', + 'font-family' => '"Droid Sans", sans-serif', + 'ressource' => 'https://fonts.cdnfonts.com/css/droid-sans-2' + ], + 'droid-serif-2'=> [ + 'name' => 'Droid Serif', + 'font-family' => '"Droid Serif", serif', + 'ressource' => 'https://fonts.cdnfonts.com/css/droid-serif-2' + ], + 'indie-flower'=> [ + 'name' => 'Indie Flower', + 'font-family' => '"Indie Flower", sans-serif', + 'ressource' => 'https://fonts.cdnfonts.com/css/indie-flower' + ], + 'liberation-sans'=> [ + 'name' => 'Liberation Sans', + 'font-family' => '"Liberation Sans", sans-serif', + 'ressource' => 'https://fonts.cdnfonts.com/css/liberation-sans' + ], + 'liberation-serif'=> [ + 'name' => 'Liberation Serif', + 'font-family' => '"Liberation Serif", serif', + 'ressource' => 'https://fonts.cdnfonts.com/css/liberation-serif' + ], + 'lobster-2'=> [ + 'name' => 'Lobster', + 'font-family' => 'Lobster, sans-serif', + 'ressource' => 'https://fonts.cdnfonts.com/css/lobster-2' + ], + 'lato'=> [ + 'name' => 'lato', + 'font-family' => 'Lato, sans-serif', + 'ressource' => 'https://fonts.cdnfonts.com/css/lato' + ], + 'lora'=> [ + 'name' => 'Lora', + 'font-family' => 'Lora, serif', + 'ressource' => 'https://fonts.cdnfonts.com/css/lora' + ], + 'old-standard-tt-3'=> [ + 'name' => 'Old Standard TT', + 'font-family' => '"Old Standard TT", serif', + 'ressource' => 'https://fonts.cdnfonts.com/css/old-standard-tt-3' + ], + 'open-sans' => [ + 'name' => 'Open Sans', + 'font-family' => '"Open Sans", sans-serif', + 'ressource' => 'https://fonts.cdnfonts.com/css/open-sans' + ], + 'oswald-4'=> [ + 'name' => 'Oswald', + 'font-family' => 'Oswald, sans-serif', + 'ressource' => 'https://fonts.cdnfonts.com/css/oswald-4' + ], + 'pt-mono'=> [ + 'name' => 'PT Mono', + 'font-family' => '"PT Mono", monospace', + 'ressource' => 'https://fonts.cdnfonts.com/css/pt-mono' + ], + 'pt-serif'=> [ + 'name' => "PR Serif", + 'font-family' => '"PT Serif", serif', + 'ressource' => 'https://fonts.cdnfonts.com/css/pt-serif' + ], + 'rancho'=> [ + 'name' => 'Rancho', + 'font-family' => 'Rancho, sans-serif', + 'ressource' => 'https://fonts.cdnfonts.com/css/rancho' + ], + 'roboto'=> [ + 'name' => 'Roboto', + 'font-family' => 'Roboto, sans-serif', + 'ressource' => 'https://fonts.cdnfonts.com/css/roboto' + ], + 'ubuntu'=> [ + 'name' => 'Ubuntu', + 'font-family' => 'Ubuntu, sans-serif', + 'ressource' => 'https://fonts.cdnfonts.com/css/ubuntu' + ], + 'vollkorn'=> [ + 'name' => 'Vollkorn', + 'font-family' => 'Vollkorn, serif', + 'ressource' => 'https://fonts.cdnfonts.com/css/vollkorn' + ] ] ], 'page' => [ @@ -153,7 +233,7 @@ class init extends common { ], 'footer' => [ 'backgroundColor' => 'rgba(255, 255, 255, 1)', - 'font' => 'open-sans', + 'font' => 'georgia', 'fontSize' => '.8em', 'fontWeight' => 'normal', 'height' => '5px', @@ -180,7 +260,7 @@ class init extends common { ], 'header' => [ 'backgroundColor' => 'rgba(32, 59, 82, 1)', - 'font' => 'oswald-4', + 'font' => 'arial', 'fontSize' => '2em', 'fontWeight' => 'normal', 'height' => '150px', @@ -203,7 +283,7 @@ class init extends common { 'menu' => [ 'backgroundColor' => 'rgba(32, 59, 82, 1)', 'backgroundColorSub' => 'rgba(32, 59, 82, 1)', - 'font' => 'open-sans', + 'font' => 'georgia', 'fontSize' => '1em', 'fontWeight' => 'normal', 'height' => '15px 10px', @@ -234,13 +314,13 @@ class init extends common { 'borderColor' => 'rgba(236, 239, 241, 1)' ], 'text' => [ - 'font' => 'open-sans', + 'font' => 'georgia', 'fontSize' => '13px', 'textColor' => 'rgba(33, 34, 35, 1)', 'linkColor' => 'rgba(74, 105, 189, 1)' ], 'title' => [ - 'font' => 'oswald-4', + 'font' => 'arial', 'fontWeight' => 'normal', 'textColor' => 'rgba(74, 105, 189, 1)', 'textTransform' => 'none' @@ -252,9 +332,9 @@ class init extends common { ], 'admin' => [ 'backgroundColor' => 'rgba(255, 255, 255, 1)', - 'fontText' => 'open-sans', + 'fontText' => 'georgia', 'fontSize' => '13px', - 'fontTitle' => 'oswald-4', + 'fontTitle' => 'arial', 'colorText' => 'rgba(33, 34, 35, 1)', 'colorTitle' => 'rgba(74, 105, 189, 1)', 'backgroundColorButton' => 'rgba(63, 125, 250, 1)', diff --git a/core/module/page/page.php b/core/module/page/page.php index ec4f51a6..aea77605 100644 --- a/core/module/page/page.php +++ b/core/module/page/page.php @@ -392,19 +392,25 @@ class page extends common { $lastPosition = 1; $hierarchy = $this->getInput('pageEditParentPageId') ? $this->getHierarchy($this->getInput('pageEditParentPageId')) : array_keys($this->getHierarchy()); $position = $this->getInput('pageEditPosition', helper::FILTER_INT); + $extraPosition = $this->getinput('pageEditExtraPosition', helper::FILTER_BOOLEAN); foreach($hierarchy as $hierarchyPageId) { - // Ignore la page en cours de modification - if($hierarchyPageId === $this->getUrl(2)) { - continue; - } - // Incrémente de +1 pour laisser la place à la position de la page en cours de modification - if($lastPosition === $position) { + + // Ne traite que les pages du menu sélectionné + if ($this->getData(['page', $hierarchyPageId, 'extraPosition']) === $extraPosition ) { + // Ignore la page en cours de modification + if($hierarchyPageId === $this->getUrl(2) ) { + continue; + } + // Incrémente de +1 pour laisser la place à la position de la page en cours de modification + if($lastPosition === $position) { + $lastPosition++; + } + // Change la position + $this->setData(['page', $hierarchyPageId, 'position', $lastPosition]); + // Incrémente pour la prochaine position $lastPosition++; } - // Change la position - $this->setData(['page', $hierarchyPageId, 'position', $lastPosition]); - // Incrémente pour la prochaine position - $lastPosition++; + } if ($this->getinput('pageEditBlock') !== 'bar') { $barLeft = $this->getinput('pageEditBarLeft'); @@ -516,7 +522,7 @@ class page extends common { } } } - self::$moduleIds = array_merge( ['' => 'Aucun'] , helper::arrayCollumn(helper::getModules(),'realName','SORT_ASC')); // Pages sans parent + self::$moduleIds = array_merge( ['' => 'Aucun'] , helper::arrayColumn(helper::getModules(),'realName','SORT_ASC')); // Pages sans parent foreach($this->getHierarchy() as $parentPageId => $childrenPageIds) { if($parentPageId !== $this->getUrl(2)) { self::$pagesNoParentId[$parentPageId] = $this->getData(['page', $parentPageId, 'title']); diff --git a/core/module/sitemap/sitemap.php b/core/module/sitemap/sitemap.php index 3807a403..0537f648 100644 --- a/core/module/sitemap/sitemap.php +++ b/core/module/sitemap/sitemap.php @@ -42,8 +42,8 @@ class sitemap extends common !empty($this->getData(['module',$parentId, 'posts' ]))) { $items .= '
    '; // Ids des articles par ordre de publication - $articleIdsPublishedOns = helper::arrayCollumn($this->getData(['module', $parentId,'posts']), 'publishedOn', 'SORT_DESC'); - $articleIdsStates = helper::arrayCollumn($this->getData(['module', $parentId, 'posts']), 'state', 'SORT_DESC'); + $articleIdsPublishedOns = helper::arrayColumn($this->getData(['module', $parentId,'posts']), 'publishedOn', 'SORT_DESC'); + $articleIdsStates = helper::arrayColumn($this->getData(['module', $parentId, 'posts']), 'state', 'SORT_DESC'); $articleIds = []; foreach ($articleIdsPublishedOns as $articleId => $articlePublishedOn) { if ($articlePublishedOn <= time() and $articleIdsStates[$articleId]) { @@ -78,8 +78,8 @@ class sitemap extends common !empty($this->getData(['module', $childId, 'posts' ]))) { $items .= '
      '; // Ids des articles par ordre de publication - $articleIdsPublishedOns = helper::arrayCollumn($this->getData(['module', $childId,'posts']), 'publishedOn', 'SORT_DESC'); - $articleIdsStates = helper::arrayCollumn($this->getData(['module', $childId, 'posts']), 'state', 'SORT_DESC'); + $articleIdsPublishedOns = helper::arrayColumn($this->getData(['module', $childId,'posts']), 'publishedOn', 'SORT_DESC'); + $articleIdsStates = helper::arrayColumn($this->getData(['module', $childId, 'posts']), 'state', 'SORT_DESC'); $articleIds = []; foreach ($articleIdsPublishedOns as $articleId => $articlePublishedOn) { if ($articlePublishedOn <= time() and $articleIdsStates[$articleId]) { diff --git a/core/module/theme/theme.php b/core/module/theme/theme.php index b68ae856..613d8513 100644 --- a/core/module/theme/theme.php +++ b/core/module/theme/theme.php @@ -1,1049 +1,1122 @@ - - * @copyright Copyright (C) 2008-2018, Rémi Jean - * @license GNU General Public License, version 3 - * @link http://zwiicms.fr/ - * @copyright : Frédéric Tempez - * @copyright Copyright (C) 2018-2022, Frédéric Tempez - */ - -class theme extends common { - - public static $actions = [ - 'advanced' => self::GROUP_ADMIN, - 'body' => self::GROUP_ADMIN, - 'footer' => self::GROUP_ADMIN, - 'header' => self::GROUP_ADMIN, - 'index' => self::GROUP_ADMIN, - 'menu' => self::GROUP_ADMIN, - 'reset' => self::GROUP_ADMIN, - 'site' => self::GROUP_ADMIN, - 'admin' => self::GROUP_ADMIN, - 'manage' => self::GROUP_ADMIN, - 'export' => self::GROUP_ADMIN, - 'import' => self::GROUP_ADMIN, - 'save' => self::GROUP_ADMIN, - 'fonts' => self::GROUP_ADMIN, - 'fontAdd' => self::GROUP_ADMIN, - 'fontDelete' => self::GROUP_ADMIN - ]; - public static $aligns = [ - 'left' => 'À gauche', - 'center' => 'Au centre', - 'right' => 'À droite' - ]; - public static $attachments = [ - 'scroll' => 'Standard', - 'fixed' => 'Fixe' - ]; - public static $containerWides = [ - 'container' => 'Limitée au site', - 'none' => 'Etendue sur la page' - ]; - public static $footerblocks = [ - 1 => [ - 'hide' => 'Masqué', - 'center' => 'Affiché' ], - 2 => [ - 'hide' => 'Masqué', - 'left' => 'À gauche', - 'right' => 'À droite' ], - 3 => [ - 'hide' => 'Masqué', - 'left' => 'À gauche', - 'center' => 'Au centre', - 'right' => 'À droite' ], - 4 => [ - 'hide' => 'Masqué', - 'left' => 'En haut', - 'center' => 'Au milieu', - 'right' => 'En bas' ] - ]; - - public static $fontWeights = [ - 'normal' => 'Maigre', - 'bold' => 'Gras' - ]; - public static $footerHeights = [ - '0px' => 'Nulles (0px)', - '5px' => 'Très petites (5px)', - '10px' => 'Petites (10px)', - '15px' => 'Moyennes (15px)', - '20px' => 'Grandes (20px)' - ]; - public static $footerPositions = [ - 'hide' => 'Caché', - 'site' => 'Dans le site', - 'body' => 'En dessous du site' - ]; - public static $footerFontSizes = [ - '.8em' => 'Très petite (80%)', - '.9em' => 'Petite (90%)', - '1em' => 'Standard (100%)', - '1.1em' => 'Moyenne (110%)', - '1.2em' => 'Grande (120%)', - '1.3em' => 'Très grande (130%)' - ]; - public static $headerFontSizes = [ - '1.6em' => 'Très petite (160%)', - '1.8em' => 'Petite (180%)', - '2em' => 'Moyenne (200%)', - '2.2em' => 'Grande (220%)', - '2.4vmax' => 'Très grande (240%)' - ]; - public static $headerHeights = [ - 'unset' => 'Libre', // texte dynamique cf header.js.php - '100px' => 'Très petite (100px) ', - '150px' => 'Petite (150px)', - '200px' => 'Moyenne (200px)', - '300px' => 'Grande (300px)', - '400px' => 'Très grande (400px)', - ]; - public static $headerPositions = [ - 'body' => 'Au dessus du site', - 'site' => 'Dans le site', - 'hide' => 'Cachée' - ]; - public static $headerFeatures = [ - 'wallpaper' => 'Couleur unie ou papier-peint', - 'feature' => 'Contenu personnalisé' - ]; - public static $imagePositions = [ - 'top left' => 'En haut à gauche', - 'top center' => 'En haut au centre', - 'top right' => 'En haut à droite', - 'center left' => 'Au milieu à gauche', - 'center center' => 'Au milieu au centre', - 'center right' => 'Au milieu à droite', - 'bottom left' => 'En bas à gauche', - 'bottom center' => 'En bas au centre', - 'bottom right' => 'En bas à droite' - ]; - public static $menuFontSizes = [ - '.8em' => 'Très petite (80%)', - '.9em' => 'Petite (90%)', - '1em' => 'Standard (100%)', - '1.1em' => 'Moyenne (110%)', - '1.2em' => 'Grande (120%)', - '1.3em' => 'Très grande (130%)' - ]; - public static $menuHeights = [ - '5px 10px' => 'Très petite', - '10px' => 'Petite', - '15px 10px' => 'Moyenne', - '20px 15px' => 'Grande', - '25px 15px' => 'Très grande' - ]; - public static $menuPositionsSite = [ - 'top' => 'En-dehors du site', - 'site-first' => 'Avant la bannière', - 'site-second' => 'Après la bannière', - 'hide' => 'Caché' - ]; - public static $menuPositionsBody = [ - 'top' => 'En-dehors du site', - 'body-first' => 'Avant la bannière', - 'body-second' => 'Après la bannière', - 'site' => 'Dans le site', - 'hide' => 'Caché' - ]; - public static $menuRadius = [ - '0px' => 'Aucun', - '3px 3px 0px 0px' => 'Très léger', - '6px 6px 0px 0px' => 'Léger', - '9px 9px 0px 0px' => 'Moyen', - '12px 12px 0px 0px' => 'Important', - '15px 15px 0px 0px' => 'Très important' - ]; - public static $radius = [ - '0px' => 'Aucun', - '5px' => 'Très léger', - '10px' => 'Léger', - '15px' => 'Moyen', - '25px' => 'Important', - '50px' => 'Très important' - ]; - public static $repeats = [ - 'no-repeat' => 'Ne pas répéter', - 'repeat-x' => 'Sur l\'axe horizontal', - 'repeat-y' => 'Sur l\'axe vertical', - 'repeat' => 'Sur les deux axes' - ]; - public static $shadows = [ - '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 $siteFontSizes = [ - '12px' => '12 pixels', - '13px' => '13 pixels', - '14px' => '14 pixels', - '15px' => '15 pixels', - '16px' => '16 pixels' - ]; - public static $bodySizes = [ - 'auto' => 'Automatique', - '100% 100%' => 'Image étirée (100% 100%)', - 'cover' => 'Responsive (cover)', - 'contain' => 'Responsive (contain)' - ]; - public static $textTransforms = [ - 'none' => 'Standard', - 'lowercase' => 'Minuscules', - 'uppercase' => 'Majuscules', - 'capitalize' => 'Majuscule à chaque mot' - ]; - public static $siteWidths = [ - '750px' => 'Petite (750 pixels)', - '960px' => 'Moyenne (960 pixels)', - '1170px' => 'Grande (1170 pixels)', - '100%' => 'Fluide (100%)' - ]; - public static $headerWide = [ - 'auto auto' => 'Automatique', - '100% 100%' => 'Image étirée (100% 100%)', - 'cover' => 'Responsive (cover)', - 'contain' => 'Responsive (contain)' - ]; - public static $footerTemplate = [ - '1' => 'Une seule colonne', - '2' => 'Deux colonnes : 1/2 - 1/2', - '3' => 'Trois colonnes : 1/3 - 1/3 - 1/3', - '4' => 'Trois lignes superposées' - ]; - public static $burgerContent = [ - 'none' => 'Aucun', - 'title' => 'Titre du site', - 'logo' => 'Logo du site' - ]; - - - // Variable pour construire la liste des pages du site - public static $pagesList = []; - // Variable pour construire la liste des fontes installées - public static $fontsList = []; - - /** - * Thème des écrans d'administration - */ - public function admin() { - // Soumission du formulaire - if($this->isPost()) { - $this->setData(['admin', [ - 'backgroundColor' => $this->getInput('adminBackgroundColor'), - 'colorTitle' => $this->getInput('adminColorTitle'), - 'colorText' => $this->getInput('adminColorText'), - 'colorButtonText' => $this->getInput('adminColorButtonText'), - 'backgroundColorButton' => $this->getInput('adminColorButton'), - 'backgroundColorButtonGrey' => $this->getInput('adminColorGrey'), - 'backgroundColorButtonRed' => $this->getInput('adminColorRed'), - 'backgroundColorButtonGreen'=> $this->getInput('adminColorGreen'), - 'backgroundColorButtonHelp'=> $this->getInput('adminColorHelp'), - 'fontText' => $this->getInput('adminFontText'), - 'fontSize' => $this->getInput('adminFontTextSize'), - 'fontTitle' => $this->getInput('adminFontTitle'), - 'backgroundBlockColor' => $this->getInput('adminBackGroundBlockColor'), - 'borderBlockColor' => $this->getInput('adminBorderBlockColor'), - ]]); - // Valeurs en sortie - $this->addOutput([ - 'notification' => 'Modifications enregistrées', - 'redirect' => helper::baseUrl() . 'theme/admin', - 'state' => true - ]); - } - // Valeurs en sortie - $this->addOutput([ - 'title' => 'Administration', - 'view' => 'admin', - 'vendor' => [ - 'tinycolorpicker' - ], - ]); - } - - /** - * Mode avancé - */ - public function advanced() { - // Soumission du formulaire - if($this->isPost()) { - // Enregistre le CSS - file_put_contents(self::DATA_DIR.'custom.css', $this->getInput('themeAdvancedCss', null)); - // Valeurs en sortie - $this->addOutput([ - 'notification' => 'Modifications enregistrées', - 'redirect' => helper::baseUrl() . 'theme/advanced', - 'state' => true - ]); - } - // Valeurs en sortie - $this->addOutput([ - 'title' => 'Éditeur CSS', - 'vendor' => [ - 'codemirror' - ], - 'view' => 'advanced' - ]); - } - - /** - * Options de l'arrière plan - */ - public function body() { - // Soumission du formulaire - if($this->isPost()) { - $this->setData(['theme', 'body', [ - 'backgroundColor' => $this->getInput('themeBodyBackgroundColor'), - 'image' => $this->getInput('themeBodyImage'), - 'imageAttachment' => $this->getInput('themeBodyImageAttachment'), - 'imagePosition' => $this->getInput('themeBodyImagePosition'), - 'imageRepeat' => $this->getInput('themeBodyImageRepeat'), - 'imageSize' => $this->getInput('themeBodyImageSize'), - 'toTopbackgroundColor' => $this->getInput('themeBodyToTopBackground'), - 'toTopColor' => $this->getInput('themeBodyToTopColor') - ]]); - // Valeurs en sortie - $this->addOutput([ - 'notification' => 'Modifications enregistrées', - 'redirect' => helper::baseUrl() . 'theme', - 'state' => true - ]); - } - // Valeurs en sortie - $this->addOutput([ - 'title' => 'Personnalisation de l\'arrière plan', - 'vendor' => [ - 'tinycolorpicker' - ], - 'view' => 'body' - ]); - } - - /** - * Options du pied de page - */ - public function footer() { - // Soumission du formulaire - if($this->isPost()) { - if ( $this->getInput('themeFooterCopyrightPosition') === 'hide' && - $this->getInput('themeFooterSocialsPosition') === 'hide' && - $this->getInput('themeFooterTextPosition') === 'hide' ) { - // Valeurs en sortie - $this->addOutput([ - 'notification' => 'Sélectionnez au moins un contenu à afficher', - 'redirect' => helper::baseUrl() . 'theme/footer', - 'state' => false - ]); - } else { - $this->setData(['theme', 'footer', [ - 'backgroundColor' => $this->getInput('themeFooterBackgroundColor'), - 'copyrightAlign' => $this->getInput('themeFooterCopyrightAlign'), - 'height' => $this->getInput('themeFooterHeight'), - 'loginLink' => $this->getInput('themeFooterLoginLink'), - 'margin' => $this->getInput('themeFooterMargin', helper::FILTER_BOOLEAN), - 'position' => $this->getInput('themeFooterPosition'), - 'fixed' => $this->getInput('themeFooterFixed', helper::FILTER_BOOLEAN), - 'socialsAlign' => $this->getInput('themeFooterSocialsAlign'), - 'text' => $this->getInput('themeFooterText', null), - 'textAlign' => $this->getInput('themeFooterTextAlign'), - 'textColor' => $this->getInput('themeFooterTextColor'), - 'copyrightPosition' => $this->getInput('themeFooterCopyrightPosition'), - 'textPosition' => $this->getInput('themeFooterTextPosition'), - 'socialsPosition' => $this->getInput('themeFooterSocialsPosition'), - 'textTransform' => $this->getInput('themeFooterTextTransform'), - 'font' => $this->getInput('themeFooterFont'), - 'fontSize' => $this->getInput('themeFooterFontSize'), - 'fontWeight' => $this->getInput('themeFooterFontWeight'), - 'displayVersion' => $this->getInput('themefooterDisplayVersion', helper::FILTER_BOOLEAN), - 'displaySiteMap' => $this->getInput('themefooterDisplaySiteMap', helper::FILTER_BOOLEAN), - 'displayCopyright' => $this->getInput('themefooterDisplayCopyright', helper::FILTER_BOOLEAN), - 'displayCookie' => $this->getInput('themefooterDisplayCookie', helper::FILTER_BOOLEAN), - 'displayLegal' => $this->getInput('themeFooterDisplayLegal', helper::FILTER_BOOLEAN), - 'displaySearch' => $this->getInput('themeFooterDisplaySearch', helper::FILTER_BOOLEAN), - 'displayMemberBar'=> $this->getInput('themeFooterDisplayMemberBar', helper::FILTER_BOOLEAN), - 'template' => $this->getInput('themeFooterTemplate') - ]]); - - // Sauvegarder la configuration localisée - $this->setData(['locale','legalPageId', $this->getInput('configLegalPageId')]); - $this->setData(['locale','searchPageId', $this->getInput('configSearchPageId')]); - - // Valeurs en sortie - $this->addOutput([ - 'notification' => 'Modifications enregistrées', - 'redirect' => helper::baseUrl() . 'theme', - 'state' => true - ]); - } - } - - // Liste des pages - self::$pagesList = $this->getData(['page']); - foreach(self::$pagesList as $page => $pageId) { - if ($this->getData(['page',$page,'block']) === 'bar' || - $this->getData(['page',$page,'disable']) === true) { - unset(self::$pagesList[$page]); - } - } - - // Valeurs en sortie - $this->addOutput([ - 'title' => 'Personnalisation du pied de page', - 'vendor' => [ - 'tinycolorpicker', - 'tinymce' - ], - 'view' => 'footer' - ]); - } - - /** - * Options de la bannière - */ - public function header() { - // Soumission du formulaire - if($this->isPost()) { - // Modification des URL des images dans la bannière perso - $featureContent = $this->getInput('themeHeaderText', null); - $featureContent = str_replace(helper::baseUrl(false,false), './', $featureContent); - - /** - * Stocker les images incluses dans la bannière perso dans un tableau - */ - preg_match_all('/]+>/i',$featureContent, $results); - foreach($results[0] as $value) { - // Lire le contenu XML - $sx = simplexml_load_string($value); - // Élément à remplacer - $files [] = str_replace('./site/file/source/','',(string) $sx[0]['src']); - } - - // Sauvegarder - $this->setData(['theme', 'header', [ - 'backgroundColor' => $this->getInput('themeHeaderBackgroundColor'), - 'font' => $this->getInput('themeHeaderFont'), - 'fontSize' => $this->getInput('themeHeaderFontSize'), - 'fontWeight' => $this->getInput('themeHeaderFontWeight'), - 'height' => $this->getInput('themeHeaderHeight'), - 'wide' => $this->getInput('themeHeaderWide'), - 'image' => $this->getInput('themeHeaderImage'), - 'imagePosition' => $this->getInput('themeHeaderImagePosition'), - 'imageRepeat' => $this->getInput('themeHeaderImageRepeat'), - 'margin' => $this->getInput('themeHeaderMargin', helper::FILTER_BOOLEAN), - 'position' => $this->getInput('themeHeaderPosition'), - 'textAlign' => $this->getInput('themeHeaderTextAlign'), - 'textColor' => $this->getInput('themeHeaderTextColor'), - 'textHide' => $this->getInput('themeHeaderTextHide', helper::FILTER_BOOLEAN), - 'textTransform' => $this->getInput('themeHeaderTextTransform'), - 'linkHomePage' => $this->getInput('themeHeaderlinkHomePage',helper::FILTER_BOOLEAN), - 'imageContainer' => $this->getInput('themeHeaderImageContainer'), - 'tinyHidden' => $this->getInput('themeHeaderTinyHidden', helper::FILTER_BOOLEAN), - 'feature' => $this->getInput('themeHeaderFeature'), - 'featureContent' => $featureContent, - 'featureFiles' => $files - ]]); - // Modification de la position du menu selon la position de la bannière - if ( $this->getData(['theme','header','position']) == 'site' ) - { - $this->setData(['theme', 'menu', 'position',str_replace ('body-','site-',$this->getData(['theme','menu','position']))]); - } - if ( $this->getData(['theme','header','position']) == 'body') - { - $this->setData(['theme', 'menu', 'position',str_replace ('site-','body-',$this->getData(['theme','menu','position']))]); - } - // Menu accroché à la bannière qui devient cachée - if ( $this->getData(['theme','header','position']) == 'hide' && - in_array( $this->getData(['theme','menu','position']) , ['body-first', 'site-first', 'body-first' , 'site-second']) - ) { - $this->setData(['theme', 'menu', 'position','site']); - } - // Valeurs en sortie - $this->addOutput([ - 'notification' => 'Modifications enregistrées', - 'redirect' => helper::baseUrl() . 'theme', - 'state' => true - ]); - } - // Valeurs en sortie - $this->addOutput([ - 'title' => 'Personnalisation de la bannière', - 'vendor' => [ - 'tinycolorpicker', - 'tinymce' - ], - 'view' => 'header' - ]); - } - - /** - * Accueil de la personnalisation - */ - public function index() { - // Valeurs en sortie - $this->addOutput([ - 'title' => 'Personnalisation des thèmes', - 'view' => 'index' - ]); - } - - /** - * Options du menu - */ - public function menu() { - // Soumission du formulaire - if($this->isPost()) { - $this->setData(['theme', 'menu', [ - 'backgroundColor' => $this->getInput('themeMenuBackgroundColor'), - 'backgroundColorSub' => $this->getInput('themeMenuBackgroundColorSub'), - 'font' => $this->getInput('themeMenuFont'), - 'fontSize' => $this->getInput('themeMenuFontSize'), - 'fontWeight' => $this->getInput('themeMenuFontWeight'), - 'height' => $this->getInput('themeMenuHeight'), - 'wide' => $this->getInput('themeMenuWide'), - 'loginLink' => $this->getInput('themeMenuLoginLink', helper::FILTER_BOOLEAN), - 'margin' => $this->getInput('themeMenuMargin', helper::FILTER_BOOLEAN), - 'position' => $this->getInput('themeMenuPosition'), - 'textAlign' => $this->getInput('themeMenuTextAlign'), - 'textColor' => $this->getInput('themeMenuTextColor'), - 'textTransform' => $this->getInput('themeMenuTextTransform'), - 'fixed' => $this->getInput('themeMenuFixed', helper::FILTER_BOOLEAN), - 'activeColorAuto' => $this->getInput('themeMenuActiveColorAuto', helper::FILTER_BOOLEAN), - 'activeColor' => $this->getInput('themeMenuActiveColor'), - 'activeTextColor' => $this->getInput('themeMenuActiveTextColor'), - 'radius' => $this->getInput('themeMenuRadius'), - 'burgerTitle' => $this->getInput('themeMenuBurgerTitle', helper::FILTER_BOOLEAN), - 'memberBar' => $this->getInput('themeMenuMemberBar', helper::FILTER_BOOLEAN), - 'burgerLogo' => $this->getInput('themeMenuBurgerLogo'), - 'burgerContent' => $this->getInput('themeMenuBurgerContent') - ]]); - // Valeurs en sortie - $this->addOutput([ - 'notification' => 'Modifications enregistrées', - 'redirect' => helper::baseUrl() . 'theme', - 'state' => true - ]); - } - // Valeurs en sortie - $this->addOutput([ - 'title' => 'Personnalisation du menu', - 'vendor' => [ - 'tinycolorpicker' - ], - 'view' => 'menu' - ]); - } - - /** - * Options des fontes - */ - public function fonts() { - - // Polices trouvées dans la configuration - $fonts = $this->getData(['fonts']); - - // Polices liées au thème - $used = [ - 'Bannière' => $this->getData (['theme', 'header', 'font']), - 'Menu' => $this->getData (['theme', 'menu', 'font']), - 'Titre ' => $this->getData (['theme', 'title', 'font']), - 'Texte' => $this->getData (['theme', 'text', 'font']), - 'Pied de page' => $this->getData (['theme', 'footer', 'font']), - 'Titre (admin)' => $this->getData (['admin', 'fontTitle' ]), - 'Admin (texte)' => $this->getData (['admin', 'fontText' ]) - ]; - - // Parcourir les fontes installées et construire le tableau pour le formulaire - foreach (self::$fonts as $fontId => $fontName) { - - // Fontes utilisées par le thème - $fontUsed[$fontId] = ''; - foreach ($used as $key => $value) { - if ( $value === $fontId) { - $fontUsed[$fontId] .= $key . '
      '; - } - } - self::$fontsList [] = [ - '' . $fontName . '' , - $fontId, - $fontUsed[$fontId], - //array_key_exists($fontId, $fonts['imported']) ? 'Importée' : '', - array_key_exists($fontId, $fonts['files']) ? - $fonts['files'][$fontId] : - (array_key_exists($fontId, self::$fontsWebSafe) ? 'WebSafe' : 'CDN Fonts'), - array_key_exists($fontId, $fonts['imported']) || array_key_exists($fontId, $fonts['files']) - ? template::button('themeFontDelete' . $fontId, [ - 'class' => 'themeFontDelete buttonRed', - 'href' => helper::baseUrl() . $this->getUrl(0) . '/fontDelete/' . $fontId . '/' . $_SESSION['csrf'], - 'value' => template::ico('trash'), - 'disabled' => !empty($fontUsed[$fontId]) - ]) - : '' - ]; - } - // Valeurs en sortie - $this->addOutput([ - 'title' => 'Gestion des fontes', - 'view' => 'fonts' - ]); - } - - /** - * Ajouter une fonte - */ - public function fontAdd() { - // Soumission du formulaire - if ($this->isPost()) { - - $fontId = $this->getInput('fontAddFontId', null, true); - $fontName = $this->getInput('fontAddFontName', null, true); - $filePath = $this->getInput('fontAddFile', null); - $e = explode ('/', $filePath); - $file = $e[count($e) - 1 ]; - - // Vérifier l'existence de fontId et validité de family namesi usage en ligne de cdnFonts - $data = helper::getUrlContents('https://www.cdnfonts.com/' . $fontId . '.font'); - - if ( $filePath === '' - && $fontName !== '' - && strpos($data, $fontName) === false - ) { - - // Valeurs en sortie - $this->addOutput([ - 'notification' => 'Erreur de nom de fonte ou d\'identifiant', - 'redirect' => helper::baseUrl() . 'theme/fontAdd', - 'state' => false - ]); - - } else { - - // Charger les données des fontes - $files = $this->getData(['fonts', 'files']); - $imported = $this->getData(['fonts', 'imported']); - - // Concaténation dans les tableaux existants - $imported = array_merge([$fontId => $fontName], $imported); - $files = array_merge([$fontId => $file], $files); - - // Copier la fonte si le nom du fichier est fourni - if (!empty($filePath)) { - copy ( self::FILE_DIR . 'source/' . $filePath, self::DATA_DIR . 'fonts/' . $file ); - } - - // Mettre à jour le fichier des fontes - $this->setData(['fonts', 'imported', $imported ]); - if (!empty($filePath) ) { - $this->setData(['fonts', 'files', $files ]); - } - - // Valeurs en sortie - $this->addOutput([ - 'notification' => 'La fonte a été importée', - 'redirect' => helper::baseUrl() . 'theme/fonts', - 'state' => true - ]); - } - } - // Valeurs en sortie - $this->addOutput([ - 'title' => 'Ajouter une fonte', - 'view' => 'fontAdd' - ]); - } - - /** - * Effacer une fonte - */ - public function fontDelete() { - // Jeton incorrect - if ($this->getUrl(3) !== $_SESSION['csrf']) { - // Valeurs en sortie - $this->addOutput([ - 'redirect' => helper::baseUrl() . 'theme/fonts', - 'notification' => 'Action non autorisée' - ]); - } - // Suppression - else { - - // Charger les données des fontes - $files = $this->getData(['fonts', 'files']); - $imported = $this->getData(['fonts', 'imported']); - - // Effacer le fichier existant - if ( file_exists(self::DATA_DIR . $files[$this->getUrl(2)]) ) { - unlink(self::DATA_DIR . $files[$this->getUrl(2)]); - } - - // Supprimer les entrées - unset($files[$this->getUrl(2)]); - unset($imported[$this->getUrl(2)]); - - // Mettre à jour le fichier des fontes - $this->setData(['fonts', 'files', $files ]); - $this->setData(['fonts', 'imported', $imported ]); - // Valeurs en sortie - $this->addOutput([ - 'redirect' => helper::baseUrl() . 'theme/fonts', - 'notification' => 'Fonte supprimée', - 'state' => true - ]); - } - } - - - /** - * Réinitialisation de la personnalisation avancée - */ - public function reset() { - // $url prend l'adresse sans le token - $url = explode('&',$this->getUrl(2)); - - if ( isset($_GET['csrf']) - AND $_GET['csrf'] === $_SESSION['csrf'] - ) { - // Réinitialisation - $redirect =''; - switch ($url[0]) { - case 'admin': - $this->initData('admin'); - $redirect = helper::baseUrl() . 'theme/admin'; - break; - case 'manage': - $this->initData('theme'); - $redirect = helper::baseUrl() . 'theme/manage'; - break; - case 'custom': - unlink(self::DATA_DIR.'custom.css'); - $redirect = helper::baseUrl() . 'theme/advanced'; - break; - default : - $redirect = helper::baseUrl() . 'theme'; - } - - // Valeurs en sortie - $this->addOutput([ - 'notification' => 'Réinitialisation effectuée', - 'redirect' => $redirect, - 'state' => true - ]); - } else { - // Valeurs en sortie - $this->addOutput([ - 'notification' => 'Jeton incorrect' - ]); - } - } - - - /** - * Options du site - */ - public function site() { - // Soumission du formulaire - if($this->isPost()) { - $this->setData(['theme', 'title', [ - 'font' => $this->getInput('themeTitleFont'), - 'textColor' => $this->getInput('themeTitleTextColor'), - 'fontWeight' => $this->getInput('themeTitleFontWeight'), - 'textTransform' => $this->getInput('themeTitleTextTransform') - ]]); - $this->setData(['theme', 'text', [ - 'font' => $this->getInput('themeTextFont'), - 'fontSize' => $this->getInput('themeTextFontSize'), - 'textColor' => $this->getInput('themeTextTextColor'), - 'linkColor'=> $this->getInput('themeTextLinkColor') - ]]); - $this->setData(['theme', 'site', [ - 'backgroundColor' => $this->getInput('themeSiteBackgroundColor'), - 'radius' => $this->getInput('themeSiteRadius'), - 'shadow' => $this->getInput('themeSiteShadow'), - 'width' => $this->getInput('themeSiteWidth'), - 'margin' => $this->getInput('themeSiteMargin',helper::FILTER_BOOLEAN) - ]]); - $this->setData(['theme', 'button', [ - 'backgroundColor' => $this->getInput('themeButtonBackgroundColor') - ]]); - $this->setData(['theme', 'block', [ - 'backgroundColor' => $this->getInput('themeBlockBackgroundColor'), - 'borderColor' => $this->getInput('themeBlockBorderColor') - ]]); - // Valeurs en sortie - $this->addOutput([ - 'notification' => 'Modifications enregistrées', - 'redirect' => helper::baseUrl() . 'theme', - 'state' => true - ]); - } - // Valeurs en sortie - $this->addOutput([ - 'title' => 'Personnalisation du site', - 'vendor' => [ - 'tinycolorpicker', - 'tinymce' - ], - 'view' => 'site' - ]); - } - - /** - * Import du thème - */ - public function manage() { - if($this->isPost() ) { - - $zipFilename = $this->getInput('themeManageImport', helper::FILTER_STRING_SHORT, true); - $data = $this->import(self::FILE_DIR.'source/' . $zipFilename); - if ($data['success']) { - header("Refresh:0"); - } else { - // Valeurs en sortie - $this->addOutput([ - 'notification' => $data['notification'], - 'state' => $data['success'], - 'title' => 'Gestion des thèmes', - 'view' => 'manage' - ]);; - } - } - // Valeurs en sortie - $this->addOutput([ - 'title' => 'Gestion des thèmes', - 'view' => 'manage' - ]); - } - - /** - * Importe un thème - * @param string Url du thème à télécharger - * @param @return array contenant $success = true ou false ; $ notification string message à afficher - */ - - public function import($zipName = '') { - - if ($zipName !== '' && - file_exists($zipName)) { - // Init variables de retour - $success = false; - $notification = ''; - // Dossier temporaire - $tempFolder = uniqid(); - // Ouvrir le zip - $zip = new ZipArchive(); - if ($zip->open($zipName) === TRUE) { - mkdir (self::TEMP_DIR . $tempFolder, 0755); - $zip->extractTo(self::TEMP_DIR . $tempFolder ); - $modele = ''; - // Archive de thème ? - if ( - file_exists(self::TEMP_DIR . $tempFolder . '/site/data/custom.css') - AND file_exists(self::TEMP_DIR . $tempFolder . '/site/data/theme.css') - AND file_exists(self::TEMP_DIR . $tempFolder . '/site/data/theme.json') - ) { - $modele = 'theme'; - } - if( - file_exists(self::TEMP_DIR . $tempFolder . '/site/data/admin.json') - AND file_exists(self::TEMP_DIR . $tempFolder . '/site/data/admin.css') - ) { - $modele = 'admin'; - - } - if (!empty($modele) - ) { - // traiter l'archive - $success = $zip->extractTo('.'); - - // Substitution des fontes Google - if ($modele = 'theme') { - $c = $this->subFonts(self::DATA_DIR . 'theme.json'); - // Un remplacement nécessite la régénération de la feuille de style - if ($c > 0 - AND file_exists(self::DATA_DIR . 'theme.css') - ) { - unlink(self::DATA_DIR . 'theme.css'); - } - } - if ($modele = 'admin') { - $c = $this->subFonts(self::DATA_DIR . 'admin.json'); - // Un remplacement nécessite la régénération de la feuille de style - if ($c > 0 - AND file_exists(self::DATA_DIR . 'admin.css') - ) { - unlink(self::DATA_DIR . 'admin.css'); - } - } - - // traitement d'erreur - $notification = $success ? 'Le thème a été importé' : 'Erreur lors de l\'extraction, vérifiez les permissions.'; - - - } else { - // pas une archive de thème - $success = false; - $notification = 'Ce n\'est pas l\'archive d\'un thème !'; - } - // Supprimer le dossier temporaire même si le thème est invalide - $this->removeDir(self::TEMP_DIR . $tempFolder); - $zip->close(); - } else { - // erreur à l'ouverture - $success = false; - $notification = 'Impossible d\'ouvrir l\'archive'; - } - return (['success' => $success, 'notification' => $notification]); - } - - return (['success' => false, 'notification' => 'Archive non spécifiée ou introuvable']); - } - - - - /** - * Export du thème - */ - public function export() { - // Make zip - $zipFilename = $this->zipTheme($this->getUrl(2)); - // Téléchargement du ZIP - header('Content-Description: File Transfer'); - header('Content-Type: application/octet-stream'); - header('Content-Transfer-Encoding: binary'); - header('Content-Disposition: attachment; filename="' . $zipFilename . '"'); - header('Content-Length: ' . filesize(self::TEMP_DIR . $zipFilename)); - readfile(self::TEMP_DIR . $zipFilename); - // Nettoyage du dossier - unlink (self::TEMP_DIR . $zipFilename); - exit(); - } - - /** - * Export du thème - */ - public function save() { - // Make zip - $zipFilename = $this->zipTheme($this->getUrl(2)); - // Téléchargement du ZIP - if (!is_dir(self::FILE_DIR.'source/theme')) { - mkdir(self::FILE_DIR.'source/theme', 0755); - } - copy (self::TEMP_DIR . $zipFilename , self::FILE_DIR.'source/theme/' . $zipFilename); - // Nettoyage du dossier - unlink (self::TEMP_DIR . $zipFilename); - // Valeurs en sortie - $this->addOutput([ - 'notification' => 'Archive '.$zipFilename.' sauvegardée avec succès', - 'redirect' => helper::baseUrl() . 'theme/manage', - 'state' => true - ]); - } - - /** - * construction du zip Fonction appelée par export() et save() - * @param string $modele theme ou admin - */ - private function zipTheme($modele) { - // Creation du dossier - $zipFilename = $modele . date('Y-m-d-H-i-s', time()) . '.zip'; - $zip = new ZipArchive(); - if ($zip->open(self::TEMP_DIR . $zipFilename, ZipArchive::CREATE | ZipArchive::OVERWRITE ) === TRUE) { - switch ($modele) { - case 'admin': - $zip->addFile(self::DATA_DIR.'admin.json',self::DATA_DIR.'admin.json'); - $zip->addFile(self::DATA_DIR.'admin.css',self::DATA_DIR.'admin.css'); - break; - case 'theme': - $zip->addFile(self::DATA_DIR.'theme.json',self::DATA_DIR.'theme.json'); - $zip->addFile(self::DATA_DIR.'theme.css',self::DATA_DIR.'theme.css'); - $zip->addFile(self::DATA_DIR.'custom.css',self::DATA_DIR.'custom.css'); - // Traite l'image dans le body - if ($this->getData(['theme','body','image']) !== '' ) { - $zip->addFile(self::FILE_DIR.'source/'.$this->getData(['theme','body','image']), - self::FILE_DIR.'source/'.$this->getData(['theme','body','image']) - ); - } - // Traite l'image dans le header - if ($this->getData(['theme','header','image']) !== '' ) { - $zip->addFile(self::FILE_DIR.'source/'.$this->getData(['theme','header','image']), - self::FILE_DIR.'source/'.$this->getData(['theme','header','image']) - ); - } - // Traite les images du header perso - if (!empty($this->getData(['theme','header','featureFiles'])) ) { - foreach($this->getData(['theme','header','featureFiles']) as $value) { - $zip->addFile(self::FILE_DIR . 'source/' . $value, - self::FILE_DIR . 'source/' . $value ); - } - } - break; - } - $ret = $zip->close(); - } - return ($zipFilename); - } - - /** - * Subsitution des fontes de Google Fonts vers CdnFont grâce à un tableau de conversion - * @param string $file, nom du fichier json à convertir - * @return int nombre de substitution effectuées - */ - private function subFonts($file) { - // Tableau de substitution des fontes - $fonts = [ - 'Abril+Fatface' => 'abril-fatface', - 'Arimo' => 'arimo', - 'Arvo' => 'arvo', - 'Berkshire+Swash' => 'berkshire-swash', - 'Cabin' => 'genera', - 'Dancing+Script' => 'dancing-script', - 'Droid+Sans' => 'droid-sans-2', - 'Droid+Serif' => 'droid-serif-2', - 'Fira+Sans' => 'fira-sans', - 'Inconsolata' => 'inconsolata-2', - 'Indie+Flower' =>'indie-flower', - 'Josefin+Slab' => 'josefin-sans-std', - 'Lobster' => 'lobster-2', - 'Lora' => 'lora', - 'Lato' =>'lato', - 'Marvel' => 'montserrat-ace', - 'Old+Standard+TT' => 'old-standard-tt-3', - 'Open+Sans' =>'open-sans', - // Corriger l'erreur de nom de police installée par défaut, il manquait un O en majuscule - 'open+Sans' =>'open-sans', - 'Oswald' =>'oswald-4', - 'PT+Mono' => 'pt-mono', - 'PT+Serif' =>'pt-serif', - 'Raleway' => 'raleway-5', - 'Rancho' => 'rancho', - 'Roboto' => 'Roboto', - 'Signika' => 'signika', - 'Ubuntu' => 'ubuntu', - 'Vollkorn' => 'vollkorn' - ]; - - $data = file_get_contents($file); - $count = 0; - foreach ($fonts as $oldId => $newId){ - $data = str_replace($oldId, $newId, $data, $c); - $count = $count + (int) $c; - } - // Sauvegarder la chaîne modifiée - if ($count > 0) { - file_put_contents($file, $data); - } - // Retourner le nombre d'occurrences - return ($count); - } - -} + + * @copyright Copyright (C) 2008-2018, Rémi Jean + * @license GNU General Public License, version 3 + * @link http://zwiicms.fr/ + * @copyright : Frédéric Tempez + * @copyright Copyright (C) 2018-2022, Frédéric Tempez + */ + +class theme extends common { + + public static $actions = [ + 'advanced' => self::GROUP_ADMIN, + 'body' => self::GROUP_ADMIN, + 'footer' => self::GROUP_ADMIN, + 'header' => self::GROUP_ADMIN, + 'index' => self::GROUP_ADMIN, + 'menu' => self::GROUP_ADMIN, + 'reset' => self::GROUP_ADMIN, + 'site' => self::GROUP_ADMIN, + 'admin' => self::GROUP_ADMIN, + 'manage' => self::GROUP_ADMIN, + 'export' => self::GROUP_ADMIN, + 'import' => self::GROUP_ADMIN, + 'save' => self::GROUP_ADMIN, + 'fonts' => self::GROUP_ADMIN, + 'fontAdd' => self::GROUP_ADMIN, + 'fontEdit' => self::GROUP_ADMIN, + 'fontDelete' => self::GROUP_ADMIN + ]; + public static $aligns = [ + 'left' => 'À gauche', + 'center' => 'Au centre', + 'right' => 'À droite' + ]; + public static $attachments = [ + 'scroll' => 'Standard', + 'fixed' => 'Fixe' + ]; + public static $containerWides = [ + 'container' => 'Limitée au site', + 'none' => 'Etendue sur la page' + ]; + public static $footerblocks = [ + 1 => [ + 'hide' => 'Masqué', + 'center' => 'Affiché' ], + 2 => [ + 'hide' => 'Masqué', + 'left' => 'À gauche', + 'right' => 'À droite' ], + 3 => [ + 'hide' => 'Masqué', + 'left' => 'À gauche', + 'center' => 'Au centre', + 'right' => 'À droite' ], + 4 => [ + 'hide' => 'Masqué', + 'left' => 'En haut', + 'center' => 'Au milieu', + 'right' => 'En bas' ] + ]; + + public static $fontWeights = [ + 'normal' => 'Maigre', + 'bold' => 'Gras' + ]; + public static $footerHeights = [ + '0px' => 'Nulles (0px)', + '5px' => 'Très petites (5px)', + '10px' => 'Petites (10px)', + '15px' => 'Moyennes (15px)', + '20px' => 'Grandes (20px)' + ]; + public static $footerPositions = [ + 'hide' => 'Caché', + 'site' => 'Dans le site', + 'body' => 'En dessous du site' + ]; + public static $footerFontSizes = [ + '.8em' => 'Très petite (80%)', + '.9em' => 'Petite (90%)', + '1em' => 'Standard (100%)', + '1.1em' => 'Moyenne (110%)', + '1.2em' => 'Grande (120%)', + '1.3em' => 'Très grande (130%)' + ]; + public static $headerFontSizes = [ + '1.6em' => 'Très petite (160%)', + '1.8em' => 'Petite (180%)', + '2em' => 'Moyenne (200%)', + '2.2em' => 'Grande (220%)', + '2.4vmax' => 'Très grande (240%)' + ]; + public static $headerHeights = [ + 'unset' => 'Libre', // texte dynamique cf header.js.php + '100px' => 'Très petite (100px) ', + '150px' => 'Petite (150px)', + '200px' => 'Moyenne (200px)', + '300px' => 'Grande (300px)', + '400px' => 'Très grande (400px)', + ]; + public static $headerPositions = [ + 'body' => 'Au dessus du site', + 'site' => 'Dans le site', + 'hide' => 'Cachée' + ]; + public static $headerFeatures = [ + 'wallpaper' => 'Couleur unie ou papier-peint', + 'feature' => 'Contenu personnalisé' + ]; + public static $imagePositions = [ + 'top left' => 'En haut à gauche', + 'top center' => 'En haut au centre', + 'top right' => 'En haut à droite', + 'center left' => 'Au milieu à gauche', + 'center center' => 'Au milieu au centre', + 'center right' => 'Au milieu à droite', + 'bottom left' => 'En bas à gauche', + 'bottom center' => 'En bas au centre', + 'bottom right' => 'En bas à droite' + ]; + public static $menuFontSizes = [ + '.8em' => 'Très petite (80%)', + '.9em' => 'Petite (90%)', + '1em' => 'Standard (100%)', + '1.1em' => 'Moyenne (110%)', + '1.2em' => 'Grande (120%)', + '1.3em' => 'Très grande (130%)' + ]; + public static $menuHeights = [ + '5px 10px' => 'Très petite', + '10px' => 'Petite', + '15px 10px' => 'Moyenne', + '20px 15px' => 'Grande', + '25px 15px' => 'Très grande' + ]; + public static $menuPositionsSite = [ + 'top' => 'En-dehors du site', + 'site-first' => 'Avant la bannière', + 'site-second' => 'Après la bannière', + 'hide' => 'Caché' + ]; + public static $menuPositionsBody = [ + 'top' => 'En-dehors du site', + 'body-first' => 'Avant la bannière', + 'body-second' => 'Après la bannière', + 'site' => 'Dans le site', + 'hide' => 'Caché' + ]; + public static $menuRadius = [ + '0px' => 'Aucun', + '3px 3px 0px 0px' => 'Très léger', + '6px 6px 0px 0px' => 'Léger', + '9px 9px 0px 0px' => 'Moyen', + '12px 12px 0px 0px' => 'Important', + '15px 15px 0px 0px' => 'Très important' + ]; + public static $radius = [ + '0px' => 'Aucun', + '5px' => 'Très léger', + '10px' => 'Léger', + '15px' => 'Moyen', + '25px' => 'Important', + '50px' => 'Très important' + ]; + public static $repeats = [ + 'no-repeat' => 'Ne pas répéter', + 'repeat-x' => 'Sur l\'axe horizontal', + 'repeat-y' => 'Sur l\'axe vertical', + 'repeat' => 'Sur les deux axes' + ]; + public static $shadows = [ + '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 $siteFontSizes = [ + '12px' => '12 pixels', + '13px' => '13 pixels', + '14px' => '14 pixels', + '15px' => '15 pixels', + '16px' => '16 pixels' + ]; + public static $bodySizes = [ + 'auto' => 'Automatique', + '100% 100%' => 'Image étirée (100% 100%)', + 'cover' => 'Responsive (cover)', + 'contain' => 'Responsive (contain)' + ]; + public static $textTransforms = [ + 'none' => 'Standard', + 'lowercase' => 'Minuscules', + 'uppercase' => 'Majuscules', + 'capitalize' => 'Majuscule à chaque mot' + ]; + public static $siteWidths = [ + '750px' => 'Petite (750 pixels)', + '960px' => 'Moyenne (960 pixels)', + '1170px' => 'Grande (1170 pixels)', + '100%' => 'Fluide (100%)' + ]; + public static $headerWide = [ + 'auto auto' => 'Automatique', + '100% 100%' => 'Image étirée (100% 100%)', + 'cover' => 'Responsive (cover)', + 'contain' => 'Responsive (contain)' + ]; + public static $footerTemplate = [ + '1' => 'Une seule colonne', + '2' => 'Deux colonnes : 1/2 - 1/2', + '3' => 'Trois colonnes : 1/3 - 1/3 - 1/3', + '4' => 'Trois lignes superposées' + ]; + public static $burgerContent = [ + 'none' => 'Aucun', + 'title' => 'Titre du site', + 'logo' => 'Logo du site' + ]; + + + // Variable pour construire la liste des pages du site + public static $pagesList = []; + // Variable pour construire la liste des fontes installées + public static $fontsList = []; + // Variable pour détailler les fontes installées + public static $fontsDetail = []; + + /** + * Thème des écrans d'administration + */ + public function admin() { + // Soumission du formulaire + if($this->isPost()) { + $this->setData(['admin', [ + 'backgroundColor' => $this->getInput('adminBackgroundColor'), + 'colorTitle' => $this->getInput('adminColorTitle'), + 'colorText' => $this->getInput('adminColorText'), + 'colorButtonText' => $this->getInput('adminColorButtonText'), + 'backgroundColorButton' => $this->getInput('adminColorButton'), + 'backgroundColorButtonGrey' => $this->getInput('adminColorGrey'), + 'backgroundColorButtonRed' => $this->getInput('adminColorRed'), + 'backgroundColorButtonGreen'=> $this->getInput('adminColorGreen'), + 'backgroundColorButtonHelp'=> $this->getInput('adminColorHelp'), + 'fontText' => $this->getInput('adminFontText'), + 'fontSize' => $this->getInput('adminFontTextSize'), + 'fontTitle' => $this->getInput('adminFontTitle'), + 'backgroundBlockColor' => $this->getInput('adminBackGroundBlockColor'), + 'borderBlockColor' => $this->getInput('adminBorderBlockColor'), + ]]); + // Valeurs en sortie + $this->addOutput([ + 'notification' => 'Modifications enregistrées', + 'redirect' => helper::baseUrl() . 'theme/admin', + 'state' => true + ]); + } + // Valeurs en sortie + $this->addOutput([ + 'title' => 'Administration', + 'view' => 'admin', + 'vendor' => [ + 'tinycolorpicker' + ], + ]); + } + + /** + * Mode avancé + */ + public function advanced() { + // Soumission du formulaire + if($this->isPost()) { + // Enregistre le CSS + file_put_contents(self::DATA_DIR.'custom.css', $this->getInput('themeAdvancedCss', null)); + // Valeurs en sortie + $this->addOutput([ + 'notification' => 'Modifications enregistrées', + 'redirect' => helper::baseUrl() . 'theme/advanced', + 'state' => true + ]); + } + // Valeurs en sortie + $this->addOutput([ + 'title' => 'Éditeur CSS', + 'vendor' => [ + 'codemirror' + ], + 'view' => 'advanced' + ]); + } + + /** + * Options de l'arrière plan + */ + public function body() { + // Soumission du formulaire + if($this->isPost()) { + $this->setData(['theme', 'body', [ + 'backgroundColor' => $this->getInput('themeBodyBackgroundColor'), + 'image' => $this->getInput('themeBodyImage'), + 'imageAttachment' => $this->getInput('themeBodyImageAttachment'), + 'imagePosition' => $this->getInput('themeBodyImagePosition'), + 'imageRepeat' => $this->getInput('themeBodyImageRepeat'), + 'imageSize' => $this->getInput('themeBodyImageSize'), + 'toTopbackgroundColor' => $this->getInput('themeBodyToTopBackground'), + 'toTopColor' => $this->getInput('themeBodyToTopColor') + ]]); + // Valeurs en sortie + $this->addOutput([ + 'notification' => 'Modifications enregistrées', + 'redirect' => helper::baseUrl() . 'theme', + 'state' => true + ]); + } + // Valeurs en sortie + $this->addOutput([ + 'title' => 'Personnalisation de l\'arrière plan', + 'vendor' => [ + 'tinycolorpicker' + ], + 'view' => 'body' + ]); + } + + /** + * Options du pied de page + */ + public function footer() { + // Soumission du formulaire + if($this->isPost()) { + if ( $this->getInput('themeFooterCopyrightPosition') === 'hide' && + $this->getInput('themeFooterSocialsPosition') === 'hide' && + $this->getInput('themeFooterTextPosition') === 'hide' ) { + // Valeurs en sortie + $this->addOutput([ + 'notification' => 'Sélectionnez au moins un contenu à afficher', + 'redirect' => helper::baseUrl() . 'theme/footer', + 'state' => false + ]); + } else { + $this->setData(['theme', 'footer', [ + 'backgroundColor' => $this->getInput('themeFooterBackgroundColor'), + 'copyrightAlign' => $this->getInput('themeFooterCopyrightAlign'), + 'height' => $this->getInput('themeFooterHeight'), + 'loginLink' => $this->getInput('themeFooterLoginLink'), + 'margin' => $this->getInput('themeFooterMargin', helper::FILTER_BOOLEAN), + 'position' => $this->getInput('themeFooterPosition'), + 'fixed' => $this->getInput('themeFooterFixed', helper::FILTER_BOOLEAN), + 'socialsAlign' => $this->getInput('themeFooterSocialsAlign'), + 'text' => $this->getInput('themeFooterText', null), + 'textAlign' => $this->getInput('themeFooterTextAlign'), + 'textColor' => $this->getInput('themeFooterTextColor'), + 'copyrightPosition' => $this->getInput('themeFooterCopyrightPosition'), + 'textPosition' => $this->getInput('themeFooterTextPosition'), + 'socialsPosition' => $this->getInput('themeFooterSocialsPosition'), + 'textTransform' => $this->getInput('themeFooterTextTransform'), + 'font' => $this->getInput('themeFooterFont'), + 'fontSize' => $this->getInput('themeFooterFontSize'), + 'fontWeight' => $this->getInput('themeFooterFontWeight'), + 'displayVersion' => $this->getInput('themefooterDisplayVersion', helper::FILTER_BOOLEAN), + 'displaySiteMap' => $this->getInput('themefooterDisplaySiteMap', helper::FILTER_BOOLEAN), + 'displayCopyright' => $this->getInput('themefooterDisplayCopyright', helper::FILTER_BOOLEAN), + 'displayCookie' => $this->getInput('themefooterDisplayCookie', helper::FILTER_BOOLEAN), + 'displayLegal' => $this->getInput('themeFooterDisplayLegal', helper::FILTER_BOOLEAN), + 'displaySearch' => $this->getInput('themeFooterDisplaySearch', helper::FILTER_BOOLEAN), + 'displayMemberBar'=> $this->getInput('themeFooterDisplayMemberBar', helper::FILTER_BOOLEAN), + 'template' => $this->getInput('themeFooterTemplate') + ]]); + + // Sauvegarder la configuration localisée + $this->setData(['locale','legalPageId', $this->getInput('configLegalPageId')]); + $this->setData(['locale','searchPageId', $this->getInput('configSearchPageId')]); + + // Valeurs en sortie + $this->addOutput([ + 'notification' => 'Modifications enregistrées', + 'redirect' => helper::baseUrl() . 'theme', + 'state' => true + ]); + } + } + + // Liste des pages + self::$pagesList = $this->getData(['page']); + foreach(self::$pagesList as $page => $pageId) { + if ($this->getData(['page',$page,'block']) === 'bar' || + $this->getData(['page',$page,'disable']) === true) { + unset(self::$pagesList[$page]); + } + } + // Lire les fontes installées + $this->enumFonts(); + // Valeurs en sortie + $this->addOutput([ + 'title' => 'Personnalisation du pied de page', + 'vendor' => [ + 'tinycolorpicker', + 'tinymce' + ], + 'view' => 'footer' + ]); + } + + /** + * Options de la bannière + */ + public function header() { + // Soumission du formulaire + if($this->isPost()) { + // Modification des URL des images dans la bannière perso + $featureContent = $this->getInput('themeHeaderText', null); + $featureContent = str_replace(helper::baseUrl(false,false), './', $featureContent); + + /** + * Stocker les images incluses dans la bannière perso dans un tableau + */ + preg_match_all('/]+>/i',$featureContent, $results); + foreach($results[0] as $value) { + // Lire le contenu XML + $sx = simplexml_load_string($value); + // Élément à remplacer + $files [] = str_replace('./site/file/source/','',(string) $sx[0]['src']); + } + + // Sauvegarder + $this->setData(['theme', 'header', [ + 'backgroundColor' => $this->getInput('themeHeaderBackgroundColor'), + 'font' => $this->getInput('themeHeaderFont'), + 'fontSize' => $this->getInput('themeHeaderFontSize'), + 'fontWeight' => $this->getInput('themeHeaderFontWeight'), + 'height' => $this->getInput('themeHeaderHeight'), + 'wide' => $this->getInput('themeHeaderWide'), + 'image' => $this->getInput('themeHeaderImage'), + 'imagePosition' => $this->getInput('themeHeaderImagePosition'), + 'imageRepeat' => $this->getInput('themeHeaderImageRepeat'), + 'margin' => $this->getInput('themeHeaderMargin', helper::FILTER_BOOLEAN), + 'position' => $this->getInput('themeHeaderPosition'), + 'textAlign' => $this->getInput('themeHeaderTextAlign'), + 'textColor' => $this->getInput('themeHeaderTextColor'), + 'textHide' => $this->getInput('themeHeaderTextHide', helper::FILTER_BOOLEAN), + 'textTransform' => $this->getInput('themeHeaderTextTransform'), + 'linkHomePage' => $this->getInput('themeHeaderlinkHomePage',helper::FILTER_BOOLEAN), + 'imageContainer' => $this->getInput('themeHeaderImageContainer'), + 'tinyHidden' => $this->getInput('themeHeaderTinyHidden', helper::FILTER_BOOLEAN), + 'feature' => $this->getInput('themeHeaderFeature'), + 'featureContent' => $featureContent, + 'featureFiles' => $files + ]]); + // Modification de la position du menu selon la position de la bannière + if ( $this->getData(['theme','header','position']) == 'site' ) + { + $this->setData(['theme', 'menu', 'position',str_replace ('body-','site-',$this->getData(['theme','menu','position']))]); + } + if ( $this->getData(['theme','header','position']) == 'body') + { + $this->setData(['theme', 'menu', 'position',str_replace ('site-','body-',$this->getData(['theme','menu','position']))]); + } + // Menu accroché à la bannière qui devient cachée + if ( $this->getData(['theme','header','position']) == 'hide' && + in_array( $this->getData(['theme','menu','position']) , ['body-first', 'site-first', 'body-first' , 'site-second']) + ) { + $this->setData(['theme', 'menu', 'position','site']); + } + // Valeurs en sortie + $this->addOutput([ + 'notification' => 'Modifications enregistrées', + 'redirect' => helper::baseUrl() . 'theme', + 'state' => true + ]); + } + // Lire les fontes installées + $this->enumFonts(); + // Valeurs en sortie + $this->addOutput([ + 'title' => 'Personnalisation de la bannière', + 'vendor' => [ + 'tinycolorpicker', + 'tinymce' + ], + 'view' => 'header' + ]); + } + + /** + * Accueil de la personnalisation + */ + public function index() { + // Valeurs en sortie + $this->addOutput([ + 'title' => 'Personnalisation des thèmes', + 'view' => 'index' + ]); + } + + /** + * Options du menu + */ + public function menu() { + // Soumission du formulaire + if($this->isPost()) { + $this->setData(['theme', 'menu', [ + 'backgroundColor' => $this->getInput('themeMenuBackgroundColor'), + 'backgroundColorSub' => $this->getInput('themeMenuBackgroundColorSub'), + 'font' => $this->getInput('themeMenuFont'), + 'fontSize' => $this->getInput('themeMenuFontSize'), + 'fontWeight' => $this->getInput('themeMenuFontWeight'), + 'height' => $this->getInput('themeMenuHeight'), + 'wide' => $this->getInput('themeMenuWide'), + 'loginLink' => $this->getInput('themeMenuLoginLink', helper::FILTER_BOOLEAN), + 'margin' => $this->getInput('themeMenuMargin', helper::FILTER_BOOLEAN), + 'position' => $this->getInput('themeMenuPosition'), + 'textAlign' => $this->getInput('themeMenuTextAlign'), + 'textColor' => $this->getInput('themeMenuTextColor'), + 'textTransform' => $this->getInput('themeMenuTextTransform'), + 'fixed' => $this->getInput('themeMenuFixed', helper::FILTER_BOOLEAN), + 'activeColorAuto' => $this->getInput('themeMenuActiveColorAuto', helper::FILTER_BOOLEAN), + 'activeColor' => $this->getInput('themeMenuActiveColor'), + 'activeTextColor' => $this->getInput('themeMenuActiveTextColor'), + 'radius' => $this->getInput('themeMenuRadius'), + 'burgerTitle' => $this->getInput('themeMenuBurgerTitle', helper::FILTER_BOOLEAN), + 'memberBar' => $this->getInput('themeMenuMemberBar', helper::FILTER_BOOLEAN), + 'burgerLogo' => $this->getInput('themeMenuBurgerLogo'), + 'burgerContent' => $this->getInput('themeMenuBurgerContent') + ]]); + // Valeurs en sortie + $this->addOutput([ + 'notification' => 'Modifications enregistrées', + 'redirect' => helper::baseUrl() . 'theme', + 'state' => true + ]); + } + // Lire les fontes installées + $this->enumFonts(); + // Valeurs en sortie + $this->addOutput([ + 'title' => 'Personnalisation du menu', + 'vendor' => [ + 'tinycolorpicker' + ], + 'view' => 'menu' + ]); + } + + /** + * Options des fontes + */ + public function fonts() { + + // Polices liées au thème + $used = [ + 'Bannière' => $this->getData (['theme', 'header', 'font']), + 'Menu' => $this->getData (['theme', 'menu', 'font']), + 'Titre ' => $this->getData (['theme', 'title', 'font']), + 'Texte' => $this->getData (['theme', 'text', 'font']), + 'Pied de page' => $this->getData (['theme', 'footer', 'font']), + 'Titre (admin)' => $this->getData (['admin', 'fontTitle' ]), + 'Admin (texte)' => $this->getData (['admin', 'fontText' ]) + ]; + + // Récupérer le détail des fontes installées + $f = $this->getFonts(); + + // Parcourir les fontes disponibles et construire le tableau pour le formulaire + foreach ($f as $type => $typeValue) { + + foreach ($typeValue as $fontId => $fontValue) { + // Fontes utilisées par les thèmes + $fontUsed[$fontId] = ''; + foreach ($used as $key => $value) { + if ( $value === $fontId) { + $fontUsed[$fontId] .= $key . '
      '; + } + } + self::$fontsDetail [] = [ + $fontId, + '' . $f[$type][$fontId]['name'] . '' , + $f[$type][$fontId]['font-family'], + $fontUsed[$fontId], + $type, + $type !== 'websafe' ? template::button('themeFontEdit' . $fontId, [ + 'class' => 'themeFontEdit', + 'href' => helper::baseUrl() . $this->getUrl(0) . '/fontEdit/' . $type . '/' . $fontId . '/' . $_SESSION['csrf'], + 'value' => template::ico('pencil'), + 'disabled' => !empty($fontUsed[$fontId]) + ]) + : '', + $type !== 'websafe' ? template::button('themeFontDelete' . $fontId, [ + 'class' => 'themeFontDelete buttonRed', + 'href' => helper::baseUrl() . $this->getUrl(0) . '/fontDelete/' . $type . '/' . $fontId . '/' . $_SESSION['csrf'], + 'value' => template::ico('cancel'), + 'disabled' => !empty($fontUsed[$fontId]) + ]) + : '' + ]; + } + } + sort(self::$fontsDetail); + // Valeurs en sortie + $this->addOutput([ + 'title' => 'Gestion des fontes', + 'view' => 'fonts' + ]); + } + + /** + * Ajouter une fonte + */ + public function fontAdd() { + // Soumission du formulaire + if ($this->isPost()) { + // Type d'import en ligne ou local + $type = $this->getInput('fontAddFontImported', helper::FILTER_BOOLEAN) ? 'imported' : 'files'; + $ressource = $type === 'imported' ? $this->getInput('fontAddUrl', helper::FILTER_STRING_SHORT) : $this->getInput('fontAddFile', helper::FILTER__SHORT_STRING); + $fontId = $this->getInput('fontAddFontId', helper::FILTER_STRING_SHORT, true); + $fontName = $this->getInput('fontAddFontName', helper::FILTER_STRING_SHORT, true); + $fontFamilyName = $this->getInput('fontAddFontFamilyName', helper::FILTER_STRING_SHORT, true); + + // Vérifier l'existence de fontId et validité de family name si usage en ligne de cdnFonts + + // Charger les données des fontes + $fonts = $this->getData(['fonts']); + + // Concaténation dans les tableaux existants + $t = [ $fontId => [ + 'name' => $fontName, + 'font-family' => $fontFamilyName, + 'ressource' => $ressource + ]]; + + // Stocker les fontes + $this->setData(['fonts', $type, [ $fontId => + [ + 'name' => $fontName, + 'font-family' => $fontFamilyName, + 'ressource' => $ressource + ]] + ]); + + // Copier la fonte si le nom du fichier est fourni + if ( $type === 'files' && + is_file(self::FILE_DIR . 'source/' . $ressource) + ) { + copy ( self::FILE_DIR . 'source/' . $ressource, self::DATA_DIR . 'fonts/' . $ressource ); + } + + // Valeurs en sortie + $this->addOutput([ + 'notification' => 'La fonte a été créée', + 'redirect' => helper::baseUrl() . 'theme/fonts', + 'state' => true + ]); + } + // Valeurs en sortie + $this->addOutput([ + 'title' => 'Ajouter une fonte', + 'view' => 'fontAdd' + ]); + } + + + /** + * Ajouter une fonte + */ + public function fontEdit() { + // Soumission du formulaire + if ($this->isPost()) { + // Type d'import en ligne ou local + $type = $this->getInput('fontEditFontImported', helper::FILTER_BOOLEAN) ? 'imported' : 'files'; + $ressource = $type === 'imported' ? $this->getInput('fontEditUrl', helper::FILTER_STRING_SHORT) : $this->getInput('fontEditFile', helper::FILTER__SHORT_STRING); + $fontId = $this->getInput('fontEditFontId', helper::FILTER_STRING_SHORT, true); + $fontName = $this->getInput('fontEditFontName', helper::FILTER_STRING_SHORT, true); + $fontFamilyName = $this->getInput('fontEditFontFamilyName', helper::FILTER_STRING_SHORT, true); + + // Vérifier l'existence de fontId et validité de family name si usage en ligne de cdnFonts + + // Charger les données des fontes + $fonts = $this->getData(['fonts']); + + // Concaténation dans les tableaux existants + $t = [ $fontId => [ + 'name' => $fontName, + 'font-family' => $fontFamilyName, + 'ressource' => $ressource + ]]; + + // Stocker les fontes + $this->setData(['fonts', $type, [ $fontId => + [ + 'name' => $fontName, + 'font-family' => $fontFamilyName, + 'ressource' => $ressource + ]] + ]); + + // Copier la fonte si le nom du fichier est fourni + if ( $type === 'files' && + is_file(self::FILE_DIR . 'source/' . $ressource) + ) { + copy ( self::FILE_DIR . 'source/' . $ressource, self::DATA_DIR . 'fonts/' . $ressource ); + } + + // Valeurs en sortie + $this->addOutput([ + 'notification' => 'La fonte a été actualisée', + 'redirect' => helper::baseUrl() . 'theme/fonts', + 'state' => true + ]); + } + // Valeurs en sortie + $this->addOutput([ + 'title' => 'Editer une fonte', + 'view' => 'fontEdit' + ]); + } + + /** + * Effacer une fonte + */ + public function fontDelete() { + // Jeton incorrect + if ($this->getUrl(4) !== $_SESSION['csrf']) { + // Valeurs en sortie + $this->addOutput([ + 'redirect' => helper::baseUrl() . 'theme/fonts', + 'notification' => 'Action non autorisée' + ]); + } + // Suppression + else { + + // Effacer la fonte de la base + $this->deleteData(['fonts', $this->getUrl(2), $this->getUrl(3)]); + + // Effacer le fichier existant + if ( $this->getUrl(2) === 'file' && + file_exists(self::DATA_DIR . $this->getUrl(2)) ) { + unlink(self::DATA_DIR . $this->getUrl(2)); + } + + // Valeurs en sortie + $this->addOutput([ + 'redirect' => helper::baseUrl() . 'theme/fonts', + 'notification' => 'La fonte a été supprimée', + 'state' => true + ]); + } + } + + + /** + * Réinitialisation de la personnalisation avancée + */ + public function reset() { + // $url prend l'adresse sans le token + $url = explode('&',$this->getUrl(2)); + + if ( isset($_GET['csrf']) + AND $_GET['csrf'] === $_SESSION['csrf'] + ) { + // Réinitialisation + $redirect =''; + switch ($url[0]) { + case 'admin': + $this->initData('admin'); + $redirect = helper::baseUrl() . 'theme/admin'; + break; + case 'manage': + $this->initData('theme'); + $redirect = helper::baseUrl() . 'theme/manage'; + break; + case 'custom': + unlink(self::DATA_DIR.'custom.css'); + $redirect = helper::baseUrl() . 'theme/advanced'; + break; + default : + $redirect = helper::baseUrl() . 'theme'; + } + + // Valeurs en sortie + $this->addOutput([ + 'notification' => 'Réinitialisation effectuée', + 'redirect' => $redirect, + 'state' => true + ]); + } else { + // Valeurs en sortie + $this->addOutput([ + 'notification' => 'Jeton incorrect' + ]); + } + } + + + /** + * Options du site + */ + public function site() { + // Soumission du formulaire + if($this->isPost()) { + $this->setData(['theme', 'title', [ + 'font' => $this->getInput('themeTitleFont'), + 'textColor' => $this->getInput('themeTitleTextColor'), + 'fontWeight' => $this->getInput('themeTitleFontWeight'), + 'textTransform' => $this->getInput('themeTitleTextTransform') + ]]); + $this->setData(['theme', 'text', [ + 'font' => $this->getInput('themeTextFont'), + 'fontSize' => $this->getInput('themeTextFontSize'), + 'textColor' => $this->getInput('themeTextTextColor'), + 'linkColor'=> $this->getInput('themeTextLinkColor') + ]]); + $this->setData(['theme', 'site', [ + 'backgroundColor' => $this->getInput('themeSiteBackgroundColor'), + 'radius' => $this->getInput('themeSiteRadius'), + 'shadow' => $this->getInput('themeSiteShadow'), + 'width' => $this->getInput('themeSiteWidth'), + 'margin' => $this->getInput('themeSiteMargin',helper::FILTER_BOOLEAN) + ]]); + $this->setData(['theme', 'button', [ + 'backgroundColor' => $this->getInput('themeButtonBackgroundColor') + ]]); + $this->setData(['theme', 'block', [ + 'backgroundColor' => $this->getInput('themeBlockBackgroundColor'), + 'borderColor' => $this->getInput('themeBlockBorderColor') + ]]); + // Valeurs en sortie + $this->addOutput([ + 'notification' => 'Modifications enregistrées', + 'redirect' => helper::baseUrl() . 'theme', + 'state' => true + ]); + } + // Lire les fontes installées + $this->enumFonts(); + // Valeurs en sortie + $this->addOutput([ + 'title' => 'Personnalisation du site', + 'vendor' => [ + 'tinycolorpicker', + 'tinymce' + ], + 'view' => 'site' + ]); + } + + /** + * Import du thème + */ + public function manage() { + if($this->isPost() ) { + + $zipFilename = $this->getInput('themeManageImport', helper::FILTER_STRING_SHORT, true); + $data = $this->import(self::FILE_DIR.'source/' . $zipFilename); + if ($data['success']) { + header("Refresh:0"); + } else { + // Valeurs en sortie + $this->addOutput([ + 'notification' => $data['notification'], + 'state' => $data['success'], + 'title' => 'Gestion des thèmes', + 'view' => 'manage' + ]);; + } + } + // Valeurs en sortie + $this->addOutput([ + 'title' => 'Gestion des thèmes', + 'view' => 'manage' + ]); + } + + /** + * Importe un thème + * @param string Url du thème à télécharger + * @param @return array contenant $success = true ou false ; $ notification string message à afficher + */ + + public function import($zipName = '') { + + if ($zipName !== '' && + file_exists($zipName)) { + // Init variables de retour + $success = false; + $notification = ''; + // Dossier temporaire + $tempFolder = uniqid(); + // Ouvrir le zip + $zip = new ZipArchive(); + if ($zip->open($zipName) === TRUE) { + mkdir (self::TEMP_DIR . $tempFolder, 0755); + $zip->extractTo(self::TEMP_DIR . $tempFolder ); + $modele = ''; + // Archive de thème ? + if ( + file_exists(self::TEMP_DIR . $tempFolder . '/site/data/custom.css') + AND file_exists(self::TEMP_DIR . $tempFolder . '/site/data/theme.css') + AND file_exists(self::TEMP_DIR . $tempFolder . '/site/data/theme.json') + ) { + $modele = 'theme'; + } + if( + file_exists(self::TEMP_DIR . $tempFolder . '/site/data/admin.json') + AND file_exists(self::TEMP_DIR . $tempFolder . '/site/data/admin.css') + ) { + $modele = 'admin'; + + } + if (!empty($modele) + ) { + // traiter l'archive + $success = $zip->extractTo('.'); + + // Substitution des fontes Google + if ($modele = 'theme') { + $c = $this->subFonts(self::DATA_DIR . 'theme.json'); + // Un remplacement nécessite la régénération de la feuille de style + if ($c > 0 + AND file_exists(self::DATA_DIR . 'theme.css') + ) { + unlink(self::DATA_DIR . 'theme.css'); + } + } + if ($modele = 'admin') { + $c = $this->subFonts(self::DATA_DIR . 'admin.json'); + // Un remplacement nécessite la régénération de la feuille de style + if ($c > 0 + AND file_exists(self::DATA_DIR . 'admin.css') + ) { + unlink(self::DATA_DIR . 'admin.css'); + } + } + + // traitement d'erreur + $notification = $success ? 'Le thème a été importé' : 'Erreur lors de l\'extraction, vérifiez les permissions.'; + + + } else { + // pas une archive de thème + $success = false; + $notification = 'Ce n\'est pas l\'archive d\'un thème !'; + } + // Supprimer le dossier temporaire même si le thème est invalide + $this->removeDir(self::TEMP_DIR . $tempFolder); + $zip->close(); + } else { + // erreur à l'ouverture + $success = false; + $notification = 'Impossible d\'ouvrir l\'archive'; + } + return (['success' => $success, 'notification' => $notification]); + } + + return (['success' => false, 'notification' => 'Archive non spécifiée ou introuvable']); + } + + + + /** + * Export du thème + */ + public function export() { + // Make zip + $zipFilename = $this->zipTheme($this->getUrl(2)); + // Téléchargement du ZIP + header('Content-Description: File Transfer'); + header('Content-Type: application/octet-stream'); + header('Content-Transfer-Encoding: binary'); + header('Content-Disposition: attachment; filename="' . $zipFilename . '"'); + header('Content-Length: ' . filesize(self::TEMP_DIR . $zipFilename)); + readfile(self::TEMP_DIR . $zipFilename); + // Nettoyage du dossier + unlink (self::TEMP_DIR . $zipFilename); + exit(); + } + + /** + * Export du thème + */ + public function save() { + // Make zip + $zipFilename = $this->zipTheme($this->getUrl(2)); + // Téléchargement du ZIP + if (!is_dir(self::FILE_DIR.'source/theme')) { + mkdir(self::FILE_DIR.'source/theme', 0755); + } + copy (self::TEMP_DIR . $zipFilename , self::FILE_DIR.'source/theme/' . $zipFilename); + // Nettoyage du dossier + unlink (self::TEMP_DIR . $zipFilename); + // Valeurs en sortie + $this->addOutput([ + 'notification' => 'Archive '.$zipFilename.' sauvegardée avec succès', + 'redirect' => helper::baseUrl() . 'theme/manage', + 'state' => true + ]); + } + + /** + * construction du zip Fonction appelée par export() et save() + * @param string $modele theme ou admin + */ + private function zipTheme($modele) { + // Creation du dossier + $zipFilename = $modele . date('Y-m-d-H-i-s', time()) . '.zip'; + $zip = new ZipArchive(); + if ($zip->open(self::TEMP_DIR . $zipFilename, ZipArchive::CREATE | ZipArchive::OVERWRITE ) === TRUE) { + switch ($modele) { + case 'admin': + $zip->addFile(self::DATA_DIR.'admin.json',self::DATA_DIR.'admin.json'); + $zip->addFile(self::DATA_DIR.'admin.css',self::DATA_DIR.'admin.css'); + break; + case 'theme': + $zip->addFile(self::DATA_DIR.'theme.json',self::DATA_DIR.'theme.json'); + $zip->addFile(self::DATA_DIR.'theme.css',self::DATA_DIR.'theme.css'); + $zip->addFile(self::DATA_DIR.'custom.css',self::DATA_DIR.'custom.css'); + // Traite l'image dans le body + if ($this->getData(['theme','body','image']) !== '' ) { + $zip->addFile(self::FILE_DIR.'source/'.$this->getData(['theme','body','image']), + self::FILE_DIR.'source/'.$this->getData(['theme','body','image']) + ); + } + // Traite l'image dans le header + if ($this->getData(['theme','header','image']) !== '' ) { + $zip->addFile(self::FILE_DIR.'source/'.$this->getData(['theme','header','image']), + self::FILE_DIR.'source/'.$this->getData(['theme','header','image']) + ); + } + // Traite les images du header perso + if (!empty($this->getData(['theme','header','featureFiles'])) ) { + foreach($this->getData(['theme','header','featureFiles']) as $value) { + $zip->addFile(self::FILE_DIR . 'source/' . $value, + self::FILE_DIR . 'source/' . $value ); + } + } + break; + } + $ret = $zip->close(); + } + return ($zipFilename); + } + + /** + * Substitution des fontes de Google Fonts vers CdnFont grâce à un tableau de conversion + * Cette fonction est utilisée par l'import. + * @param string $file, nom du fichier json à convertir + * @return int nombre de substitution effectuées + */ + private function subFonts($file) { + // Tableau de substitution des fontes + $fonts = [ + 'Abril+Fatface' => 'abril-fatface', + 'Arimo' => 'arimo', + 'Arvo' => 'arvo', + 'Berkshire+Swash' => 'berkshire-swash', + 'Cabin' => 'genera', + 'Dancing+Script' => 'dancing-script', + 'Droid+Sans' => 'droid-sans-2', + 'Droid+Serif' => 'droid-serif-2', + 'Fira+Sans' => 'fira-sans', + 'Inconsolata' => 'inconsolata-2', + 'Indie+Flower' =>'indie-flower', + 'Josefin+Slab' => 'josefin-sans-std', + 'Lobster' => 'lobster-2', + 'Lora' => 'lora', + 'Lato' =>'lato', + 'Marvel' => 'montserrat-ace', + 'Old+Standard+TT' => 'old-standard-tt-3', + 'Open+Sans' =>'open-sans', + // Corriger l'erreur de nom de police installée par défaut, il manquait un O en majuscule + 'open+Sans' =>'open-sans', + 'Oswald' =>'oswald-4', + 'PT+Mono' => 'pt-mono', + 'PT+Serif' =>'pt-serif', + 'Raleway' => 'raleway-5', + 'Rancho' => 'rancho', + 'Roboto' => 'Roboto', + 'Signika' => 'signika', + 'Ubuntu' => 'ubuntu', + 'Vollkorn' => 'vollkorn' + ]; + + $data = file_get_contents($file); + $count = 0; + foreach ($fonts as $oldId => $newId){ + $data = str_replace($oldId, $newId, $data, $c); + $count = $count + (int) $c; + } + // Sauvegarder la chaîne modifiée + if ($count > 0) { + file_put_contents($file, $data); + } + // Retourner le nombre d'occurrences + return ($count); + } + + // Retourne un tableau simple des fonts installées idfont avec le nom + // Cette fonction est utile aux sélecteurs de fonts dans les formulaires. + public function enumFonts() { + // Récupère la liste des fontes installées + $f = $this->getFonts(); + // Construit un tableau avec leur ID et leur famille + foreach(['websafe', 'imported', 'files'] as $type) { + foreach ($f[$type] as $fontId => $fontValue ) { + $fonts [$fontId] = $fontValue['name']; + } + } + ksort($fonts); + self::$fontsList = $fonts; + } + +} diff --git a/core/module/theme/view/fontAdd/fontAdd.js.php b/core/module/theme/view/fontAdd/fontAdd.js.php index dd53c7cf..e9105513 100644 --- a/core/module/theme/view/fontAdd/fontAdd.js.php +++ b/core/module/theme/view/fontAdd/fontAdd.js.php @@ -15,7 +15,8 @@ */ $(document).ready(function(){ $('input[name=fontAddFontImported]').prop('checked', true); - $('#fontAddFileWrapper').hide(); + $('input[name=fontAddFontUrl]').prop('checked', false); + $('#containerFontAddFile').hide(); }); @@ -28,7 +29,8 @@ $("input[name=fontAddFontImported]").on("click", function() { } else { $('input[name=fontAddFontFile]').prop('checked', true); } - $('#fontAddFileWrapper').hide(); + $('#containerFontAddFile').hide(); + $('#containerFontAddUrl').show(); }); $("input[name=fontAddFontFile]").on("click", function() { @@ -37,5 +39,6 @@ $("input[name=fontAddFontFile]").on("click", function() { } else { $('input[name=fontAddFontImported]').prop('checked', true); } - $('#fontAddFileWrapper').show(); + $('#containerFontAddFile').show(); + $('#containerFontAddUrl').hide(); }); diff --git a/core/module/theme/view/fontAdd/fontAdd.php b/core/module/theme/view/fontAdd/fontAdd.php index e1bc9976..804b3674 100644 --- a/core/module/theme/view/fontAdd/fontAdd.php +++ b/core/module/theme/view/fontAdd/fontAdd.php @@ -9,7 +9,7 @@ ]); ?>
- 'https://doc.zwiicms.fr/fontes#add', 'target' => '_blank', 'ico' => 'help', @@ -30,14 +30,10 @@

Identité de la fonte

- 'Police utilisée en ligne, se connecter sur cdnFonts pour récupérer les informations nécessaires.' - ]); ?> +
- '
Sélectionnez un fichier de fonte au format WOFF.' - ]); ?> +
@@ -45,23 +41,39 @@ 'off', 'label' => 'Identifiant (sans espace ni majuscule)', - 'placeholder' => 'perry-gothic' + 'placeholder' => 'big-marker-extrude' ]); ?>
'off', - 'label' => 'Nom (Font Family)', - 'placeholder' => 'PerryGothic' + 'label' => 'Nom', + 'placeholder' => 'Big Marker Extrude' ]); ?>
+
+ 'off', + 'label' => 'Famille', + 'placeholder' => "'Big Marker Extrude', sans-serif" + ]); ?> +
+
+
'Fichier de police (Format WOFF)', - 'placeholder' => 'https://fonts.cdnfonts.com/s/7896/PERRYGOT.woff' + 'label' => 'Fichier de fonte (Format WOFF)' + ]); ?> +
+
+
+
+ 'Url du fichier de fonte', + 'placeholder' => 'https://fonts.cdnfonts.com/css/big-marker-extrude' ]); ?>
diff --git a/core/module/theme/view/fontEdit/fontEdit.css b/core/module/theme/view/fontEdit/fontEdit.css new file mode 100644 index 00000000..52709ea6 --- /dev/null +++ b/core/module/theme/view/fontEdit/fontEdit.css @@ -0,0 +1,18 @@ +/** + * 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 + * @copyright Copyright (C) 2008-2018, Rémi Jean + * @author Frédéric Tempez + * @copyright Copyright (C) 2018-2022, Frédéric Tempez + * @license GNU General Public License, version 3 + * @link http://zwiicms.fr/ + */ + + +/** NE PAS EFFACER +* admin.css +*/ \ No newline at end of file diff --git a/core/module/theme/view/fontEdit/fontEdit.js.php b/core/module/theme/view/fontEdit/fontEdit.js.php new file mode 100644 index 00000000..d702e658 --- /dev/null +++ b/core/module/theme/view/fontEdit/fontEdit.js.php @@ -0,0 +1,44 @@ +/** + * 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 Frédéric Tempez + * @copyright Copyright (C) 2018-2022, Frédéric Tempez + * @license GNU General Public License, version 3 + * @link http://zwiicms.fr/ + */ + + +/** + * Option par défaut du sélecteur de mode + */ + $(document).ready(function(){ + $('input[name=fontEditFontImported]').prop('checked', true); + $('input[name=fontEditFontUrl]').prop('checked', false); + $('#containerfontEditFile').hide(); +}); + + +/** + * Mode téléchargement en ligne de la fonte ou installation locale + */ +$("input[name=fontEditFontImported]").on("click", function() { + if( $('input[name=fontEditFontImported]').is(':checked') ){ + $('input[name=fontEditFontFile]').prop('checked', false); + } else { + $('input[name=fontEditFontFile]').prop('checked', true); + } + $('#containerfontEditFile').hide(); + $('#containerfontEditUrl').show(); +}); + +$("input[name=fontEditFontFile]").on("click", function() { + if( $('input[name=fontEditFontFile]').is(':checked') ){ + $('input[name=fontEditFontImported]').prop('checked', false); + } else { + $('input[name=fontEditFontImported]').prop('checked', true); + } + $('#containerfontEditFile').show(); + $('#containerfontEditUrl').hide(); +}); diff --git a/core/module/theme/view/fontEdit/fontEdit.php b/core/module/theme/view/fontEdit/fontEdit.php new file mode 100644 index 00000000..33fec58c --- /dev/null +++ b/core/module/theme/view/fontEdit/fontEdit.php @@ -0,0 +1,87 @@ + +
+
+ 'buttonGrey', + 'href' => helper::baseUrl() . 'theme/fonts', + 'ico' => 'left', + 'value' => 'Retour' + ]); ?> +
+
+ 'https://doc.zwiicms.fr/fontes#add', + 'target' => '_blank', + 'ico' => 'help', + 'value' => 'Aide', + 'class' => 'buttonHelp' + ]); ?> +
+
+ 'Valider', + 'uniqueSubmission' => true + ]); ?> +
+
+
+
+
+

Identité de la fonte

+
+
+ $this->getUrl(2) === 'imported' ? true : false + ]); ?> +
+
+ $this->getUrl(2) === 'file' ? true : false + ]); ?> +
+
+
+
+ 'off', + 'label' => 'Identifiant (sans espace ni majuscule)', + 'value' => $this->getUrl(3) + ]); ?> +
+
+ 'off', + 'label' => 'Nom', + 'value' => $this->getData(['fonts', $this->getUrl(2), $this->getUrl(3), 'name']) + ]); ?> +
+
+
+
+ 'off', + 'label' => 'Famille', + 'value' => $this->getData(['fonts', $this->getUrl(2), $this->getUrl(3), 'font-family']) + ]); ?> +
+
+
+
+ 'Fichier de fonte (Format WOFF)', + 'value' => $this->getUrl(2) === 'file' ? $this->getData(['fonts', $this->getUrl(2), $this->getUrl(3), 'ressource']) : '' + ]); ?> +
+
+
+
+ 'Url du fichier de fonte', + 'value' => $this->getUrl(2) === 'imported' ? $this->getData(['fonts', $this->getUrl(2), $this->getUrl(3), 'ressource']) : '' + ]); ?> +
+
+
+
+
+ \ No newline at end of file diff --git a/core/module/theme/view/fonts/fonts.php b/core/module/theme/view/fonts/fonts.php index 9a5a7815..e6b95c92 100644 --- a/core/module/theme/view/fonts/fonts.php +++ b/core/module/theme/view/fonts/fonts.php @@ -23,8 +23,8 @@ ]); ?>
- - + + \ No newline at end of file diff --git a/core/module/theme/view/footer/footer.php b/core/module/theme/view/footer/footer.php index 9c47aa82..7afcf447 100644 --- a/core/module/theme/view/footer/footer.php +++ b/core/module/theme/view/footer/footer.php @@ -133,7 +133,7 @@ ]); ?>
- 'Aucune'] , helper::arrayCollumn($module::$pagesList, 'title', 'SORT_ASC') ) , [ + 'Aucune'] , helper::arrayColumn($module::$pagesList, 'title', 'SORT_ASC') ) , [ 'label' => 'Page "Mentions légales" ' . template::flag('site', '20px'), 'selected' => $this->getData(['locale', 'legalPageId']) ]); ?> @@ -147,7 +147,7 @@ ]); ?>
- 'Aucune'] , helper::arrayCollumn($module::$pagesList, 'title', 'SORT_ASC') ) , [ + 'Aucune'] , helper::arrayColumn($module::$pagesList, 'title', 'SORT_ASC') ) , [ 'label' => 'Page "Rechercher" ' . template::flag('site', '20px'), 'selected' => $this->getData(['locale', 'searchPageId']) ]); ?> @@ -171,7 +171,7 @@

Mise en forme du texte

- 'Police', 'selected' => $this->getData(['theme', 'footer', 'font']), 'fonts' => true diff --git a/core/module/theme/view/header/header.php b/core/module/theme/view/header/header.php index 232953db..0f6abeaf 100644 --- a/core/module/theme/view/header/header.php +++ b/core/module/theme/view/header/header.php @@ -106,7 +106,7 @@ ]); ?>
- 'Police', 'selected' => $this->getData(['theme', 'header', 'font']), 'fonts' => true diff --git a/core/module/theme/view/menu/menu.php b/core/module/theme/view/menu/menu.php index 9bcbb88a..46c943ba 100644 --- a/core/module/theme/view/menu/menu.php +++ b/core/module/theme/view/menu/menu.php @@ -183,7 +183,7 @@

Mise en forme du texte

- 'Police', 'selected' => $this->getData(['theme', 'menu', 'font']), 'fonts' => true diff --git a/core/module/theme/view/site/site.php b/core/module/theme/view/site/site.php index 7f4c4e67..b4a6bd42 100644 --- a/core/module/theme/view/site/site.php +++ b/core/module/theme/view/site/site.php @@ -158,7 +158,7 @@

Mise en forme du texte

- 'Police', 'selected' => $this->getData(['theme', 'text', 'font']), 'fonts' => true @@ -179,7 +179,7 @@

Mise en forme des titres

- 'Police', 'selected' => $this->getData(['theme', 'title', 'font']), 'fonts' => true diff --git a/core/module/user/user.php b/core/module/user/user.php index 8818502a..c9682de1 100644 --- a/core/module/user/user.php +++ b/core/module/user/user.php @@ -336,7 +336,7 @@ class user extends common { * Liste des utilisateurs */ public function index() { - $userIdsFirstnames = helper::arrayCollumn($this->getData(['user']), 'firstname'); + $userIdsFirstnames = helper::arrayColumn($this->getData(['user']), 'firstname'); ksort($userIdsFirstnames); foreach($userIdsFirstnames as $userId => $userFirstname) { if ($this->getData(['user', $userId, 'group'])) { @@ -399,7 +399,7 @@ class user extends common { ] ]); // Verrouillage des IP - $ipBlackList = helper::arrayCollumn($this->getData(['blacklist']), 'ip'); + $ipBlackList = helper::arrayColumn($this->getData(['blacklist']), 'ip'); if ( $this->getData(['blacklist',$userId,'connectFail']) >= $this->getData(['config', 'connect', 'attempt']) AND in_array($this->getData(['blacklist',$userId,'ip']),$ipBlackList) ) { $logStatus = 'Compte inconnu verrouillé'; diff --git a/module/blog/blog.php b/module/blog/blog.php index 19e861e4..85608c01 100644 --- a/module/blog/blog.php +++ b/module/blog/blog.php @@ -144,8 +144,8 @@ class blog extends common { $feeds->setDate(date('r',time())); $feeds->addGenerator(); // Corps des articles - $articleIdsPublishedOns = helper::arrayCollumn($this->getData(['module', $this->getUrl(0), 'posts']), 'publishedOn', 'SORT_DESC'); - $articleIdsStates = helper::arrayCollumn($this->getData(['module', $this->getUrl(0),'posts']), 'state', 'SORT_DESC'); + $articleIdsPublishedOns = helper::arrayColumn($this->getData(['module', $this->getUrl(0), 'posts']), 'publishedOn', 'SORT_DESC'); + $articleIdsStates = helper::arrayColumn($this->getData(['module', $this->getUrl(0),'posts']), 'state', 'SORT_DESC'); foreach( $articleIdsPublishedOns as $articleId => $articlePublishedOn ) { if( $articlePublishedOn <= time() AND $articleIdsStates[$articleId] ) { // Miniature @@ -234,7 +234,7 @@ class blog extends common { ]); } // Liste des utilisateurs - self::$users = helper::arrayCollumn($this->getData(['user']), 'firstname'); + self::$users = helper::arrayColumn($this->getData(['user']), 'firstname'); ksort(self::$users); foreach(self::$users as $userId => &$userFirstname) { $userFirstname = $userFirstname . ' ' . $this->getData(['user', $userId, 'lastname']); @@ -263,7 +263,7 @@ class blog extends common { 'value' => 'Tout effacer' ]); // Ids des commentaires par ordre de création - $commentIds = array_keys(helper::arrayCollumn($comments, 'createdOn', 'SORT_DESC')); + $commentIds = array_keys(helper::arrayColumn($comments, 'createdOn', 'SORT_DESC')); // Pagination $pagination = helper::pagination($commentIds, $this->getUrl(),$this->getData(['module', $this->getUrl(0), 'config', 'itemsperPage']) ); // Liste des pages @@ -503,6 +503,78 @@ class blog extends common { 'state' => true ]); } else { + // Ids des articles par ordre de publication + $articleIds = array_keys(helper::arrayColumn($this->getData(['module', $this->getUrl(0), 'posts']), 'publishedOn', 'SORT_DESC')); + // Gestion des droits d'accès + $filterData=[]; + foreach ($articleIds as $key => $value) { + if ( + ( // Propriétaire + $this->getData(['module', $this->getUrl(0), 'posts', $value,'editConsent']) === self::EDIT_OWNER + AND ( $this->getData(['module', $this->getUrl(0), 'posts', $value,'userId']) === $this->getUser('id') + OR $this->getUser('group') === self::GROUP_ADMIN ) + ) + + OR ( + // Groupe + $this->getData(['module', $this->getUrl(0), 'posts', $value,'editConsent']) !== self::EDIT_OWNER + AND $this->getUser('group') >= $this->getData(['module',$this->getUrl(0), 'posts', $value,'editConsent']) + ) + OR ( + // Tout le monde + $this->getData(['module', $this->getUrl(0), 'posts', $value,'editConsent']) === self::EDIT_ALL + ) + ) { + $filterData[] = $value; + } + } + $articleIds = $filterData; + // Pagination + $pagination = helper::pagination($articleIds, $this->getUrl(),$this->getData(['module', $this->getUrl(0),'config', 'itemsperPage'])); + // Liste des pages + self::$pages = $pagination['pages']; + // Articles en fonction de la pagination + for($i = $pagination['first']; $i < $pagination['last']; $i++) { + // Nombre de commentaires à approuver et approuvés + $approvals = helper::arrayColumn($this->getData(['module', $this->getUrl(0), 'posts', $articleIds[$i], 'comment' ]),'approval', 'SORT_DESC'); + if ( is_array($approvals) ) { + $a = array_values($approvals); + $toApprove = count(array_keys($a,false)); + $approved = count(array_keys($a,true)); + } else { + $toApprove = 0; + $approved = count($this->getData(['module', $this->getUrl(0), 'posts', $articleIds[$i],'comment'])); + } + // Met en forme le tableau + $date = mb_detect_encoding(strftime('%d %B %Y', $this->getData(['module', $this->getUrl(0), 'posts', $articleIds[$i], 'publishedOn'])), 'UTF-8', true) + ? strftime('%d %B %Y', $this->getData(['module', $this->getUrl(0), 'posts', $articleIds[$i], 'publishedOn'])) + : utf8_encode(strftime('%d %B %Y', $this->getData(['module', $this->getUrl(0), 'posts', $articleIds[$i], 'publishedOn']))); + $heure = mb_detect_encoding(strftime('%H:%M', $this->getData(['module', $this->getUrl(0), 'posts', $articleIds[$i], 'publishedOn'])), 'UTF-8', true) + ? strftime('%H:%M', $this->getData(['module', $this->getUrl(0), 'posts', $articleIds[$i], 'publishedOn'])) + : utf8_encode(strftime('%H:%M', $this->getData(['module', $this->getUrl(0), 'posts', $articleIds[$i], 'publishedOn']))); + self::$articles[] = [ + '' . + $this->getData(['module', $this->getUrl(0), 'posts', $articleIds[$i], 'title']) . + '', + $date .' à '. $heure, + self::$states[$this->getData(['module', $this->getUrl(0), 'posts', $articleIds[$i], 'state'])], + // Bouton pour afficher les commentaires de l'article + template::button('blogConfigComment' . $articleIds[$i], [ + 'class' => ($toApprove || $approved ) > 0 ? '' : 'buttonGrey' , + 'href' => ($toApprove || $approved ) > 0 ? helper::baseUrl() . $this->getUrl(0) . '/comment/' . $articleIds[$i] : '', + 'value' => $toApprove > 0 ? $toApprove . '/' . $approved : $approved + ]), + template::button('blogConfigEdit' . $articleIds[$i], [ + 'href' => helper::baseUrl() . $this->getUrl(0) . '/edit/' . $articleIds[$i] . '/' . $_SESSION['csrf'], + 'value' => template::ico('pencil') + ]), + template::button('blogConfigDelete' . $articleIds[$i], [ + 'class' => 'blogConfigDelete buttonRed', + 'href' => helper::baseUrl() . $this->getUrl(0) . '/delete/' . $articleIds[$i] . '/' . $_SESSION['csrf'], + 'value' => template::ico('cancel') + ]) + ]; + } // Valeurs en sortie $this->addOutput([ 'title' => 'Options de configuration', @@ -612,7 +684,7 @@ class blog extends common { ]); } // Liste des utilisateurs - self::$users = helper::arrayCollumn($this->getData(['user']), 'firstname'); + self::$users = helper::arrayColumn($this->getData(['user']), 'firstname'); ksort(self::$users); foreach(self::$users as $userId => &$userFirstname) { // Les membres ne sont pas éditeurs, les exclure de la liste @@ -726,7 +798,7 @@ class blog extends common { // Ligne suivante si affichage du nombre total de commentaires approuvés sous l'article self::$nbCommentsApproved = count($commentsApproved); } - $commentIds = array_keys(helper::arrayCollumn($commentsApproved, 'createdOn', 'SORT_DESC')); + $commentIds = array_keys(helper::arrayColumn($commentsApproved, 'createdOn', 'SORT_DESC')); // Pagination $pagination = helper::pagination($commentIds, $this->getUrl(), $this->getData(['module', $this->getUrl(0),'config', 'itemsperPage']),'#comment'); // Liste des pages @@ -766,8 +838,8 @@ class blog extends common { // Liste des articles else { // Ids des articles par ordre de publication - $articleIdsPublishedOns = helper::arrayCollumn($this->getData(['module', $this->getUrl(0),'posts']), 'publishedOn', 'SORT_DESC'); - $articleIdsStates = helper::arrayCollumn($this->getData(['module', $this->getUrl(0), 'posts']), 'state', 'SORT_DESC'); + $articleIdsPublishedOns = helper::arrayColumn($this->getData(['module', $this->getUrl(0),'posts']), 'publishedOn', 'SORT_DESC'); + $articleIdsStates = helper::arrayColumn($this->getData(['module', $this->getUrl(0), 'posts']), 'state', 'SORT_DESC'); $articleIds = []; foreach($articleIdsPublishedOns as $articleId => $articlePublishedOn) { if($articlePublishedOn <= time() AND $articleIdsStates[$articleId]) { diff --git a/module/form/form.php b/module/form/form.php index fa4c3c3f..9735d90e 100644 --- a/module/form/form.php +++ b/module/form/form.php @@ -106,6 +106,13 @@ class form extends common { * Configuration */ public function config() { + // Liste des utilisateurs + $userIdsFirstnames = helper::arrayColumn($this->getData(['user']), 'firstname'); + ksort($userIdsFirstnames); + self::$listUsers [] = ''; + foreach($userIdsFirstnames as $userId => $userFirstname) { + self::$listUsers [] = $userId; + } // Soumission du formulaire if($this->isPost()) { // Génération des données vides diff --git a/module/form/view/config/config.js.php b/module/form/view/config/config.js.php index 2d64a2aa..c0873314 100644 --- a/module/form/view/config/config.js.php +++ b/module/form/view/config/config.js.php @@ -78,7 +78,7 @@ function position() { var inputUid = 0; var inputs = getData(['module', $this->getUrl(0), 'input'])); ?>; if(inputs) { - var inputsPerPosition = getData(['module', $this->getUrl(0), 'input']), 'position', 'SORT_ASC')); ?>; + var inputsPerPosition = getData(['module', $this->getUrl(0), 'input']), 'position', 'SORT_ASC')); ?>; $.each(inputsPerPosition, function(id) { add(inputUid, inputs[id]); inputUid++; diff --git a/module/gallery/gallery.php b/module/gallery/gallery.php index ea0fc1d5..c7583fd5 100644 --- a/module/gallery/gallery.php +++ b/module/gallery/gallery.php @@ -320,7 +320,7 @@ class gallery extends common { //Affichage de la galerie triée $g = $this->getData(['module', $this->getUrl(0), 'content']); - $p = helper::arrayCollumn(helper::arrayCollumn($g,'config'),'position'); + $p = helper::arrayColumn(helper::arrayColumn($g,'config'),'position'); asort($p,SORT_NUMERIC); $galleries = []; foreach ($p as $positionId => $item) { @@ -678,7 +678,7 @@ class gallery extends common { else { // Tri des galeries suivant l'ordre défini $g = $this->getData(['module', $this->getUrl(0), 'content']); - $p = helper::arrayCollumn(helper::arrayCollumn($g,'config'),'position'); + $p = helper::arrayColumn(helper::arrayColumn($g,'config'),'position'); asort($p,SORT_NUMERIC); $galleries = []; foreach ($p as $positionId => $item) { diff --git a/module/news/news.php b/module/news/news.php index ab5016f6..3dce3dac 100644 --- a/module/news/news.php +++ b/module/news/news.php @@ -114,8 +114,8 @@ class news extends common { $feeds->setDate(date('r',time())); $feeds->addGenerator(); // Corps des articles - $newsIdsPublishedOns = helper::arrayCollumn($this->getData(['module', $this->getUrl(0), 'posts']), 'publishedOn', 'SORT_DESC'); - $newsIdsStates = helper::arrayCollumn($this->getData(['module', $this->getUrl(0), 'posts']), 'state', 'SORT_DESC'); + $newsIdsPublishedOns = helper::arrayColumn($this->getData(['module', $this->getUrl(0), 'posts']), 'publishedOn', 'SORT_DESC'); + $newsIdsStates = helper::arrayColumn($this->getData(['module', $this->getUrl(0), 'posts']), 'state', 'SORT_DESC'); foreach($newsIdsPublishedOns as $newsId => $newsPublishedOn) { if($newsPublishedOn <= time() AND $newsIdsStates[$newsId]) { $newsArticle = $feeds->createNewItem(); @@ -166,7 +166,7 @@ class news extends common { ]); } // Liste des utilisateurs - self::$users = helper::arrayCollumn($this->getData(['user']), 'firstname'); + self::$users = helper::arrayColumn($this->getData(['user']), 'firstname'); ksort(self::$users); foreach(self::$users as $userId => &$userFirstname) { $userFirstname = $userFirstname . ' ' . $this->getData(['user', $userId, 'lastname']); @@ -290,6 +290,49 @@ class news extends common { 'state' => true ]); } else { + // Ids des news par ordre de publication + $newsIds = array_keys(helper::arrayColumn($this->getData(['module', $this->getUrl(0), 'posts']), 'publishedOn', 'SORT_DESC')); + // Pagination + $pagination = helper::pagination($newsIds, $this->getUrl(),$this->getData(['module', $this->getUrl(0), 'config', 'itemsperPage']) ); + // Liste des pages + self::$pages = $pagination['pages']; + // News en fonction de la pagination + for($i = $pagination['first']; $i < $pagination['last']; $i++) { + // Met en forme le tableau + $dateOn = mb_detect_encoding(strftime('%d %B %Y', $this->getData(['module', $this->getUrl(0),'posts', $newsIds[$i], 'publishedOn'])), 'UTF-8', true) + ? strftime('%d %B %Y', $this->getData(['module', $this->getUrl(0),'posts', $newsIds[$i], 'publishedOn'])) + : utf8_encode(strftime('%d %B %Y', $this->getData(['module', $this->getUrl(0),'posts', $newsIds[$i], 'publishedOn']))); + $dateOn .= ' à '; + $dateOn .= mb_detect_encoding(strftime('%H:%M', $this->getData(['module', $this->getUrl(0),'posts', $newsIds[$i], 'publishedOn'])), 'UTF-8', true) + ? strftime('%H:%M', $this->getData(['module', $this->getUrl(0),'posts', $newsIds[$i], 'publishedOn'])) + : utf8_encode(strftime('%H:%M', $this->getData(['module', $this->getUrl(0),'posts', $newsIds[$i], 'publishedOn']))); + if ($this->getData(['module', $this->getUrl(0),'posts', $newsIds[$i], 'publishedOff'])) { + $dateOff = mb_detect_encoding(strftime('%d %B %Y', $this->getData(['module', $this->getUrl(0),'posts', $newsIds[$i], 'publishedOff'])), 'UTF-8', true) + ? strftime('%d %B %Y', $this->getData(['module', $this->getUrl(0),'posts', $newsIds[$i], 'publishedOff'])) + : utf8_encode(strftime('%d %B %Y', $this->getData(['module', $this->getUrl(0),'posts', $newsIds[$i], 'publishedOff']))); + $dateOff .= ' à '; + $dateOff .= mb_detect_encoding(strftime('%H:%M', $this->getData(['module', $this->getUrl(0),'posts', $newsIds[$i], 'publishedOff'])), 'UTF-8', true) + ? strftime('%H:%M', $this->getData(['module', $this->getUrl(0),'posts', $newsIds[$i], 'publishedOff'])) + : utf8_encode(strftime('%H:%M', $this->getData(['module', $this->getUrl(0),'posts', $newsIds[$i], 'publishedOff']))); + } else { + $dateOff = 'Permanent'; + } + self::$news[] = [ + $this->getData(['module', $this->getUrl(0),'posts', $newsIds[$i], 'title']), + $dateOn, + $dateOff, + self::$states[$this->getData(['module', $this->getUrl(0),'posts', $newsIds[$i], 'state'])], + template::button('newsConfigEdit' . $newsIds[$i], [ + 'href' => helper::baseUrl() . $this->getUrl(0) . '/edit/' . $newsIds[$i]. '/' . $_SESSION['csrf'], + 'value' => template::ico('pencil') + ]), + template::button('newsConfigDelete' . $newsIds[$i], [ + 'class' => 'newsConfigDelete buttonRed', + 'href' => helper::baseUrl() . $this->getUrl(0) . '/delete/' . $newsIds[$i] . '/' . $_SESSION['csrf'], + 'value' => template::ico('cancel') + ]) + ]; + } // Valeurs en sortie $this->addOutput([ 'title' => 'Options de configuration', @@ -381,7 +424,7 @@ class news extends common { ]); } // Liste des utilisateurs - self::$users = helper::arrayCollumn($this->getData(['user']), 'firstname'); + self::$users = helper::arrayColumn($this->getData(['user']), 'firstname'); ksort(self::$users); foreach(self::$users as $userId => &$userFirstname) { $userFirstname = $userFirstname . ' ' . $this->getData(['user', $userId, 'lastname']); @@ -434,8 +477,8 @@ class news extends common { } else { // Affichage index // Ids des news par ordre de publication - $newsIdsPublishedOns = helper::arrayCollumn($this->getData(['module', $this->getUrl(0), 'posts']), 'publishedOn', 'SORT_DESC'); - $newsIdsStates = helper::arrayCollumn($this->getData(['module', $this->getUrl(0), 'posts']), 'state', 'SORT_DESC'); + $newsIdsPublishedOns = helper::arrayColumn($this->getData(['module', $this->getUrl(0), 'posts']), 'publishedOn', 'SORT_DESC'); + $newsIdsStates = helper::arrayColumn($this->getData(['module', $this->getUrl(0), 'posts']), 'state', 'SORT_DESC'); $newsIds = []; foreach($newsIdsPublishedOns as $newsId => $newsPublishedOn) { $newsIdsPublishedOff = $this->getData(['module', $this->getUrl(0), 'posts', $newsId, 'publishedOff']);