Skip to content

Conversation

@jonwaldstein
Copy link
Contributor

@jonwaldstein jonwaldstein commented Dec 15, 2025

Resolves: GIVE-3021

Description

This should solve all our Give user role problems 🤞

For context, our custom give user roles have been around since the beginning of time. Over time, we have gotten out of sync with user roles/caps and the features we have. This PR tries to correct that by digging through the depths of GiveWP and updating all the permission checks to utilize a centralized UserPermission facade.

Affects

  • Everything 😬
  • The give_worker role has migration to replace edit_give_payments with view_give_payments

Visuals

GiveWP Role Permissions Matrix

Donations

Role View Edit Delete
Administrator
GiveWP Manager
GiveWP Accountant
GiveWP Worker
GiveWP Donor

Donors

Role View Edit Delete
Administrator
GiveWP Manager
GiveWP Accountant
GiveWP Worker
GiveWP Donor

Forms

Role View Edit Delete Publish
Administrator
GiveWP Manager
GiveWP Accountant
GiveWP Worker
GiveWP Donor

Reports

Role View Export
Administrator
GiveWP Manager
GiveWP Accountant
GiveWP Worker
GiveWP Donor

Settings & Tools

Role Manage Settings View Sensitive Data
Administrator
GiveWP Manager
GiveWP Accountant
GiveWP Worker
GiveWP Donor

Testing Instructions

ZIP: https://github.com/impress-org/givewp/actions/runs/20375958542

We need to test every user role scenario outlined here:
https://givewp.com/documentation/core/give-user-roles/

Pre-review Checklist

  • Acceptance criteria satisfied and marked in related issue
  • Relevant @unreleased tags included in DocBlocks
  • Includes unit tests
  • Reviewed by the designer (if follows a design)
  • Self Review of code and UX completed

@jonwaldstein jonwaldstein changed the title refactor: update campaign permissions with new facade refactor: update Give permissions with new facade Dec 18, 2025
@jonwaldstein jonwaldstein changed the title refactor: update Give permissions with new facade Fix: make Give 4.0+ compatible with legacy user roles Dec 18, 2025
@jonwaldstein jonwaldstein marked this pull request as ready for review December 18, 2025 19:18
@glaubersilva glaubersilva self-requested a review December 18, 2025 19:22
@glaubersilva
Copy link
Contributor

@jonwaldstein I started an initial overview, but I will need more time, so I'll keep checking it tomorrow. What I can see now is that in the PR descriptions says that the GiveWP Worker role can't view forms, but in the docs, we have this information for this same role: Read/Edit/Delete/Publish GiveWP Forms

@jonwaldstein
Copy link
Contributor Author

jonwaldstein commented Dec 18, 2025

@glaubersilva thanks man! take your time. I think that's a typo in the description from my personal assistant 😏 - I'll update it

Copy link
Contributor

@glaubersilva glaubersilva left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jonwaldstein This is a great and massive work! Thanks for getting some time to tackle this beast. Overall, everything looks right to me. I just left some comments and questions about possible improvements.


// Check REST API route for post ID (e.g., /wp/v2/pages/123)
if (defined('REST_REQUEST') && REST_REQUEST) {
$cachedPostId = $this->getPostIdFromRestRoute();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if we can use get_queried_object() or get_queried_object_id(); instead of $this->getPostIdFromRestRoute() since these methods are used inside the rest_get_queried_resource_route() method to compose the route URL.

Copy link
Contributor Author

@jonwaldstein jonwaldstein Dec 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a great question! I had to investigate this. Apparently get_queried_object does not work within this request nor will rest_get_queried_resource_route because they operate in a different kind of request geared towards the frontend. I had opus explain this to me in laymans terms because I was confused LOL

Think of WordPress as having two different doors for incoming requests:

Door 1: The Front Door (Normal page visits)

  1. When someone visits yoursite.com/my-campaign-page/:
  2. WordPress says "Someone wants to see a page!"
  3. WordPress looks up which page, loads it, and remembers: "We're showing page #123"
  4. get_queried_object() asks: "What are we showing?" → WordPress answers: "Page #123"

Door 2: The Side Door (REST API calls)

  1. When the block editor calls yoursite.com/wp-json/wp/v2/pages/123:
  2. WordPress says "This is an API call, not a page visit"
  3. WordPress hands it off to the REST server, which reads the URL directly
  4. WordPress never bothers to remember "we're showing page #123"—it's just an API call
  5. get_queried_object() asks: "What are we showing?" → WordPress says: "¯\(ツ)_/¯ Nothing, this isn't a page visit"

The Bottom Line:
get_queried_object() only works when someone is visiting a page. During an API call, nobody is "visiting" anything—it's just data being requested. WordPress doesn't track it the same way.
So you have to read the URL yourself to find the 123.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice analogy! Living and learning. hahaha

@jonwaldstein
Copy link
Contributor Author

@glaubersilva thanks man!, ready for re-review 🪇

Copy link
Contributor

@glaubersilva glaubersilva left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jonwaldstein Great job man! It's ready to be intensively tested by QA now. 😅 🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants