Below is a differential between the unpatched vulnerable code and the patched update, for reference.
--- a/wp-user-avatar/src/Admin/SettingsPages/EmailSettings/EmailSettingsPage.php
+++ b/wp-user-avatar/src/Admin/SettingsPages/EmailSettings/EmailSettingsPage.php
@@ -190,7 +190,7 @@
'title' => esc_html__('Renewal Order Receipt', 'wp-user-avatar'),
'subject' => sprintf(esc_html__('Subscription Renewal Receipt', 'wp-user-avatar'), $site_title),
'message' => $this->get_order_receipt_content(true),
- 'description' => esc_html__('Email sent to customer whenever a renewal order occurs.', 'wp-user-avatar'),
+ 'description' => esc_html__('Email sent to customers whenever a renewal order occurs.', 'wp-user-avatar'),
'recipient' => esc_html__('Customers', 'wp-user-avatar'),
'placeholders' => $this->get_order_placeholders()
],
@@ -210,7 +210,7 @@
'title' => esc_html__('Subscription Cancelled Notification', 'wp-user-avatar'),
'subject' => sprintf(esc_html__('Your subscription has been cancelled.', 'wp-user-avatar'), $site_title),
'message' => $this->get_subscription_cancelled_content(),
- 'description' => esc_html__('Email sent to customer whenever their subscription is cancelled.', 'wp-user-avatar'),
+ 'description' => esc_html__('Email sent to customers whenever their subscription is cancelled.', 'wp-user-avatar'),
'recipient' => esc_html__('Customers', 'wp-user-avatar'),
'placeholders' => $this->get_subscription_placeholders()
],
@@ -220,7 +220,17 @@
'title' => esc_html__('Subscription Expired Notification', 'wp-user-avatar'),
'subject' => sprintf(esc_html__('Your subscription has expired.', 'wp-user-avatar'), $site_title),
'message' => $this->get_subscription_expired_content(),
- 'description' => esc_html__('Email sent to customer whenever their subscription expires.', 'wp-user-avatar'),
+ 'description' => esc_html__('Email sent to customers whenever their subscription expires.', 'wp-user-avatar'),
+ 'recipient' => esc_html__('Customers', 'wp-user-avatar'),
+ 'placeholders' => $this->get_subscription_placeholders()
+ ],
+ [
+ 'type' => self::SUBSCRIPTION_EMAIL_TYPE,
+ 'key' => 'subscription_payment_failed_notification',
+ 'title' => esc_html__('Subscription Payment Failed Notification', 'wp-user-avatar'),
+ 'subject' => sprintf(esc_html__('Your subscription payment failed.', 'wp-user-avatar'), $site_title),
+ 'message' => $this->get_subscription_payment_failed_content(),
+ 'description' => esc_html__('Email sent to customers whenever a recurring payment that should renew their subscription fails or goes unpaid.', 'wp-user-avatar'),
'recipient' => esc_html__('Customers', 'wp-user-avatar'),
'placeholders' => $this->get_subscription_placeholders()
],
@@ -230,7 +240,7 @@
'title' => esc_html__('Subscription Completed Notification', 'wp-user-avatar'),
'subject' => sprintf(esc_html__('Your subscription is now complete.', 'wp-user-avatar'), $site_title),
'message' => $this->get_subscription_completed_content(),
- 'description' => esc_html__('Email sent to customer whenever they complete their subscription payments.', 'wp-user-avatar'),
+ 'description' => esc_html__('Email sent to customers whenever they complete their subscription payments.', 'wp-user-avatar'),
'recipient' => esc_html__('Customers', 'wp-user-avatar'),
'placeholders' => $this->get_subscription_placeholders()
],
@@ -240,7 +250,7 @@
'title' => esc_html__('Upcoming Renewal Reminder', 'wp-user-avatar'),
'subject' => sprintf(esc_html__('Your subscription is renewing soon.', 'wp-user-avatar'), $site_title),
'message' => $this->get_subscription_renewal_reminder_content(),
- 'description' => esc_html__('Email sent to customer to remind them that their subscription is approaching its renewal.', 'wp-user-avatar'),
+ 'description' => esc_html__('Email sent to customers to remind them that their subscription is approaching its renewal.', 'wp-user-avatar'),
'recipient' => esc_html__('Customers', 'wp-user-avatar'),
'placeholders' => $this->get_subscription_placeholders(),
'reminder_days' => '1'
@@ -251,7 +261,7 @@
'title' => esc_html__('Upcoming Expiration Reminder', 'wp-user-avatar'),
'subject' => sprintf(esc_html__('Your subscription is expiring soon.', 'wp-user-avatar'), $site_title),
'message' => $this->get_subscription_renewal_reminder_content(true),
- 'description' => esc_html__('Email sent to customer to remind them that their subscription is approaching its expiration.', 'wp-user-avatar'),
+ 'description' => esc_html__('Email sent to customers to remind them that their subscription is approaching its expiration.', 'wp-user-avatar'),
'recipient' => esc_html__('Customers', 'wp-user-avatar'),
'placeholders' => $this->get_subscription_placeholders(),
'reminder_days' => '1'
@@ -262,7 +272,7 @@
'title' => esc_html__('After Subscription Expired Notification', 'wp-user-avatar'),
'subject' => sprintf(esc_html__('Your subscription has expired.', 'wp-user-avatar'), $site_title),
'message' => $this->get_subscription_expired_content(),
- 'description' => esc_html__('Email sent to customer few days after their subscription expires.', 'wp-user-avatar'),
+ 'description' => esc_html__('Email sent to customers few days after their subscription expires.', 'wp-user-avatar'),
'recipient' => esc_html__('Customers', 'wp-user-avatar'),
'placeholders' => $this->get_subscription_placeholders(),
'reminder_days' => '2'
--- a/wp-user-avatar/src/Admin/SettingsPages/Membership/CustomersPage/SettingsPage.php
+++ b/wp-user-avatar/src/Admin/SettingsPages/Membership/CustomersPage/SettingsPage.php
@@ -227,7 +227,7 @@
->utc()->toDateTimeString();
}
- $amount = ppress_var($customer_data, 'order_amount', '');
+ $amount = ppress_sanitize_amount(ppress_var($customer_data, 'order_amount', ''));
if (empty($amount) || Calculator::init($amount)->isNegativeOrZero()) {
$amount = ppress_get_plan($plan_id)->get_price();
--- a/wp-user-avatar/src/Admin/SettingsPages/Membership/OrdersPage/SettingsPage.php
+++ b/wp-user-avatar/src/Admin/SettingsPages/Membership/OrdersPage/SettingsPage.php
@@ -238,7 +238,7 @@
$coupon_id = (int)$_POST['coupon_code'];
$tax_amount = sanitize_text_field($_POST['tax']);
- $plan_price = ! empty($plan_price) ? $plan_price : PlanFactory::fromId($plan_id)->get_price();
+ $plan_price = ! empty($plan_price) ? ppress_sanitize_amount($plan_price) : PlanFactory::fromId($plan_id)->get_price();
$order = OrderFactory::fromId($order_id);
$order->plan_id = ppress_sanitize_amount($plan_id);
@@ -271,7 +271,7 @@
if (TaxService::init()->is_tax_enabled() && ! empty($tax_amount) && TaxService::init()->is_price_inclusive_tax()) {
- $subtotal = Calculator::init($plan_price)->minus($order->discount)->minus($tax_amount);
+ $subtotal = Calculator::init($plan_price)->minus($order->discount)->minus($order->tax);
$order->subtotal = $subtotal->val();
--- a/wp-user-avatar/src/Admin/SettingsPages/Membership/SettingsFieldsParser.php
+++ b/wp-user-avatar/src/Admin/SettingsPages/Membership/SettingsFieldsParser.php
@@ -110,7 +110,7 @@
case 'checkbox':
$checkbox_label = esc_html(ppress_var($config, 'checkbox_label', '', true));
printf('<input type="hidden" name="%1$s" value="false">', $field_id);
- printf('<label><input type="checkbox" name="%1$s" value="true"%2$s>%3$s</label>', $field_id, checked('true', $field_data, false), $checkbox_label);
+ printf('<label><input id="%4$s" type="checkbox" name="%1$s" value="true"%2$s>%3$s</label>', $field_id, checked('true', $field_data, false), $checkbox_label, $config['id']);
break;
default:
do_action('ppress_admin_settings_fields_parser_field', $field_data, $config, $this);
--- a/wp-user-avatar/src/Admin/SettingsPages/Membership/views/add-edit-plan.php
+++ b/wp-user-avatar/src/Admin/SettingsPages/Membership/views/add-edit-plan.php
@@ -32,7 +32,7 @@
return $core_roles;
})();
-$plan_details = [
+$plan_details = apply_filters('ppress_admin_membership_plan_details', [
[
'id' => 'name',
'type' => 'text',
@@ -63,7 +63,7 @@
'label' => esc_html__('Price', 'wp-user-avatar') . sprintf(' (%s)', ppress_get_currency_symbol()),
'description' => esc_html__('The price of this membership plan. Enter 0.00 to make this plan free.', 'wp-user-avatar')
]
-];
+]);
$subscription_settings = apply_filters('ppress_admin_membership_plan_subscription_settings', [
[
--- a/wp-user-avatar/src/Classes/ExtensionManager.php
+++ b/wp-user-avatar/src/Classes/ExtensionManager.php
@@ -44,6 +44,7 @@
const SLICEWP = 'slicewp';
const AFFILIATEWP = 'affiliatewp';
const AUTORENEWAL_CHECKBOX = 'autorenewal_checkbox';
+ const PAY_WHAT_YOU_WANT = 'pay_what_you_want';
public static function is_premium()
{
@@ -87,6 +88,7 @@
self::LIFTERLMS => 'ProfilePressLibsodiumLifterLMS',
self::INVITATION_CODES => 'ProfilePressLibsodiumInvitationCodesInit',
self::FIXED_SUBSCRIPTION_EXPIRATION => 'ProfilePressLibsodiumFixedSubscriptionExpiration',
+ self::PAY_WHAT_YOU_WANT => 'ProfilePressLibsodiumPayWhatYouWant',
self::SLICEWP => 'ProfilePressLibsodiumSliceWPInit',
self::AFFILIATEWP => 'ProfilePressLibsodiumAffiliateWPInit',
self::AUTORENEWAL_CHECKBOX => 'ProfilePressLibsodiumAutoRenewalCheckboxInit',
@@ -137,6 +139,12 @@
'description' => esc_html__('Set specific expiration dates for non-recurring membership plans.', 'wp-user-avatar'),
'icon' => '<span class="dashicons dashicons-clock"></span>'
],
+ self::PAY_WHAT_YOU_WANT => [
+ 'title' => esc_html__('Pay What You Want', 'wp-user-avatar'),
+ 'url' => 'https://profilepress.com/addons/pay-what-you-want/?utm_source=liteplugin&utm_medium=extension-page&utm_campaign=learn-more',
+ 'description' => esc_html__('Let customers pay what they want for your products and memberships by offering a variable pricing option during checkout.', 'wp-user-avatar'),
+ 'icon' => '<svg viewBox="0 0 640 512" xmlns="http://www.w3.org/2000/svg"><path d="m0 8c0-13.3 10.7-24 24-24h45.3c27.1 0 50.3 19.4 55.1 46l.4 2h187.2v102.1l-31-31c-9.4-9.4-24.6-9.4-33.9 0s-9.4 24.6 0 33.9l72 72c9.4 9.4 24.6 9.4 33.9 0l72-72c9.4-9.4 9.4-24.6 0-33.9s-24.6-9.4-33.9 0l-31 31v-102.1h177.4c20 0 35.1 18.2 31.4 37.9l-31.1 165.9c-5.7 30.3-32.1 52.2-62.9 52.2h-303.6l5.1 28.3c2.1 11.4 12 19.7 23.6 19.7h256c13.3 0 24 10.7 24 24s-10.7 24-24 24h-255.9c-34.8 0-64.6-24.9-70.8-59.1l-52.1-286.3c-.7-3.8-4-6.6-7.9-6.6h-45.3c-13.3 0-24-10.7-24-24zm160 456a48 48 0 1 1 96 0 48 48 0 1 1 -96 0zm224 0a48 48 0 1 1 96 0 48 48 0 1 1 -96 0z"/></svg>'
+ ],
self::RECEIPT => [
'title' => esc_html__('Receipt', 'wp-user-avatar'),
'url' => 'https://profilepress.com/addons/receipt/?utm_source=liteplugin&utm_medium=extension-page&utm_campaign=learn-more',
--- a/wp-user-avatar/src/Functions/MSFunctions.php
+++ b/wp-user-avatar/src/Functions/MSFunctions.php
@@ -470,15 +470,16 @@
*/
function ppress_get_currency_symbol($currency = '')
{
- if ( ! $currency) {
- $currency = ppress_get_currency();
- }
+ return ppress_cache_transform('ppress_get_currency_symbol_'.$currency, function() use ($currency) {
+
+ if ( ! $currency) $currency = ppress_get_currency();
- $symbols = ppress_get_currency_symbols();
+ $symbols = ppress_get_currency_symbols();
- $currency_symbol = isset($symbols[$currency]) ? $symbols[$currency] : '';
+ $currency_symbol = $symbols[$currency] ?? '';
- return apply_filters('ppress_currency_symbol', $currency_symbol, $currency);
+ return apply_filters('ppress_currency_symbol', $currency_symbol, $currency);
+ });
}
@@ -496,7 +497,7 @@
}
$currencies = ppress_get_currencies();
- $name = isset($currencies[$code]) ? $currencies[$code] : $code;
+ $name = $currencies[$code] ?? $code;
return apply_filters('ppress_currency_name', $name);
}
--- a/wp-user-avatar/src/Membership/Controllers/CheckoutController.php
+++ b/wp-user-avatar/src/Membership/Controllers/CheckoutController.php
@@ -475,10 +475,7 @@
try {
if (empty($_POST['plan_id'])) {
-
- throw new Exception(
- esc_html__('Please enter a plan ID.', 'wp-user-avatar')
- );
+ throw new Exception(esc_html__('Please enter a plan ID.', 'wp-user-avatar'));
}
global $cart_vars;
@@ -569,6 +566,8 @@
];
}
+ do_action('ppress_update_order_review_actions', $post_data, $planObj, $cart_vars);
+
wp_send_json_success(
apply_filters('ppress_update_order_review_response', [
'fragments' => apply_filters('ppress_update_order_review_fragments', $fragments)
--- a/wp-user-avatar/src/Membership/CurrencyFormatter.php
+++ b/wp-user-avatar/src/Membership/CurrencyFormatter.php
@@ -105,8 +105,6 @@
{
$amount = $this->amount;
- if (Calculator::init($amount)->isNegativeOrZero()) $amount = '0';
-
$sep_found = strpos($amount, $this->decimal_separator);
if (',' === $this->decimal_separator && false !== $sep_found) {
$whole = substr($amount, 0, $sep_found);
@@ -122,7 +120,9 @@
}
// one last formatting check especially when amount contains currency
- $amount = preg_replace('/[^0-9.]/', '', $amount);
+ $amount = preg_replace('/[^0-9.-]/', '', $amount);
+
+ if ( ! is_numeric($amount) || Calculator::init($amount)->isNegativeOrZero()) $amount = '0';
return $amount;
}
--- a/wp-user-avatar/src/Membership/Emails/EmailDataTrait.php
+++ b/wp-user-avatar/src/Membership/Emails/EmailDataTrait.php
@@ -182,6 +182,19 @@
return ob_get_clean();
}
+ public function get_subscription_payment_failed_content()
+ {
+ ob_start();
+ ?>
+ <p>Hi {{first_name}},</p>
+ <p>The payment to renew the subscription for {{plan_name}} failed or is unpaid. Please update your payment method or subscribe again to keep your membership active.</p>
+ <div style="margin:30px 0 0;padding: 10px 0 50px 0; text-align: center;">
+ <a style="background: #555555; color: #fff; padding: 12px 30px; text-decoration: none; border-radius: 3px; letter-spacing: 0.3px;" href="{{subscription_url}}">Manage Subscription</a>
+ </div>
+ <?php
+ return ob_get_clean();
+ }
+
public function get_subscription_renewal_reminder_content($expiration = false)
{
ob_start();
--- a/wp-user-avatar/src/Membership/Emails/SubscriptionPaymentFailedNotification.php
+++ b/wp-user-avatar/src/Membership/Emails/SubscriptionPaymentFailedNotification.php
@@ -0,0 +1,53 @@
+<?php
+
+namespace ProfilePressCoreMembershipEmails;
+
+use ProfilePressCoreMembershipModelsCustomerCustomerFactory;
+use ProfilePressCoreMembershipModelsSubscriptionSubscriptionEntity;
+
+class SubscriptionPaymentFailedNotification extends AbstractMembershipEmail
+{
+ const ID = 'subscription_payment_failed_notification';
+
+ const DEDUPE_META_KEY = 'payment_failed_email_sent';
+
+ public function __construct()
+ {
+ add_action('ppress_subscription_payment_failed', [$this, 'dispatch_email']);
+ }
+
+ /**
+ * @param SubscriptionEntity $subscription
+ *
+ * @return void
+ */
+ public function dispatch_email($subscription)
+ {
+ if ( ! apply_filters('ppress_membership_subscription_payment_failed_email_enabled', true, $subscription)) return;
+
+ if (ppress_get_setting(self::ID . '_email_enabled', 'on') !== 'on') return;
+
+ // ensures gateway payment retries do not re-send the email within the same billing period.
+ if ($subscription->get_meta(self::DEDUPE_META_KEY) === $subscription->expiration_date) return;
+
+ $placeholders_values = $this->get_subscription_placeholders_values($subscription);
+
+ $subject = apply_filters('ppress_' . self::ID . '_email_subject', $this->parse_placeholders(
+ ppress_get_setting(self::ID . '_email_subject', esc_html__('Your subscription payment failed.', 'wp-user-avatar'), true),
+ $placeholders_values,
+ $subscription
+ ), $subscription);
+
+ $message = apply_filters('ppress_' . self::ID . '_email_content', $this->parse_placeholders(
+ ppress_get_setting(self::ID . '_email_content', $this->get_subscription_payment_failed_content(), true),
+ $placeholders_values,
+ $subscription
+ ), $subscription);
+
+ $recipient = apply_filters('ppress_' . self::ID . '_recipient', CustomerFactory::fromId($subscription->customer_id)->get_email(), $subscription);
+
+ if (ppress_send_email($recipient, $subject, $message)) {
+ $subscription->update_meta(self::DEDUPE_META_KEY, $subscription->expiration_date);
+ }
+ }
+}
--- a/wp-user-avatar/src/Membership/Init.php
+++ b/wp-user-avatar/src/Membership/Init.php
@@ -13,6 +13,7 @@
use ProfilePressCoreMembershipEmailsSubscriptionCompletedNotification;
use ProfilePressCoreMembershipEmailsSubscriptionExpirationReminder;
use ProfilePressCoreMembershipEmailsSubscriptionExpiredNotification;
+use ProfilePressCoreMembershipEmailsSubscriptionPaymentFailedNotification;
use ProfilePressCoreMembershipEmailsSubscriptionRenewalReminder;
use ProfilePressCoreMembershipModelsCustomerCustomerFactory;
use ProfilePressCoreMembershipPaymentMethodsPaymentMethods;
@@ -40,6 +41,7 @@
SubscriptionRenewalReminder::init();
SubscriptionExpirationReminder::init();
SubscriptionAfterExpiredNotification::init();
+ SubscriptionPaymentFailedNotification::init();
StatSync::init();
--- a/wp-user-avatar/src/Membership/Models/Subscription/SubscriptionEntity.php
+++ b/wp-user-avatar/src/Membership/Models/Subscription/SubscriptionEntity.php
@@ -681,6 +681,14 @@
}
/**
+ * @return void
+ */
+ public function payment_failed()
+ {
+ do_action('ppress_subscription_payment_failed', $this);
+ }
+
+ /**
* @param $change_expiry_date
* @param int $expiration_date timestamp in UTC
*
--- a/wp-user-avatar/src/Membership/PaymentMethods/Stripe/PaymentHelpers.php
+++ b/wp-user-avatar/src/Membership/PaymentMethods/Stripe/PaymentHelpers.php
@@ -245,7 +245,7 @@
try {
$search_result = APIClass::stripeClient()->customers->search([
- 'query' => sprintf('email:'%s' AND metadata['ppress_customer_id']:'%s'', $customer->get_email(), $customer->id)
+ 'query' => sprintf('metadata['ppress_customer_id']:'%s'', $customer->id)
])->toArray();
if ( ! empty($search_result['data']) && isset($search_result['data'][0]['id'])) {
--- a/wp-user-avatar/src/Membership/PaymentMethods/Stripe/WebhookHandlers/CustomerSubscriptionUpdated.php
+++ b/wp-user-avatar/src/Membership/PaymentMethods/Stripe/WebhookHandlers/CustomerSubscriptionUpdated.php
@@ -67,11 +67,9 @@
break;
case 'past_due':
$subscription->add_note(
- sprintf(
- esc_html__('Stripe payment failed (payment is past due)', 'wp-user-avatar'),
- ppress_format_date($event_data['cancel_at'])
- )
+ esc_html__('Stripe payment failed (payment is past due)', 'wp-user-avatar')
);
+ $subscription->payment_failed();
break;
}
--- a/wp-user-avatar/src/Membership/Services/OrderService.php
+++ b/wp-user-avatar/src/Membership/Services/OrderService.php
@@ -249,12 +249,14 @@
$args = wp_parse_args($args, $defaults);
+ $planObj = ppress_get_plan(absint($args['plan_id']));
+
+ do_action('ppress_before_checkout_order_calculation', $args, $planObj);
+
$tax_rate = $args['tax_rate'];
$coupon_code = ! empty($args['coupon_code']) ? $args['coupon_code'] : '';
- $planObj = ppress_get_plan(absint($args['plan_id']));
-
$change_plan_sub_id = intval($args['change_plan_sub_id']);
$prorated_price_flag = false;
@@ -375,7 +377,7 @@
$cart->recurring_tax = $recurring_tax_amount;
$cart->expiration_date = SubscriptionService::init()->get_plan_expiration_datetime($planObj->id);
- return $cart;
+ return apply_filters('ppress_checkout_cart_entity_vars', $cart, $args);
}
public function get_customer_orders_url($customer_id, $order_status = false)
--- a/wp-user-avatar/src/ShortcodeParser/Builder/FrontendProfileBuilder.php
+++ b/wp-user-avatar/src/ShortcodeParser/Builder/FrontendProfileBuilder.php
@@ -291,16 +291,16 @@
switch ($atts['format']) {
case 'first_last_names':
- $display_name = self::$user_data->first_name . ' ' . self::$user_data->last_name;
+ $display_name = strip_shortcodes(self::$user_data->first_name) . ' ' . strip_shortcodes(self::$user_data->last_name);
break;
case 'last_first_names':
- $display_name = self::$user_data->last_name . ' ' . self::$user_data->first_name;
+ $display_name = strip_shortcodes(self::$user_data->last_name) . ' ' . strip_shortcodes(self::$user_data->first_name);
break;
case 'first_name_initial_l':
- $display_name = self::$user_data->first_name . ' ' . self::$user_data->last_name[0];
+ $display_name = strip_shortcodes(self::$user_data->first_name) . ' ' . strip_shortcodes(self::$user_data->last_name[0]);
break;
case 'f_initial_last_name':
- $display_name = self::$user_data->first_name[0] . ' ' . self::$user_data->last_name;
+ $display_name = strip_shortcodes(self::$user_data->first_name[0]) . ' ' . strip_shortcodes(self::$user_data->last_name);
break;
}
}
--- a/wp-user-avatar/src/Themes/DragDrop/MemberDirectoryListing.php
+++ b/wp-user-avatar/src/Themes/DragDrop/MemberDirectoryListing.php
@@ -122,7 +122,7 @@
if ($raw_field_type == 'profile-bio') {
$bio = get_user_meta($this->user_id, 'description', true);
- $parsed_shortcode = apply_filters('ppress_md_profile_bio', $bio, $this->user_id);
+ $parsed_shortcode = apply_filters('ppress_md_profile_bio', strip_shortcodes($bio), $this->user_id);
}
if ($raw_field_type == 'profile-website') {
--- a/wp-user-avatar/src/templates/checkout/form-checkout.php
+++ b/wp-user-avatar/src/templates/checkout/form-checkout.php
@@ -77,6 +77,8 @@
<?php ppress_render_view('checkout/form-account-info-fields', ['plan' => $planObj]); ?>
+ <?php do_action('ppress_checkout_before_payment_methods', $cart_vars, $planObj); ?>
+
<?php ppress_render_view('checkout/form-payment-methods', [
'plan' => $planObj,
'cart_vars' => $cart_vars
--- a/wp-user-avatar/third-party/vendor/composer/installed.php
+++ b/wp-user-avatar/third-party/vendor/composer/installed.php
@@ -2,4 +2,4 @@
namespace ProfilePressVendor;
-return array('root' => array('name' => '__root__', 'pretty_version' => 'dev-master', 'version' => 'dev-master', 'reference' => '9bb1bb2ae05ea9803fe79e7f846f07a3fa1c5d6c', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev' => true), 'versions' => array('__root__' => array('pretty_version' => 'dev-master', 'version' => 'dev-master', 'reference' => '9bb1bb2ae05ea9803fe79e7f846f07a3fa1c5d6c', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev_requirement' => false), 'barryvdh/composer-cleanup-plugin' => array('pretty_version' => 'dev-master', 'version' => 'dev-master', 'reference' => '80cceff45bfb85a0f49236537b1f1c928a1ee820', 'type' => 'composer-plugin', 'install_path' => __DIR__ . '/../barryvdh/composer-cleanup-plugin', 'aliases' => array(0 => '0.1.x-dev'), 'dev_requirement' => false), 'brick/math' => array('pretty_version' => '0.9.3', 'version' => '0.9.3.0', 'reference' => 'ca57d18f028f84f777b2168cd1911b0dee2343ae', 'type' => 'library', 'install_path' => __DIR__ . '/../brick/math', 'aliases' => array(), 'dev_requirement' => false), 'carbonphp/carbon-doctrine-types' => array('pretty_version' => '2.1.0', 'version' => '2.1.0.0', 'reference' => '99f76ffa36cce3b70a4a6abce41dba15ca2e84cb', 'type' => 'library', 'install_path' => __DIR__ . '/../carbonphp/carbon-doctrine-types', 'aliases' => array(), 'dev_requirement' => false), 'collizo4sky/persist-admin-notices-dismissal' => array('pretty_version' => '1.4.5', 'version' => '1.4.5.0', 'reference' => '163b868c98cf97ea15b4d7e1305e2d52c9242e7e', 'type' => 'library', 'install_path' => __DIR__ . '/../collizo4sky/persist-admin-notices-dismissal', 'aliases' => array(), 'dev_requirement' => false), 'league/csv' => array('pretty_version' => '9.8.0', 'version' => '9.8.0.0', 'reference' => '9d2e0265c5d90f5dd601bc65ff717e05cec19b47', 'type' => 'library', 'install_path' => __DIR__ . '/../league/csv', 'aliases' => array(), 'dev_requirement' => false), 'nesbot/carbon' => array('pretty_version' => '2.73.0', 'version' => '2.73.0.0', 'reference' => '9228ce90e1035ff2f0db84b40ec2e023ed802075', 'type' => 'library', 'install_path' => __DIR__ . '/../nesbot/carbon', 'aliases' => array(), 'dev_requirement' => false), 'pelago/emogrifier' => array('pretty_version' => 'v6.0.0', 'version' => '6.0.0.0', 'reference' => 'aa72d5407efac118f3896bcb995a2cba793df0ae', 'type' => 'library', 'install_path' => __DIR__ . '/../pelago/emogrifier', 'aliases' => array(), 'dev_requirement' => false), 'psr/clock' => array('pretty_version' => '1.0.0', 'version' => '1.0.0.0', 'reference' => 'e41a24703d4560fd0acb709162f73b8adfc3aa0d', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/clock', 'aliases' => array(), 'dev_requirement' => false), 'psr/clock-implementation' => array('dev_requirement' => false, 'provided' => array(0 => '1.0')), 'sabberworm/php-css-parser' => array('pretty_version' => 'v8.9.0', 'version' => '8.9.0.0', 'reference' => 'd8e916507b88e389e26d4ab03c904a082aa66bb9', 'type' => 'library', 'install_path' => __DIR__ . '/../sabberworm/php-css-parser', 'aliases' => array(), 'dev_requirement' => false), 'sniccowp/php-scoper-wordpress-excludes' => array('pretty_version' => '6.9.1', 'version' => '6.9.1.0', 'reference' => '94867711087d0efc3d361dbe068044e0124f4c0b', 'type' => 'library', 'install_path' => __DIR__ . '/../sniccowp/php-scoper-wordpress-excludes', 'aliases' => array(), 'dev_requirement' => true), 'stripe/stripe-php' => array('pretty_version' => 'v16.6.0', 'version' => '16.6.0.0', 'reference' => 'd6de0a536f00b5c5c74f36b8f4d0d93b035499ff', 'type' => 'library', 'install_path' => __DIR__ . '/../stripe/stripe-php', 'aliases' => array(), 'dev_requirement' => false), 'symfony/css-selector' => array('pretty_version' => 'v5.4.45', 'version' => '5.4.45.0', 'reference' => '4f7f3c35fba88146b56d0025d20ace3f3901f097', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/css-selector', 'aliases' => array(), 'dev_requirement' => false), 'symfony/deprecation-contracts' => array('pretty_version' => 'v2.5.4', 'version' => '2.5.4.0', 'reference' => '605389f2a7e5625f273b53960dc46aeaf9c62918', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/deprecation-contracts', 'aliases' => array(), 'dev_requirement' => false), 'symfony/polyfill-mbstring' => array('pretty_version' => 'v1.38.2', 'version' => '1.38.2.0', 'reference' => 'd3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-mbstring', 'aliases' => array(), 'dev_requirement' => false), 'symfony/polyfill-php80' => array('pretty_version' => 'v1.37.0', 'version' => '1.37.0.0', 'reference' => 'dfb55726c3a76ea3b6459fcfda1ec2d80a682411', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-php80', 'aliases' => array(), 'dev_requirement' => false), 'symfony/translation' => array('pretty_version' => 'v5.4.45', 'version' => '5.4.45.0', 'reference' => '98f26acc99341ca4bab345fb14d7b1d7cb825bed', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/translation', 'aliases' => array(), 'dev_requirement' => false), 'symfony/translation-contracts' => array('pretty_version' => 'v2.5.4', 'version' => '2.5.4.0', 'reference' => '450d4172653f38818657022252f9d81be89ee9a8', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/translation-contracts', 'aliases' => array(), 'dev_requirement' => false), 'symfony/translation-implementation' => array('dev_requirement' => false, 'provided' => array(0 => '2.3'))));
+return array('root' => array('name' => '__root__', 'pretty_version' => 'dev-master', 'version' => 'dev-master', 'reference' => '1dc62eb57d2882701429bac914b23e37a9a86dfa', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev' => true), 'versions' => array('__root__' => array('pretty_version' => 'dev-master', 'version' => 'dev-master', 'reference' => '1dc62eb57d2882701429bac914b23e37a9a86dfa', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev_requirement' => false), 'barryvdh/composer-cleanup-plugin' => array('pretty_version' => 'dev-master', 'version' => 'dev-master', 'reference' => '80cceff45bfb85a0f49236537b1f1c928a1ee820', 'type' => 'composer-plugin', 'install_path' => __DIR__ . '/../barryvdh/composer-cleanup-plugin', 'aliases' => array(0 => '0.1.x-dev'), 'dev_requirement' => false), 'brick/math' => array('pretty_version' => '0.9.3', 'version' => '0.9.3.0', 'reference' => 'ca57d18f028f84f777b2168cd1911b0dee2343ae', 'type' => 'library', 'install_path' => __DIR__ . '/../brick/math', 'aliases' => array(), 'dev_requirement' => false), 'carbonphp/carbon-doctrine-types' => array('pretty_version' => '2.1.0', 'version' => '2.1.0.0', 'reference' => '99f76ffa36cce3b70a4a6abce41dba15ca2e84cb', 'type' => 'library', 'install_path' => __DIR__ . '/../carbonphp/carbon-doctrine-types', 'aliases' => array(), 'dev_requirement' => false), 'collizo4sky/persist-admin-notices-dismissal' => array('pretty_version' => '1.4.5', 'version' => '1.4.5.0', 'reference' => '163b868c98cf97ea15b4d7e1305e2d52c9242e7e', 'type' => 'library', 'install_path' => __DIR__ . '/../collizo4sky/persist-admin-notices-dismissal', 'aliases' => array(), 'dev_requirement' => false), 'league/csv' => array('pretty_version' => '9.8.0', 'version' => '9.8.0.0', 'reference' => '9d2e0265c5d90f5dd601bc65ff717e05cec19b47', 'type' => 'library', 'install_path' => __DIR__ . '/../league/csv', 'aliases' => array(), 'dev_requirement' => false), 'nesbot/carbon' => array('pretty_version' => '2.73.0', 'version' => '2.73.0.0', 'reference' => '9228ce90e1035ff2f0db84b40ec2e023ed802075', 'type' => 'library', 'install_path' => __DIR__ . '/../nesbot/carbon', 'aliases' => array(), 'dev_requirement' => false), 'pelago/emogrifier' => array('pretty_version' => 'v6.0.0', 'version' => '6.0.0.0', 'reference' => 'aa72d5407efac118f3896bcb995a2cba793df0ae', 'type' => 'library', 'install_path' => __DIR__ . '/../pelago/emogrifier', 'aliases' => array(), 'dev_requirement' => false), 'psr/clock' => array('pretty_version' => '1.0.0', 'version' => '1.0.0.0', 'reference' => 'e41a24703d4560fd0acb709162f73b8adfc3aa0d', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/clock', 'aliases' => array(), 'dev_requirement' => false), 'psr/clock-implementation' => array('dev_requirement' => false, 'provided' => array(0 => '1.0')), 'sabberworm/php-css-parser' => array('pretty_version' => 'v8.9.0', 'version' => '8.9.0.0', 'reference' => 'd8e916507b88e389e26d4ab03c904a082aa66bb9', 'type' => 'library', 'install_path' => __DIR__ . '/../sabberworm/php-css-parser', 'aliases' => array(), 'dev_requirement' => false), 'sniccowp/php-scoper-wordpress-excludes' => array('pretty_version' => '6.9.1', 'version' => '6.9.1.0', 'reference' => '94867711087d0efc3d361dbe068044e0124f4c0b', 'type' => 'library', 'install_path' => __DIR__ . '/../sniccowp/php-scoper-wordpress-excludes', 'aliases' => array(), 'dev_requirement' => true), 'stripe/stripe-php' => array('pretty_version' => 'v16.6.0', 'version' => '16.6.0.0', 'reference' => 'd6de0a536f00b5c5c74f36b8f4d0d93b035499ff', 'type' => 'library', 'install_path' => __DIR__ . '/../stripe/stripe-php', 'aliases' => array(), 'dev_requirement' => false), 'symfony/css-selector' => array('pretty_version' => 'v5.4.45', 'version' => '5.4.45.0', 'reference' => '4f7f3c35fba88146b56d0025d20ace3f3901f097', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/css-selector', 'aliases' => array(), 'dev_requirement' => false), 'symfony/deprecation-contracts' => array('pretty_version' => 'v2.5.4', 'version' => '2.5.4.0', 'reference' => '605389f2a7e5625f273b53960dc46aeaf9c62918', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/deprecation-contracts', 'aliases' => array(), 'dev_requirement' => false), 'symfony/polyfill-mbstring' => array('pretty_version' => 'v1.38.2', 'version' => '1.38.2.0', 'reference' => 'd3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-mbstring', 'aliases' => array(), 'dev_requirement' => false), 'symfony/polyfill-php80' => array('pretty_version' => 'v1.37.0', 'version' => '1.37.0.0', 'reference' => 'dfb55726c3a76ea3b6459fcfda1ec2d80a682411', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-php80', 'aliases' => array(), 'dev_requirement' => false), 'symfony/translation' => array('pretty_version' => 'v5.4.45', 'version' => '5.4.45.0', 'reference' => '98f26acc99341ca4bab345fb14d7b1d7cb825bed', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/translation', 'aliases' => array(), 'dev_requirement' => false), 'symfony/translation-contracts' => array('pretty_version' => 'v2.5.4', 'version' => '2.5.4.0', 'reference' => '450d4172653f38818657022252f9d81be89ee9a8', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/translation-contracts', 'aliases' => array(), 'dev_requirement' => false), 'symfony/translation-implementation' => array('dev_requirement' => false, 'provided' => array(0 => '2.3'))));
--- a/wp-user-avatar/wp-user-avatar.php
+++ b/wp-user-avatar/wp-user-avatar.php
@@ -3,7 +3,7 @@
* Plugin Name: ProfilePress
* Plugin URI: https://profilepress.com
* Description: The modern WordPress membership and user profile plugin.
- * Version: 4.16.19
+ * Version: 4.17.0
* Author: ProfilePress Membership Team
* Author URI: https://profilepress.com
* Text Domain: wp-user-avatar
@@ -13,7 +13,7 @@
defined('ABSPATH') or die("No script kiddies please!");
define('PROFILEPRESS_SYSTEM_FILE_PATH', __FILE__);
-define('PPRESS_VERSION_NUMBER', '4.16.19');
+define('PPRESS_VERSION_NUMBER', '4.17.0');
if ( ! defined('PPRESS_STRIPE_API_VERSION')) {
define('PPRESS_STRIPE_API_VERSION', '2024-06-20');