feat(01-02): register job_offer CPT with ownership-enforced capabilities

- Register job_offer custom post type with German labels
- Custom capability_type 'job_offer' prevents access to regular posts
- map_meta_cap filter enforces per-post ownership
- Elementor support via show_in_rest
- Menu icon: dashicons-businessperson at position 5
- Supports: title, editor, author, thumbnail
- Archive slug: jobangebote
- Custom capabilities prevent providers from editing others' posts

Tasks completed:
- Task 1: Register job_offer custom post type
- Task 2: Add capability mapping filter for ownership enforcement

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-14 18:57:29 +09:00
parent 7722848ef9
commit 693974b561
2 changed files with 126 additions and 0 deletions

View File

@@ -28,6 +28,7 @@ define( 'DDHH_JM_PLUGIN_FILE', __FILE__ );
// Include core classes. // Include core classes.
require_once DDHH_JM_PLUGIN_DIR . 'includes/class-activator.php'; require_once DDHH_JM_PLUGIN_DIR . 'includes/class-activator.php';
require_once DDHH_JM_PLUGIN_DIR . 'includes/class-deactivator.php'; require_once DDHH_JM_PLUGIN_DIR . 'includes/class-deactivator.php';
require_once DDHH_JM_PLUGIN_DIR . 'includes/class-post-types.php';
require_once DDHH_JM_PLUGIN_DIR . 'includes/class-ddhh-job-manager.php'; require_once DDHH_JM_PLUGIN_DIR . 'includes/class-ddhh-job-manager.php';
/** /**

View File

@@ -0,0 +1,125 @@
<?php
/**
* Custom Post Types Registration
*
* @package DDHH_Job_Manager
*/
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit;
/**
* Handles custom post type registration
*/
class DDHH_JM_Post_Types {
/**
* Register custom post types
*/
public static function register() {
self::register_job_offer();
// Hook capability mapping filter
add_filter( 'map_meta_cap', array( __CLASS__, 'map_job_offer_capabilities' ), 10, 4 );
}
/**
* Register job_offer custom post type
*/
private static function register_job_offer() {
$labels = array(
'name' => _x( 'Jobangebote', 'Post type general name', 'ddhh-job-manager' ),
'singular_name' => _x( 'Jobangebot', 'Post type singular name', 'ddhh-job-manager' ),
'menu_name' => _x( 'Jobs', 'Admin Menu text', 'ddhh-job-manager' ),
'name_admin_bar' => _x( 'Jobangebot', 'Add New on Toolbar', 'ddhh-job-manager' ),
'add_new' => __( 'Neu hinzufügen', 'ddhh-job-manager' ),
'add_new_item' => __( 'Neues Jobangebot', 'ddhh-job-manager' ),
'new_item' => __( 'Neues Jobangebot', 'ddhh-job-manager' ),
'edit_item' => __( 'Jobangebot bearbeiten', 'ddhh-job-manager' ),
'view_item' => __( 'Jobangebot ansehen', 'ddhh-job-manager' ),
'all_items' => __( 'Alle Jobangebote', 'ddhh-job-manager' ),
'search_items' => __( 'Jobangebote durchsuchen', 'ddhh-job-manager' ),
'parent_item_colon' => __( 'Übergeordnetes Jobangebot:', 'ddhh-job-manager' ),
'not_found' => __( 'Keine Jobangebote gefunden.', 'ddhh-job-manager' ),
'not_found_in_trash' => __( 'Keine Jobangebote im Papierkorb gefunden.', 'ddhh-job-manager' ),
'featured_image' => _x( 'Logo', 'Overrides the "Featured Image" phrase', 'ddhh-job-manager' ),
'set_featured_image' => _x( 'Logo festlegen', 'Overrides the "Set featured image" phrase', 'ddhh-job-manager' ),
'remove_featured_image' => _x( 'Logo entfernen', 'Overrides the "Remove featured image" phrase', 'ddhh-job-manager' ),
'use_featured_image' => _x( 'Als Logo verwenden', 'Overrides the "Use as featured image" phrase', 'ddhh-job-manager' ),
'archives' => _x( 'Jobangebote Archiv', 'The post type archive label used in nav menus', 'ddhh-job-manager' ),
'insert_into_item' => _x( 'In Jobangebot einfügen', 'Overrides the "Insert into post" phrase', 'ddhh-job-manager' ),
'uploaded_to_this_item' => _x( 'Zu diesem Jobangebot hochgeladen', 'Overrides the "Uploaded to this post" phrase', 'ddhh-job-manager' ),
'filter_items_list' => _x( 'Jobangebote Liste filtern', 'Screen reader text for the filter links', 'ddhh-job-manager' ),
'items_list_navigation' => _x( 'Jobangebote Navigation', 'Screen reader text for the pagination', 'ddhh-job-manager' ),
'items_list' => _x( 'Jobangebote Liste', 'Screen reader text for the items list', 'ddhh-job-manager' ),
);
$args = array(
'labels' => $labels,
'public' => true,
'publicly_queryable' => true,
'show_ui' => true,
'show_in_menu' => true,
'query_var' => true,
'rewrite' => array( 'slug' => 'jobangebote' ),
'capability_type' => 'job_offer',
'map_meta_cap' => true,
'has_archive' => true,
'hierarchical' => false,
'menu_position' => 5,
'menu_icon' => 'dashicons-businessperson',
'supports' => array( 'title', 'editor', 'author', 'thumbnail' ),
'show_in_rest' => true,
'capabilities' => array(
'edit_post' => 'edit_job_offer',
'read_post' => 'read_job_offer',
'delete_post' => 'delete_job_offer',
'edit_posts' => 'edit_job_offers',
'edit_others_posts' => 'edit_others_job_offers',
'publish_posts' => 'publish_job_offers',
'read_private_posts' => 'read_private_job_offers',
'delete_posts' => 'delete_job_offers',
'delete_private_posts' => 'delete_private_job_offers',
'delete_published_posts' => 'delete_published_job_offers',
'delete_others_posts' => 'delete_others_job_offers',
'edit_private_posts' => 'edit_private_job_offers',
'edit_published_posts' => 'edit_published_job_offers',
'create_posts' => 'edit_job_offers',
),
);
register_post_type( 'job_offer', $args );
}
/**
* Map job_offer capabilities to enforce ownership
*
* @param array $caps Required capabilities.
* @param string $cap Capability being checked.
* @param int $user_id User ID.
* @param array $args Additional arguments.
* @return array Modified capabilities.
*/
public static function map_job_offer_capabilities( $caps, $cap, $user_id, $args ) {
// Check if this is a job_offer capability we need to map
if ( 'edit_job_offer' === $cap || 'delete_job_offer' === $cap ) {
// Get the post
$post = get_post( $args[0] );
if ( ! $post || 'job_offer' !== $post->post_type ) {
return $caps;
}
// Check if user is the post author
if ( (int) $user_id === (int) $post->post_author ) {
// User is the author - allow with base capability
$caps = array( 'edit_job_offers' );
} else {
// User is NOT the author - require elevated capability
$caps = array( 'edit_others_job_offers' );
}
}
return $caps;
}
}