PluginProbe
ActivityPub / 4.1.1
ActivityPub v4.1.1
9.3.1 9.3.0 9.2.2 9.2.1 9.2.0 9.1.0 9.0.2 9.0.1 9.0.0 8.3.0 8.2.1 8.2.0 8.1.1 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.2.0 1.3.0 2.0.0 2.0.1 2.1.0 2.1.1 All 160 releases
activitypub / includes / collection / class-extra-fields.php

class-extra-fields.php in ActivityPub 4.1.1, at includes/collection/class-extra-fields.php

289 lines 7.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Extra Fields collection file.
4 *
5 * @package Activitypub
6 */
7
8 namespace Activitypub\Collection;
9
10 use Activitypub\Link;
11
12 use function Activitypub\site_supports_blocks;
13
14 /**
15 * Extra Fields collection.
16 */
17 class Extra_Fields {
18
19 const USER_POST_TYPE = 'ap_extrafield';
20 const BLOG_POST_TYPE = 'ap_extrafield_blog';
21
22 /**
23 * Get the extra fields for a user.
24 *
25 * @param int $user_id The user ID.
26 *
27 * @return \WP_Post[] The extra fields.
28 */
29 public static function get_actor_fields( $user_id ) {
30 $is_blog = self::is_blog( $user_id );
31 $post_type = $is_blog ? self::BLOG_POST_TYPE : self::USER_POST_TYPE;
32 $args = array(
33 'post_type' => $post_type,
34 'nopaging' => true,
35 'orderby' => 'menu_order',
36 'order' => 'ASC',
37 );
38 if ( ! $is_blog ) {
39 $args['author'] = $user_id;
40 }
41
42 $query = new \WP_Query( $args );
43 $fields = $query->posts ?? array();
44
45 return apply_filters( 'activitypub_get_actor_extra_fields', $fields, $user_id );
46 }
47
48 /**
49 * Get formatted content for an extra field.
50 *
51 * @param \WP_Post $post The post.
52 *
53 * @return string The formatted content.
54 */
55 public static function get_formatted_content( $post ) {
56 $content = \get_the_content( null, false, $post );
57 $content = Link::the_content( $content, true );
58 if ( site_supports_blocks() ) {
59 $content = \do_blocks( $content );
60 }
61 $content = \wptexturize( $content );
62 $content = \wp_filter_content_tags( $content );
63
64 // Replace script and style elements.
65 $content = \preg_replace( '@<(script|style)[^>]*?>.*?</\\1>@si', '', $content );
66 $content = \strip_shortcodes( $content );
67 $content = \trim( \preg_replace( '/[\n\r\t]/', '', $content ) );
68
69 /**
70 * Filters the content of an extra field.
71 *
72 * @param string $content The content.
73 * @param \WP_Post $post The post.
74 */
75 return \apply_filters( 'activitypub_extra_field_content', $content, $post );
76 }
77
78 /**
79 * Transforms the Extra Fields (Custom Post Types) to ActivityPub Actor-Attachments.
80 *
81 * @param \WP_Post[] $fields The extra fields.
82 *
83 * @return array ActivityPub attachments.
84 */
85 public static function fields_to_attachments( $fields ) {
86 $attachments = array();
87 \add_filter(
88 'activitypub_link_rel',
89 function ( $rel ) {
90 $rel .= ' me';
91
92 return $rel;
93 }
94 );
95
96 foreach ( $fields as $post ) {
97 $content = self::get_formatted_content( $post );
98 $attachments[] = array(
99 'type' => 'PropertyValue',
100 'name' => \get_the_title( $post ),
101 'value' => \html_entity_decode(
102 $content,
103 \ENT_QUOTES,
104 'UTF-8'
105 ),
106 );
107
108 $link_added = false;
109
110 // Add support for FEP-fb2a, for more information see FEDERATION.md.
111 $link_content = \trim( \strip_tags( $content, '<a>' ) );
112 if (
113 \stripos( $link_content, '<a' ) === 0 &&
114 \stripos( $link_content, '<a', 3 ) === false &&
115 \stripos( $link_content, '</a>', \strlen( $link_content ) - 4 ) !== false &&
116 \class_exists( '\WP_HTML_Tag_Processor' )
117 ) {
118 $tags = new \WP_HTML_Tag_Processor( $link_content );
119 $tags->next_tag( 'A' );
120
121 if ( 'A' === $tags->get_tag() ) {
122 $attachment = array(
123 'type' => 'Link',
124 'name' => \get_the_title( $post ),
125 'href' => \esc_url( $tags->get_attribute( 'href' ) ),
126 );
127
128 $rel = $tags->get_attribute( 'rel' );
129
130 if ( $rel && \is_string( $rel ) ) {
131 $attachment['rel'] = \explode( ' ', $rel );
132 }
133
134 $link_added = true;
135 }
136 }
137
138 if ( ! $link_added ) {
139 $attachment = array(
140 'type' => 'Note',
141 'name' => \get_the_title( $post ),
142 'content' => \html_entity_decode(
143 $content,
144 \ENT_QUOTES,
145 'UTF-8'
146 ),
147 );
148 }
149
150 $attachments[] = $attachment;
151 }
152
153 return $attachments;
154 }
155
156 /**
157 * Check if a post type is an extra fields post type.
158 *
159 * @param string $post_type The post type.
160 *
161 * @return bool True if the post type is an extra fields post type, otherwise false.
162 */
163 public static function is_extra_fields_post_type( $post_type ) {
164 return \in_array( $post_type, array( self::USER_POST_TYPE, self::BLOG_POST_TYPE ), true );
165 }
166
167 /**
168 * Check if a post type is the `ap_extrafield` post type.
169 *
170 * @param string $post_type The post type.
171 *
172 * @return bool True if the post type is `ap_extrafield`, otherwise false.
173 */
174 public static function is_extra_field_post_type( $post_type ) {
175 return self::USER_POST_TYPE === $post_type;
176 }
177
178 /**
179 * Check if a post type is the `ap_extrafield_blog` post type.
180 *
181 * @param string $post_type The post type.
182 *
183 * @return bool True if the post type is `ap_extrafield_blog`, otherwise false.
184 */
185 public static function is_extra_field_blog_post_type( $post_type ) {
186 return self::BLOG_POST_TYPE === $post_type;
187 }
188
189 /**
190 * Add default extra fields to an actor.
191 *
192 * @param array $extra_fields The extra fields.
193 * @param int $user_id The User-ID.
194 *
195 * @return array The extra fields.
196 */
197 public static function default_actor_extra_fields( $extra_fields, $user_id ) {
198 // We'll only take action when there are none yet.
199 if ( ! empty( $extra_fields ) ) {
200 return $extra_fields;
201 }
202
203 $is_blog = self::is_blog( $user_id );
204 $already_migrated = $is_blog
205 ? \get_option( 'activitypub_default_extra_fields' )
206 : \get_user_meta( $user_id, 'activitypub_default_extra_fields', true );
207
208 if ( $already_migrated ) {
209 return $extra_fields;
210 }
211
212 \add_filter(
213 'activitypub_link_rel',
214 function ( $rel ) {
215 $rel .= ' me';
216
217 return $rel;
218 }
219 );
220
221 $defaults = array(
222 \__( 'Blog', 'activitypub' ) => \home_url( '/' ),
223 );
224
225 if ( ! $is_blog ) {
226 $author_url = \get_the_author_meta( 'user_url', $user_id );
227 $author_posts_url = \get_author_posts_url( $user_id );
228
229 $defaults[ \__( 'Profile', 'activitypub' ) ] = $author_posts_url;
230 if ( $author_url !== $author_posts_url ) {
231 $defaults[ \__( 'Homepage', 'activitypub' ) ] = $author_url;
232 }
233 }
234
235 $post_type = $is_blog ? self::BLOG_POST_TYPE : self::USER_POST_TYPE;
236 $menu_order = 10;
237
238 foreach ( $defaults as $title => $url ) {
239 if ( ! $url ) {
240 continue;
241 }
242
243 $extra_field = array(
244 'post_type' => $post_type,
245 'post_title' => $title,
246 'post_status' => 'publish',
247 'post_author' => $user_id,
248 'post_content' => self::make_paragraph_block( Link::the_content( $url ) ),
249 'comment_status' => 'closed',
250 'menu_order' => $menu_order,
251 );
252
253 $menu_order += 10;
254 $extra_field_id = wp_insert_post( $extra_field );
255 $extra_fields[] = get_post( $extra_field_id );
256 }
257
258 $is_blog
259 ? \update_option( 'activitypub_default_extra_fields', true )
260 : \update_user_meta( $user_id, 'activitypub_default_extra_fields', true );
261
262 return $extra_fields;
263 }
264
265 /**
266 * Create a paragraph block.
267 *
268 * @param string $content The content.
269 *
270 * @return string The paragraph block.
271 */
272 public static function make_paragraph_block( $content ) {
273 if ( ! site_supports_blocks() ) {
274 return $content;
275 }
276 return '<!-- wp:paragraph --><p>' . $content . '</p><!-- /wp:paragraph -->';
277 }
278
279 /**
280 * Checks if the user is the blog user.
281 *
282 * @param int $user_id The user ID.
283 * @return bool True if the user is the blog user, otherwise false.
284 */
285 private static function is_blog( $user_id ) {
286 return Users::BLOG_USER_ID === $user_id;
287 }
288 }
289