PluginProbe ʕ •ᴥ•ʔ
Jetpack – WP Security, Backup, Speed, & Growth / 16.0-beta
Jetpack – WP Security, Backup, Speed, & Growth v16.0-beta
16.0 16.0-beta 16.0-a.7 16.0-a.5 15.9.1 16.0-a.3 16.0-a.1 15.9 15.9-beta 15.9-a.7 15.9-a.5 15.9-a.3 15.9-a.1 15.8 15.8-beta 15.8-a.7 15.8-a.5 5.2.5 5.3.4 5.4.4 5.5.5 5.6.5 5.7.5 5.8.4 5.9.4 6.0.4 6.1 6.1.1 6.1.2 6.1.3 6.1.4 6.1.5 6.2 6.2.1 6.2.2 6.2.3 6.2.4 6.2.5 6.3 6.3.1 6.3.2 6.3.3 6.3.4 6.3.5 6.3.6 6.3.7 6.4 6.4.1 6.4.2 6.4.3 6.4.4 6.4.5 6.4.6 6.5 6.5.1 6.5.2 6.5.3 6.5.4 6.6 6.6.1 6.6.2 6.6.3 6.6.4 6.6.5 6.7 6.7.1 6.7.2 6.7.3 6.7.4 6.8 6.8.1 6.8.2 6.8.3 6.8.4 6.8.5 6.9 6.9.1 6.9.2 6.9.3 6.9.4 7.0 7.0.1 7.0.2 7.0.3 7.0.4 7.0.5 7.1 7.1.1 7.1.2 7.1.3 7.1.4 7.1.5 7.2 7.2.1 7.2.1.1 7.2.2 7.2.3 7.2.4 7.2.5 7.3 7.3.0.1 7.3.1 7.3.1.1 7.3.2 7.3.3 7.3.4 7.3.5 7.4 7.4.1 7.4.2 7.4.3 7.4.4 7.4.5 7.5 7.5.0.1 7.5.1 7.5.2 7.5.3 7.5.4 7.5.5 7.5.6 7.5.7 7.6 7.6.1 7.6.2 7.6.3 7.6.4 7.7 7.7.1 7.7.2 7.7.3 7.7.4 7.7.5 7.7.6 7.8 7.8.1 7.8.2 7.8.3 7.8.4 7.9 7.9.1 7.9.2 7.9.3 7.9.4 8.0 8.0.1 8.0.2 8.0.3 8.1 8.1.1 8.1.2 8.1.3 8.1.4 8.2 8.2.0.1 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.2.6 8.3 8.3.1 8.3.2 8.3.3 8.4 8.4.1 8.4.2 8.4.3 8.4.4 8.4.5 8.5 8.5.1 8.5.2 8.5.3 8.6 8.6.1 8.6.2 8.6.3 8.6.4 8.7 8.7.0.1 8.7.1 8.7.2 8.7.3 8.7.4 8.8 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.9 8.9.1 8.9.2 8.9.3 8.9.4 9.0 9.0.1 9.0.2 9.0.3 9.0.4 9.0.5 9.1 9.1.1 9.1.2 9.1.3 9.2 9.2.1 9.2.2 9.2.3 9.2.4 9.3 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.4 9.4.1 9.4.2 9.4.3 9.4.4 9.5 9.5.1 9.5.2 9.5.3 9.5.4 9.5.5 9.6 9.6.1 9.6.2 9.6.3 9.6.4 9.7 9.7.1 9.7.2 15.7-beta.2 9.7.3 15.7.1 9.8 15.8-a.1 9.8.1 15.8-a.3 9.8.2 2.0.9 9.8.3 2.1.7 9.9 2.2.10 9.9.1 2.3.10 9.9.2 2.4.7 9.9.3 2.5.5 2.6.6 2.7.5 2.8.5 2.9.6 3.0.6 3.1.5 3.2.5 3.3.6 3.4.6 3.5.6 3.6.4 3.7.5 3.8.5 3.9.10 4.0.7 4.1.4 4.2.5 4.3.5 4.4.5 4.5.3 4.6.3 4.7.4 4.8.5 4.9.3 5.0.3 5.1.4 trunk 10.0 10.0.1 10.0.2 10.1 10.1.1 10.1.2 10.2 10.2.1 10.2.2 10.2.3 10.3 10.3.1 10.3.2 10.4 10.4.1 10.4.2 10.5 10.5.1 10.5.2 10.5.3 10.6 10.6.1 10.6.2 10.7 10.7.1 10.7.2 10.8 10.8.1 10.8.2 10.9 10.9.1 10.9.2 10.9.3 11.0 11.0.1 11.0.2 11.1 11.1.1 11.1.2 11.1.3 11.1.4 11.2 11.2.1 11.2.2 11.3 11.3.1 11.3.2 11.3.3 11.3.4 11.4 11.4.1 11.4.2 11.5 11.5.1 11.5.2 11.5.3 11.6 11.6.1 11.6.2 11.7 11.7.1 11.7.2 11.7.3 11.8 11.8.3 11.8.4 11.8.5 11.8.6 11.9 11.9.1 11.9.2 11.9.3 12.0 12.0.1 12.0.2 12.1 12.1.1 12.1.2 12.2 12.2.1 12.2.2 12.3 12.3.1 12.4 12.4.1 12.5 12.5.1 12.6 12.6.1 12.6.2 12.6.3 12.7 12.7.1 12.7.2 12.8 12.8.1 12.8.2 12.9 12.9.1 12.9.2 12.9.3 12.9.4 13.0 13.0.1 13.1 13.1.1 13.1.2 13.1.3 13.1.4 13.2 13.2.1 13.2.2 13.2.3 13.3 13.3.1 13.3.2 13.4 13.4.1 13.4.2 13.4.3 13.4.4 13.5 13.5.1 13.6 13.6.1 13.7 13.7.1 13.8 13.8.1 13.8.2 13.9 13.9.1 14.0 14.1 14.2 14.2.1 14.3 14.4 14.4.1 14.5 14.6 14.7 14.8 14.9 14.9.1 15.0 15.0.1 15.0.2 15.1 15.1.1 15.2 15.3 15.3.1 15.4 15.5 15.6 15.7 15.7-a.1 15.7-a.3 15.7-a.5 15.7-a.7 15.7-beta
jetpack / modules / shortlinks / abilities / class-shortlinks-abilities.php
jetpack / modules / shortlinks / abilities Last commit date
class-shortlinks-abilities.php 1 week ago
class-shortlinks-abilities.php
208 lines
1 <?php
2 /**
3 * Jetpack Shortlinks Abilities Registration
4 *
5 * Registers Jetpack WP.me Shortlinks abilities with the WordPress Abilities API.
6 *
7 * @package automattic/jetpack
8 */
9
10 namespace Automattic\Jetpack\Plugin\Abilities;
11
12 use Automattic\Jetpack\Connection\Manager as Connection_Manager;
13 use Automattic\Jetpack\WP_Abilities\Registrar;
14
15 /**
16 * Registers Jetpack WP.me Shortlinks abilities with the WordPress Abilities API.
17 *
18 * Exposes a single read ability that returns wp.me shortlinks for the
19 * requested posts and (optionally) the site homepage so AI agents can fetch
20 * shareable URLs in bulk through the standard `wp-abilities/v1` REST surface.
21 */
22 class Shortlinks_Abilities extends Registrar {
23
24 /**
25 * Maximum number of post IDs accepted per call.
26 */
27 const MAX_POST_IDS = 100;
28
29 /**
30 * Returns the category slug this registrar owns.
31 *
32 * @return string
33 */
34 public static function get_category_slug(): string {
35 return 'jetpack-shortlinks';
36 }
37
38 /**
39 * Returns the category definition passed to wp_register_ability_category().
40 *
41 * @return array
42 */
43 public static function get_category_definition(): array {
44 return array(
45 // "Jetpack" is a product name and should not be translated.
46 'label' => 'Jetpack WP.me Shortlinks',
47 'description' => __( 'Abilities for retrieving wp.me shortlinks for posts, pages, attachments, and the site homepage.', 'jetpack' ),
48 );
49 }
50
51 /**
52 * Returns the ability specs this registrar owns as a [ slug => spec ] map.
53 *
54 * @return array<string, array>
55 */
56 public static function get_abilities(): array {
57 $item_schema = array(
58 'type' => 'object',
59 'properties' => array(
60 'post_id' => array(
61 'type' => 'integer',
62 'description' => __( '0 for the site homepage entry; otherwise the WordPress post ID.', 'jetpack' ),
63 ),
64 'post_title' => array( 'type' => 'string' ),
65 'post_type' => array(
66 'type' => 'string',
67 'description' => __( '"blog" for the homepage entry; otherwise the WordPress post type slug (post, page, attachment, or a CPT that supports shortlinks).', 'jetpack' ),
68 ),
69 'shortlink' => array(
70 'type' => 'string',
71 'description' => __( 'The wp.me URL.', 'jetpack' ),
72 ),
73 'target_url' => array(
74 'type' => 'string',
75 'description' => __( 'The canonical permalink the shortlink resolves to.', 'jetpack' ),
76 ),
77 ),
78 );
79
80 return array(
81 'jetpack-shortlinks/get-shortlinks' => array(
82 'label' => __( 'Get wp.me shortlinks', 'jetpack' ),
83 'description' => __( 'Return wp.me shortlinks for the given posts and (optionally) the site homepage. Each result is a { post_id, post_title, post_type, shortlink, target_url } object — post_id is 0 for the homepage entry, post_type is "blog". IDs that do not exist, are unreadable to the current user, or belong to a post type without shortlinks support are silently omitted (returns a shorter array, not WP_Error). Caps post_ids at 100 per call. Requires the WP.me Shortlinks Jetpack module (slug: shortlinks) to be active and the site to be connected; an unconnected site returns jetpack_shortlinks_blog_id_unavailable. Use jetpack/get-modules to verify the module is on, jetpack/set-module-status to activate it.', 'jetpack' ),
84 'input_schema' => array(
85 'type' => 'object',
86 'default' => array(),
87 'properties' => array(
88 'post_ids' => array(
89 'type' => 'array',
90 'description' => __( 'Up to 100 post IDs to fetch shortlinks for. Order is preserved in the response. Defaults to an empty list.', 'jetpack' ),
91 'maxItems' => self::MAX_POST_IDS,
92 'items' => array(
93 'type' => 'integer',
94 'minimum' => 1,
95 ),
96 ),
97 'include_blog' => array(
98 'type' => 'boolean',
99 'description' => __( 'When true, prepend a single entry for the site homepage (post_id 0, post_type "blog") to the response.', 'jetpack' ),
100 'default' => false,
101 ),
102 ),
103 'additionalProperties' => false,
104 ),
105 'output_schema' => array(
106 'type' => 'array',
107 'items' => $item_schema,
108 ),
109 'execute_callback' => array( __CLASS__, 'get_shortlinks' ),
110 'permission_callback' => array( __CLASS__, 'can_view_shortlinks' ),
111 'meta' => array(
112 'annotations' => array(
113 'readonly' => true,
114 'destructive' => false,
115 'idempotent' => true,
116 ),
117 'show_in_rest' => true,
118 'mcp' => array(
119 'public' => true,
120 'type' => 'tool', // default is already "tool", but can be explicit.
121 ),
122 ),
123 ),
124 );
125 }
126
127 /**
128 * Permission check: require edit_posts so only users with content-management
129 * rights may enumerate shortlinks. Per-post read capability is still
130 * enforced inside the execute callback so unreadable IDs are silently
131 * omitted rather than failing the whole call.
132 */
133 public static function can_view_shortlinks(): bool {
134 return current_user_can( 'edit_posts' );
135 }
136
137 /**
138 * Execute: return wp.me shortlinks for the requested posts and (optionally) the homepage.
139 *
140 * @param array|null $input Input matching the ability's input_schema.
141 * @return array|\WP_Error
142 */
143 public static function get_shortlinks( $input = null ) {
144 $input = is_array( $input ) ? $input : array();
145
146 if ( null === Connection_Manager::get_site_id( true ) ) {
147 return new \WP_Error(
148 'jetpack_shortlinks_blog_id_unavailable',
149 __( 'No Jetpack/WordPress.com blog ID is available for this site. Connect Jetpack before requesting wp.me shortlinks.', 'jetpack' )
150 );
151 }
152
153 $post_ids = array();
154 if ( isset( $input['post_ids'] ) && is_array( $input['post_ids'] ) ) {
155 foreach ( $input['post_ids'] as $candidate ) {
156 $candidate_id = absint( $candidate );
157 if ( $candidate_id > 0 ) {
158 $post_ids[] = $candidate_id;
159 }
160 }
161 }
162 if ( count( $post_ids ) > self::MAX_POST_IDS ) {
163 $post_ids = array_slice( $post_ids, 0, self::MAX_POST_IDS );
164 }
165
166 $include_blog = ! empty( $input['include_blog'] );
167
168 $out = array();
169
170 if ( $include_blog ) {
171 $blog_shortlink = wp_get_shortlink( 0, 'blog' );
172 if ( is_string( $blog_shortlink ) && '' !== $blog_shortlink ) {
173 $out[] = array(
174 'post_id' => 0,
175 'post_title' => (string) get_bloginfo( 'name' ),
176 'post_type' => 'blog',
177 'shortlink' => $blog_shortlink,
178 'target_url' => home_url( '/' ),
179 );
180 }
181 }
182
183 if ( ! empty( $post_ids ) ) {
184 _prime_post_caches( $post_ids, false, false );
185 }
186
187 foreach ( $post_ids as $post_id ) {
188 $post = get_post( $post_id );
189 if ( ! $post || ! current_user_can( 'read_post', $post_id ) ) {
190 continue;
191 }
192 $shortlink = wp_get_shortlink( $post_id, 'post' );
193 if ( ! is_string( $shortlink ) || '' === $shortlink ) {
194 continue;
195 }
196 $out[] = array(
197 'post_id' => (int) $post->ID,
198 'post_title' => (string) $post->post_title,
199 'post_type' => (string) $post->post_type,
200 'shortlink' => $shortlink,
201 'target_url' => (string) get_permalink( $post ),
202 );
203 }
204
205 return $out;
206 }
207 }
208