approver_id);
echo esc_html($decider
/* translators: %s: name of the person who decides this order */
? sprintf(__('Waiting for %s to approve or reject this order.', 'crewcommerce'), $decider->display_name)
: __('Waiting for another approver.', 'crewcommerce'));
?>
get_user_role($user_id);
if ($role && in_array($role, CrewCommerce_Approvals::get_instance()->get_roles_checked(), true)) {
// This filter runs more than once per page; only add the notice once.
$notice = __('Some orders need your manager’s approval before they are processed.', 'crewcommerce');
if (!wc_has_notice($notice, 'notice')) {
wc_add_notice($notice, 'notice');
}
}
return $fields;
}
/**
* Order confirmation text for an order that was placed but is held for
* approval. Runs on both the classic and block confirmation pages.
*/
public function approval_order_received_text($text, $order) {
if (!($order instanceof WC_Order) || !$order->has_status('pending-approval')) {
return $text;
}
$settings = get_option('crewcommerce_settings', array());
if (!empty($settings['approval_required_message'])) {
return esc_html($settings['approval_required_message']);
}
$approvals = CrewCommerce_Approvals::get_instance();
$workflow = $approvals->get_order_workflow($order->get_id());
$approver = ($workflow && $workflow->approver_id) ? get_userdata($workflow->approver_id) : false;
$message = $approver
? sprintf(
/* translators: %s: approver's name */
__('Thank you — your order has been received. It needs approval from %s before it is processed, and they have been emailed about it.', 'crewcommerce'),
$approver->display_name
)
: __('Thank you — your order has been received. It needs approval before it is processed.', 'crewcommerce');
// Nothing is charged at checkout for a held order.
if ('pending' === $approvals->status_after_approval($order)) {
$message .= ' ' . __('You have not been charged yet — once it is approved, we will email you a link to pay.', 'crewcommerce');
}
return esc_html($message) . ' ' . sprintf(
'%s',
esc_url(wc_get_account_endpoint_url('crewcommerce-my-requests')),
esc_html__('Follow it under My Requests.', 'crewcommerce')
);
}
/**
* Read a value from the current AJAX request.
*/
private function post_value($key, $type = 'int') {
// phpcs:disable WordPress.Security.NonceVerification.Missing -- every caller checks the nonce first.
if (!isset($_POST[$key])) {
return 'int' === $type ? 0 : '';
}
$value = wp_unslash($_POST[$key]); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- sanitized below by type.
// phpcs:enable
switch ($type) {
case 'key':
return sanitize_key($value);
case 'textarea':
return sanitize_textarea_field($value);
default:
return absint($value);
}
}
/**
* The viewer's company, when they are its Manager or Admin. Ends the
* request with an error otherwise.
*/
private function require_team_manager() {
$user_id = get_current_user_id();
$team_accounts = CrewCommerce_Team_Accounts::get_instance();
$company_id = (int) $team_accounts->get_user_company($user_id);
if (!$company_id || !in_array($team_accounts->get_user_role($user_id), array('admin', 'manager'), true)) {
wp_send_json_error(__('Insufficient permissions.', 'crewcommerce'));
}
return $company_id;
}
public function ajax_remove_member() {
check_ajax_referer('crewcommerce_nonce', 'nonce');
$company_id = $this->require_team_manager();
$user_id = $this->post_value('user_id');
if ($user_id === get_current_user_id()) {
wp_send_json_error(__('You cannot remove yourself.', 'crewcommerce'));
}
$team_accounts = CrewCommerce_Team_Accounts::get_instance();
if ((int) $team_accounts->get_user_company($user_id) !== $company_id) {
wp_send_json_error(__('That person is not on your team.', 'crewcommerce'));
}
// Only an Admin can remove or change another Admin.
if ('admin' === $team_accounts->get_user_role($user_id) && 'admin' !== $team_accounts->get_user_role(get_current_user_id())) {
wp_send_json_error(__('Only the company Admin can remove or change another Admin.', 'crewcommerce'));
}
$result = $team_accounts->remove_team_member($user_id, $company_id);
if (is_wp_error($result)) {
wp_send_json_error($result->get_error_message());
} elseif ($result) {
wp_send_json_success(__('Team member removed.', 'crewcommerce'));
}
wp_send_json_error(__('Could not remove the team member.', 'crewcommerce'));
}
public function ajax_update_role() {
check_ajax_referer('crewcommerce_nonce', 'nonce');
$company_id = $this->require_team_manager();
$team_accounts = CrewCommerce_Team_Accounts::get_instance();
$user_id = $this->post_value('user_id');
$new_role = $this->post_value('role', 'key');
if ((int) $team_accounts->get_user_company($user_id) !== $company_id) {
wp_send_json_error(__('That person is not on your team.', 'crewcommerce'));
}
// Only an Admin can remove or change another Admin.
if ('admin' === $team_accounts->get_user_role($user_id) && 'admin' !== $team_accounts->get_user_role(get_current_user_id())) {
wp_send_json_error(__('Only the company Admin can remove or change another Admin.', 'crewcommerce'));
}
// The Admin seat only changes hands by demoting the current Admin,
// never by assigning "admin" to someone else directly.
if ('admin' === $new_role && get_post_meta($company_id, '_company_admin', true) != $user_id) {
wp_send_json_error(__('The Admin role changes hands by changing the current Admin’s role, not by assigning it to someone else.', 'crewcommerce'));
}
$result = $team_accounts->update_member_role($user_id, $company_id, $new_role);
if (is_wp_error($result)) {
wp_send_json_error($result->get_error_message());
} elseif ($result) {
wp_send_json_success(__('Role updated.', 'crewcommerce'));
}
wp_send_json_error(__('Could not update the role.', 'crewcommerce'));
}
private function require_approver() {
$role = CrewCommerce_Team_Accounts::get_instance()->get_user_role(get_current_user_id());
if (!in_array($role, array('admin', 'manager'), true)) {
wp_send_json_error(__('Insufficient permissions.', 'crewcommerce'));
}
}
public function ajax_approve_order() {
check_ajax_referer('crewcommerce_nonce', 'nonce');
$this->require_approver();
$workflow_id = $this->post_value('workflow_id');
$approvals = CrewCommerce_Approvals::get_instance();
if ($approvals->approve_order($workflow_id, get_current_user_id(), $this->post_value('notes', 'textarea'))) {
wp_send_json_success(array('message' => $approvals->get_decision_message($workflow_id, 'approved')));
}
wp_send_json_error($approvals->get_last_error() ?: __('Could not approve the order.', 'crewcommerce'));
}
public function ajax_claim_approval() {
check_ajax_referer('crewcommerce_nonce', 'nonce');
$this->require_approver();
$result = CrewCommerce_Approvals::get_instance()->claim_approval($this->post_value('workflow_id'), get_current_user_id());
if (is_wp_error($result)) {
wp_send_json_error($result->get_error_message());
}
wp_send_json_success(__('Order claimed. You can now approve or reject it.', 'crewcommerce'));
}
public function ajax_reject_order() {
check_ajax_referer('crewcommerce_nonce', 'nonce');
$this->require_approver();
$workflow_id = $this->post_value('workflow_id');
$notes = $this->post_value('notes', 'textarea');
if ('' === $notes) {
wp_send_json_error(__('A rejection reason is required.', 'crewcommerce'));
}
$approvals = CrewCommerce_Approvals::get_instance();
if ($approvals->reject_order($workflow_id, get_current_user_id(), $notes)) {
wp_send_json_success(array('message' => $approvals->get_decision_message($workflow_id, 'rejected')));
}
wp_send_json_error($approvals->get_last_error() ?: __('Could not reject the order.', 'crewcommerce'));
}
public function ajax_cancel_approval() {
check_ajax_referer('crewcommerce_nonce', 'nonce');
$result = CrewCommerce_Approvals::get_instance()->cancel_pending_approval($this->post_value('workflow_id'), get_current_user_id());
if (is_wp_error($result)) {
wp_send_json_error($result->get_error_message());
}
wp_send_json_success(__('Approval request cancelled. Your order is on hold.', 'crewcommerce'));
}
/**
* My Requests: the requester's orders and where each one stands.
*/
public function my_requests_content() {
$user_id = get_current_user_id();
$team_accounts = CrewCommerce_Team_Accounts::get_instance();
$company_id = (int) $team_accounts->get_user_company($user_id);
if (!$company_id) {
echo '
' . esc_html__('You are not part of a company yet.', 'crewcommerce') . '