Skip to content
Open
Show file tree
Hide file tree
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
12 changes: 12 additions & 0 deletions includes/emails/class-wpum-emails.php
Original file line number Diff line number Diff line change
Expand Up @@ -402,12 +402,24 @@ public function get_tags() {
'tag' => 'login_page_url',
'function' => 'wpum_email_tag_login_page_url',
),
array(
'name' => esc_html__( 'Login page link', 'wp-user-manager' ),
'description' => esc_html__( 'Display the login page link.', 'wp-user-manager' ),
'tag' => 'login_page_link',
'function' => 'wpum_email_tag_login_page_link',
),
array(
'name' => esc_html__( 'Password recovery url', 'wp-user-manager' ),
'description' => esc_html__( 'Display the password recovery url.', 'wp-user-manager' ),
'tag' => 'recovery_url',
'function' => 'wpum_email_tag_password_recovery_url',
),
array(
'name' => esc_html__( 'Password recovery link', 'wp-user-manager' ),
'description' => esc_html__( 'Display the password recovery url as a link.', 'wp-user-manager' ),
'tag' => 'recovery_link',
'function' => 'wpum_email_tag_password_recovery_link',
),
Comment on lines +405 to +422

Copilot AI Feb 26, 2026

Copy link

Choose a reason for hiding this comment

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

According to issue #309, the client requested adding both URL and link tags for verification as well: {verification_url} and {verification_link}. This PR only implements the login_page and recovery tags but is missing the verification tags. The issue states: "I would like to make links look like buttons... {verification_url} - Display the verification url. {verification_link} - Display a link to the verification page." Consider implementing these missing tags to fully address the issue.

Copilot uses AI. Check for mistakes.
);

return apply_filters( 'wpum_email_tags', $email_tags, $this );
Expand Down
39 changes: 39 additions & 0 deletions includes/emails/wpum-email-functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,21 @@ function wpum_email_tag_login_page_url( $user_id = false ) { // phpcs:ignore Gen
$login_page_url = wpum_get_core_page_id( 'login' );
$login_page_url = get_permalink( $login_page_url );

return $login_page_url;
}

/**
* Parse the {login_page_link} tag into the email to display the site login page url as a link.
*
* @param string $user_id
*
* @return string
*/
function wpum_email_tag_login_page_link( $user_id = false ) { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.Found -- Required by email tag callback signature.

$login_page_url = wpum_get_core_page_id( 'login' );
$login_page_url = get_permalink( $login_page_url );

$url = $login_page_url;

if ( wpum_get_option( 'email_template' ) !== 'none' ) {
Expand Down Expand Up @@ -177,6 +192,30 @@ function wpum_email_tag_password_recovery_url( $user_id, $password_reset_key, $p
'action' => 'wpum-reset',
), $reset_page );

return $reset_page;
}

/**
* Parse the {recovery_link} tag into the email to display personalized password recovery url as a link.
*
* @param int $user_id
* @param string $password_reset_key
* @param string $plain_text_password
* @param string $tag
* @param string $email
*
* @return string
*/
function wpum_email_tag_password_recovery_link( $user_id, $password_reset_key, $plain_text_password, $tag, $email ) {

Copilot AI Feb 26, 2026

Copy link

Choose a reason for hiding this comment

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

Missing test coverage for the new wpum_email_tag_password_recovery_link function. While there is test coverage for other email tag functions in EmailTagsTest.php, there's no test for this new recovery_link tag function. Consider adding a test to verify that this function returns an HTML anchor tag when email_template is not 'none', and a plain URL otherwise, with the correct query parameters.

Copilot uses AI. Check for mistakes.

$reset_page = wpum_get_core_page_id( 'password' );
$reset_page = get_permalink( $reset_page );
$reset_page = add_query_arg( array(
'login' => rawurlencode( $email->user_login ),
'key' => $password_reset_key,
'action' => 'wpum-reset',
), $reset_page );

$link_color = apply_filters( 'wpum_email_tag_password_recovery_url_color', '#000' );

$output = $reset_page;
Expand Down
135 changes: 134 additions & 1 deletion tests/wpunit/Emails/EmailTagsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,145 @@ public function test_email_tag_replaced() {
* Test that {login_page_url} tag returns a URL.
*/
public function test_login_page_url_tag_replaced() {
$page_id = $this->factory()->post->create( array(
'post_type' => 'page',
'post_title' => 'Login Page',
'post_status' => 'publish',
) );

$filter = function () use ( $page_id ) {
return array( $page_id );
};
add_filter( 'wpum_get_option_login_page', $filter );

$result = wpum_email_tag_login_page_url( $this->test_user_id );

// The result should contain some URL string or link.
remove_filter( 'wpum_get_option_login_page', $filter );

$this->assertNotEmpty( $result, 'login_page_url tag should return a non-empty value.' );
}

/**
* Test that {login_page_link} tag returns an anchor tag when email_template is set.
*/
public function test_login_page_link_tag_returns_anchor() {
$page_id = $this->factory()->post->create( array(
'post_type' => 'page',
'post_title' => 'Login Page',
'post_status' => 'publish',
) );

$page_filter = function () use ( $page_id ) {
return array( $page_id );
};
add_filter( 'wpum_get_option_login_page', $page_filter );

$template_filter = function () {
return 'default';
};
add_filter( 'wpum_get_option_email_template', $template_filter );

$result = wpum_email_tag_login_page_link( $this->test_user_id );

remove_filter( 'wpum_get_option_login_page', $page_filter );
remove_filter( 'wpum_get_option_email_template', $template_filter );

$this->assertStringContainsString( '<a href=', $result, 'login_page_link tag should return an HTML anchor tag.' );
}

/**
* Test that {login_page_link} tag returns a plain URL when email_template is none.
*/
public function test_login_page_link_tag_returns_plain_url_for_none_template() {
$page_id = $this->factory()->post->create( array(
'post_type' => 'page',
'post_title' => 'Login Page',
'post_status' => 'publish',
) );

$page_filter = function () use ( $page_id ) {
return array( $page_id );
};
add_filter( 'wpum_get_option_login_page', $page_filter );

$template_filter = function () {
return 'none';
};
add_filter( 'wpum_get_option_email_template', $template_filter );

$result = wpum_email_tag_login_page_link( $this->test_user_id );

remove_filter( 'wpum_get_option_login_page', $page_filter );
remove_filter( 'wpum_get_option_email_template', $template_filter );

$this->assertStringNotContainsString( '<a href=', $result, 'login_page_link tag should return a plain URL when template is none.' );
$this->assertNotEmpty( $result );
}

/**
* Test that {recovery_link} tag returns an anchor tag when email_template is set.
*/
public function test_recovery_link_tag_returns_anchor() {
$page_id = $this->factory()->post->create( array(
'post_type' => 'page',
'post_title' => 'Password Reset Page',
'post_status' => 'publish',
) );

$page_filter = function () use ( $page_id ) {
return array( $page_id );
};
add_filter( 'wpum_get_option_password_recovery_page', $page_filter );

$template_filter = function () {
return 'default';
};
add_filter( 'wpum_get_option_email_template', $template_filter );

$user = get_user_by( 'id', $this->test_user_id );
$email = (object) array( 'user_login' => $user->user_login );

$result = wpum_email_tag_password_recovery_link( $this->test_user_id, 'test-key', '', 'recovery_link', $email );

remove_filter( 'wpum_get_option_password_recovery_page', $page_filter );
remove_filter( 'wpum_get_option_email_template', $template_filter );

$this->assertStringContainsString( '<a href=', $result, 'recovery_link tag should return an HTML anchor tag.' );
$this->assertStringContainsString( 'test-key', $result, 'recovery_link tag should include the reset key in the URL.' );
}

/**
* Test that {recovery_link} tag returns a plain URL when email_template is none.
*/
public function test_recovery_link_tag_returns_plain_url_for_none_template() {
$page_id = $this->factory()->post->create( array(
'post_type' => 'page',
'post_title' => 'Password Reset Page',
'post_status' => 'publish',
) );

$page_filter = function () use ( $page_id ) {
return array( $page_id );
};
add_filter( 'wpum_get_option_password_recovery_page', $page_filter );

$template_filter = function () {
return 'none';
};
add_filter( 'wpum_get_option_email_template', $template_filter );

$user = get_user_by( 'id', $this->test_user_id );
$email = (object) array( 'user_login' => $user->user_login );

$result = wpum_email_tag_password_recovery_link( $this->test_user_id, 'test-key', '', 'recovery_link', $email );

remove_filter( 'wpum_get_option_password_recovery_page', $page_filter );
remove_filter( 'wpum_get_option_email_template', $template_filter );

$this->assertStringNotContainsString( '<a href=', $result, 'recovery_link tag should return a plain URL when template is none.' );
$this->assertNotEmpty( $result );
}

/**
* Test that {firstname} tag is replaced.
*/
Expand Down
Loading