diff --git a/includes/client/posts.php b/includes/client/posts.php new file mode 100644 index 0000000..abcbbe8 --- /dev/null +++ b/includes/client/posts.php @@ -0,0 +1,63 @@ +set_method('POST'); + $request->set_body( wp_json_encode( $activity ) ); + $request->add_header( 'Content-Type', 'application/ld+json' ); + $server->dispatch( $request ); + } +} + +/** +Return an object of type Article +*/ +function post_to_object( $post ) { + $object = array( + '@context' => array( 'https://www.w3.org/ns/activitystreams' ), + 'type' => 'Article', + 'name' => $post->post_title, + 'content' => $post->post_content, + 'attributedTo' => get_rest_url( + null, sprintf( '/pterotype/v1/actor/%s', PTEROTYPE_BLOG_ACTOR_SLUG ) + ), + 'url' => get_permalink( $post ), + 'summary' => $post->post_excerpt, + ); + $existing = get_existing_object( $post ); + if ( $existing ) { + $object['id'] = $existing->activitypub_id; + } + return $object; +} + +function get_existing_object( $post ) { + global $wpdb; + return $wpdb->get_row( $wpdb->prepare( + 'SELECT * FROM pterotype_objects WHERE object->"$.url" = %s', get_permalink( $post ) + ) ); +} +?> diff --git a/includes/init.php b/includes/init.php index f07b1ed..8858c0d 100644 --- a/includes/init.php +++ b/includes/init.php @@ -5,6 +5,7 @@ require_once plugin_dir_path( __FILE__ ) . 'server/api.php'; require_once plugin_dir_path( __FILE__ ) . 'server/actors.php'; require_once plugin_dir_path( __FILE__ ) . 'migrations.php'; require_once plugin_dir_path( __FILE__ ) . 'server/webfinger.php'; +require_once plugin_dir_path( __FILE__ ) . 'client/posts.php'; add_action( 'rest_api_init', function() { \api\register_routes(); @@ -27,4 +28,5 @@ add_action( 'generate_rewrite_rules', '\webfinger\generate_rewrite_rules', 111 ) add_action( 'parse_request', '\webfinger\parse_request', 111 ); add_filter( 'query_vars', '\webfinger\query_vars' ); add_action( 'well_known_webfinger', '\webfinger\handle' ); +add_action( 'transition_post_status', '\posts\handle_post_status_change', 10, 3 ); ?> diff --git a/includes/pgp.php b/includes/pgp.php index 59dfb6a..f18f8ee 100644 --- a/includes/pgp.php +++ b/includes/pgp.php @@ -20,7 +20,6 @@ function persist_key( $actor_id, $public_key, $private_key ) { } function sign_data( $data, $actor_id ) { - xdebug_break(); $secret_key = get_private_key( $actor_id ); $sig = null; openssl_sign( $data, $sig, $secret_key ); @@ -30,7 +29,7 @@ function sign_data( $data, $actor_id ) { __( 'Unable to sign data', 'pterotype' ) ); } - return $sig; + return base64_encode( $sig ); } function get_public_key( $actor_id ) { diff --git a/includes/server/activities/create.php b/includes/server/activities/create.php index 05bbf8b..27e19ac 100644 --- a/includes/server/activities/create.php +++ b/includes/server/activities/create.php @@ -2,6 +2,7 @@ namespace activities\create; require_once plugin_dir_path( __FILE__ ) . '../objects.php'; +require_once plugin_dir_path( __FILE__ ) . '../actors.php'; /* Create a new post or comment (depending on $activity["object"]["type"]), @@ -88,4 +89,18 @@ function scrub_object( $object ) { unset( $object['bto'] ); return $object; } + +function make_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; +} ?> diff --git a/includes/server/activities/delete.php b/includes/server/activities/delete.php index 56ac0cd..c70b12b 100644 --- a/includes/server/activities/delete.php +++ b/includes/server/activities/delete.php @@ -2,6 +2,7 @@ namespace activities\delete; require_once plugin_dir_path( __FILE__ ) . '../objects.php'; +require_once plugin_dir_path( __FILE__ ) . '../actors.php'; function handle_outbox( $actor, $activity ) { if ( !array_key_exists( 'object', $activity ) ) { @@ -66,4 +67,17 @@ function check_authorization( $activity ) { } return true; } + +function make_delete( $actor_slug, $object ) { + $actor = \actors\get_actor_by_slug( $actor_slug ); + if ( is_wp_error( $actor ) ) { + return $actor; + } + return array( + '@context' => 'https://www.w3.org/ns/activitystreams', + 'type' => 'Delete', + 'actor' => $actor, + 'object' => $object + ); +} ?> diff --git a/includes/server/activities/update.php b/includes/server/activities/update.php index 256e156..4b406ed 100644 --- a/includes/server/activities/update.php +++ b/includes/server/activities/update.php @@ -26,7 +26,7 @@ function handle_outbox( $actor_slug, $activity ) { array( 'status' => 400 ) ); } - $existing_object = \objects\get_object_by_actvitypub_id( $update_object['id'] ); + $existing_object = \objects\get_object_by_activitypub_id( $update_object['id'] ); if ( is_wp_error( $existing_object ) ) { return $existing_object; } @@ -92,4 +92,17 @@ function check_authorization( $activity ) { } return true; } + +function make_update( $actor_slug, $object ) { + $actor = \actors\get_actor_by_slug( $actor_slug ); + if ( is_wp_error( $actor ) ) { + return $actor; + } + return array( + '@context' => 'https://www.w3.org/ns/activitystreams', + 'type' => 'Update', + 'actor' => $actor, + 'object' => $object + ); +} ?> diff --git a/includes/server/inbox.php b/includes/server/inbox.php index e52008d..1008578 100644 --- a/includes/server/inbox.php +++ b/includes/server/inbox.php @@ -24,6 +24,7 @@ require_once plugin_dir_path( __FILE__ ) . 'activities/undo.php'; require_once plugin_dir_path( __FILE__ ) . '../util.php'; function handle_activity( $actor_slug, $activity ) { + // TODO verify the authenticity of the activity $activity = \util\dereference_object( $activity ); if ( !array_key_exists( 'type', $activity ) ) { return new \WP_Error( diff --git a/includes/server/objects.php b/includes/server/objects.php index abc4358..e0b33b2 100644 --- a/includes/server/objects.php +++ b/includes/server/objects.php @@ -145,25 +145,23 @@ function update_object( $object ) { $res = $wpdb->update( 'pterotype_objects', array( 'object' => $object_json ), - array( 'id' => $id ), + array( 'activitypub_id' => $object['id'] ), '%s', '%d' ); if ( !$res ) { return new \WP_Error( 'db_error', __( 'Failed to update object row', 'pterotype' ) ); } - $activites_res = $wpdb->query( $wpdb->prepare( - ' - UPDATE pterotype_activities - SET activity = JSON_SET(activity, "$.object", %s) - WHERE activity->"$.object.id" = %s; - ', - $object_json, $object['id'] + $referencing_activities = $wpdb->get_results( $wpdb->prepare( + 'SELECT * FROM pterotype_activities WHERE activity->"$.object.id" = %s', + $object['id'] ) ); - if ( $activities_res === false ) { - return new \WP_Error( - 'db_error', __( 'Failed to update associated activities', 'pterotype' ) - ); + if ( $referencing_activities ) { + foreach ( $referencing_activities as $activity_row ) { + $activity = json_decode( $activity_row->activity, true ); + $activity['object'] = $object; + \activities\persist_activity( $activity ); + } } return $object; } diff --git a/includes/server/outbox.php b/includes/server/outbox.php index e3cfdee..3966330 100644 --- a/includes/server/outbox.php +++ b/includes/server/outbox.php @@ -182,16 +182,6 @@ function persist_activity( $actor_slug, $activity ) { } 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; + return \activities\create\make_create( $actor_slug, $object ); } ?>