JFIF $ d d 7 * Z qn )ZP 0 !1 A "#a$2Qr D8 a Ri [f \m I ykI w0 c u F c Rı?lO7 к _f˓ [C $殷WF< _W ԣ s Kc ëI zyQy /_LK ℂ ;C",p F A : /] =H ~ , l s / 9 ć: [=/#f ; ) x { ٛE Q )~ = 𘙲r*2~ a _V = ' ku m F D } KYYC )( { * g& f `툪 r y ` = ^ c J. I ]( * `wq 1dđ #̩ ͑ 0 ; H ] u 搂 @:~ ו K L N s h } O I R* 8 :2 ! lD JV o ( 3 = M ( z Ȱ+i *N A r6K n S l ) ! J J Ӂ* % ݉?|D } d5: eP0 R; {$X' x F @ .ÊB {,WJ uQ ɲRI ;9 Q E琯 6 2fT .DU J ;*c P A\IL Nj! J ۱+ O\ ͔ ] ޒ S J ȧ c%A N ol ՎprU L Zԛe r E2= X D Xg VQeӓ k y P7 U* o m Q I s ,K `) 6\G3t?pgjr m ۛجw luGt f h 9uyP 0D;Uڽ"OXl i f $ ) &|ML 0 Z rm1 [ H XP l P R0 'G=i 2N +0 e 2 ]] 9 VT P O 7 h(F * 癈 ' = Q VZD F,d ߬ ~ T X G[ `le 69C R(!S2! P < 0 x < !1AQ "Raq 02Br #S CTb ? Ζ "]mH5WR 7 k.ۛ ! } Q~ + yԏ z |@ T20 S~ K e k *zF f^2X *( @ 8 r ? C I uI|֓>^Ex LgNU Y+{.R Ѫ τV YT D I 6 2 '8Y2 7'\T P.6 d &˦ @V q i |8 -O Ε ] ʔ U= T L 8= ;6c | !qfF3 a ů& ~$ l} 'NW U s$U k^S V : U#6w + +s &r+n ڐ { @ 29gL u " T Ù M=6 (^ "7 r}=6Yݾ lC u hquymp Ǧ G jhs ǜNl ɻ} o 7 #S6 a w 4 ! OS r D 5 7 % | ?x> L | / nD 6?/8 w # [ ) L 7 +6〼T A T g ! %5 Mm Z /c -{1_Je "| ^$ 'O & ޱմ < H vNqϡQ$ < 6 &Nݛ ֨tǻN (9 n ru~'όN sMG& ,uH Kw *Ī 5@ u6 BԒ i YN * f 0 _ GhKW u lT <nj- 0{ M L~ | /a v\ E = ?1 \ɟuq Ђ Y O a K ޡP q $ H8o Q˼EV ~ k 0 h' L Pp M -M" m^ !6l nմ 쮝C U T . ! :vMǨb h ډ Vc r @~p # !1QAa q ? AL0L x LU 4 d ; x " 16ad0 7.\ߋ 0 = P l v/ " c A Ay A|2pO8"d MV #1] = \ " ˡ ] k v I9 d ۓ & q ) ǐq E ꞅ v "P )q X &Q З non]я u ג./ ; gZ$ M QР 2M ]h ni 0 P $ێ 3CɏGjώy : m c # S_ l@ '_ \m|C 2`K _ 1 cIvGc $? PCQ S+D ? K aײ k Fr b 8 ύ NEدg ĝ U 3 6 #Ik+ v { v i ( ވ ? a e) X xy/*@Q Ǽ Ծ ) $ IWO l c G; !i k{ gOŀ L ('x T rb $ w) R $ & N1E td U3Uȉ1p M"N* (DNy d96.(jQ) X 5 c QɎMy W ? Q *!R > 6=7)Xj 5`J ] e 8%t ! + ' ! 1Q 5 !1 AQaq ё #2 "0BRb ? G t^ ## .l lQ T $ v , ,m 㵜5u bV =sY+ @d { N ! dn O < .- B; _w J t 6;Q Jd. Q c%p{ 1 ,sND dF H I0 Гo X ш e黅X ۢ F :)[ F G X ƹ / w _c MeD ,ʡc c . W D tA $ j@ : ) - #u c1< @ۗ9F ) KJ- hpP] _ x [ q B lb p ʖ w q " LFGd ƶ * s +ډ_Zc " ? % t[I P 6 J ]# =ɺ V v v CGs Gh1 > )6 |e y ? L ӣ m,4 G W Ui ` ] uJVo VDG< SB 6ϏQ @ TiU l y O U 0 kfV ~ ~}S Z @ *WU Ui ## ; s /[ = ! 7}" W N ] ' (L ! ~ y5 g9T̅J kbM' +s :S +B) v @ M j e C f j E 0 Y\Qn z G 1 д~ W o{T 9?` Rm yhsy3 !HAD ] m c1 ~ 2 L S u7x T ;j$ `} 4-> L# vzŏ I L S ֭ T { r jGK C ; b pU= - ` Bs K. S F w4 M q] Z dH S 0 ) tLg
<?php
if ( ! defined( 'ABSPATH' ) ) exit;
// ─────────────────────────────────────────────
// Sous-menu : Mise en page
// ─────────────────────────────────────────────
// ─────────────────────────────────────────────
// Valeurs par défaut globales
// ─────────────────────────────────────────────
function cet_layout_defaults() {
return array(
'max_width' => '1200px',
'width' => '100%',
'margin_top' => '0',
'margin_bottom'=> '0',
'margin_left' => 'auto',
'margin_right' => 'auto',
'padding_top' => '2rem',
'padding_bottom'=> '2rem',
'padding_left' => '1.5rem',
'padding_right'=> '1.5rem',
'gap' => '2rem',
'sidebar_width'=> '300px',
);
}
// ─────────────────────────────────────────────
// Page de réglages Mise en page
// ─────────────────────────────────────────────
function cet_render_layout_settings_form() {
cet_render_layout_settings_page_inner();
}
function cet_render_layout_settings_page() {
echo '<div class="wrap" style="max-width:820px;"><h1>Mise en page</h1>';
cet_render_layout_settings_page_inner();
echo '</div>';
}
function cet_render_layout_settings_page_inner() {
if ( isset( $_POST['cet_layout_nonce'] ) &&
wp_verify_nonce( $_POST['cet_layout_nonce'], 'cet_save_layout' ) &&
current_user_can( 'manage_options' ) ) {
$fields = array_keys( cet_layout_defaults() );
$global = array();
foreach ( $fields as $key ) {
$val = isset( $_POST[ 'cet_layout_' . $key ] )
? sanitize_text_field( $_POST[ 'cet_layout_' . $key ] )
: '';
$global[ $key ] = $val;
}
update_option( 'cet_layout_global', $global );
echo '<div class="notice notice-success is-dismissible"><p>Réglages de mise en page enregistrés.</p></div>';
}
$defaults = cet_layout_defaults();
$global = wp_parse_args( (array) get_option( 'cet_layout_global', array() ), $defaults );
// Récupère tous les gabarits de type wrapper pour les surcharges
$wrappers = get_posts( array(
'post_type' => 'cet_template',
'posts_per_page' => -1,
'post_status' => 'publish',
'meta_query' => array(
array( 'key' => '_cet_template_type', 'value' => 'wrapper' ),
),
) );
?>
<div class="wrap" style="max-width:820px;">
<h1>Mise en page</h1>
<p>Définissez les espacements globaux appliqués à tous les gabarits, puis surchargez par gabarit si nécessaire. Les valeurs acceptent toutes les unités CSS : <code>px</code>, <code>em</code>, <code>rem</code>, <code>%</code>, <code>auto</code>.</p>
<style>
.cet-lp-section { background:#fff; border:1px solid #ddd; border-radius:6px; margin-bottom:20px; }
.cet-lp-head { padding:12px 18px; background:#f9f9f9; border-bottom:1px solid #eee; font-size:14px; font-weight:600; display:flex; align-items:center; justify-content:space-between; cursor:pointer; }
.cet-lp-head:hover { background:#f0f0f0; }
.cet-lp-body { padding:18px 20px; }
.cet-lp-grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(220px,1fr)); gap:12px 20px; margin-bottom:16px; }
.cet-lp-field { display:flex; flex-direction:column; gap:4px; }
.cet-lp-field label { font-size:12px; font-weight:600; color:#555; }
.cet-lp-field input { border:1px solid #ddd; border-radius:4px; padding:5px 8px; font-size:13px; font-family:monospace; }
.cet-lp-field input:focus { border-color:#2271b1; outline:none; box-shadow:0 0 0 1px #2271b1; }
.cet-lp-group-title { font-size:11px; font-weight:600; color:#888; text-transform:uppercase; letter-spacing:.04em; margin:14px 0 8px; border-top:1px solid #f0f0f0; padding-top:12px; }
.cet-lp-preview { background:#f6f6f6; border:1px dashed #ccc; border-radius:4px; padding:10px 14px; font-size:12px; color:#666; margin-top:8px; font-family:monospace; }
</style>
<form method="post">
<?php wp_nonce_field( 'cet_save_layout', 'cet_layout_nonce' ); ?>
<!-- Réglages globaux -->
<div class="cet-lp-section">
<div class="cet-lp-head" onclick="this.nextElementSibling.style.display=this.nextElementSibling.style.display===\'none\'?\'block\':\'none\'">
<span>🌐 Réglages globaux <small style="font-weight:400;color:#888;">— s\'appliquent à tous les gabarits</small></span>
<span>▼</span>
</div>
<div class="cet-lp-body">
<div class="cet-lp-group-title">Dimensions</div>
<div class="cet-lp-grid">
<?php cet_lp_field( 'cet_layout_width', 'Largeur', $global['width'], 'ex: 100%, 960px' ); ?>
<?php cet_lp_field( 'cet_layout_max_width', 'Largeur maximale', $global['max_width'], 'ex: 1200px, 90rem' ); ?>
<?php cet_lp_field( 'cet_layout_gap', 'Gouttiere (gap)', $global['gap'], 'ex: 2rem, 30px' ); ?>
<?php cet_lp_field( 'cet_layout_sidebar_width', 'Largeur sidebar', $global['sidebar_width'], 'ex: 300px, 25%' ); ?>
</div>
<div class="cet-lp-group-title">Marges externes (margin)</div>
<div class="cet-lp-grid">
<?php cet_lp_field( 'cet_layout_margin_top', 'Haut', $global['margin_top'], 'ex: 0, 2rem' ); ?>
<?php cet_lp_field( 'cet_layout_margin_bottom', 'Bas', $global['margin_bottom'], 'ex: 0, 2rem' ); ?>
<?php cet_lp_field( 'cet_layout_margin_left', 'Gauche', $global['margin_left'], 'ex: auto, 0' ); ?>
<?php cet_lp_field( 'cet_layout_margin_right', 'Droite', $global['margin_right'], 'ex: auto, 0' ); ?>
</div>
<div class="cet-lp-group-title">Espacement interne (padding)</div>
<div class="cet-lp-grid">
<?php cet_lp_field( 'cet_layout_padding_top', 'Haut', $global['padding_top'], 'ex: 2rem, 40px' ); ?>
<?php cet_lp_field( 'cet_layout_padding_bottom', 'Bas', $global['padding_bottom'], 'ex: 2rem, 40px' ); ?>
<?php cet_lp_field( 'cet_layout_padding_left', 'Gauche', $global['padding_left'], 'ex: 1.5rem, 20px' ); ?>
<?php cet_lp_field( 'cet_layout_padding_right', 'Droite', $global['padding_right'], 'ex: 1.5rem, 20px' ); ?>
</div>
<div class="cet-lp-preview" id="cet-global-preview"></div>
</div>
</div>
<?php submit_button( 'Enregistrer la mise en page' ); ?>
</form>
<!-- Surcharges par gabarit -->
<?php if ( ! empty( $wrappers ) ) : ?>
<h2 style="font-size:15px;margin:28px 0 12px;">Surcharges par gabarit</h2>
<p style="color:#666;font-size:13px;margin-bottom:16px;">Laissez un champ vide pour utiliser la valeur globale.</p>
<form method="post">
<?php wp_nonce_field( 'cet_save_layout', 'cet_layout_nonce' ); ?>
<?php foreach ( $wrappers as $wrapper ) :
$overrides = (array) get_post_meta( $wrapper->ID, '_cet_layout_overrides', true );
$vals = wp_parse_args( $overrides, array_fill_keys( array_keys( $defaults ), '' ) );
?>
<div class="cet-lp-section">
<div class="cet-lp-head" onclick="this.nextElementSibling.style.display=this.nextElementSibling.style.display===\'none\'?\'block\':\'none\'">
<span>⬜ <?php echo esc_html( $wrapper->post_title ); ?> <small style="font-weight:400;color:#888;">#<?php echo $wrapper->ID; ?></small></span>
<span>▼</span>
</div>
<div class="cet-lp-body" style="display:none;">
<div class="cet-lp-group-title">Dimensions</div>
<div class="cet-lp-grid">
<?php cet_lp_override_field( $wrapper->ID, 'width', 'Largeur', $vals['width'], 'ex: 100%' ); ?>
<?php cet_lp_override_field( $wrapper->ID, 'max_width', 'Largeur maximale', $vals['max_width'], 'ex: 1200px' ); ?>
<?php cet_lp_override_field( $wrapper->ID, 'gap', 'Gouttiere', $vals['gap'], 'ex: 2rem' ); ?>
<?php cet_lp_override_field( $wrapper->ID, 'sidebar_width', 'Largeur sidebar', $vals['sidebar_width'], 'ex: 300px' ); ?>
</div>
<div class="cet-lp-group-title">Marges externes</div>
<div class="cet-lp-grid">
<?php cet_lp_override_field( $wrapper->ID, 'margin_top', 'Haut', $vals['margin_top'], '' ); ?>
<?php cet_lp_override_field( $wrapper->ID, 'margin_bottom', 'Bas', $vals['margin_bottom'], '' ); ?>
<?php cet_lp_override_field( $wrapper->ID, 'margin_left', 'Gauche', $vals['margin_left'], '' ); ?>
<?php cet_lp_override_field( $wrapper->ID, 'margin_right', 'Droite', $vals['margin_right'], '' ); ?>
</div>
<div class="cet-lp-group-title">Espacement interne</div>
<div class="cet-lp-grid">
<?php cet_lp_override_field( $wrapper->ID, 'padding_top', 'Haut', $vals['padding_top'], '' ); ?>
<?php cet_lp_override_field( $wrapper->ID, 'padding_bottom', 'Bas', $vals['padding_bottom'], '' ); ?>
<?php cet_lp_override_field( $wrapper->ID, 'padding_left', 'Gauche', $vals['padding_left'], '' ); ?>
<?php cet_lp_override_field( $wrapper->ID, 'padding_right', 'Droite', $vals['padding_right'], '' ); ?>
</div>
<p style="margin-top:12px;">
<button type="submit" name="cet_save_override" value="<?php echo $wrapper->ID; ?>" class="button button-primary">
Enregistrer pour ce gabarit
</button>
<button type="submit" name="cet_reset_override" value="<?php echo $wrapper->ID; ?>" class="button" style="margin-left:8px;">
Revenir aux valeurs globales
</button>
</p>
</div>
</div>
<?php endforeach; ?>
</form>
<?php endif; ?>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
function updatePreview() {
var fields = ['width','max_width','margin_top','margin_bottom','margin_left','margin_right',
'padding_top','padding_bottom','padding_left','padding_right','gap','sidebar_width'];
var parts = [];
fields.forEach(function(k) {
var el = document.querySelector('[name="cet_layout_' + k + '"]');
if (el && el.value) parts.push(k.replace(/_/g,'-') + ': ' + el.value);
});
var p = document.getElementById('cet-global-preview');
if (p) p.textContent = '.cet-wrapper-layout {\n ' + parts.join(';\n ') + ';\n}';
}
document.querySelectorAll('[name^="cet_layout_"]').forEach(function(el) {
el.addEventListener('input', updatePreview);
});
updatePreview();
});
</script>
<?php
}
// Sauvegarde des surcharges par gabarit
function cet_save_layout_overrides() {
if ( ! isset( $_POST['cet_layout_nonce'] ) ||
! wp_verify_nonce( $_POST['cet_layout_nonce'], 'cet_save_layout' ) ||
! current_user_can( 'manage_options' ) ) return;
// Reset
if ( isset( $_POST['cet_reset_override'] ) ) {
$wrapper_id = absint( $_POST['cet_reset_override'] );
delete_post_meta( $wrapper_id, '_cet_layout_overrides' );
return;
}
// Save
if ( isset( $_POST['cet_save_override'] ) ) {
$wrapper_id = absint( $_POST['cet_save_override'] );
$keys = array_keys( cet_layout_defaults() );
$overrides = array();
foreach ( $keys as $key ) {
$val = isset( $_POST[ 'cet_override_' . $wrapper_id . '_' . $key ] )
? sanitize_text_field( $_POST[ 'cet_override_' . $wrapper_id . '_' . $key ] )
: '';
if ( $val !== '' ) $overrides[ $key ] = $val;
}
update_post_meta( $wrapper_id, '_cet_layout_overrides', $overrides );
}
}
add_action( 'admin_init', 'cet_save_layout_overrides' );
// ─────────────────────────────────────────────
// Helpers champs admin
// ─────────────────────────────────────────────
function cet_lp_field( $name, $label, $value, $placeholder = '' ) {
?>
<div class="cet-lp-field">
<label><?php echo esc_html( $label ); ?></label>
<input type="text" name="<?php echo esc_attr( $name ); ?>"
value="<?php echo esc_attr( $value ); ?>"
placeholder="<?php echo esc_attr( $placeholder ); ?>">
</div>
<?php
}
function cet_lp_override_field( $wrapper_id, $key, $label, $value, $placeholder = '' ) {
$name = 'cet_override_' . $wrapper_id . '_' . $key;
?>
<div class="cet-lp-field">
<label><?php echo esc_html( $label ); ?></label>
<input type="text" name="<?php echo esc_attr( $name ); ?>"
value="<?php echo esc_attr( $value ); ?>"
placeholder="<?php echo esc_attr( $placeholder ?: '(global)' ); ?>">
</div>
<?php
}
// ─────────────────────────────────────────────
// Résolution des valeurs CSS pour un wrapper donné
// Priorité : surcharge gabarit > global > défaut
// ─────────────────────────────────────────────
function cet_get_layout_css( $wrapper_id = 0 ) {
$defaults = cet_layout_defaults();
$global = wp_parse_args( (array) get_option( 'cet_layout_global', array() ), $defaults );
$overrides = $wrapper_id ? (array) get_post_meta( $wrapper_id, '_cet_layout_overrides', true ) : array();
$resolved = array();
foreach ( $defaults as $key => $default ) {
if ( isset( $overrides[ $key ] ) && $overrides[ $key ] !== '' ) {
$resolved[ $key ] = $overrides[ $key ];
} elseif ( isset( $global[ $key ] ) && $global[ $key ] !== '' ) {
$resolved[ $key ] = $global[ $key ];
} else {
$resolved[ $key ] = $default;
}
}
return $resolved;
}
// ─────────────────────────────────────────────
// Injection du CSS wrapper dans le <head>
// Remplace les valeurs en dur de hooks.php
// ─────────────────────────────────────────────
function cet_inject_layout_css() {
if ( ! is_singular() && ! is_archive() && ! is_home() ) return;
// Détermine le wrapper actif
$wrapper_id = 0;
if ( is_singular() ) {
$wrappers = (array) get_option( 'cet_wrappers', array() );
$cfg = $wrappers[ get_post_type() ] ?? array();
$default = is_array( $cfg ) ? (int) ( $cfg['default'] ?? 0 ) : (int) $cfg;
$overrides = is_array( $cfg ) ? (array) ( $cfg['overrides'] ?? array() ) : array();
$post_id = get_the_ID();
$wrapper_id = array_key_exists( $post_id, $overrides ) ? (int) $overrides[ $post_id ] : $default;
} elseif ( is_home() || is_category() || is_tag() || is_tax() ) {
$tax_wrappers = (array) get_option( 'cet_tax_wrappers', array() );
$key = is_home() ? '__blog__' : ( get_queried_object()->taxonomy ?? '' );
$cfg = $tax_wrappers[ $key ] ?? array();
$wrapper_id = is_array( $cfg ) ? (int) ( $cfg['default'] ?? 0 ) : (int) $cfg;
}
if ( ! $wrapper_id ) return;
$v = cet_get_layout_css( $wrapper_id );
?>
<style id="cet-wrapper-layout">
.cet-wrapper-layout {
display: grid;
width: <?php echo esc_attr( $v['width'] ); ?>;
max-width: <?php echo esc_attr( $v['max_width'] ); ?>;
margin: <?php echo esc_attr( $v['margin_top'] ); ?> <?php echo esc_attr( $v['margin_right'] ); ?> <?php echo esc_attr( $v['margin_bottom'] ); ?> <?php echo esc_attr( $v['margin_left'] ); ?>;
padding: <?php echo esc_attr( $v['padding_top'] ); ?> <?php echo esc_attr( $v['padding_right'] ); ?> <?php echo esc_attr( $v['padding_bottom'] ); ?> <?php echo esc_attr( $v['padding_left'] ); ?>;
gap: <?php echo esc_attr( $v['gap'] ); ?>;
align-items: start;
}
.cet-layout-right { grid-template-columns: 1fr <?php echo esc_attr( $v['sidebar_width'] ); ?>; grid-template-areas: "main sidebar"; }
.cet-layout-left { grid-template-columns: <?php echo esc_attr( $v['sidebar_width'] ); ?> 1fr; grid-template-areas: "sidebar main"; }
.cet-layout-full { grid-template-columns: 1fr; grid-template-areas: "main"; }
.cet-main-content { grid-area: main; min-width: 0; }
.cet-sidebar { grid-area: sidebar; min-width: 0; }
@media (max-width: 768px) {
.cet-wrapper-layout {
grid-template-columns: 1fr !important;
grid-template-areas: "main" "sidebar" !important;
padding-left: 1rem;
padding-right: 1rem;
}
}
</style>
<?php
}
add_action( 'wp_head', 'cet_inject_layout_css', 25 );