<?php
/**
 * Let per-page grant holders duplicate the pages they look after.
 *
 * WordPress has no way to draft changes to a page that is already live, so the
 * working method is: duplicate the page, edit the copy, then paste the finished
 * content back over the original. That needs the Duplicate Post plugin, which
 * gates on a single global `copy_posts` capability — and grant holders have no
 * roles, so they had none of it.
 *
 * Three things make this safe rather than a hole:
 *
 *  1. Duplicate Post is configured with `duplicate_post_copystatus = 0`, so a
 *     copy is always created as a DRAFT. Nothing becomes public by duplicating.
 *  2. Its meta blacklist is empty, so `bw_editors` copies to the duplicate —
 *     the person who made the copy can edit it, and nobody else gains access.
 *  3. `copy_posts` is global and the plugin never checks permission on the post
 *     being copied (`Permissions_Helper::is_current_user_allowed_to_copy()` is
 *     nothing but `current_user_can( 'copy_posts' )`). So the per-post check it
 *     lacks is added below — on the action itself, not merely on the link,
 *     because hiding a link is presentation and this needs to be enforcement.
 *
 * @package Kadence-Child
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/** Grant holders may copy. The per-post limit is enforced separately, below. */
add_filter(
	'user_has_cap',
	function ( $allcaps, $required, $args, $user ) {
		if ( ! isset( $args[0] ) || 'copy_posts' !== $args[0] ) {
			return $allcaps;
		}
		if ( ! $user instanceof WP_User || ! $user->ID || ! empty( $allcaps['copy_posts'] ) ) {
			return $allcaps;
		}
		if ( bw_access_user_grant_types( $user->ID ) ) {
			$allcaps['copy_posts'] = true;
		}
		return $allcaps;
	},
	10,
	4
);

/** Only offer Duplicate on items this person can actually edit. */
add_filter(
	'duplicate_post_show_link',
	function ( $show, $post ) {
		if ( ! $show || ! $post instanceof WP_Post ) {
			return $show;
		}
		return current_user_can( 'edit_post', $post->ID );
	},
	10,
	2
);

/**
 * Enforce the same limit on the actions.
 *
 * Runs at priority 1, ahead of the plugin's own handlers, and reads the post id
 * exactly as they do. Without this, `copy_posts` would allow duplicating any
 * page by id — the copy would be useless to them, since `bw_editors` would name
 * someone else, but it would still put a draft of content they cannot see into
 * the site.
 */
foreach ( array( 'duplicate_post_clone', 'duplicate_post_new_draft', 'duplicate_post_rewrite' ) as $bw_dup_action ) {
	add_action(
		'admin_action_' . $bw_dup_action,
		function () {
			$id = 0;
			if ( isset( $_GET['post'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- the plugin verifies the nonce; this only narrows what it will act on.
				$id = (int) wp_unslash( $_GET['post'] );
			} elseif ( isset( $_POST['post'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
				$id = (int) wp_unslash( $_POST['post'] );
			}
			if ( $id && ! current_user_can( 'edit_post', $id ) ) {
				wp_die(
					esc_html__( 'You can only duplicate a page you have been given access to.', 'kadence-child' ),
					esc_html__( 'Not allowed', 'kadence-child' ),
					array( 'response' => 403 )
				);
			}
		},
		1
	);
}
unset( $bw_dup_action );
