pterotype/inc/outbox.php

173 lines
5.7 KiB
PHP
Raw Normal View History

2018-08-21 13:17:07 +00:00
<?php
2018-08-22 12:33:21 +00:00
/*
When an Activity is received (i.e. POSTed) to an Actor's outbox, the server must:
2018-08-21 13:17:07 +00:00
2018-08-22 12:34:28 +00:00
0. Make sure the request is authenticated
2018-08-22 12:33:21 +00:00
1. Add the Activity to the Actor's outbox collection in the DB
2. Deliver the Activity to the appropriate inboxes based on the received Activity
This involves discovering all the inboxes, including nested ones if the target
is a collection, deduplicating inboxes, and the POSTing the Activity to each
target inbox.
3. Perform side effects as necessary
*/
namespace outbox;
2018-08-29 20:38:10 +00:00
require_once plugin_dir_path( __FILE__ ) . '/activities.php';
require_once plugin_dir_path( __FILE__ ) . '/actors.php';
2018-09-10 00:48:14 +00:00
require_once plugin_dir_path( __FILE__ ) . '/deliver.php';
2018-08-29 21:19:10 +00:00
require_once plugin_dir_path( __FILE__ ) . '/activities/create.php';
require_once plugin_dir_path( __FILE__ ) . '/activities/update.php';
2018-09-01 14:14:11 +00:00
require_once plugin_dir_path( __FILE__ ) . '/activities/delete.php';
require_once plugin_dir_path( __FILE__ ) . '/activities/like.php';
2018-09-04 06:01:34 +00:00
require_once plugin_dir_path( __FILE__ ) . '/activities/follow.php';
2018-09-04 17:28:40 +00:00
require_once plugin_dir_path( __FILE__ ) . '/activities/block.php';
2018-09-26 03:46:31 +00:00
require_once plugin_dir_path( __FILE__ ) . '/activities/undo.php';
2018-08-25 13:31:20 +00:00
function handle_activity( $actor_slug, $activity ) {
2018-08-29 21:19:00 +00:00
// TODO handle authentication/authorization
2018-09-15 21:46:53 +00:00
if ( !array_key_exists( 'type', $activity ) ) {
2018-08-29 20:38:10 +00:00
return new \WP_Error(
2018-08-27 22:36:18 +00:00
'invalid_activity',
2018-09-19 15:16:41 +00:00
__( 'Invalid activity', 'pterotype' ),
2018-08-27 22:36:18 +00:00
array( 'status' => 400 )
2018-08-25 13:31:20 +00:00
);
}
$res = persist_activity( $actor_slug, $activity );
if ( is_wp_error( $res ) ) {
return $res;
}
2018-08-29 20:38:10 +00:00
switch ( $activity['type'] ) {
case 'Create':
$activity = \activities\create\handle_outbox( $actor_slug, $activity );
2018-08-25 13:31:20 +00:00
break;
2018-08-29 20:38:10 +00:00
case 'Update':
$activity = \activities\update\handle_outbox( $actor_slug, $activity );
2018-08-25 13:31:20 +00:00
break;
2018-08-29 20:38:10 +00:00
case 'Delete':
$activity = \activities\delete\handle_outbox( $actor_slug, $activity );
2018-08-25 13:31:20 +00:00
break;
2018-08-29 20:38:10 +00:00
case 'Follow':
$activity = \activities\follow\handle_outbox( $actor_slug, $activity );
2018-08-25 13:31:20 +00:00
break;
2018-08-29 20:38:10 +00:00
case 'Add':
return new \WP_Error(
'not_implemented',
2018-09-19 15:16:41 +00:00
__( 'The Add activity has not been implemented', 'pterotype' ),
array( 'status' => 501 )
);
2018-08-25 13:31:20 +00:00
break;
2018-08-29 20:38:10 +00:00
case 'Remove':
return new \WP_Error(
'not_implemented',
2018-09-19 15:16:41 +00:00
__( 'The Remove activity has not been implemented', 'pterotype' ),
array( 'status' => 501 )
);
2018-08-25 13:31:20 +00:00
break;
2018-08-29 20:38:10 +00:00
case 'Like':
$activity = \activities\like\handle_outbox( $actor_slug, $activity );
2018-08-25 13:31:20 +00:00
break;
2018-08-29 20:38:10 +00:00
case 'Block':
$activity = \activities\block\handle_outbox( $actor_slug, $activity );
2018-08-25 13:31:20 +00:00
break;
2018-08-29 20:38:10 +00:00
case 'Undo':
2018-09-26 03:46:31 +00:00
$activity = \activities\undo\handle_outbox( $actor_slug, $activity );
2018-08-25 13:31:20 +00:00
break;
2018-09-23 23:29:20 +00:00
case 'Accept':
$activity = \activities\accept\handle_inbox( $actor_slug, $activity );
break;
// For the other activities, just persist and deliver
case 'Reject':
case 'Announce':
case 'Arrive':
case 'Dislike':
case 'Flag':
case 'Ignore':
case 'Invite':
case 'Join':
case 'Leave':
case 'Listen':
case 'Move':
case 'Offer':
case 'Question':
case 'Read':
case 'TentativeReject':
case 'TentativeAccept':
case 'Travel':
case 'View':
break;
// For all other objects, wrap in a Create activity
2018-08-27 22:36:18 +00:00
default:
$create_activity = wrap_object_in_create( $activity );
2018-09-05 04:21:08 +00:00
if ( is_wp_error( $create_activity ) ) {
return $create_activity;
}
$activity = \activities\create\handle_outbox( $actor_slug, $create_activity );
2018-08-27 22:36:18 +00:00
break;
2018-08-25 13:31:20 +00:00
}
2018-08-28 22:07:04 +00:00
if ( is_wp_error( $activity ) ) {
return $activity;
}
deliver_activity( $activity );
return $res;
2018-08-28 22:07:04 +00:00
}
function get_outbox( $actor_slug ) {
global $wpdb;
// TODO what sort of joins should these be?
$results = $wpdb->get_results( $wpdb->prepare(
"
2018-09-19 21:33:20 +00:00
SELECT pterotype_activities.activity FROM pterotype_outbox
JOIN pterotype_actors
ON pterotype_actors.id = pterotype_outbox.actor_id
JOIN pterotype_activities
ON pterotype_activities.id = pterotype_outbox.activity_id
WHERE pterotype_pterotype_outbox.actor_id = %d
",
$actor_id
) );
// TODO return PagedCollection if $activites is too big
return \collections\make_ordered_collection( array_map(
function ( $result) {
return json_decode( $result->activity, true);
},
$results
) );
}
2018-08-28 22:07:04 +00:00
function deliver_activity( $activity ) {
2018-09-10 00:48:14 +00:00
\deliver\deliver_activity( $activity );
2018-09-14 01:52:13 +00:00
$activity = \activities\strip_private_fields( $activity );
return $activity;
2018-08-28 22:07:04 +00:00
}
function persist_activity( $actor_slug, $activity ) {
2018-08-28 22:07:04 +00:00
global $wpdb;
$activity = \activities\strip_private_fields( $activity );
2018-09-19 11:56:57 +00:00
$activity = \activities\create_local_activity( $activity );
2018-08-29 20:38:10 +00:00
$activity_id = $wpdb->insert_id;
$actor_id = \actors\get_actor_id( $actor_slug );
2018-09-19 21:33:20 +00:00
$wpdb->insert( 'pterotype_outbox', array(
'actor_id' => $actor_id,
'activity_id' => $activity_id,
) );
2018-08-29 21:04:24 +00:00
$response = new \WP_REST_Response();
2018-08-28 22:07:04 +00:00
$response->set_status( 201 );
2018-08-29 20:38:10 +00:00
$response->header( 'Location', $activity['id'] );
2018-08-28 22:07:04 +00:00
return $response;
}
2018-09-05 04:21:08 +00:00
function wrap_object_in_create( $actor_slug, $object ) {
$actor = \actors\get_actor_by_slug( $actor_slug );
if ( is_wp_error( $actor ) ) {
return $actor;
}
$activity = array(
'@context' => 'https://www.w3.org/ns/activitystreams',
'type' => 'Create',
'actor' => $actor,
'object' => $object
);
return $activity;
}
2018-08-21 13:17:07 +00:00
?>