nom, 'items' => [ID, ID…] ]. * Les items sont des réalisations ou des articles ; le premier est la carte * de devant dans le paquet. Nom court d'un article sur les cartes : méta `_yb_short_label`. * * Admin : Profil → Compétences (créer / renommer / réordonner / supprimer * des compétences, y ajouter des réalisations et des articles). */ /** Liste prête pour le gabarit : [ nom => [ [post, kind, name, tag, thumb, wipe], … ] ]. */ function yb2026_get_proofs() { $rows = get_option('yb_proofs', array()); $out = array(); foreach ((array) $rows as $row) { $links = array(); foreach ((array) ($row['items'] ?? array()) as $id) { $p = get_post((int) $id); if (!$p || $p->post_status !== 'publish' || !in_array($p->post_type, array('realisation', 'post'), true)) continue; $is_post = $p->post_type === 'post'; $short = $is_post ? (string) get_post_meta($p->ID, '_yb_short_label', true) : ''; $cat = $is_post ? get_the_category($p->ID) : array(); $links[] = array( 'post' => $p, 'kind' => $is_post ? 'article' : 'projet', 'name' => $short !== '' ? $short : yb2026_short_title($p), 'tag' => $is_post ? 'ARTICLE · ' . mb_strtoupper($cat ? $cat[0]->name : 'BLOG') : (string) get_post_meta($p->ID, '_yb_tag', true), 'thumb' => get_the_post_thumbnail_url($p, 'large'), 'wipe' => $is_post ? 'LECTURE' : mb_strtoupper(yb2026_short_title($p)), ); } if ($links && !empty($row['skill'])) $out[$row['skill']] = $links; } return $out; } /* ── Admin ──────────────────────────────────────────────────────────── */ add_action('admin_menu', function () { add_submenu_page('yb-profil', 'Compétences', 'Compétences', 'edit_pages', 'yb-competences', 'yb2026_proofs_page'); }); function yb2026_proofs_page() { $rows = (array) get_option('yb_proofs', array()); $reals = get_posts(array('post_type' => 'realisation', 'post_status' => 'publish', 'numberposts' => -1, 'orderby' => 'title', 'order' => 'ASC')); $arts = get_posts(array('post_type' => 'post', 'post_status' => 'publish', 'numberposts' => -1)); $label = function ($p) { $s = $p->post_type === 'post' ? (string) get_post_meta($p->ID, '_yb_short_label', true) : ''; return ($p->post_type === 'post' ? 'Article · ' : 'Réalisation · ') . ($s !== '' ? $s : yb2026_short_title($p)); }; $all = array(); foreach (array_merge($reals, $arts) as $p) $all[$p->ID] = $label($p); /* Contenus rattachés à aucune compétence : signalés en haut de page */ $used = array(); foreach ($rows as $r) foreach ((array) ($r['items'] ?? array()) as $id) $used[(int) $id] = true; $orphans = array_diff_key($all, $used); $options = function () use ($reals, $arts, $label) { $h = ''; }; $chip = function ($id, $row) use ($all) { return '' . esc_html($all[$id] ?? ('#' . $id)) . ' '; }; ?>
Chaque compétence apparaît sur la page Compétences, dans « Chaque compétence a son projet ». Le premier contenu d'une compétence est la carte de devant ; avec plusieurs contenus, un clic ouvre le menu circulaire.
Compétences enregistrées.
Pas encore rattachés :