When using the product % discount I get a fatal error on the front page of my site, but probably also on other pages.

Fatal error: Cannot use string offset as an array in /data/disk/o1/static/commerce_kickstart-7.x-2.0-rc1/profiles/commerce_kickstart/modules/contrib/commerce_discount/commerce_discount.rules.inc on line 143

Comments

lsolesen’s picture

Did a print_r() to see what was going on:

Array
(
    [0] => Array
        (
            [name] => base_price
            [price] => Array
                (
                    [amount] => 12000
                    [currency_code] => DKK
                    [data] => Array
                        (
                        )

                )

            [included] => 1
        )

    [1] => Array
        (
            [name] => tax|danish_vat
            [price] => Array
                (
                    [amount] => 3000
                    [currency_code] => DKK
                    [data] => Array
                        (
                            [tax_rate] => Array
                                (
                                    [name] => danish_vat
                                    [display_title] => Moms
                                    [description] => 
                                    [rate] => 0.25
                                    [type] => vat
                                    [rules_component] => commerce_tax_rate_danish_vat
                                    [default_rules_component] => 1
                                    [price_component] => tax|danish_vat
                                    [calculation_callback] => commerce_tax_rate_calculate
                                    [module] => commerce_tax_ui
                                    [title] => Danish VAT
                                    [admin_list] => 1
                                )

                        )

                )

            [included] => 1
        )

)
danish_vat

Seems that the last "danish_vat" creates the error. I am not sure how that got into the components.

BarisW’s picture

Same here with latest commerce_discount update. We have a Dutch VAT.
When I change the % discount to a fixed discount, the errors are gone.

The error is that the site crashes on admin/commerce/orders and when ordering products.

EntityMetadataWrapperException: Invalid data value given. Be sure it matches the required data type and format. in EntityMetadataWrapper->set() (line 122 of /profiles/commerce_kickstart/modules/contrib/entity/includes/entity.wrapper.inc).

pcambra’s picture

Title: Product % discount gives fatal error » Product % discount gives fatal error when including a tax

Ok, error identified, it's happening for Product % coupons that have taxes included

ericmulder1980’s picture

Version: 7.x-1.x-dev » 7.x-1.0-alpha1

Perhaps some extra info to get this fixed. I am getting this error when i have multiple discounts setup. These are the steps to reproduce this.

1) Setup CK as usual and create some products.
2) Create your first discount based on a percentage, for example 25%
3) Place an order
4) Check your orders overview, everything should still be fine.
5) Create your second discount based on a percentage, for example 50%
6) Place a second order.

It fails as soon as you place a product in your shopping cart and go to your shopping cart page.

DatabaseTransactionOutOfOrderException: in DatabaseConnection->rollback() (line 1042 of /includes/database/database.inc).

Also the order overview now fails with the following error

EntityMetadataWrapperException: Invalid data value given. Be sure it matches the required data type and format. in EntityMetadataWrapper->set() (line 122 of /profiles/commerce_kickstart/modules/contrib/entity/includes/entity.wrapper.inc).

Now in the above example it will add both the 25% and 50% discount to the same product. In my example i have created a custom rule condition that let's you select a product type and an amount. The rules only fire when you have added a given amount of products of type x. In the rules log i can see that the proper rule is fired.

Hope this gives you some extra information to get this fixed.

ericmulder1980’s picture

When i disable the rule that does the taxes calculation i still have this error so perhaps it's not related to taxes?

pcambra’s picture

Yeah, I guess it doesn't work very well with multiple price components, that's the reason

dubs’s picture

I've got this to work by altering the line in question: -

if (is_array($component) && !empty($component['price']['data']['discount_name']) && $component['price']['data']['discount_name'] == $discount_name) {

I'm not sure if this just bypasses the double-check, but it stops the error and the cart seems to calculate correctly.

lsolesen’s picture

Status: Active » Needs review
StatusFileSize
new793 bytes

Expressed as a patch.

Status: Needs review » Needs work

The last submitted patch, check-if-array-issue-1789412.patch, failed testing.

lsolesen’s picture

Status: Needs work » Needs review

#8: check-if-array-issue-1789412.patch queued for re-testing.

Status: Needs review » Needs work

The last submitted patch, check-if-array-issue-1789412.patch, failed testing.

pcambra’s picture

Status: Needs work » Fixed

Fixed it in a slightly different way, see the commit here:

http://drupalcode.org/project/commerce_discount.git/commit/319204a

Thanks for the report and the follow up!!

ericmulder1980’s picture

I was extremely happy to see this was fixed. However after some more testing the EntityMetadataWrapperException and DatabaseTransactionOutOfOrderException returned as soon as i have placed multiple orders while having multiple discounts setup.

I will create a new issue with the exact details on how to reproduce this.

BarisW’s picture

Version: 7.x-1.0-alpha1 » 7.x-1.x-dev
Status: Fixed » Active

I've spoken with ericmulder1980 and it seems that the steps listed in #4 still produces these errors.

Re-opening this issue as the commit in #12 doesn't fully fix the problem.

pcambra’s picture

I've just tried the steps in #4 several times:

1) Setup CK as usual and create some products.
2) Create your first discount based on a percentage, for example 25%
3) Place an order
4) Check your orders overview, everything should still be fine.
5) Create your second discount based on a percentage, for example 50%
6) Place a second order.

But I guess I need more info, I've requested the rules that are failing to @ericmulder1980 on Friday, could someone that can reproduce the issue exportthe rules that are affecting this and attach them here?

ericmulder1980’s picture

Sorry for the delay. Here is the code for the condition. I removed the customer name from the code and changed everything to 'mymodule'.

Implementation of hook_rules_condition_info().

/**
 * Implements hook_rules_condition_info().
 */
function mymodule_product_selection_rules_condition_info() {
  $items = array(
    'order_contains_x_products_of_type_x' => array(
      'group' => 'MyModule',
      'label' => t('Order contains X products of product type X'),
      'base' => 'mymodule_product_selection_order_contains_x_products_of_type_x',
      'parameter' => array(
        'entity' => array(
          'label' => t('Order'),
          'type' => 'entity',
          'wrapped' => TRUE,
        ),
        'product_type' => array(
          'label' => t('Product type'),
          'type' => 'list<text>',
          'options list' => 'mymodule_product_selection_commerce_product_types',
          'description' => t('The type of products to check for'),
        ),
        'operator' => array(
          'type' => 'text',
          'label' => t('Operator'),
          'description' => t('The comparison operator to use against the total number of products on the order.'),
          'default value' => '>=',
          'options list' => 'commerce_numeric_comparison_operator_options_list',
          'restriction' => 'input',
        ),
        'value' => array(
          'type' => 'text',
          'label' => t('Quantity'),
          'default value' => 1,
          'description' => t('The value to compare against the total quantity of products on the order.'),
        ),
      ),
    ),
  );
  return $items;
}

Implementation of hook_rules_condition_info()

/**
 * Rules condition: Order contains x products of type x
 */
function mymodule_product_selection_order_contains_x_products_of_type_x(EntityDrupalWrapper $wrapper, $product_type, $operator, $amount) {

  // Reset our counter.
  $count = 0;

  // Loop trough all line items and check for the product type.
  foreach ($wrapper->commerce_line_items->value() as $line_item) {
    $line_item_wrapper = entity_metadata_wrapper('commerce_line_item', $line_item);
    if ($line_item_wrapper->value()->type == 'product') {
      $product_id = $line_item_wrapper->value()->commerce_product[LANGUAGE_NONE][0]['product_id'];
      $product = commerce_product_load($product_id);
      if ($product->type == key($product_type)) {
        $count++;
      }
    }
  }

  // Run the 2 numbers against an evaluation function.
  $result = mymodule_product_selection_eval($count, $operator, $amount);

  return (bool) $result;
}

The evaluation function for the product type and amount

/**
 * Performs an evaluation based on 2 values and an operator.
 */
function mymodule_product_selection_eval($var1, $operator, $var2) {
  switch ($operator) {
    case '<':
      return $var1 < $var2;
      break;

    case '<=':
      return $var1 <= $var2;
      break;

    case '=':
      return $var1 == $var2;
      break;

    case '>=':
      return $var1 >= $var2;
      break;

    case '>':
      return $var1 > $var2;
      break;
  }
}

Hope you can reproduce this with the above code.

ericmulder1980’s picture

StatusFileSize
new520 bytes

Ok, we finally resolved where this issue comes from. when using the EntityMetadataWrapper to set values for the total_amount in commerce_discount_remove_discount_components() it fails when the given amount is a float value and not an integer value.

The validate function in entity.wrapper.inc validates the $value against $this->type. This results in float == integer, which fails.

So forcing the entered data to be a string fixes this issue and makes me very very very happy :)

Special thanx to pcambra for putting effort into fixing this problem and sharing thoughts on IRC.

Attached patch fixes the issue.

ericmulder1980’s picture

Status: Active » Needs review

changed status to needs review.

pcambra’s picture

Status: Needs review » Fixed

I've confirmed that this error is only happening with Commerce Kickstart RC1 and it's due that this patch #1518084: Expose a new property to Entity API (Amount floatted) is applied there and not in Drupal Commerce core.
There are plans for removing this from kickstart itself but the workaround in #17 is valid for those affected.

Setting back to fixed as it will be eventually corrected in kickstart.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

giorgosk’s picture

just noting here that I was getting the same error with CK RC3 but latest DEV of commerce_discount fixed this

Fatal error: Cannot use string offset as an array in /home/domain/public_html/profiles/commerce_kickstart/modules/contrib/commerce_discount/commerce_discount.rules.inc on line 143

Status: Closed (fixed) » Needs work

The last submitted patch, 17: discount-percentage-error-1789412.patch, failed testing.

joelpittet’s picture

Issue summary: View changes
Status: Needs work » Closed (fixed)