namespace = CampaignRoute::NAMESPACE; } /** * @since 4.13.0 add schema * @since 4.0.0 */ public function register_routes() { register_rest_route( $this->namespace, '/' . CampaignRoute::CAMPAIGN . '/comments', [ [ 'methods' => WP_REST_Server::READABLE, 'callback' => [$this, 'get_items'], 'permission_callback' => '__return_true', // Public endpoint; access is validated inside get_items() based on campaign status and page privacy. 'args' => [ 'id' => [ 'type' => 'integer', 'required' => true, 'sanitize_callback' => 'absint', ], 'perPage' => [ 'type' => 'integer', 'required' => false, 'sanitize_callback' => 'absint', ], 'anonymous' => [ 'type' => 'boolean', 'required' => false, 'default' => true, ], ], ], 'schema' => [$this, 'get_public_item_schema'], ] ); } /** * @since 4.14.6 check campaign status to block comments on inactive campaigns for non-admins * @since 4.0.0 * * @throws Exception * * @return WP_REST_Response|WP_Error */ public function get_items($request) { $campaignId = $request->get_param('id'); $perPage = $request->get_param('perPage'); $anonymous = $request->get_param('anonymous'); $campaign = Campaign::find($campaignId); if (!$campaign) { $response = new WP_Error('campaign_not_found', __('Campaign not found', 'give'), ['status' => 404]); return rest_ensure_response($response); } $canViewPrivate = UserPermissions::campaigns()->canViewPrivate(); if (!$campaign->status->isActive() && !$canViewPrivate) { return rest_ensure_response( new WP_Error( 'rest_forbidden', __('You do not have permission to view this campaign.', 'give'), ['status' => CampaignPermissions::authorizationStatusCode()] ) ); } $query = (new CampaignDonationQuery($campaign)) ->joinDonationMeta(DonationMetaKeys::DONOR_ID, 'donorIdMeta') ->joinDonationMeta(DonationMetaKeys::COMMENT, 'commentMeta') ->joinDonationMeta(DonationMetaKeys::ANONYMOUS, 'anonymousMeta') ->leftJoin('give_donors', 'donorIdMeta.meta_value', 'donors.id', 'donors'); if (!$anonymous) { $query->where('anonymousMeta.meta_value', '1', '!='); } $query->where('commentMeta.meta_value', '', '!='); $query->whereIsNotNull('commentMeta.meta_value'); $query->select( 'donorIdMeta.meta_value as donorId', 'commentMeta.meta_value as comment', 'anonymousMeta.meta_value as anonymous', 'donation.post_date as date', 'donors.name as donorName', 'donors.email as email' ); $donations = $query->limit($perPage)->getAll(); $formattedComments = array_map(function ($donation) { $donorName = $donation->anonymous === '1' ? __('Anonymous') : $donation->donorName; $avatarEmail = $donation->anonymous === '1' ? '' : ($donation->email ?? ''); return [ 'donorName' => $donorName, 'comment' => $donation->comment, 'anonymous' => $donation->anonymous === '1', 'date' => human_time_diff(strtotime($donation->date)), 'avatar' => (string) get_avatar_url($avatarEmail), ]; }, $donations); $items = new WP_REST_Response($formattedComments); return rest_ensure_response($items); } /** * @since 4.13.0 */ public function get_item_schema(): array { return [ '$schema' => 'http://json-schema.org/draft-04/schema#', 'title' => 'givewp/campaign-comments', 'description' => esc_html__('Provides comments for a specific campaign.', 'give'), 'type' => 'object', 'properties' => [ 'id' => [ 'type' => 'integer', 'description' => esc_html__('The Campaign ID.', 'give'), 'required' => true, ], 'perPage' => [ 'type' => 'integer', 'description' => esc_html__('Comments per page', 'give'), ], 'anonymous' => [ 'type' => 'boolean', 'description' => esc_html__('Include anonymous comments', 'give'), ], ], ]; } }