Normalize attributes that can have mixed value types (#586)

* fix #571

* support empty values

* fix phpcs issues

* test for `null`

* use `object_to_uri`  on followers list
This commit is contained in:
Matthias Pfefferle 2023-12-05 18:59:00 +01:00 committed by GitHub
parent ef96008cb3
commit 93b2f1ee7d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 145 additions and 15 deletions

View file

@ -3,7 +3,9 @@ namespace Activitypub;
use Activitypub\Collection\Followers; use Activitypub\Collection\Followers;
use Activitypub\Collection\Users as User_Collection; use Activitypub\Collection\Users as User_Collection;
use Activitypub\is_user_type_disabled;
use function Activitypub\object_to_uri;
use function Activitypub\is_user_type_disabled;
class Blocks { class Blocks {
public static function init() { public static function init() {
@ -140,7 +142,7 @@ class Blocks {
return sprintf( return sprintf(
$template, $template,
esc_url( $data['url'] ), esc_url( object_to_uri( $data['url'] ) ),
esc_attr( $data['name'] ), esc_attr( $data['name'] ),
esc_attr( $data['icon']['url'] ), esc_attr( $data['icon']['url'] ),
esc_html( $data['name'] ), esc_html( $data['name'] ),

View file

@ -47,3 +47,32 @@ if ( ! function_exists( 'is_countable' ) ) {
return is_array( $value ) || $value instanceof \Countable; return is_array( $value ) || $value instanceof \Countable;
} }
} }
/**
* Polyfill for `array_is_list()` function added in PHP 7.3.
*
* @param array $array The array to check.
*
* @return bool True if `$array` is a list, otherwise false.
*/
if ( ! function_exists( 'array_is_list' ) ) {
function array_is_list( $array ) {
if ( ! is_array( $array ) ) {
return false;
}
if ( array_values( $array ) === $array ) {
return true;
}
$next_key = -1;
foreach ( $array as $k => $v ) {
if ( ++$next_key !== $k ) {
return false;
}
}
return true;
}
}

View file

@ -698,3 +698,40 @@ function url_to_commentid( $url ) {
return null; return null;
} }
/**
* Get the URI of an ActivityPub object
*
* @param array $object The ActivityPub object
*
* @return string The URI of the ActivityPub object
*/
function object_to_uri( $object ) {
// check if it is already simple
if ( ! $object || is_string( $object ) ) {
return $object;
}
// check if it is a list, then take first item
// this plugin does not support collections
if ( array_is_list( $object ) ) {
$object = $object[0];
}
// check if it is simplified now
if ( is_string( $object ) ) {
return $object;
}
// return part of Object that makes most sense
switch ( $object['type'] ) {
case 'Link':
$object = $object['href'];
break;
default:
$object = $object['id'];
break;
}
return $object;
}

View file

@ -8,6 +8,7 @@ use Activitypub\Activity\Activity;
use Activitypub\Collection\Users as User_Collection; use Activitypub\Collection\Users as User_Collection;
use function Activitypub\get_context; use function Activitypub\get_context;
use function Activitypub\object_to_uri;
use function Activitypub\url_to_authorid; use function Activitypub\url_to_authorid;
use function Activitypub\get_rest_url_by_path; use function Activitypub\get_rest_url_by_path;
use function Activitypub\get_remote_metadata_by_actor; use function Activitypub\get_remote_metadata_by_actor;
@ -237,14 +238,7 @@ class Inbox {
$params['actor'] = array( $params['actor'] = array(
'required' => true, 'required' => true,
'sanitize_callback' => function( $param, $request, $key ) { 'sanitize_callback' => function( $param, $request, $key ) {
if ( \is_array( $param ) ) { return object_to_uri( $param );
if ( isset( $param['id'] ) ) {
$param = $param['id'];
} else {
$param = $param['url'];
}
}
return \esc_url_raw( $param );
}, },
); );
@ -286,10 +280,7 @@ class Inbox {
'required' => true, 'required' => true,
//'type' => array( 'object', 'string' ), //'type' => array( 'object', 'string' ),
'sanitize_callback' => function( $param, $request, $key ) { 'sanitize_callback' => function( $param, $request, $key ) {
if ( ! \is_string( $param ) ) { return object_to_uri( $param );
$param = $param['id'];
}
return \esc_url_raw( $param );
}, },
); );

View file

@ -5,6 +5,8 @@ use WP_List_Table;
use Activitypub\Collection\Users; use Activitypub\Collection\Users;
use Activitypub\Collection\Followers as FollowerCollection; use Activitypub\Collection\Followers as FollowerCollection;
use function Activitypub\object_to_uri;
if ( ! \class_exists( '\WP_List_Table' ) ) { if ( ! \class_exists( '\WP_List_Table' ) ) {
require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php'; require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
} }
@ -101,7 +103,7 @@ class Followers extends WP_List_Table {
'icon' => esc_attr( $follower->get_icon_url() ), 'icon' => esc_attr( $follower->get_icon_url() ),
'post_title' => esc_attr( $follower->get_name() ), 'post_title' => esc_attr( $follower->get_name() ),
'username' => esc_attr( $follower->get_preferred_username() ), 'username' => esc_attr( $follower->get_preferred_username() ),
'url' => esc_attr( $follower->get_url() ), 'url' => esc_attr( object_to_uri( $follower->get_url() ) ),
'identifier' => esc_attr( $follower->get_id() ), 'identifier' => esc_attr( $follower->get_id() ),
'published' => esc_attr( $follower->get_published() ), 'published' => esc_attr( $follower->get_published() ),
'modified' => esc_attr( $follower->get_updated() ), 'modified' => esc_attr( $follower->get_updated() ),

View file

@ -77,4 +77,73 @@ class Test_Functions extends ActivityPub_TestCase_Cache_HTTP {
$query_result = \Activitypub\object_id_to_comment( $duplicate_comment_source_id ); $query_result = \Activitypub\object_id_to_comment( $duplicate_comment_source_id );
$this->assertFalse( $query_result ); $this->assertFalse( $query_result );
} }
/**
* @dataProvider object_to_uri_provider
*/
public function test_object_to_uri( $input, $output ) {
$this->assertEquals( $output, \Activitypub\object_to_uri( $input ) );
}
public function object_to_uri_provider() {
return array(
array( null, null ),
array( 'https://example.com', 'https://example.com' ),
array( array( 'https://example.com' ), 'https://example.com' ),
array(
array(
'https://example.com',
'https://example.org',
),
'https://example.com',
),
array(
array(
'type' => 'Link',
'href' => 'https://example.com',
),
'https://example.com',
),
array(
array(
array(
'type' => 'Link',
'href' => 'https://example.com',
),
array(
'type' => 'Link',
'href' => 'https://example.org',
),
),
'https://example.com',
),
array(
array(
'type' => 'Actor',
'id' => 'https://example.com',
),
'https://example.com',
),
array(
array(
array(
'type' => 'Actor',
'id' => 'https://example.com',
),
array(
'type' => 'Actor',
'id' => 'https://example.org',
),
),
'https://example.com',
),
array(
array(
'type' => 'Activity',
'id' => 'https://example.com',
),
'https://example.com',
),
);
}
} }