PluginProbe
ActivityPub / 2.5.0
ActivityPub v2.5.0
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 / class-blocks.php

class-blocks.php in ActivityPub 2.5.0, at includes/class-blocks.php

160 lines 5.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Activitypub;
3
4 use Activitypub\Collection\Followers;
5 use Activitypub\Collection\Users as User_Collection;
6
7 use function Activitypub\object_to_uri;
8 use function Activitypub\is_user_type_disabled;
9
10 class Blocks {
11 public static function init() {
12 // this is already being called on the init hook, so just add it.
13 self::register_blocks();
14 \add_action( 'wp_enqueue_scripts', array( self::class, 'add_data' ) );
15 \add_action( 'enqueue_block_editor_assets', array( self::class, 'add_data' ) );
16 }
17
18 public static function add_data() {
19 $context = is_admin() ? 'editor' : 'view';
20 $followers_handle = 'activitypub-followers-' . $context . '-script';
21 $follow_me_handle = 'activitypub-follow-me-' . $context . '-script';
22 $data = array(
23 'namespace' => ACTIVITYPUB_REST_NAMESPACE,
24 'enabled' => array(
25 'site' => ! is_user_type_disabled( 'blog' ),
26 'users' => ! is_user_type_disabled( 'user' ),
27 ),
28 );
29 $js = sprintf( 'var _activityPubOptions = %s;', wp_json_encode( $data ) );
30 \wp_add_inline_script( $followers_handle, $js, 'before' );
31 \wp_add_inline_script( $follow_me_handle, $js, 'before' );
32 }
33
34 public static function register_blocks() {
35 \register_block_type_from_metadata(
36 ACTIVITYPUB_PLUGIN_DIR . '/build/followers',
37 array(
38 'render_callback' => array( self::class, 'render_follower_block' ),
39 )
40 );
41 \register_block_type_from_metadata(
42 ACTIVITYPUB_PLUGIN_DIR . '/build/follow-me',
43 array(
44 'render_callback' => array( self::class, 'render_follow_me_block' ),
45 )
46 );
47 }
48
49 private static function get_user_id( $user_string ) {
50 if ( is_numeric( $user_string ) ) {
51 return absint( $user_string );
52 }
53 // any other non-numeric falls back to 0, including the `site` string used in the UI
54 return 0;
55 }
56
57 /**
58 * Filter an array by a list of keys.
59 * @param array $array The array to filter.
60 * @param array $keys The keys to keep.
61 * @return array The filtered array.
62 */
63 protected static function filter_array_by_keys( $array, $keys ) {
64 return array_intersect_key( $array, array_flip( $keys ) );
65 }
66
67 /**
68 * Render the follow me block.
69 * @param array $attrs The block attributes.
70 * @return string The HTML to render.
71 */
72 public static function render_follow_me_block( $attrs ) {
73 $user_id = self::get_user_id( $attrs['selectedUser'] );
74 $user = User_Collection::get_by_id( $user_id );
75 if ( ! is_wp_error( $user ) ) {
76 $attrs['profileData'] = self::filter_array_by_keys(
77 $user->to_array(),
78 array( 'icon', 'name', 'webfinger' )
79 );
80 }
81
82 // add `@` prefix if it's missing
83 if ( '@' !== substr( $attrs['profileData']['webfinger'], 0, 1 ) ) {
84 $attrs['profileData']['webfinger'] = '@' . $attrs['profileData']['webfinger'];
85 }
86
87 $wrapper_attributes = get_block_wrapper_attributes(
88 array(
89 'aria-label' => __( 'Follow me on the Fediverse', 'activitypub' ),
90 'class' => 'activitypub-follow-me-block-wrapper',
91 'data-attrs' => wp_json_encode( $attrs ),
92 )
93 );
94 // todo: render more than an empty div?
95 return '<div ' . $wrapper_attributes . '></div>';
96 }
97
98 public static function render_follower_block( $attrs ) {
99 $followee_user_id = self::get_user_id( $attrs['selectedUser'] );
100 $per_page = absint( $attrs['per_page'] );
101 $follower_data = Followers::get_followers_with_count( $followee_user_id, $per_page );
102
103 $attrs['followerData']['total'] = $follower_data['total'];
104 $attrs['followerData']['followers'] = array_map(
105 function ( $follower ) {
106 return self::filter_array_by_keys(
107 $follower->to_array(),
108 array( 'icon', 'name', 'preferredUsername', 'url' )
109 );
110 },
111 $follower_data['followers']
112 );
113 $wrapper_attributes = get_block_wrapper_attributes(
114 array(
115 'aria-label' => __( 'Fediverse Followers', 'activitypub' ),
116 'class' => 'activitypub-follower-block',
117 'data-attrs' => wp_json_encode( $attrs ),
118 )
119 );
120
121 $html = '<div ' . $wrapper_attributes . '>';
122 if ( $attrs['title'] ) {
123 $html .= '<h3>' . esc_html( $attrs['title'] ) . '</h3>';
124 }
125 $html .= '<ul>';
126 foreach ( $follower_data['followers'] as $follower ) {
127 $html .= '<li>' . self::render_follower( $follower ) . '</li>';
128 }
129 // We are only pagination on the JS side. Could be revisited but we gotta ship!
130 $html .= '</ul></div>';
131 return $html;
132 }
133
134 public static function render_follower( $follower ) {
135 $external_svg = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" class="components-external-link__icon css-rvs7bx esh4a730" aria-hidden="true" focusable="false"><path d="M18.2 17c0 .7-.6 1.2-1.2 1.2H7c-.7 0-1.2-.6-1.2-1.2V7c0-.7.6-1.2 1.2-1.2h3.2V4.2H7C5.5 4.2 4.2 5.5 4.2 7v10c0 1.5 1.2 2.8 2.8 2.8h10c1.5 0 2.8-1.2 2.8-2.8v-3.6h-1.5V17zM14.9 3v1.5h3.7l-6.4 6.4 1.1 1.1 6.4-6.4v3.7h1.5V3h-6.3z"></path></svg>';
136 $template =
137 '<a href="%s" title="%s" class="components-external-link activitypub-link" target="_blank" rel="external noreferrer noopener">
138 <img width="40" height="40" src="%s" class="avatar activitypub-avatar" />
139 <span class="activitypub-actor">
140 <strong class="activitypub-name">%s</strong>
141 <span class="sep">/</span>
142 <span class="activitypub-handle">@%s</span>
143 </span>
144 %s
145 </a>';
146
147 $data = $follower->to_array();
148
149 return sprintf(
150 $template,
151 esc_url( object_to_uri( $data['url'] ) ),
152 esc_attr( $data['name'] ),
153 esc_attr( $data['icon']['url'] ),
154 esc_html( $data['name'] ),
155 esc_html( $data['preferredUsername'] ),
156 $external_svg
157 );
158 }
159 }
160