Jump to:

2082 Posts in 1002 Topics by 452 members

E-Commerce Modules

SilverStripe Forums » E-Commerce Modules » Fixes for ecommerce 0.8.*

Discuss about the various e-commerce modules available:
Ecommerce, SS Shop, SilverCart and SwipeStripe
Alternatively, have a look the shared mailinglist.

Moderators: martimiz, Nicolaas, Sean, frankmullenger, biapar, Willr, Ingo, Jedateach, swaiba, simon_w

Page: 1
Go to End
Author Topic: 1169 Views
  • inCharge
    Avatar
    Community Member
    102 Posts

    Fixes for ecommerce 0.8.* Link to this post

    This is a fix for 0.8.0, 0.8.1 and (as of now) the current BurnBright version:

    Using the FlatTaxModifier, I'm getting the following error when it is the second of two modifiers. The same problem probably also happens with other modifiers that iterate through all the modifiers. (It needs to do that to calculate tax on shipping etc)

    Debug::fatalHandler(256,Uncaught Exception: Object->__call(): the method 'total' does not exist on 'DataObjectSet' in ...\sapphire\core\Object.php,724,Array)
    exceptionHandler(exception 'Exception' with message 'Object->__call(): the method 'total' does not exist on 'DataObjectSet'' in ...sapphire\core\Object.php:724
    Stack trace:
    #0 ...\model\Order.php(609): Object->__call('Total', Array)
    #1 ...\model\Order.php(609): DataObjectSet->Total()
    #2 ...\modifiers\FlatTaxModifier.php(104): Order->ModifiersSubTotal('FlatTaxModifier')
    #3 ...\modifiers\FlatTaxModifier.php(93): FlatTaxModifier->TaxableAmount()
    ...etc...

    The cause is in Order.php, in the createModifiers function.
    To fix it, change from...

    return $write ? $this->modifiersFromDatabase() : new DataObjectSet($modifiers);

    ...to...

    return $write ? $this->modifiersFromDatabase() : $modifiers;

    ...because $modifiers is already a DataObjectSet, so the old code creates a nested DataObjectSet. When the result is returned, and the caller tries to interate through the modifiers, it finds the nested DataObjectSet instead of a Modifier, which is why the error message says 'total' does not exist on 'DataObjectSet'.

    I haven't tested older versions, but in version 8.0, ShoppingCart::get_modifiers() changed to return a dataset instead of an array, so looks like it affects all versions since then.

  • inCharge
    Avatar
    Community Member
    102 Posts

    Re: Fixes for ecommerce 0.8.* Link to this post

    When a ModifierForm is submitted, it goes to 404 Page Not Found: "Sorry, it seems you were trying to access a page that doesn't exist."

    The cause in CheckoutPage.php, in initVirtualMethods. To fix it, add the call to self::uninherited_static.

       protected function initVirtualMethods() {
          if($forms = $this->ModifierForms()) {
             foreach($forms as $form) {
                $this->addWrapperMethod($form->Name(), 'getOrderModifierForm');
                self::$allowed_actions[] = $form->Name(); // add all these forms to the list of allowed actions also
             }

             // Force this controller class to update its cache of allowed_actions
             self::uninherited_static('CheckoutPage_Controller', 'allowed_actions', true);
          }
       }

    Why? Because actions are added to the allowed_actions array AFTER it has been read and cached by Object::uninherited_static, so the request handler doesn't see the dynamically added action. The solution is to call Object::uninherited_static again with the parameter 'uncached' as 'true', which forces the cache to be updated.

    This code has been there since at least version 0.6, so either nobody has ever used ModifierForms, which is possible as I can't see any shipped examples. Or maybe the cacheing mechanism was introduced after the code was written, although I just checked SilverStripe 2.7 and it has the same cacheing code.

  • Jedateach
    Avatar
    Forum Moderator
    227 Posts

    Re: Fixes for ecommerce 0.8.* Link to this post

    hi inCharge, thanks for sharing your problems / solutions here.

    In a nutshell what this code is trying to achieve is to allow any modifier form to be processed when they are submitted on the checkout page. Because your selection of modifiers is customizable, the initVirtualMethods function is needed to add each modifier form to the CheckoutPage_Controller. Normally you would add MyModiferForm to the ChecoutPage_Controller class, and this also becomes an action you can submit the form to.
    The second part of adding an action to a controller is to allow it to be called, so that's why we need to update the allowed_actions static array.

    Historically, I'm not sure modifier forms have ever worked / been used. I've revisited this code in trunk recently, when I finally needed to create a modifier with a form (for entering discount coupons). The coupon module isn't finished, but the modifier forms processing probably does. One change was to move the initVirtualMethods code to a unique controller... with the intention of allowing a modifier form to be added to / processed from any part of the site you want to add it on.

    Anyway, thanks again, hope this helps. You're most welcome to test out the trunk code, we're currently trying to get it stable for a release.

  • inCharge
    Avatar
    Community Member
    102 Posts

    Re: Fixes for ecommerce 0.8.* Link to this post

    I'm using a modifier form to allow the cutomer to select a shipping/delivery service - i.e. Standard/Express etc. It works fine once the cacheing issue mentioned above is fixed.

    One aspect of the modifier form that I find strange is that each modifier form has its own <form> tags and Submit button. I don't think the customer expects to see more than one Submit button. Wouldn't it be better to have all the fields in one form? Maybe Ajax is the answer.

    > You're most welcome to test out the trunk code, we're currently trying to get it stable for a release.

    I was hoping to use that code for this project, but it wasn't ready, so I used 8.1. Hope to be upgrading before long. It's good to see those nightly test-run emails coming through to the Google group.

    Thanks,
    Jules

  • inCharge
    Avatar
    Community Member
    102 Posts

    Re: Fixes for ecommerce 0.8.* Link to this post

    This is another part of the CheckOut page fix detailed above.

    It seems that the allowed_actions array must be declared for the Modifier Form actions to be added dynamically.

    class CheckoutPage_Controller extends Page_Controller {

       static $allowed_actions = array(
          'OrderForm'
       );

  • inCharge
    Avatar
    Community Member
    102 Posts

    Re: Fixes for ecommerce 0.8.* Link to this post

    Sometimes you want to leave the variation label blank (e.g. Size), and just display the variation description and price. At the moment, if the variation label is empty, there's an unwanted colon

    Also, sometimes the variation value is empty e.g. if there are multiple variation types, but one type is not applicable for some variations.

    e.g. If the variation label is empty, it shows...

    :85x200 cms, :
    or
    :85x200 cms, :Gold artwork
    or
    :, :Gold artwork

    ...but I want to show...

    85x200 cms
    or
    85x200 cms, Gold artwork
    or
    Gold artwork

    So in ProductVariation.php, I changed the getTitle function to...

       function getTitle(){
          $values = $this->AttributeValues();
          if($values->exists()){
             $labelvalues = array();
             foreach($values as $value){
                $l = $value->Type()->Label;
                $v = $value->Value;
                if ( $l && $v )
                   $labelvalues[] = $l . ':' . $v;
                else if ( $v )
                   $labelvalues[] = $v;
                }
             return implode(', ',$labelvalues);
          }
          return $this->InternalItemID;
       }

    This change should be backwardly compatible, because I can't think why the leading colon would ever be desirable.

  • inCharge
    Avatar
    Community Member
    102 Posts

    Re: Fixes for ecommerce 0.8.* Link to this post

    This isn't a fix as such.

    Objects typically have a debug() method, which is really useful for ...er... debugging. In the .ss file, just add $debug to see the properties of the object in the current context.

    The Product object has a debug method, but it doesn't show all the properties. To see all properies, in product.php, change debug to...

       public function debug() {
          $Title = $this->Title;
          $Price = $this->Price;
          $Weight = $this->Weight;
          $Model = $this->Model;
          $FeaturedProduct = $this->FeaturedProduct;
          $AllowPurchase = $this->AllowPurchase;
          $InternalItemID = $this->InternalItemID;
          $NumberSold = $this->NumberSold;

          $html = parent::debug() .<<<HTML
             <h3>Product class details</h3>
             <p>
                <b>Title : </b>$Title<br/>
                <b>Price : </b>$Price<br/>
                <b>Weight : </b>$Weight<br/>
                <b>Model : </b>$Model<br/>
                <b>FeaturedProduct : </b>$FeaturedProduct<br/>
                <b>AllowPurchase : </b>$AllowPurchase<br/>
                <b>InternalItemID : </b>$InternalItemID<br/>
                <b>NumberSold : </b>$NumberSold<br/>
             </p>
    HTML;

          return $html;
       }

    By the way, also in Product.php, the Product_OrderItem class also has a debug function, which includes the line...

          $this->extend('updateDebug',$html);


    ...but I don't see how this can ever work, because the extension can't return anything, can it?

    1169 Views
Page: 1
Go to Top

Want to know more about the company that brought you SilverStripe? Then check out SilverStripe.com

Comments on this website? Please give feedback.