get( $ability_key, 'abilities', true, false ); } public static function allowed_post_statuses() { return array_map( 'sanitize_text_field', apply_filters( 'adcmdr_ability_list_ads_allowed_post_statuses', array( 'publish', 'draft' ) ) ); } private static function ability_category() { return 'ad-management'; } public function register_categories( $categories ) { wp_register_ability_category( self::ability_category(), array( 'label' => __( 'Ad Management', 'ad-commander' ), 'description' => __( 'Abilities for managing ads.', 'ad-commander' ), ) ); } public function register_abilities( $abilities ) { if ( $this->is_enabled( 'ability_get_ad_stats' ) ) { $this->register_ability_get_ad_stats(); } if ( $this->is_enabled( 'ability_list_ads' ) ) { $this->register_ability_list_ads(); $this->register_ability_get_ad(); } } private function register_ability_get_ad_stats() { wp_register_ability( 'ad-commander/get-ad-stats', array( 'label' => __( 'Get Ad Statistics', 'ad-commander' ), 'description' => __( 'Retrieves impression and click statistics for a specific ad or all ads within a date range.', 'ad-commander' ), 'category' => self::ability_category(), 'input_schema' => array( 'type' => 'object', 'properties' => array( 'period' => array( 'type' => 'string', 'enum' => array_keys( AdminReports::allowed_periods() ), 'description' => __( 'The time period for which to retrieve statistics. Defaults to past_7_days. Use custom to specify a custom date range.', 'ad-commander' ), ), 'group_by' => array( 'type' => 'string', 'enum' => array_keys( AdminReports::allowed_group_by() ), 'description' => __( 'How to group the statistics by time period. Defaults to day.', 'ad-commander' ), ), 'start_date' => array( 'type' => 'string', 'description' => __( 'Start date in Y-m-d format. Required when period is custom.', 'ad-commander' ), ), 'end_date' => array( 'type' => 'string', 'description' => __( 'End date in Y-m-d format. Required when period is custom.', 'ad-commander' ), ), 'filter_by_ad_ids' => array( 'type' => 'array', 'items' => array( 'type' => 'integer' ), 'description' => __( 'Optional array of ad post IDs to filter results by.', 'ad-commander' ), ), ), ), 'output_schema' => array( 'type' => 'object', 'properties' => array( 'by_date' => array( 'type' => 'array', 'description' => __( 'Statistics grouped by date.', 'ad-commander' ), 'items' => array( 'type' => 'object', 'properties' => array( 'date' => array( 'type' => 'string', 'description' => __( 'Formatted date label for the item period.', 'ad-commander' ), ), 'date_alt' => array( 'type' => 'string', 'description' => __( 'Alternate shorter date label for the item period.', 'ad-commander' ), ), 'timestamp' => array( 'type' => 'integer', 'description' => __( 'Unix timestamp for the item period. If group_by is week or month, this represents the start of the period.', 'ad-commander' ), ), 'impressions' => array( 'type' => 'integer', 'description' => __( 'The number of impressions for all ads on this item period.', 'ad-commander' ), ), 'clicks' => array( 'type' => 'integer', 'description' => __( 'The number of clicks on all ads on this item period.', 'ad-commander' ), ), 'ctr' => array( 'type' => 'number', 'description' => __( 'Click-through rate as a percentage for all ads on this item period.', 'ad-commander' ), ), ), ), ), 'by_ad' => array( 'type' => 'array', 'description' => __( 'Statistics grouped by ad.', 'ad-commander' ), 'items' => array( 'type' => 'object', 'properties' => array( 'ad_id' => array( 'type' => 'integer', 'description' => __( 'The ad\'s post ID.', 'ad-commander' ), ), 'ad' => array( 'type' => 'string', 'description' => __( 'The ad title.', 'ad-commander' ), ), 'edit_link' => array( 'type' => 'string', 'description' => __( 'URL to edit the ad.', 'ad-commander' ), ), 'impressions' => array( 'type' => 'integer', 'description' => __( 'The number of impressions for the ad in the chosen time period.', 'ad-commander' ), ), 'clicks' => array( 'type' => 'integer', 'description' => __( 'The number of clicks on the ad in the chosen time period.', 'ad-commander' ), ), 'ctr' => array( 'type' => 'number', 'description' => __( 'Click-through rate as a percentage for the ad during the chosen time period.', 'ad-commander' ), ), ), ), ), 'by_group' => array( 'type' => 'array', 'description' => __( 'Statistics grouped by ad group. Includes ads currently in groups, even if they are in the trash or draft mode. Ads removed from a group are not counted. If an ad is in multiple groups, its stats will be included in each group, regardless of where the ad displayed.', 'ad-commander' ), 'items' => array( 'type' => 'object', 'properties' => array( 'group_id' => array( 'type' => 'integer', 'description' => __( 'The group\'s term ID.', 'ad-commander' ), ), 'group' => array( 'type' => 'string', 'description' => __( 'The group name.', 'ad-commander' ), ), 'impressions' => array( 'type' => 'integer', 'description' => __( 'The number of impressions for all ads in the group during the chosen time period.', 'ad-commander' ), ), 'clicks' => array( 'type' => 'integer', 'description' => __( 'The number of clicks on all ads in the group during the chosen time period.', 'ad-commander' ), ), 'ctr' => array( 'type' => 'number', 'description' => __( 'Click-through rate as a percentage for the group during the chosen time period.', 'ad-commander' ), ), ), ), ), ), ), 'execute_callback' => 'adcmdr_ability_get_ad_stats', 'permission_callback' => function () { return current_user_can( AdCommander::capability() ); }, 'meta' => array( 'show_in_rest' => true, 'mcp' => array( 'public' => true, 'type' => 'tool', ), 'annotations' => array( 'readonly' => true, 'destructive' => false, 'idempotent' => true, ), ), ) ); } private static function shared_list_ad_input_schema() { return array( 'post_statuses' => array( 'type' => 'array', 'items' => array( 'type' => 'string', 'enum' => self::allowed_post_statuses(), ), 'description' => __( 'Optional array of post statuses to filter by. Defaults to both.', 'ad-commander' ), ), 'detailed' => array( 'type' => 'boolean', 'description' => __( 'Whether to include detailed information about each ad, including but not limited to the ad type, expiration options, and more. Does not include ad statistics. Defaults to false.', 'ad-commander' ), ), 'include_groups' => array( 'type' => 'boolean', 'description' => __( 'Whether to include the ad groups that each ad belongs to in the output. Defaults to false.', 'ad-commander-pro' ), ), ); } private static function shared_list_ad_output_schema() { return apply_filters( 'adcmdr_ability_list_ads_output_properties', array( 'ad_id' => array( 'type' => 'integer', 'description' => __( 'The ad\'s post ID.', 'ad-commander' ), ), 'ad_title' => array( 'type' => 'string', 'description' => __( 'The ad title.', 'ad-commander' ), ), 'ad_status' => array( 'type' => 'string', 'description' => __( 'The ad\'s post status.', 'ad-commander' ), ), 'ad_type' => array( 'type' => 'string', 'description' => __( 'The ad type, which will indicate whether this is an Image/Banner ad, AdSense ad, Text or Code (ad network) ad, or Rich Content ad. Only included when detailed is true.', 'ad-commander' ), ), 'banner_image_url' => array( 'type' => 'string', 'description' => __( 'The URL of the banner image for this ad. Only included when ad_type is "bannerad" and when detailed is true.', 'ad-commander' ), ), 'banner_image_width' => array( 'type' => 'integer', 'description' => __( 'The width of the banner image for this ad in pixels. Only included when ad_type is "bannerad" and when detailed is true.', 'ad-commander' ), ), 'banner_image_height' => array( 'type' => 'integer', 'description' => __( 'The height of the banner image for this ad in pixels. Only included when ad_type is "bannerad" and when detailed is true.', 'ad-commander' ), ), 'banner_linked_url' => array( 'type' => 'string', 'description' => __( 'The URL that the banner image for this ad links to when clicked. Only included when ad_type is "bannerad" and when detailed is true.', 'ad-commander' ), ), 'adsense_ad_mode' => array( 'type' => 'string', 'description' => __( 'The ad mode for this ad if it is an AdSense ad. This could be manual, direct, or ad_code. Manual ads are built with fields, Direct ads are selected through the AdSense API, and ad_code ads use custom ad code. Only included when ad_type is "adsense" and when detailed is true.', 'ad-commander' ), ), ) ); } private static function shared_list_ad_meta() { return array( 'show_in_rest' => true, 'mcp' => array( 'public' => true, 'type' => 'tool', ), 'annotations' => array( 'readonly' => true, 'destructive' => false, 'idempotent' => true, ), ); } private function register_ability_list_ads() { wp_register_ability( 'ad-commander/list-ads', array( 'label' => __( 'List Ads', 'ad-commander' ), 'description' => __( 'Retrieves a list of ads with basic information to help identify them. Only ads with publish or draft status are returned.', 'ad-commander' ), 'category' => self::ability_category(), 'input_schema' => array( 'type' => 'object', 'properties' => array_merge( array( 'ad_ids' => array( 'type' => 'array', 'items' => array( 'type' => 'integer' ), 'description' => __( 'Optional array of ad post IDs to retrieve. If not specified, all ads are returned.', 'ad-commander' ), ), ), self::shared_list_ad_input_schema(), ), ), 'output_schema' => array( 'type' => 'array', 'description' => __( 'A list of ads.', 'ad-commander' ), 'items' => array( 'type' => 'object', 'properties' => self::shared_list_ad_output_schema(), ), ), 'execute_callback' => 'adcmdr_ability_list_ads', 'permission_callback' => function () { return current_user_can( AdCommander::capability() ); }, 'meta' => self::shared_list_ad_meta(), ) ); } private function register_ability_get_ad() { wp_register_ability( 'ad-commander/get-ad', array( 'label' => __( 'Get Ad', 'ad-commander' ), 'description' => __( 'Retrieves detailed information about a specific ad.', 'ad-commander' ), 'category' => self::ability_category(), 'input_schema' => array( 'type' => 'object', 'properties' => array_merge( array( 'ad_id' => array( 'type' => 'integer', 'description' => __( 'The ID of the ad to retrieve.', 'ad-commander' ), ), ), self::shared_list_ad_input_schema() ), ), 'output_schema' => array( 'type' => 'object', 'description' => __( 'Detailed information about the ad.', 'ad-commander' ), 'properties' => self::shared_list_ad_output_schema(), ), 'execute_callback' => 'adcmdr_ability_list_ads', 'permission_callback' => function () { return current_user_can( AdCommander::capability() ); }, 'meta' => self::shared_list_ad_meta(), ) ); } }