wordpress-plugin-to-emdash

Par emdash-cms · emdash

Portez un plugin WordPress vers EmDash CMS. Utilisez cette skill lorsqu'on vous demande de migrer, convertir ou porter un plugin WordPress, une fonctionnalité de thème ou un type de contenu personnalisé vers EmDash. Fournit un mapping de concepts et des patterns d'implémentation.

npx skills add https://github.com/emdash-cms/emdash --skill wordpress-plugin-to-emdash

Porter des plugins WordPress vers EmDash

Cette skill mappe les concepts WordPress à leurs équivalents EmDash pour le portage de plugins. Pour les détails généraux de création de plugins (structure, definePlugin(), hooks, stockage, interface admin, etc.), consultez la skill creating-plugins.

Approche de migration

  1. Comprendre le plugin — Ce qu'il fait, pas comment
  2. Identifier les concepts — Types de contenu, pages admin, hooks, shortcodes
  3. Mapper vers EmDash — Utiliser les tableaux ci-dessous
  4. Implémenter en TypeScript — Partant de zéro, pas une portage ligne par ligne. Consultez la skill creating-plugins pour les détails d'implémentation.
  5. Tester le comportement — Même résultat, implémentation différente

Mappage des concepts

Contenu et données

WordPress EmDash Notes
register_post_type() SchemaRegistry.createCollection() Via Admin API ou fichier seed
register_taxonomy() Table _emdash_taxonomy_defs Hiérarchique ou plate, attachée aux collections
register_meta() / ACF Champs de collection via SchemaRegistry Tous deviennent des champs de schéma typés
get_post_meta() entry.data.fieldName Accès typé direct
get_option() getSiteSetting() / ctx.kv Paramètres du site ou KV nommacé par plugin
WP_Query getEmDashCollection() Requêtes d'exécution avec filtres
get_post($id) getEmDashEntry(collection, slug) Retourne entry ou null
wp_insert_post() POST /_emdash/api/content/{type} API REST
wp_update_post() PUT /_emdash/api/content/{type}/{id} API REST
wp_delete_post() DELETE /_emdash/api/content/{type}/{id} Suppression logicielle
Tables personnalisées Collections de stockage de plugin ctx.storage.collectionName.put/get/query

Configuration du site

WordPress EmDash Notes
get_bloginfo('name') getSiteSetting('title') Depuis la table options avec préfixe site:
get_option('blogdesc') getSiteSetting('tagline') API des paramètres du site
Personnalisateur de thème Page admin Paramètres du site /_emdash/admin/settings
site_icon getSiteSetting('favicon') Référence média
custom_logo getSiteSetting('logo') Référence média

Menus de navigation

WordPress EmDash Notes
register_nav_menu() Créer un menu via admin ou seed Table _emdash_menus
wp_nav_menu() getMenu(name) Retourne { items: MenuItem[] }
wp_nav_menu_item Table _emdash_menu_items Type : custom, page, post, taxonomy
_menu_item_object_id reference_id + reference_collection Liens vers entries de contenu
Emplacements de menu Requête par nom dans les templates Aucun concept d'emplacements — requête directe

Taxonomies

WordPress EmDash Notes
register_taxonomy() Table _emdash_taxonomy_defs Définir via admin, seed, ou API
get_terms() getTaxonomyTerms(name) Retourne l'arborescence pour hiérarchique
get_the_terms() getEntryTerms(collection, id, name) Termes pour entry spécifique
wp_set_post_terms() TaxonomyRepository.setTermsForEntry() Remplacer termes pour entry
Taxonomie hiérarchique hierarchical: true dans définition Style catégories
Taxonomie plate hierarchical: false Style tags

Widgets et barres latérales

WordPress EmDash Notes
register_sidebar() Table _emdash_widget_areas Créer via admin ou seed
dynamic_sidebar() getWidgetArea(name) Retourne { widgets: Widget[] }
Classe WP_Widget Types de widget : content, menu, component Simplifié — 3 types seulement
Widget texte type: 'content' + Portable Text Widget de texte enrichi
Widget Menu Nav type: 'menu' + menuName Référence un menu
Widgets personnalisés type: 'component' + componentId Composants enregistrés par plugin

Interface admin

WordPress EmDash Notes
add_menu_page() admin.pages dans definePlugin() Configuration du plugin
add_submenu_page() Pages admin imbriquées Le parent détermine la hiérarchie
add_settings_section() admin.settingsSchema Page de paramètres auto-générée
add_meta_box() Groupes de champs dans schéma collection Configuration UI dans schéma
wp_enqueue_script() Imports ESM dans composants admin React (approuvé) ou Block Kit (sandboxé)
Avis admin Notifications toast Via framework interface admin

Hooks

WordPress EmDash Notes
add_action('init') Hook plugin:install S'exécute une fois à la première installation
add_action('save_post') Hook content:afterSave Filtrer par event.collection
add_action('before_delete_post') Hook content:beforeDelete Retourner false pour empêcher
add_action('wp_head') Hook page:metadata / page:fragments Les métadonnées sont sandbox-safe ; scripts approuvés seulement
add_action('rest_api_init') definePlugin({ routes }) Approuvé uniquement
add_filter('the_content') Composants Portable Text Renderers de bloc personnalisés
add_filter('the_title') Logique de template Gérer dans composant Astro

Sortie frontale

WordPress EmDash Notes
add_shortcode() Bloc personnalisé Portable Text Contenu → bloc. Template → composant. Approuvé seulement.
register_block_type() Bloc PT + componentsEntry Données bloc → props composant Astro. Approuvé seulement.
Tags de template Expressions Astro get_the_title(){post.data.title}
Widgets Zone widget + composants Requête avec getWidgetArea()

Stockage de plugin

WordPress EmDash Notes
get_option('plugin_*') ctx.kv.get(key) Automatiquement nommacé par plugin
update_option() ctx.kv.set(key, value) Stockage KV scoped
delete_option() ctx.kv.delete(key) Supprimer une clé simple
Tables personnalisées ctx.storage.collection Collections de documents avec index
Transients KV de plugin Pas de TTL pour l'instant

Modèles spécifiques au portage

Ces modèles couvrent des concepts spécifiques à WordPress qui n'ont pas de mappage 1:1 direct. Pour les modèles généraux de plugin (définir hooks, stockage, routes, interface admin), consultez la skill creating-plugins.

Shortcodes → Blocs Portable Text

Les shortcodes WordPress ([youtube id="xxx"]) deviennent des types de bloc personnalisé Portable Text. Les données de bloc remplacent les attributs du shortcode, et un composant Astro remplace la fonction de rendu du shortcode. C'est une fonction approuvée uniquement.

// WordPress
add_shortcode('youtube', function($atts) {
    return '<iframe src="https://youtube.com/embed/' . $atts['id'] . '"></iframe>';
});

// EmDash — déclaration de type de bloc dans definePlugin()
admin: {
    portableTextBlocks: [{
        type: "youtube",
        label: "YouTube Video",
        icon: "video",
        fields: [
            { type: "text_input", action_id: "id", label: "YouTube URL" },
            { type: "text_input", action_id: "title", label: "Title" },
        ],
    }],
}

// EmDash — composant Astro pour rendu
// src/astro/YouTube.astro
const { id, title } = Astro.props.node;
const videoId = id?.match(/(?:v=|youtu\.be\/)([^&]+)/)?.[1] ?? id;
// <iframe src={`https://youtube-nocookie.com/embed/${videoId}`} ... />

Options API → KV de plugin

L'API get_option/update_option de WordPress mappe vers le stockage KV du plugin. La différence clé : les options WordPress sont globales, le KV d'EmDash est automatiquement scoped au plugin.

// WordPress
$count = get_option("myplugin_post_count", 0);
update_option("myplugin_post_count", $count + 1);
delete_option("myplugin_temp_data");

// EmDash — pas de préfixe nécessaire, automatiquement scoped
const count = (await ctx.kv.get<number>("post-count")) ?? 0;
await ctx.kv.set("post-count", count + 1);
await ctx.kv.delete("temp-data");

Tables de base de données personnalisées → Collections de stockage

Les plugins WordPress qui créent des tables personnalisées avec $wpdb->query("CREATE TABLE ...") doivent utiliser les collections de stockage EmDash à la place. Aucune migration nécessaire — déclarez le schéma dans definePlugin() et il est automatiquement provisionné.

// WordPress
$wpdb->insert($table, ['form_id' => $id, 'data' => json_encode($data), 'created_at' => current_time('mysql')]);
$results = $wpdb->get_results("SELECT * FROM $table WHERE form_id = '$id' ORDER BY created_at DESC LIMIT 50");

// EmDash — déclaré dans definePlugin()
storage: {
    submissions: {
        indexes: ["formId", "createdAt", ["formId", "createdAt"]],
    },
},

// Dans un hook ou gestionnaire de route
await ctx.storage.submissions!.put(entryId, { formId, data, createdAt: new Date().toISOString() });
const result = await ctx.storage.submissions!.query({
    where: { formId },
    orderBy: { createdAt: "desc" },
    limit: 50,
});

Ensemencement de données (remplace contenu de démarrage, configuration de thème)

Les plugins WordPress qui appellent wp_insert_term(), register_nav_menu(), ou insèrent du contenu par défaut à l'activation doivent utiliser un fichier seed :

{
    "version": "1",
    "settings": { "title": "My Site", "tagline": "Welcome" },
    "taxonomies": [
        {
            "name": "category",
            "label": "Categories",
            "hierarchical": true,
            "collections": ["posts"],
            "terms": [
                { "slug": "news", "label": "News" },
                { "slug": "tutorials", "label": "Tutorials" }
            ]
        }
    ],
    "menus": [
        {
            "name": "primary",
            "label": "Primary Navigation",
            "items": [
                { "type": "custom", "label": "Home", "url": "/" },
                { "type": "page", "ref": "about", "collection": "pages" }
            ]
        }
    ],
    "redirects": [
        { "source": "/?p=123", "destination": "/about" },
        { "source": "/old-contact", "destination": "/contact", "type": 301 }
    ]
}

Enregistrez dans .emdash/seed.json (ou connectez via package.json#emdash.seed) ; le runtime l'applique au prochain démarrage initial quand la base de données est vide.

Utilisez redirects pour les URLs WordPress héritées qui reçoivent encore du trafic après migration.

Interrogation de contenu (remplace WP_Query)

// WordPress
$query = new WP_Query(['post_type' => 'post', 'category_name' => 'tech', 'posts_per_page' => 10]);

// EmDash — dans frontmatter de composant Astro
import { getEmDashCollection, getEntryTerms } from "emdash";
const { entries } = await getEmDashCollection("posts", {
    where: { category: "technology" },
    limit: 10,
});

Menus (remplace wp_nav_menu)

// WordPress
wp_nav_menu(['theme_location' => 'primary']);

// EmDash — dans composant Astro
import { getMenu } from "emdash";
const nav = await getMenu("primary");
// nav.items[].label, nav.items[].url, nav.items[].children

Zones de widgets (remplace dynamic_sidebar)

// WordPress
dynamic_sidebar("sidebar-1");

// EmDash — dans composant Astro
import { getWidgetArea } from "emdash";
const sidebar = await getWidgetArea("sidebar");
// sidebar.widgets[].type: "content" | "menu" | "component"

Signaux d'alerte (Nécessite décision humaine)

Signaler ces éléments pour révision — ils peuvent nécessiter des décisions architecturales :

  1. Intégration profonde WP — Hooks dans les fonctionnalités du noyau WP absentes d'EmDash
  2. Dépendances de thème — Suppose une structure de thème spécifique
  3. Fonctionnalités multisite — Non supportées
  4. WP_Query complexe — Les requêtes de métadonnées peuvent nécessiter une implémentation personnalisée
  5. SQL direct — Le schéma diffère, utiliser Kysely ou stockage de plugin
  6. Abus de session/transient — Nécessite une couche de cache appropriée
  7. Vérifications de capacité utilisateur — Réviser mappage de rôles (futur)
  8. Buffering ob_start() — Modèle PHP, repenser pour le streaming
  9. Tâches Cronwp_schedule_event() n'a pas d'équivalent direct ; nécessite cron de plateforme

Format de sortie

Lors du portage d'un plugin, fournir :

  1. Analyse — Ce que fait le plugin WP (concepts, pas code)
  2. Mappage de concepts — Quels concepts WP mappent vers quelles fonctionnalités EmDash
  3. Code de pluginsrc/descriptor.ts et src/index.ts (utiliser skill creating-plugins pour structure)
  4. Données seed — Si le plugin a besoin de taxonomies/menus/widgets par défaut
  5. Composants Astro — Pour sortie frontale
  6. Signaux d'alerte — Tout ce qui nécessite une décision humaine

Skills similaires