Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 69 additions & 2 deletions src/SEOPress.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Yard\Brave\Hooks;

use Yard\Brave\Hooks\Traits\ParentPage;
use Yard\Hook\Action;
use Yard\Hook\Filter;

#[Plugin('wp-seopress-pro/seopress-pro.php')]
Expand Down Expand Up @@ -41,10 +42,76 @@ public function addBreadcrumb(array $breadcrumbs): array
#[Filter('seopress_capability')]
public function dashboardOptions(string $cap, string $context): string
{
if ('menu' == $context || 'bot' == $context) {
$cap = 'edit_posts';
if (! is_admin()) {
return $cap;
}

// Lower the main SEO menu cap from manage_options to edit_redirections so roles without manage_options can access it.
if ('menu' === $context && 'manage_options' === $cap) {
return 'edit_redirections';
}
Comment thread
Copilot marked this conversation as resolved.
Comment on lines +49 to 52

return $cap;
}

/**
* Removes the SEOPress Dashboard and License submenu pages for users without manage_options.
*
* Both pages use seopress_capability('manage_options', 'menu') which our filter lowers to
* edit_redirections, making them visible to restricted users. They serve no purpose for those
* users, so we remove them from the menu here.
*/
#[Action('admin_menu', 99)]
public function removeRestrictedMenuPages(): void
{
if (current_user_can('manage_options')) {
return;
}

remove_submenu_page('seopress-option', 'seopress-option');
remove_submenu_page('seopress-option', 'seopress-license');
}

/**
* Maps the edit_posts capability of the seopress_bot post type to edit_broken_links.
*
* seopress_bot uses capability_type => 'post', so WordPress checks edit_posts when a user
* navigates to edit.php?post_type=seopress_bot. Non-admin users with only edit_broken_links
* do not have edit_posts and are blocked. Remapping to edit_broken_links aligns the broken-links
* list access with the redirections list access level.
*/
#[Filter('register_post_type_args')]
public function makeBotPostTypeAccessible(array $args, string $postType): array
{
if ('seopress_bot' !== $postType) {
return $args;
}

$args['capabilities']['edit_posts'] = 'edit_broken_links';

return $args;
}

/**
* Registers the seopress_404 post type on init for users without manage_options.
*
* SEOPress registers this post type on init for manage_options users, but falls back to admin_init
* for others (redirections.php). WordPress validates admin pages such as edit.php?post_type=seopress_404
* before admin_init fires, so for those users the post type does not exist yet and WordPress blocks
* access to the page. Registering unconditionally on init matches the timing SEOPress uses for
* privileged users; post_type_exists() prevents double registration.
*/
#[Action('init', 10)]
public function registerRedirectionsPostType(): void
{
if (! is_admin() || current_user_can('manage_options')) {
return;
}

if (post_type_exists('seopress_404') || ! function_exists('seopress_404_fn')) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

|| ! function_exists('seopress_404_fn') kan evt aan de if statement hierboven toegevoegd worden toch?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Ik vind de 2 if statements nu goed verdeeld, eerst de admin checks en daarna die van SeoPress.

return;
}

seopress_404_fn();
}
Comment thread
Copilot marked this conversation as resolved.
}
Loading