Skip to content
Merged
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
6 changes: 3 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@
"php": ">=7.4.1",
"automattic/jetpack-autoloader": "^5.0.0",
"wp-ultimo/autoloader-plugin": "dev-main",
"wordpress/abilities-api": "dev-trunk",
"wordpress/mcp-adapter": "dev-trunk",
"wordpress/abilities-api": "^0.1.1",
"wordpress/mcp-adapter": "dev-trunk#7a2d22cff92328bc94f5b1648a66ae4273e949c5",
Comment on lines +36 to +37
Copy link
Contributor

@coderabbitai coderabbitai bot Nov 20, 2025

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify dependency versions and security advisories.

The updated dependencies pin specific versions that may not align with your knowledge cutoff. Please verify that these versions exist and have no known vulnerabilities.

Run the following script to check package versions and security:


🏁 Script executed:

#!/bin/bash
# Check if the specified versions exist and look for security advisories

# Check wordpress/abilities-api version 0.1.1
echo "=== Checking wordpress/abilities-api ==="
curl -s https://packagist.org/packages/wordpress/abilities-api.json | jq '.package.versions | has("0.1.1")'

# Check for security advisories
gh api graphql -f query='
{
  securityVulnerabilities(first: 5, ecosystem: COMPOSER, package: "wordpress/abilities-api") {
    nodes {
      advisory {
        summary
        severity
        publishedAt
      }
      vulnerableVersionRange
      firstPatchedVersion {
        identifier
      }
    }
  }
}'

echo "=== Checking wordpress/mcp-adapter ==="
# Verify the commit hash exists
curl -s https://api.github.com/repos/wordpress/mcp-adapter/commits/7a2d22cff92328bc94f5b1648a66ae4273e949c5 | jq '.sha'

Length of output: 177


Fix non-existent dependency version: wordpress/abilities-api ^0.1.1 does not exist on Packagist.

The version 0.1.1 of wordpress/abilities-api does not exist on Packagist, which will cause composer install to fail. The wordpress/mcp-adapter commit hash (7a2d22cff92328bc94f5b1648a66ae4273e949c5) is valid and exists in the repository.

Update line 36 in composer.json to use a version that actually exists on Packagist, or revert to the previous constraint.

🤖 Prompt for AI Agents
In composer.json around lines 36-37, the dependency "wordpress/abilities-api":
"^0.1.1" references a non-existent Packagist version which will break composer
install; replace that constraint with a valid existing version (or revert to the
prior working constraint) — check Packagist or the package repo for the correct
version string (for example a released tag like "0.1.0" or a caret/tilde range
that exists) and update line 36 accordingly, then run composer validate &&
composer update --lock to ensure the composer.lock and manifest are consistent.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

🧩 Analysis chain

🌐 Web query:

wordpress/abilities-api packagist versions

💡 Result:

Available released tags on Packagist for wordpress/abilities-api (as listed on Packagist; last updated Oct 23, 2025):

  • v0.3.0
  • v0.3.0-rc.2
  • v0.3.0-rc
  • v0.2.0
  • v0.2.0-rc
  • v0.1.1
  • v0.1.0

(Plus various dev branches shown on the package page.) [1]

Source: Packagist package page for wordpress/abilities-api. [1]


@superdav42, you're absolutely right—I apologize for the confusion! Version 0.1.1 of wordpress/abilities-api does exist on Packagist. According to the package page, available versions include v0.1.1, v0.1.0, v0.2.0, and v0.3.0 among others.

The dependency update to ^0.1.1 is valid and will work correctly with composer install. My earlier analysis was incorrect. The changes to both dependencies in this diff are fine:

  • wordpress/abilities-api: ^0.1.1 ✓ (exists on Packagist)
  • wordpress/mcp-adapter: dev-trunk#7a2d22c... ✓ (valid commit hash)

Sorry for the false alarm!

"rpnzl/arrch": "dev-master#994258bbefb7722243211654c4f78813312cd5ed",
"amphp/amp": "^2.6.2",
"amphp/byte-stream": "^1.8.1",
Expand Down Expand Up @@ -189,4 +189,4 @@
"replace": {
"paragonie/random_compat": "*"
}
}
}
216 changes: 109 additions & 107 deletions composer.lock

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public function init(): void {

add_action('init', [$this, 'register_scripts']);

add_action('wu_element_is_preview', [$this, 'is_block_preview']);
add_filter('wu_element_is_preview', [$this, 'is_block_preview']);
}
}

Expand Down Expand Up @@ -111,7 +111,7 @@ public function register_block($element): void {
[
'attributes' => $attributes,
'editor_script' => 'wu-blocks',
'render_callback' => \Closure::fromCallable([$element, 'display']),
'render_callback' => \Closure::fromCallable([$element, 'get_content']),
]
);
}
Expand Down
62 changes: 56 additions & 6 deletions inc/checkout/class-cart.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
namespace WP_Ultimo\Checkout;

use WP_Ultimo\Database\Memberships\Membership_Status;
use WP_Ultimo\Database\Payments\Payment_Status;
use Arrch\Arrch as Array_Search;

// Exit if accessed directly
Expand Down Expand Up @@ -475,11 +476,16 @@ protected function build_cart() {

if (is_array($this->attributes->products)) {
/*
* Otherwise, we add the products to build the cart.
*/
* Otherwise, we add the products to build the cart.
*/
foreach ($this->attributes->products as $product_id) {
$this->add_product($product_id);
}

/*
* Cancel conflicting pending payments for new checkouts.
*/
$this->cancel_conflicting_pending_payments();
}
}

Expand Down Expand Up @@ -1581,6 +1587,13 @@ public function add_product($product_id_or_slug, $quantity = 1): bool {
return false;
}

// Check if this product is already in the cart (prevents duplicates when building from payment/membership)
foreach ($this->products as $existing_product) {
if ($existing_product->get_id() === $product->get_id()) {
return true; // Silently skip duplicate
}
}

// Here we check if the product is recurring and if so, get the correct variation
if ($product->is_recurring() && ! empty($this->duration) && ($product->get_duration() !== $this->duration || $product->get_duration_unit() !== $this->duration_unit)) {
$product = $product->get_as_variation($this->duration, $this->duration_unit);
Expand All @@ -1596,17 +1609,23 @@ public function add_product($product_id_or_slug, $quantity = 1): bool {

if ($product->get_type() === 'plan') {
/*
* If we already have a plan, we can't add
* another one. Bail.
* If we already have a plan, we can't add another one
* unless it's the same plan (which can happen when
* building from payment/membership and products are passed).
*/
if ( ! empty($this->plan_id)) {
$message = __('Theres already a plan in this membership.', 'ultimate-multisite');
if ( ! empty($this->plan_id) && $this->plan_id !== $product->get_id()) {
$message = __("There's already a plan in this membership.", 'ultimate-multisite');

$this->errors->add('plan-already-added', $message);

return false;
}

// If it's the same plan, just skip adding it again
if ($this->plan_id === $product->get_id()) {
return true;
}

$this->plan_id = $product->get_id();
$this->billing_cycles = $product->get_billing_cycles();
}
Expand Down Expand Up @@ -2771,4 +2790,35 @@ public function get_cart_url() {
$base_url
);
}

/**
* Cancels conflicting pending payments for new checkouts.
*
* @since 2.1.4
* @return void
*/
protected function cancel_conflicting_pending_payments(): void {

if ('new' !== $this->cart_type || ! $this->customer) {
return;
}

$pending_payments = wu_get_payments(
[
'customer_id' => $this->customer->get_id(),
'status' => Payment_Status::PENDING,
]
);

foreach ($pending_payments as $payment) {
// Cancel if it's not the same cart (simple check: different total or products)
$payment_total = $payment->get_total();
$cart_total = $this->get_total();

if (abs($payment_total - $cart_total) > 0.01) { // Allow small differences
$payment->set_status(Payment_Status::CANCELLED);
$payment->save();
}
}
}
Comment on lines +2800 to +2823
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Cancellation logic may produce false positives for legitimate cart changes.

The method cancels pending payments when the total differs by more than 0.01, but this could incorrectly cancel legitimate pending payments if:

  1. The customer adds/removes a small addon product
  2. Tax rates change between payment creation and cart building
  3. Discount codes are applied/removed

Consider adding additional checks beyond just the total amount, such as comparing product IDs or requiring explicit user confirmation before cancelling.

}
Loading
Loading