/** * Check that current product variation is valid * * @param Array $data Submitted data * @return Boolean Returns TRUE if the submitted data is valid, otherwise FALSE. */ function php($data) { $valid = parent::php($data); $fields = $this->form->Fields(); //Check that variation exists if necessary $form = $this->form; $request = $this->form->getRequest(); //Get product variations from options sent //TODO refactor this $productVariations = new DataObjectSet(); $options = $request->postVar('Options'); $product = DataObject::get_by_id($data['ProductClass'], $data['ProductID']); $variations = $product ? $product->Variations() : new DataObjectSet(); if ($variations && $variations->exists()) { foreach ($variations as $variation) { $variationOptions = $variation->Options()->map('AttributeID', 'ID'); if ($options == $variationOptions && $variation->isEnabled()) { $productVariations->push($variation); } } } if ((!$productVariations || !$productVariations->exists()) && $product && $product->requiresVariation()) { $this->form->sessionMessage(_t('Form.VARIATIONS_REQUIRED', 'This product requires options before it can be added to the cart.'), 'bad'); //Have to set an error for Form::validate() $this->errors[] = true; $valid = false; return $valid; } //Validate that the product/variation being added is inStock() $stockLevel = 0; if ($product) { if ($product->requiresVariation()) { $stockLevel = $productVariations->First()->StockLevel()->Level; } else { $stockLevel = $product->StockLevel()->Level; } } if ($stockLevel == 0) { $this->form->sessionMessage(_t('Form.STOCK_LEVEL', ''), 'bad'); //Have to set an error for Form::validate() $this->errors[] = true; $valid = false; } //Validate the quantity is not greater than the available stock $quantity = $request->postVar('Quantity'); if ($stockLevel > 0 && $stockLevel < $quantity) { $this->form->sessionMessage(_t('Form.STOCK_LEVEL_MORE_THAN_QUANTITY', 'The quantity is greater than available stock for this product.'), 'bad'); //Have to set an error for Form::validate() $this->errors[] = true; $valid = false; } return $valid; }
/** * Test {@link DataObjectSet->exists()} */ function testExists() { // Test an empty set $set = new DataObjectSet(); $this->assertFalse($set->exists(), 'Empty set doesn\'t exist.'); // Test a non-empty set $set = DataObject::get('DataObjectSetTest_TeamComment', '', "\"ID\" ASC"); $this->assertTrue($set->exists(), 'Non-empty set does exist.'); }
/** * Get options for a product and return for use in the form * Must get options for nextAttributeID, but these options should be filtered so * that only the options for the variations that match attributeID and optionID * are returned. * * In other words, do not just return options for a product, return options for product * variations. * * Usually called via AJAX. * * @param SS_HTTPRequest $request * @return String JSON encoded string for use to update options in select fields on Product page */ public function options(SS_HTTPRequest $request) { $data = array(); $product = $this->data(); $options = new DataObjectSet(); $variations = $product->Variations(); $filteredVariations = new DataObjectSet(); $attributeOptions = $request->postVar('Options'); $nextAttributeID = $request->postVar('NextAttributeID'); //Filter variations to match attribute ID and option ID //Variations need to have the same option for each attribute ID in POST data to be considered if ($variations && $variations->exists()) { foreach ($variations as $variation) { $variationOptions = array(); //if ($attributeOptions && is_array($attributeOptions)) { foreach ($attributeOptions as $attributeID => $optionID) { //Get option for attribute ID, if this variation has options for every attribute in the array then add it to filtered $attributeOption = $variation->getOptionForAttribute($attributeID); if ($attributeOption && $attributeOption->ID == $optionID) { $variationOptions[$attributeID] = $optionID; } } //} if ($variationOptions == $attributeOptions && $variation->isEnabled()) { $filteredVariations->push($variation); } } } //Find options in filtered variations that match next attribute ID //All variations must have options for all attributes so this is belt and braces really if ($filteredVariations && $filteredVariations->exists()) { foreach ($filteredVariations as $variation) { $attributeOption = $variation->getOptionForAttribute($nextAttributeID); if ($attributeOption) { $options->push($attributeOption); } } } if ($options && $options->exists()) { $map = $options->map(); //This resets the array counter to 0 which ruins the attribute IDs //array_unshift($map, 'Please Select'); $data['options'] = $map; $data['count'] = count($map); $data['nextAttributeID'] = $nextAttributeID; } return json_encode($data); }
/** * Add an item to the order representing the product, * if an item for this product exists increase the quantity. Update the Order total afterward. * * @param DataObject $product The product to be represented by this order item * @param DataObjectSet $productOptions The product variations to be added, usually just one */ function addItem(DataObject $product, $quantity = 1, DataObjectSet $productOptions = null) { //Check that product options exist if product requires them //TODO perform this validation in Item->validate(), cannot at this stage because Item is written before ItemOption, no transactions, chicken/egg problem if ((!$productOptions || !$productOptions->exists()) && $product->requiresVariation()) { user_error("Cannot add item to cart, product options are required.", E_USER_WARNING); //Debug::friendlyError(); return; } //Increment the quantity if this item exists already $item = $this->findIdenticalItem($product, $productOptions); if ($item && $item->exists()) { $item->Quantity = $item->Quantity + $quantity; $item->write(); } else { //TODO this needs transactions for Item->validate() to check that ItemOptions exist for Item before it is written $item = new Item(); $item->ObjectID = $product->ID; $item->ObjectClass = $product->class; $item->ObjectVersion = $product->Version; $item->Amount->setAmount($product->Amount->getAmount()); $item->Amount->setCurrency($product->Amount->getCurrency()); $item->Quantity = $quantity; $item->OrderID = $this->ID; $item->write(); if ($productOptions && $productOptions->exists()) { foreach ($productOptions as $productOption) { $itemOption = new ItemOption(); $itemOption->ObjectID = $productOption->ID; $itemOption->ObjectClass = $productOption->class; $itemOption->ObjectVersion = $productOption->Version; $itemOption->Amount->setAmount($productOption->Amount->getAmount()); $itemOption->Amount->setCurrency($productOption->Amount->getCurrency()); $itemOption->ItemID = $item->ID; $itemOption->write(); } } } $this->updateTotal(); }