WordPress.org

Make WordPress Core

Opened 3 years ago

Last modified 2 years ago

#38276 new feature request

"Is thing public/accessible" API

Reported by: jdgrimes Owned by:
Milestone: Awaiting Review Priority: normal
Severity: normal Version: 4.7
Component: Role/Capability Keywords: dev-feedback
Focuses: Cc:
PR Number:

Description

Question: How do you check if a non-logged-in user is allowed to view something in WordPress? (Posts specifically, and also in general?)

Answer: Within WordPress there is no API for checking whether a non-logged-in user is allowed to view a post or other object.

Capabilities API

There is the role and capabilities API, but only logged-in users will have a role or any capabilities. A visitor to the site who is not logged-in will thus not have even the read capability. WP_User::has_cap( 'read' ), and thus current_user_can( 'read' ), will return false, while user_can() will peremptorily return false if the user ID passed does not exist before even calling WP_User::has_cap().

Thus, while we can check if a logged-in/existing user can view a post via the capability API, we cannot use it to check whether a non-logged-in user can view the post.

Underlying Philosophy

The underlying philosophy that is used within WordPress is that objects such as posts are public by default. Everything is accessible to everyone unless specifically restricted.

This is, in a word, a blacklist-style approach. The object is public, unless it blacklists/restricts itself in some way.

When an object is public, the capabilities API, and the concept of capabilities in general, no longer applies as to whether that object is accessible. The object is accessible by default.

The question becomes “is this post publicly visible?” rather than “does this user have the ability to view this post?"

The capabilities API, on the other hand, operates on a whitelist philosophy—nobody is allowed to do anything (and thus nobody has any capabilities), unless specifically granted permission.

These two different approaches make sense in different scenarios. However, it starts to get sticky when the two intersect. And that is exactly what happens with the read capability: we're now checking the whitelist to check a blacklist. And when the user isn't logged in, the capability isn't in the whitelist, which causes everything to get blacklisted—they don't have the capabilities to read any posts at all.

Why doesn't this explode?

Obviously, WordPress has gotten along quite well up to this point without everything flying apart though. Non-logged-in users can view public posts—otherwise you and I wouldn't be able to see about 25% of the web right now. So yes, of course non-logged-in users do get to view those posts. They are public, they aren't restricted. But they get to view them despite not having the read capability.

In other words, usually this doesn't cause any issues. That's why nobody has brought it up before (that I know of—probably they have). Why? Because usually posts are retrieved for display via WP_Query, and it bypasses the read capability. Instead, it works from the philosophy of public by default discussed above, and internally handles all of the logic for checking if the post is publicly visible or restricted from the current user. So, any time that you are using WP_Query, you will automatically get all of the posts, minus those that were restricted in some way (blacklisting, as it were).

Okay, so then who cares?

Good question. After all, shouldn't we always be using WP_Query to retrieve posts?

People not using WP_Query

Well, yes. But, what if we aren't retrieving a post? What if we have a plugin where we are storing some information that relates to a post in a separate table, and we want to display that information publicly on the site. But because that information references the post in a potentially identifying manner, we can't show it to users who can't view the post. I'd say that's a perfectly valid use-case.

So how would we check if the current user can see the information for a particular post? I know what you were about to suggest: "Use current_user_can()!" But yeah, now you know why that won't work: that's a capability check, and non-logged-in users will not have any capabilities. So non-logged-in users wouldn't be able to view the information for any of the posts, even those that they can view publicly on the site.

Now, you might say, "Just check if the post is public." Yes, and thanks for telling my how to do that. Should I use the just_check_if_the_post_is_public() function? :-) That's what this ticket is about.

People adding accessibility restrictions

Another reason to care about this is that it means that when somebody wants to restrict the visibility of posts they have to hook-in multiple places: in the capabilities API for the read cap, and for the post retrieval logic in WP_Query.

That is not the main focus of this ticket, and it may not really be practical to solve at all. However, I'm not sure how many developers realize that they need to consider both of these things.

So what do you propose?

In this ticket, I'm not really suggesting that we:

  • throw out the read capability. (Back-compat nightmare.)
  • modify the caps API to handle non-logged-in users differently. (Fundamental change in an API, probably not practical.)

I am suggesting that there is a need for a new API, to formally provide a means of determining whether a post (or any object) is publicly accessible. This API would include a function like is_thing_accessible( $thing_id ) (and perhaps is_thing_accessible_for_user( $user_id, $thing_id )).

Is that really needed?

Now, I know that some might suggest that this really isn't needed, because you can just check if the post has a public status. That is true in theory, but in practice things are more complex.

First, let me reiterate that what I'm proposing isn't just for posts, it is for any objects, of which posts are one, comments another, users another.

Secondly, using posts as an example,a plugin can add extra restrictions that cause posts with otherwise public stati to not be publicly accessible to all users. So it isn't a viable solution to just duplicate each core check that would normally apply to posts—others might be added by plugins.

For capability checks I don't have to worry about that. I just check for a particular cap and anything that affects that cap will just hook into map_meta_cap and I never have to know. But if the user is logged out I can't use the capability API, and suddenly the onus is on me to know about every possible restriction that could ever apply to a post, in order to check if the post is public. I should be able to check is_thing_accessible( $post_id ) and just forget it, same as I can do with current_user_can( 'read_post', $post_id ).

We are talking about non-logged-in users here after all. If a restriction isn't taken into account, it doesn't just mean that some less privileged users can view the object, it means that everybody can.


I brought this up and discussed it with @johnbillion in the #core channel on Slack before creating this (admittedly long-winded) ticket.

Attachments (1)

poc-1.php (1.8 KB) - added by jdgrimes 3 years ago.
Basic POC of what an API like this might look like

Download all attachments as: .zip

Change History (14)

#1 @jdgrimes
3 years ago

Another thing that I'm not proposing we do here is change the blacklist-style philosophy of WordPress where everything is public by default, unless restricted. I'd just like to see us centralize the code that restricts things from being visible, so that plugins can more easily check that.


I should note that the read capability is sort of an outlier in the caps API. All of the other core capabilities, as far as I can tell, are related create/update/delete user actions. It is only with posts that the capability API intersects with object visibility.

Again, I'm not trying to change that with this ticket, but I do wonder whether long-term we should reconsider whether the read capability should be a capability at all. Of course, an API like the one proposed here would have to exist before the read capability could ever be deprecated or anything like that, much less removed. This ticket could be a first step in that direction. But again, it doesn't have to be, I guess.


To fill in some more detail about what I envision in the is_thing_accessible() function, when I first created this ticket I was envisioning it as accepting an object ID (and I guess what type of object it was, though I left that out of the example function signatures given). Possibly then it would just wrap a filter, passing it these arguments and filtering whether the object was accessible, which would be true by default. Then the restrictions for each object type would be provided by hooking into this filter.

Now, when I created the ticket, I was kind of envisioning the is_thing_accessible() function automatically working based on the current user, kind of as a direct complement to current_user_can(). So it would also grab the current user and also pass that in to the filter. The is_thing_accessible_for_user() would then compliment the user_can() function, as it were, and allow you to pass the user ID in.

Just now though, I was wondering whether that is the correct approach. I suppose that really the user is irrelevant if we are just checking whether the object is public. If the object is public, then that means anyone can view it. It doesn't matter who the user is. So if we limit the API to only check if the object is totally public, the current user shouldn't be taken into account.

In that case the API would compliment the capability API by providing a way to check if something is publicly visible to non-logged-in users, but might not actually replace the read capability, because it wouldn't provide granular checks for different roles/capabilities of logged-in users. And I suppose that maybe that is only right.

So in other words, this would be practical logic:

$can_view = ( 
    is_thing_public( 'post', $post_id )
    || ( is_user_logged_in() && current_user_can( 'read_post', $post_id ) )
);

#2 @jdgrimes
3 years ago

One way to prevent duplication between query classes (WP_Query, for example), and this API, would be to break each visibility restriction rule out into its own class. This class would have one method that could modify the query, and another one that could analyze a given object and tell whether it was publicly accessible (for the is_thing_accessible() function/API).

Well, OK, I guess that doesn't necessarily reduce duplication, but it does centralize that duplication of logic that has to be applied differently in different circumstances. So when updating the logic for one of the circumstances (like a query), we'd be hard-pressed to forget to update the logic for the other scenario (object check) accordingly.

There are then other cool possibilities, like having each rule provide a human-readable description of itself (another method on the rule object). Then we could tell a user why they couldn't view a particular post using this information. (If a plugin added an additional rule, that would automatically be incorporated.) Another use-case would be telling an admin that even though they can view a particular object, not everybody can, only users who this, this, and this. Though with that example, I guess I'm talking about this not being a user-agnostic boolean check again.

#3 follow-up: @PieWP
3 years ago

In regards of combining the WP_Query and the is_thing_accessable():

Keeping the Query filter aligned with a custom callback as suggested is quite hard. You often have to modify the query in strange ways typing actual custom SQL; which in its turn might cause SQL errors for many reasons. In addition to that your callback gets modified by the entire codebase due to filters. So the callback you initially set up might easily dealign when installing other plugins who (unintentionally) dealign your is_thing_accessable() check.

these are the issues I encountered with our client for whom we build a similar extension

p.s. I actually also don't trust other people with extending the Query / writing SQL, think of the SQL injections ;P

Alternative approach

An alternative approach would be to use a binary system similar to for instance your file system capabilities. Thing is that your check is way more complex so it would be more similar to the error_setting value in your php.ini. In this solution you would map every capability to a prime number, your current rights would be a sum of this prime number which you could compare against a new column within the database.

Using these a binary tree you get a common divider shared within the meta_caps which you can use in your is_thing_accessable and in your WP_Query. This mapping from capability to a binary would obviously occure under 'under water' to keep it as user friendly as possible.

The massive issue of this approach is: how do you build the binary tree? Your capability should always have the same binary value assigned to it; otherwise you would get a mismatch in your rights. That would hint towards storing a mapper in an option, which is fine until you try to transfer or import the posts from another system. How would you merge or handle capabilites whom are not known in the imported system? Or how would you handle the 'read' capability which has a value of '1' in your system but a value of '3' in the imported system? (although this ticket would effect importing in some way regardless of the chosen solution)

Pro Con
+ Using binary comparisons your database queries will remain fast - How to build up the binary tree in a stable way?
+ compare issues between code and database solved - not very human readable values
+ Very easy in usage for new WP developers
Last edited 3 years ago by PieWP (previous) (diff)

#4 in reply to: ↑ 3 @jdgrimes
3 years ago

Replying to PieWP:

In regards of combining the WP_Query and the is_thing_accessable():

Keeping the Query filter aligned with a custom callback as suggested is quite hard. You often have to modify the query in strange ways typing actual custom SQL; which in its turn might cause SQL errors for many reasons. In addition to that your callback gets modified by the entire codebase due to filters. So the callback you initially set up might easily dealign when installing other plugins who (unintentionally) dealign your is_thing_accessable() check.

Yes, I had considered the possibility that this would require abstracting out SQL strings, though I'm not sure exactly what that would look like since I haven't investigated exactly what WP_Query is doing here (though I'm about to do that now).

these are the issues I encountered with our client for whom we build a similar extension

p.s. I actually also don't trust other people with extending the Query / writing SQL, think of the SQL injections ;P

True, but filters already exist that pass in the raw query before it is sent to the database. Probably most devs who would break them horribly don't know that they exist though. So yeah, that may be ea valid concern.

Alternative approach

I don't think that approach would be feasible for WordPress core, because of the issues with making the binary tree stable, especially when plugins want to add their own rules.

It is also a bit beyond what I was envisioning for this ticket. I wasn't really planning to completely change what WordPress looks at in order to determine whether a post is public, just to abstract that logic out so that it is more accessible. I hope such a fundamental change wouldn't be necessary, though perhaps it is. But if so, I have a feeling that the core devs would see it as too much work for too little benefit. As I investigate this further, I'll get a better idea of whether something like that would be necessary or not.

#5 follow-up: @jdgrimes
3 years ago

Taking a look at the list of core capabilities, I have confirmed that read is pretty unique. The only other caps that would really relate at all to read and not just create/update/delete actions would be list_users and perhaps the manage_* caps.

That is just useful information to consider in determining the ultimate scope of this ticket. The most narrow scope would be to create an is_post_public() function, that only works for posts and returns a boolean value. The broadest scope would be to create an is_thing_accessible() function, that works for all types of objects and determines whether the object is accessible to a particular user, not just whether the object is public. In between the two extremes would be the is_post_accessible() and is_thing_public() functions.

The fact that only the posts really have a read capability might indicate that while a broader API is useful, in terms of core it isn't really needed. However, we could also look at that conversely: if we are going to do an is_thing_public() API as opposed to just an is_post_pubic() API, it makes sense to go full-blown is_thing_accessible(). Because for non-post objects, there is no current_user_can( 'read_other_object' ) to fall back to for providing more granular accessibility checking for logged-in users, like there would be the read_post cap for posts. In other words, we'd be able to do a basic check as to whether something is public, but we wouldn't be able to check whether a particular user could still view that non-public thing. Unless of course we add more read-type caps to capability API for other objects. But honestly I don't know that we want to encourage that.

#6 in reply to: ↑ 5 ; follow-up: @PieWP
3 years ago

Replying to jdgrimes:

Unless of course we add more read-type caps to capability API for other objects. But honestly I don't know that we want to encourage that.

The first thing people will ask (once is_post_accessible() is introduced) will be: why can't I do this for terms/taxonomies?So let me ask the question in advance: Why would it make sense to hide a post but not to hide a term?

Quite similar to the term_meta which was recently introduced (and already saw a request for term_relationship_meta passing by). With WP becoming more and more Object Orientated I can only assume we will see a WP_Taxonomy class soon; which will contain a similar cap attribute compared to the WP_Post_Type class.

Please note I'm not trying to bash by questioning everything, just really want this feature to be introduced. My daily work involves making business portals based on WP so features like this are quite handy.

#7 @jdgrimes
3 years ago

How WP_Query handles visibility

There are three primary elements that play a role:

  • Post passwords — These don't actually hide the post itself, but they do obscure its contents.
  • Post statuses — These can be public, private, protected, or excluded from searches.
  • The perm query arg — This can be 'readable' or 'editable', or empty (which it is by default, and which basically indicates "all posts").

It is important to keep in mind that WP_Query functions to both query posts, and also retrieve individual posts. For this reason, some of the logic that relates to post visibility is duplicated, to optimize based on which of these use-cases a query instance is for. Our main concern here is how to relate these checks to an individual post, but in WP_Query the logic may not all be expressed in relation to just a single post. That's not a problem, it is just something to keep in mind so that we make sure we don't miss any relevant logic.

Post Passwords

The simplest and most straightforward logic revolves around posts with passwords. So we'll tackle that first. There are two references to post passwords. The first is in WP_Query::parse_search(), which causes password-protected posts to be excluded when the query is a search query (i.e., s query arg is being used to search for words in post content), and the user is not logged in. Again, the post content is what is hidden by the password, so that is being excluded from searching. Posts with passwords aren't otherwise excluded from queries. The only other place that post passwords are referenced is in WP_Query::get_posts(), where the post_password and has_password query args are handled. The latter is apparently unrestricted, while the former will cause the perm arg to be set to 'readable'. More on that below.

Basically, post passwords, though they do relate to the visibility of post contents, do not relate to the visibility of posts themselves. This means that we can ignore them in relation to an is_thing_accessible() API. Or better yet, we can think about the potential for an is_object_attribute_accessible() feature of the API. I think post passwords and other methods of restricting both post contents and other object attributes demonstrates that the potential usefulness of such an API exists.

Post Statuses

The log for post statuses is split for $this->is_single and non-$this->is_single queries, as mentioned above.

First, we'll consider the logic that is applied when the query is_single || is_page. What happens is that the object for the post's status is retrieved, and if $post_status_obj->public is true, no further action is taken. However, if the post status is not public, other logic kicks in. This other logic can be circumvented by the logic for the post_status query arg, whose handling we'll consider below, with the logic that is applied when a query that is not for a single post. But assuming that the post_status query arg hasn't been passed, it pretty much breaks down to this:

  • public status — Anyone can view. Note that if it isn't public and the user isn't logged in, they can't view the post. It's that simple.
  • protected status — The user must be logged in, and they must have the edit_post capability for that post.
  • private status — The user must be logged in, and they must have the read_post capability for that post.

Don't forget though that there was a caveat in there: this logic is only applied if the post_status query arg hasn't been passed. That's because further up there is some complex logic relating to the post_status query arg which is applied both when querying for a single post and when querying for multiple posts. In that case, the query has specifically asked for a particular post status, and so it will get it, regardless of user permissions, unless the perm query arg is also set (which it isn't by default). We'll look more at the perm query arg below. But basically, the post_status arg is designed to allow a query to override the default permissions that would normally apply to posts. So it really isn't important for us to consider it too deeply in regard to post accessibility checks.

There is one more piece of logic that involves posts statuses, which is only applied when the post_status query arg isn't used and when $this->is_singular is false. This logic basically duplicates that which is applied when is_single || is_page, discussed above. All public statuses are included by default, private statuses are only shown to users who can read_private_posts or when the current user is the post author (essentially what it means to have the read_post capability for a private post). The main difference is that protected statuses are only shown in the admin, and only if the post type specifically requests it. Again, all of this only applies to generic queries, not checking the ability of a user to access a particular post. So it isn't particularly important in the development of an is_thing_accessible() API. One takeaway though is that here WP_Query basically reproduces the logic it expects the capabilities API to apply to posts, just in query form. This reminds us again that a filter on map_meta_cap, or changes to map_meta_cap() itself, won't automatically be reflected in WP_Query.

The perm Query Arg

As you might have gleaned from the above discussion, the perm query arg is only applied when the post_status query arg is set. The post_status query arg's only job is to override default handling for post permissions, and the perm arg dictates how aggressive it is in this. As noted above, this logic isn't particularly important to us, but I'm addressing it here for clarity. It can take three values:

  • empty — This is the default, and it indicates that a the post statuses in post_status should be included without any permission checks at all. Only post statuses that have specifically requested to be excluded from searches may be left out.
  • editable — This will cause only posts that the current user would have the capabilities to edit to be included.
  • readable — This will cause only posts that the current user would have the capabilities to read to be included.

So once again WP_Query basically replicates the logic that it expects the capabilities API to apply to posts, just in query form.

Again, I've only addressed this for completeness, it isn't our main focus in this ticket.

Discussion

Three main takeaways:

  • We should probably consider an is_thing_attribute_accessible() API, cf. password-protected posts.
  • Post statuses are the only visibility restricting thing that WP_Query takes into account for posts themselves (as opposed to password-protected post content).
  • Post statuses are either totally public, or they are restricted, which always falls back to the capabilities API.

The implications of the latter two points is that currently WordPress is designed to only restrict post visibility based on post statuses. While it is possible for plugins to imagine all sorts of other things that might dictate post visibility, the only method that WordPress provides is a binary choice of an always-public status or an always-restricted (though possibly to varying degrees) status. Plugins can hook into the Query API, and/or into the Capabilities API, in order to provide handling for other situations. However, both of these APIs only allow the plugin to implement restrictions, neither of them makes it possible for it to indicate when a post is public.

The post status API does, but is simply not a fit for every time that a plugin wants to restrict post visibility. That is why an "is thing public" API is needed: it will not just wrap the post status API, it will also allow plugins to more confidently tinker with post visibility through custom means. More confidently, because they will be able to hook into the is_thing_accessible() API to provide that public vs restricted information for objects, so that it can actually be conveyed to other plugins in this way. Which again, as we've shown above, neither the caps nor query API do.

#8 in reply to: ↑ 6 @jdgrimes
3 years ago

Replying to PieWP:

Replying to jdgrimes:

Unless of course we add more read-type caps to capability API for other objects. But honestly I don't know that we want to encourage that.

The first thing people will ask (once is_post_accessible() is introduced) will be: why can't I do this for terms/taxonomies?So let me ask the question in advance: Why would it make sense to hide a post but not to hide a term?

I agree with this, though I haven't been entirely sure that this ticket should go whole-hog or whether that would be biting off more that anybody is willing to chew (I'm thinking more and more that we should though).

My point in that particular quote though, was more that I question whether the capability API, specifically, is really a good fit for visibility restrictions. As opposed to this proposed API, which is somewhat separate. Because visibility restrictions are things that we want to check against non-logged-in users, and the capability API has no application to non-logged-in users. So although the two currently intersect with the post statuses and read_post, I'm not sure that this is a pattern that we want to start using for other objects, or whether going forward it would be better to keep the capabilities solely about what somebody is allowed to do, and the accessibility API proposed here deal with what one is allowed to see.

Although, that does make me wonder whether some "can user do" checks couldn't possibly relate to non-logged-in users as well (in other words, some actions can be public just as some objects can). But as I said in the OP, changing the capabilities API as a whole to apply to non-logged-in users would probably break too much stuff. I dunno though, maybe that angle should be explored more as well.

Please note I'm not trying to bash by questioning everything, just really want this feature to be introduced. My daily work involves making business portals based on WP so features like this are quite handy.

No worries, I really appreciate your input. :-)

@jdgrimes
3 years ago

Basic POC of what an API like this might look like

#9 follow-up: @jdgrimes
3 years ago

  • Keywords dev-feedback added
  • Summary changed from "Is thing public" API to "Is thing public/accessible" API

Another benefit of "is accessible" vs just "is public" is that it allows for more granular rules in relation to non-logged-in users as well. In other words, strictly speaking, if something is public, it is public for all non-logged-in users. With an "is accessible for user" API, that doesn't have to be the case, the IP of the current non-logged-in user can be taken into account, etc. I don't see any reason to arbitrarily restrict ourselves to building an "is public" API, when an "is accessible" API can be build on the same basic structure but provides many more opportunities for usefulness.


I think maybe we should think of this ticket more like a "feature project" then a regular ticket. When it comes to fleshing out the API in more detail, we might indeed want to branch out onto GitHub, and then come back here with t he finished patch. First though, I want to get a very basic POC up and get a few more eyes on this ticket, to see if others (especially committers) feel that it is headed in the right direction.


Actually, yeah, I just added a basic POC: poc-1.php. It's purpose is just to give something more tangible to help people understand what exactly we are talking about here. The final implementation might be completely different, but it should ultimately provide the same information to anything that calls it: whether the item is accessible to the user.

Notes:

The logic for posts from WP_Query condenses down to be unexpectedly simple. The raw logic that would come from WP_Query would be more complex, looking something like this:

<?php
                $status = get_post_status( $post_id );
                $post_status = get_post_status_object( $status );

                if ( $post_status->public ) {
                        $is_accessible = true;
                } elseif ( $post_status->protected ) {
                        $is_accessible = user_can( $user_id, 'edit_post', $post_id );
                } elseif ( $post_status->private ) {
                        $is_accessible = user_can( $user_id, 'read_post', $post_id );
                } else {
                        $is_accessible = false;
                }

The reason for the extra complexity there is that WP_Query's logic attempts to take a short-cut by anticipating some of the logic in the capabilities API. In other words, instead of just leaving all of the handling for non-public post statuses to the capabilities API, it applies its own logic intended to be roughly equivalent to what the capabilities API would do. This once again demonstrates a lack of unity in the post accessibility "API" as it currently stands. Anybody wanting to influence that logic has to do so in multiple locations.

The logic in WP_Query is basically equivalent to the default logic in map_meta_cap(), but there is one difference: if the post's status is not public, private, or protected, then it is excluded entirely. In map_meta_cap() such a post status would be less restricted, defaulting to the read capability for that post type if the user was the author, or user_can( 'edit_post' ) otherwise. This may be intentional, since WP_Query does choose to exclude some posts that are otherwise accessible to the user, for various reasons (like they aren't intended to be searchable in that way).

(Note that this also brings to light something that might be worth considering in building this API, and that is that post accessibility doesn't equal post searchability. The post may be accessible to the user in general, but that might not mean that it should be made accessible to them in every context and by every means. Something to think about.)

Anyway, in the POC I haven't made any assumptions in regard to the caps API like this, but instead fall back on it directly if the post status isn't public. I believe that this is the correct behavior, at least in the context of this API.

This ticket was mentioned in Slack in #core by jdgrimes. View the logs.


3 years ago

#11 @johnjamesjacoby
3 years ago

There is an exist capability that is assumed truthy by default, that concludes all users are allowed to exist.

Visitors that are not logged in are, IMO, a safe on/off check. The only use/case for caps for logged-out users is a cookie based thing ala comments (and allowing previous commenters to comment unmoderated.)

Once a visitor is no longer a human with intent, but rather a machine with programmed purpose, I think you're right that the boundaries start to get fuzzy.

There's a lot to read through here to catch-up, so I'd like to do that before commenting more in-depth as to not accidentally sidetrack any efforts here.

#12 @Kenshino
3 years ago

Ditto - need some time to read through and comment back.

My general thoughts are - other enterprise CMS I used to work with does have some sort of a is_public() check. So I'm thinking why not WordPress? Let me do some digging around.

#13 in reply to: ↑ 9 @jdgrimes
2 years ago

[These were notes I had written down soon after the OP, and just never posted them.]

Replying to jdgrimes:

(Note that this also brings to light something that might be worth considering in building this API, and that is that post accessibility doesn't equal post searchability. The post may be accessible to the user in general, but that might not mean that it should be made accessible to them in every context and by every means. Something to think about.)

Thinking more about this, anything that hooks into the API could base whether something is accessible on the current application state, of course. But that is different than knowing exactly what context the accessibility check is in reference to. In other words, are we checking:

  • whether the user can view the post,
  • whether they can view the post in the admin,
  • or whether they can view the post in a particular list table in the admin (for example)?

The basic API I've been envisioning here is mainly about that first, most general case. The second case could also in theory be implemented with it as well, in the sense that a different result could be returned based on is_admin() or other things relating to application state. The problem is when we get into more granular checks like the third case, where what particular context we are going to display the item in may or may not be apparent just from the current application state.

Of course, individual contexts in which an item is displayed can provide their own method of letting something hook in and affect whether an item should be displayed in that context.

I guess that really, this would be starting to intersect whether a user can view something with whether it is supposed to be displayed. Which are really two different things.


In regard to attribute visibility, one of the use-cases I was thinking of was when plugins provide shortcodes that are used in post content that hide all or most of the context. However, when they only hide part of the content, things become more complex.

Note: See TracTickets for help on using tickets.