errors * * @var string */ private $error; /** * A list of errors * * @var array */ private $errors; /** * The WordPress User ID, or 0 for whole site. * @var int */ private $user_id; /** * Maps the meta fields to the local db fields * * @var array */ private $map_meta = array( 'name' => 'name', 'preferredUsername' => 'username', 'inbox' => 'inbox', 'url' => 'url', ); /** * Constructor * * @param string|WP_Post $actor The Actor-URL or WP_Post Object. * @param int $user_id The WordPress User ID. 0 Represents the whole site. */ public function __construct( $actor ) { $post = null; if ( \is_a( $actor, 'WP_Post' ) ) { $post = $actor; } else { global $wpdb; $post_id = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE guid=%s", esc_sql( $actor ) ) ); if ( $post_id ) { $post = get_post( $post_id ); } else { $this->actor = $actor; } } if ( $post ) { $this->id = $post->ID; $this->actor = $post->guid; $this->updated_at = $post->post_modified; } } /** * Magic function to implement getter and setter * * @param string $method The method name. * @param string $params The method params. * * @return void */ public function __call( $method, $params ) { $var = \strtolower( \substr( $method, 4 ) ); if ( \strncasecmp( $method, 'get', 3 ) === 0 ) { if ( empty( $this->$var ) ) { return $this->get( $var ); } return $this->$var; } if ( \strncasecmp( $method, 'set', 3 ) === 0 ) { $this->$var = $params[0]; } } /** * Magic function to return the Actor-URL when the Object is used as a string * * @return string */ public function __toString() { return $this->get_actor(); } /** * Prefill the Object with the meta data. * * @param array $meta The meta data. * * @return void */ public function from_meta( $meta ) { $this->meta = $meta; foreach ( $this->map_meta as $remote => $internal ) { if ( ! empty( $meta[ $remote ] ) ) { $this->$internal = $meta[ $remote ]; } } if ( ! empty( $meta['icon']['url'] ) ) { $this->avatar = $meta['icon']['url']; } if ( ! empty( $meta['endpoints']['sharedInbox'] ) ) { $this->shared_inbox = $meta['endpoints']['sharedInbox']; } elseif ( ! empty( $meta['inbox'] ) ) { $this->shared_inbox = $meta['inbox']; } $this->updated_at = \time(); } /** * Get the data by the given attribute * * @param string $attribute The attribute name. * * @return mixed The attribute value. */ public function get( $attribute ) { if ( ! is_null( $this->$attribute ) ) { return $this->$attribute; } $attribute_value = get_post_meta( $this->id, $attribute, true ); if ( $attribute_value ) { $this->$attribute = $attribute_value; return $attribute_value; } $attribute_value = $this->get_meta_by( $attribute ); if ( $attribute_value ) { $this->$attribute = $attribute_value; return $attribute_value; } return null; } /** * Get a URL for the follower. Creates one out of the actor if no URL was set. */ public function get_url() { if ( $this->get( 'url' ) ) { return $this->get( 'url' ); } $actor = $this->get_actor(); // normalize $actor = ltrim( $actor, '@' ); $parts = explode( '@', $actor ); return sprintf( 'https://%s/@%s', $parts[1], $parts[0] ); } /** * Set new Error * * @param mixed $error The latest HTTP-Error. * * @return void */ public function set_error( $error ) { $this->errors = array(); $this->error = $error; } /** * Get the errors. * * @return mixed */ public function get_errors() { if ( $this->errors ) { return $this->errors; } $this->errors = get_post_meta( $this->id, 'errors' ); return $this->errors; } /** * Reset (delete) all errors. * * @return void */ public function reset_errors() { delete_post_meta( $this->id, 'errors' ); } /** * Count the errors. * * @return int The number of errors. */ public function count_errors() { $errors = $this->get_errors(); if ( is_array( $errors ) && ! empty( $errors ) ) { return count( $errors ); } return 0; } /** * Return the latest error message. * * @return string The error message. */ public function get_latest_error_message() { $errors = $this->get_errors(); if ( is_array( $errors ) && ! empty( $errors ) ) { return reset( $errors ); } return ''; } /** * Get the meta data by the given attribute. * * @param string $attribute The attribute name. * * @return mixed $attribute The attribute value. */ public function get_meta_by( $attribute ) { $meta = $this->get_meta(); if ( ! is_array( $meta ) ) { return null; } // try mapped data (see $this->map_meta) foreach ( $this->map_meta as $remote => $local ) { if ( $attribute === $local && isset( $meta[ $remote ] ) ) { return $meta[ $remote ]; } } return null; } /** * Get the meta data. * * @return array $meta The meta data. */ public function get_meta() { if ( $this->meta ) { return $this->meta; } return null; } /** * Update the current Follower-Object. * * @return void */ public function update() { if ( ! $this->updated_at ) { $this->updated_at = \time(); } $this->save(); } /** * Save the current Follower-Object. * * @return void */ public function save() { $args = array( 'ID' => $this->id, 'guid' => $this->actor, 'post_title' => $this->get_name(), 'post_author' => 0, 'post_type' => Followers::POST_TYPE, 'post_content' => wp_json_encode( $this->meta ), 'post_modified' => gmdate( 'Y-m-d H:i:s', $this->updated_at ), 'meta_input' => $this->get_post_meta_input(), ); $post_id = wp_insert_post( $args ); $this->id = $post_id; } /** * Upsert the current Follower-Object. * * @return void */ public function upsert() { if ( $this->id ) { $this->update(); } else { $this->save(); } } /** * Delete the current Follower-Object. * * @return void */ public function delete() { wp_delete_post( $this->id ); } /** * Update the post meta. * * @return void */ protected function get_post_meta_input() { $attributes = array( 'inbox', 'shared_inbox', 'avatar', 'name', 'username' ); $meta_input = array(); foreach ( $attributes as $attribute ) { if ( $this->get( $attribute ) ) { $meta_input[ $attribute ] = $this->get( $attribute ); } } if ( $this->error ) { if ( is_string( $this->error ) ) { $error = $this->error; } elseif ( is_wp_error( $this->error ) ) { $error = $this->error->get_error_message(); } else { $error = __( 'Unknown Error or misconfigured Error-Message', 'activitypub' ); } $meta_input['errors'] = array( $error ); } return $meta_input; } }