__( 'Strains', 'weedops' ), 'labels' => [ 'name' => __( 'Strains', 'weedops' ), 'singular_name' => __( 'Strain', 'weedops' ), 'add_new' => __( 'Add New', 'weedops' ), 'add_new_item' => __( 'Add New Strain', 'weedops' ), 'edit_item' => __( 'Edit Strain', 'weedops' ), 'new_item' => __( 'New Strain', 'weedops' ), 'view_item' => __( 'View Strain', 'weedops' ), 'search_items' => __( 'Search Strains', 'weedops' ), 'not_found' => __( 'No strains found', 'weedops' ), 'not_found_in_trash' => __( 'No strains in trash', 'weedops' ), 'menu_name' => __( 'Strains', 'weedops' ), ], 'public' => true, 'show_ui' => true, 'show_in_menu' => true, 'show_in_rest' => true, 'rest_base' => 'strains', 'menu_icon' => 'dashicons-palmtree', 'supports' => [ 'title', 'editor', 'thumbnail', 'excerpt', 'custom-fields', 'revisions' ], 'has_archive' => true, 'rewrite' => [ 'slug' => 'strains', 'with_front' => false ], 'capability_type' => 'post', 'map_meta_cap' => true, ] ); // ── Cannabis Products ───────────────────────────────────────────────────── register_post_type( 'wo_product', [ 'label' => __( 'Cannabis Products', 'weedops' ), 'labels' => [ 'name' => __( 'Cannabis Products', 'weedops' ), 'singular_name' => __( 'Cannabis Product', 'weedops' ), 'add_new_item' => __( 'Add New Product', 'weedops' ), 'edit_item' => __( 'Edit Product', 'weedops' ), 'not_found' => __( 'No products found', 'weedops' ), ], 'public' => true, 'show_in_rest' => true, 'rest_base' => 'cannabis-products', 'supports' => [ 'title', 'editor', 'thumbnail', 'excerpt', 'custom-fields' ], 'menu_icon' => 'dashicons-archive', 'has_archive' => true, 'rewrite' => [ 'slug' => 'products', 'with_front' => false ], 'capability_type' => 'post', ] ); // ── Compliance Records ──────────────────────────────────────────────────── register_post_type( 'wo_compliance', [ 'label' => __( 'Compliance Records', 'weedops' ), 'labels' => [ 'name' => __( 'Compliance Records', 'weedops' ), 'singular_name' => __( 'Compliance Record', 'weedops' ), 'add_new_item' => __( 'Add Record', 'weedops' ), ], 'public' => false, 'show_ui' => true, 'show_in_menu' => true, 'show_in_rest' => true, 'rest_base' => 'compliance', 'supports' => [ 'title', 'custom-fields' ], 'menu_icon' => 'dashicons-shield', 'capability_type' => 'post', ] ); // ── Dispensaries / Locations ────────────────────────────────────────────── register_post_type( 'wo_dispensary', [ 'label' => __( 'Dispensaries', 'weedops' ), 'public' => true, 'show_in_rest' => true, 'rest_base' => 'dispensaries', 'supports' => [ 'title', 'editor', 'thumbnail', 'custom-fields' ], 'menu_icon' => 'dashicons-location-alt', 'has_archive' => true, 'rewrite' => [ 'slug' => 'dispensaries', 'with_front' => false ], ] ); } add_action( 'init', 'weedops_register_post_types' ); // ───────────────────────────────────────────────────────────────────────────── // Taxonomies // ───────────────────────────────────────────────────────────────────────────── function weedops_register_taxonomies(): void { // ── Strain Type: indica / sativa / hybrid / cbd ─────────────────────────── register_taxonomy( 'wo_strain_type', [ 'wo_strain', 'wo_product' ], [ 'label' => __( 'Strain Type', 'weedops' ), 'labels' => [ 'name' => __( 'Strain Types', 'weedops' ), 'singular_name' => __( 'Strain Type', 'weedops' ), 'add_new_item' => __( 'Add Strain Type', 'weedops' ), 'search_items' => __( 'Search Types', 'weedops' ), ], 'hierarchical' => true, 'show_in_rest' => true, 'rest_base' => 'strain-types', 'rewrite' => [ 'slug' => 'strain-type' ], 'show_admin_column' => true, ] ); // ── Effects (relaxed, euphoric, creative, …) ────────────────────────────── register_taxonomy( 'wo_effect', [ 'wo_strain', 'wo_product' ], [ 'label' => __( 'Effects', 'weedops' ), 'labels' => [ 'name' => __( 'Effects', 'weedops' ), 'singular_name' => __( 'Effect', 'weedops' ), 'add_new_item' => __( 'Add Effect', 'weedops' ), ], 'hierarchical' => false, 'show_in_rest' => true, 'rest_base' => 'effects', 'rewrite' => [ 'slug' => 'effect' ], 'show_admin_column' => true, ] ); // ── Terpenes ────────────────────────────────────────────────────────────── register_taxonomy( 'wo_terpene', [ 'wo_strain', 'wo_product' ], [ 'label' => __( 'Terpenes', 'weedops' ), 'hierarchical' => false, 'show_in_rest' => true, 'rest_base' => 'terpenes', 'rewrite' => [ 'slug' => 'terpene' ], ] ); // ── Product Category (flower / concentrate / edible / topical / …) ──────── register_taxonomy( 'wo_product_cat', [ 'wo_product' ], [ 'label' => __( 'Product Category', 'weedops' ), 'hierarchical' => true, 'show_in_rest' => true, 'rest_base' => 'product-categories', 'rewrite' => [ 'slug' => 'product-category' ], ] ); // ── Compliance Status ───────────────────────────────────────────────────── register_taxonomy( 'wo_compliance_status', [ 'wo_compliance', 'wo_product' ], [ 'label' => __( 'Compliance Status', 'weedops' ), 'hierarchical' => true, 'show_in_rest' => true, 'public' => false, 'show_ui' => true, ] ); } add_action( 'init', 'weedops_register_taxonomies' ); // ───────────────────────────────────────────────────────────────────────────── // Meta Field Registration (REST API + Gutenberg) // ───────────────────────────────────────────────────────────────────────────── function weedops_register_meta_fields(): void { // Strain meta $strain_meta = [ 'wo_thc_percent' => [ 'type' => 'number', 'label' => 'THC %', 'sanitize' => 'floatval' ], 'wo_cbd_percent' => [ 'type' => 'number', 'label' => 'CBD %', 'sanitize' => 'floatval' ], 'wo_genetics' => [ 'type' => 'string', 'label' => 'Genetics / Lineage', 'sanitize' => 'sanitize_text_field' ], 'wo_flowering_time' => [ 'type' => 'integer', 'label' => 'Flowering Time (days)', 'sanitize' => 'absint' ], 'wo_yield_indoor' => [ 'type' => 'string', 'label' => 'Indoor Yield', 'sanitize' => 'sanitize_text_field' ], 'wo_yield_outdoor' => [ 'type' => 'string', 'label' => 'Outdoor Yield', 'sanitize' => 'sanitize_text_field' ], 'wo_difficulty' => [ 'type' => 'string', 'label' => 'Grow Difficulty', 'sanitize' => 'sanitize_text_field' ], ]; foreach ( $strain_meta as $key => $config ) { register_post_meta( 'wo_strain', $key, [ 'type' => $config['type'], 'single' => true, 'show_in_rest' => true, 'description' => $config['label'], 'sanitize_callback' => $config['sanitize'], 'auth_callback' => fn() => current_user_can( 'edit_posts' ), ] ); } // Product meta $product_meta = [ 'wo_sku' => [ 'type' => 'string', 'label' => 'SKU / License #', 'sanitize' => 'sanitize_text_field' ], 'wo_batch_id' => [ 'type' => 'string', 'label' => 'Batch ID', 'sanitize' => 'sanitize_text_field' ], 'wo_lab_tested' => [ 'type' => 'boolean', 'label' => 'Lab Tested', 'sanitize' => 'rest_sanitize_boolean' ], 'wo_coa_url' => [ 'type' => 'string', 'label' => 'COA (Certificate of Analysis) URL','sanitize' => 'esc_url_raw' ], 'wo_price_gram' => [ 'type' => 'number', 'label' => 'Price per Gram', 'sanitize' => 'floatval' ], 'wo_inventory_qty' => [ 'type' => 'integer', 'label' => 'Inventory Qty (g)', 'sanitize' => 'absint' ], 'wo_origin_state' => [ 'type' => 'string', 'label' => 'Origin State', 'sanitize' => 'sanitize_text_field' ], 'wo_license_no' => [ 'type' => 'string', 'label' => 'Producer License #', 'sanitize' => 'sanitize_text_field' ], ]; foreach ( $product_meta as $key => $config ) { register_post_meta( 'wo_product', $key, [ 'type' => $config['type'], 'single' => true, 'show_in_rest' => true, 'description' => $config['label'], 'sanitize_callback' => $config['sanitize'], 'auth_callback' => fn() => current_user_can( 'edit_posts' ), ] ); } } add_action( 'init', 'weedops_register_meta_fields' ); // ───────────────────────────────────────────────────────────────────────────── // Admin Meta Box — Strain Details // ───────────────────────────────────────────────────────────────────────────── function weedops_add_strain_meta_box(): void { add_meta_box( 'wo_strain_details', __( 'Strain Details', 'weedops' ), 'weedops_render_strain_meta_box', 'wo_strain', 'normal', 'high' ); } add_action( 'add_meta_boxes', 'weedops_add_strain_meta_box' ); function weedops_render_strain_meta_box( WP_Post $post ): void { wp_nonce_field( 'wo_save_strain_details', 'wo_strain_nonce' ); $thc = get_post_meta( $post->ID, 'wo_thc_percent', true ); $cbd = get_post_meta( $post->ID, 'wo_cbd_percent', true ); $genetics = get_post_meta( $post->ID, 'wo_genetics', true ); $difficulty = get_post_meta( $post->ID, 'wo_difficulty', true ); // Strain type from taxonomy $strain_types = get_the_terms( $post->ID, 'wo_strain_type' ); $current_type = ( $strain_types && ! is_wp_error( $strain_types ) ) ? $strain_types[0]->slug : ''; // Effects from taxonomy $effects_terms = get_terms( [ 'taxonomy' => 'wo_effect', 'hide_empty' => false ] ); $assigned_effects = wp_get_post_terms( $post->ID, 'wo_effect', [ 'fields' => 'ids' ] ); ?>
$type_slug ] ); $term_id = is_wp_error( $inserted ) ? 0 : $inserted['term_id']; } else { $term_id = $term->term_id; } if ( $term_id ) { wp_set_post_terms( $post_id, [ $term_id ], 'wo_strain_type' ); } } else { wp_set_post_terms( $post_id, [], 'wo_strain_type' ); } } // Effects — array of term IDs $effect_ids = isset( $_POST['wo_effect_terms'] ) ? array_map( 'absint', (array) $_POST['wo_effect_terms'] ) : []; wp_set_post_terms( $post_id, $effect_ids, 'wo_effect' ); } add_action( 'save_post_wo_strain', 'weedops_save_strain_meta' );