/** * Restores the Cart from the Order ID given * * Redirects to the login when nobody is logged in. * Redirects to the history overview when the Order cannot be loaded, * or when it does not belong to the current Customer. * When $editable is true, redirects to the detail view of the first * Item for editing. Editing will be disabled otherwise. * @global array $_ARRAYLANG * @param integer $order_id The Order ID * @param boolean $editable Items in the Cart are editable iff true */ static function from_order($order_id, $editable = false) { global $_ARRAYLANG; $objCustomer = Shop::customer(); if (!$objCustomer) { \Message::information($_ARRAYLANG['TXT_SHOP_ORDER_LOGIN_TO_REPEAT']); \Cx\Core\Csrf\Controller\Csrf::redirect(\Cx\Core\Routing\Url::fromModuleAndCmd('Shop', 'login') . '?redirect=' . base64_encode(\Cx\Core\Routing\Url::fromModuleAndCmd('Shop', 'cart') . '?order_id=' . $order_id)); } $customer_id = $objCustomer->getId(); $order = Order::getById($order_id); if (!$order || $order->customer_id() != $customer_id) { \Message::warning($_ARRAYLANG['TXT_SHOP_ORDER_INVALID_ID']); \Cx\Core\Csrf\Controller\Csrf::redirect(\Cx\Core\Routing\Url::fromModuleAndCmd('Shop', 'history')); } // Optional! self::destroy(); $_SESSION['shop']['shipperId'] = $order->shipment_id(); $_SESSION['shop']['paymentId'] = $order->payment_id(); $order_attributes = $order->getOptionArray(); $count = null; $arrAttributes = Attributes::getArray($count, 0, -1, null, array()); // Find an Attribute and option IDs for the reprint type $attribute_id_reprint = $option_id_reprint = NULL; if (!$editable) { //DBG::log("Cart::from_order(): Checking for reprint..."); foreach ($arrAttributes as $attribute_id => $objAttribute) { if ($objAttribute->getType() == Attribute::TYPE_EZS_REPRINT) { //DBG::log("Cart::from_order(): TYPE reprint"); $options = $objAttribute->getOptionArray(); if ($options) { $option_id_reprint = current(array_keys($options)); $attribute_id_reprint = $attribute_id; //DBG::log("Cart::from_order(): Found reprint Attribute $attribute_id_reprint, option $option_id_reprint"); break; } } } } foreach ($order->getItems() as $item) { $item_id = $item['item_id']; $attributes = $order_attributes[$item_id]; $options = array(); foreach ($attributes as $attribute_id => $attribute) { // foreach (array_keys($attribute['options']) as $option_id) { foreach ($attribute['options'] as $option_id => $option) { //DBG::log("Cart::from_order(): Option: ".var_export($option, true)); switch ($arrAttributes[$attribute_id]->getType()) { case Attribute::TYPE_TEXT_OPTIONAL: case Attribute::TYPE_TEXT_MANDATORY: case Attribute::TYPE_TEXTAREA_OPTIONAL: case Attribute::TYPE_TEXTAREA_MANDATORY: case Attribute::TYPE_EMAIL_OPTIONAL: case Attribute::TYPE_EMAIL_MANDATORY: case Attribute::TYPE_URL_OPTIONAL: case Attribute::TYPE_URL_MANDATORY: case Attribute::TYPE_DATE_OPTIONAL: case Attribute::TYPE_DATE_MANDATORY: case Attribute::TYPE_NUMBER_INT_OPTIONAL: case Attribute::TYPE_NUMBER_INT_MANDATORY: case Attribute::TYPE_NUMBER_FLOAT_OPTIONAL: case Attribute::TYPE_NUMBER_FLOAT_MANDATORY: case Attribute::TYPE_EZS_ACCOUNT_3: case Attribute::TYPE_EZS_ACCOUNT_4: case Attribute::TYPE_EZS_IBAN: case Attribute::TYPE_EZS_IN_FAVOR_OF: case Attribute::TYPE_EZS_REFERENCE: case Attribute::TYPE_EZS_CLEARING: case Attribute::TYPE_EZS_DEPOSIT_FOR_6: case Attribute::TYPE_EZS_DEPOSIT_FOR_2L: case Attribute::TYPE_EZS_DEPOSIT_FOR_2H: case Attribute::TYPE_EZS_PURPOSE_35: case Attribute::TYPE_EZS_PURPOSE_50: $options[$attribute_id][] = $option['name']; break; case Attribute::TYPE_EZS_REDPLATE: case Attribute::TYPE_EZS_CONFIRMATION: if (!$attribute_id_reprint) { //DBG::log("Cart::from_order(): No reprint, adding option {$option['name']}"); $options[$attribute_id][] = $option_id; } break; case Attribute::TYPE_EZS_REPRINT: // Automatically added below when appropriate break; default: // case Attribute::TYPE_EZS_ZEWOLOGO: // case Attribute::TYPE_EZS_EXPRESS: // case Attribute::TYPE_EZS_PURPOSE_BOLD: $options[$attribute_id][] = $option_id; break; } //DBG::log("Cart::from_order(): Added option: ".var_export($options, true)); } } if ($attribute_id_reprint) { $options[$attribute_id_reprint][] = $option_id_reprint; //DBG::log("Cart::from_order(): Item has reprint Attribute, added $attribute_id_reprint => ($option_id_reprint)"); } self::add_product(array('id' => $item['product_id'], 'quantity' => $item['quantity'], 'options' => $options)); } if ($attribute_id_reprint) { // Mark the Cart as being unchanged since the restore, so the // additional cost for some Attributes won't be added again. self::restored_order_id($order_id); } \Message::information($_ARRAYLANG['TXT_SHOP_ORDER_RESTORED']); // Enable for production \Cx\Core\Csrf\Controller\Csrf::redirect(\Cx\Core\Routing\Url::fromModuleAndCmd('Shop', 'cart')); }
/** * Set up the HTML elements for all the Product Attributes of any Product. * * The following types of Attributes are supported: * 0 Dropdown menu, customers may select no (the default) or one option. * 1 Radio buttons, customers need to select one option. * 2 Checkboxes, customers may select no, one or several options. * 3 Dropdown menu, customers need to select one option. * 4 Optional text field * 5 Mandatory text field * 6 Optional file upload field * 7 Mandatory file upload field * Types 1 and 3 are functionally identical, they only differ by * the kind of widget being used. * The individual Product Attributes carry a unique ID enabling the * JavaScript code contained within the Shop page to verify that * all mandatory choices have been made before any Product can * be added to the cart. * @param integer $product_id The Product ID * @param string $formName The name of the HTML form containing * the Product and options * @param integer $cart_id The optional cart Product ID, * null if not applicable. * @param boolean $flagUpload If a product has an upload * Attribute associated with it, * this parameter will be set to true * @return string The string with the HTML code */ static function productOptions($product_id, $formName, $cart_id = null, &$flagUpload = false) { global $_ARRAYLANG; //\DBG::log("productOptions($product_id, $formName, $cart_id, $flagUpload): Entered"); // Semicolon separated list of Attribute name IDs to verify // before the Product is added to the cart $checkOptionIds = ''; // check if the product option block exists in the template if (self::$objTemplate->blockExists('shopProductOptionsRow') && self::$objTemplate->blockExists('shopProductOptionsValuesRow')) { $domId = 0; $count = 0; $arrAttributes = Attributes::getArray($count, null, null, '`ord` ASC', array('product_id' => $product_id)); //\DBG::log("Attributes: ".var_export($arrAttributes, true)); // When there are no Attributes for this Product, hide the // options blocks if (empty($arrAttributes)) { self::$objTemplate->hideBlock('shopProductOptionsRow'); self::$objTemplate->hideBlock('shopProductOptionsValuesRow'); } else { // Loop through the Attribute Names for the Product foreach ($arrAttributes as $attribute_id => $objAttribute) { $mandatory = false; $arrOptions = Attributes::getOptionArrayByAttributeId($attribute_id); $arrRelation = Attributes::getRelationArray($product_id); // This attribute does not apply for this product if (empty($arrRelation)) { continue; } $selectValues = ''; // create head of option menu/checkbox/radiobutton switch ($objAttribute->getType()) { case Attribute::TYPE_CHECKBOX: case Attribute::TYPE_TEXT_OPTIONAL: case Attribute::TYPE_UPLOAD_OPTIONAL: case Attribute::TYPE_TEXTAREA_OPTIONAL: case Attribute::TYPE_EMAIL_OPTIONAL: case Attribute::TYPE_EMAIL_OPTIONAL: case Attribute::TYPE_URL_OPTIONAL: case Attribute::TYPE_DATE_OPTIONAL: case Attribute::TYPE_NUMBER_INT_OPTIONAL: case Attribute::TYPE_NUMBER_FLOAT_OPTIONAL: // No container nor hidden field for optional types break; case Attribute::TYPE_MENU_OPTIONAL: // There is no hidden input field here either, // but the dropdown menu container $selectValues = '<select name="productOption[' . $attribute_id . ']" id="productOption-' . $product_id . '-' . $attribute_id . '-' . $domId . '" style="width:180px;">' . "\n" . '<option value="0">' . $objAttribute->getName() . ' ' . $_ARRAYLANG['TXT_CHOOSE'] . "</option>\n"; break; case Attribute::TYPE_RADIOBUTTON: case Attribute::TYPE_TEXT_MANDATORY: case Attribute::TYPE_UPLOAD_MANDATORY: case Attribute::TYPE_TEXTAREA_MANDATORY: case Attribute::TYPE_EMAIL_MANDATORY: case Attribute::TYPE_URL_MANDATORY: case Attribute::TYPE_DATE_MANDATORY: case Attribute::TYPE_NUMBER_INT_MANDATORY: case Attribute::TYPE_NUMBER_FLOAT_MANDATORY: $mandatory = true; // The Attribute name, indicating a mandatory option. $selectValues = '<input type="hidden" id="productOption-' . $product_id . '-' . $attribute_id . '" value="' . $objAttribute->getName() . '" />' . "\n"; // The Attribute verification regex, if applicable $regex = Attribute::getVerificationRegex($objAttribute->getType()); if ($regex != '') { $selectValues .= '<input type="hidden" id="attributeVerification-' . $product_id . '-' . $attribute_id . '" value="' . $regex . '" />' . "\n"; } $checkOptionIds .= "{$attribute_id};"; break; case Attribute::TYPE_MENU_MANDATORY: $selectValues = '<input type="hidden" id="productOption-' . $product_id . '-' . $attribute_id . '" value="' . $objAttribute->getName() . '" />' . "\n" . '<select name="productOption[' . $attribute_id . ']" id="productOption-' . $product_id . '-' . $attribute_id . '-' . $domId . '" style="width:180px;">' . "\n" . (count($arrOptions) > 1 ? '<option value="0">' . $objAttribute->getName() . ' ' . $_ARRAYLANG['TXT_CHOOSE'] . "</option>\n" : ''); $checkOptionIds .= "{$attribute_id};"; break; } $i = 0; foreach ($arrOptions as $option_id => $arrOption) { // This option does not apply to this product if (!isset($arrRelation[$option_id])) { continue; } $option_price = ''; $selected = false; // Show the price only if non-zero if ($arrOption['price'] != 0) { $option_price = ' (' . Currency::getCurrencyPrice($arrOption['price']) . ' ' . Currency::getActiveCurrencySymbol() . ')'; } // mark the option value as selected if it was before // and this page was requested from the cart if (isset($cart_id)) { $options = Cart::get_options_array($cart_id, $attribute_id); if (is_array($options) && in_array($option_id, $options)) { $selected = true; } } // create option menu/checkbox/radiobutton switch ($objAttribute->getType()) { case Attribute::TYPE_MENU_OPTIONAL: $selectValues .= '<option value="' . $option_id . '" ' . ($selected ? 'selected="selected"' : '') . ' >' . $arrOption['value'] . $option_price . "</option>\n"; break; case Attribute::TYPE_RADIOBUTTON: $selectValues .= '<input type="radio" name="productOption[' . $attribute_id . ']" id="productOption-' . $product_id . '-' . $attribute_id . '-' . $domId . '" value="' . $option_id . '"' . ($selected ? ' checked="checked"' : '') . ' /><label for="productOption-' . $product_id . '-' . $attribute_id . '-' . $domId . '"> ' . $arrOption['value'] . $option_price . "</label><br />\n"; break; case Attribute::TYPE_CHECKBOX: $selectValues .= '<input type="checkbox" name="productOption[' . $attribute_id . '][' . $i . ']" id="productOption-' . $product_id . '-' . $attribute_id . '-' . $domId . '" value="' . $option_id . '"' . ($selected ? ' checked="checked"' : '') . ' /><label for="productOption-' . $product_id . '-' . $attribute_id . '-' . $domId . '"> ' . $arrOption['value'] . $option_price . "</label><br />\n"; break; case Attribute::TYPE_MENU_MANDATORY: $selectValues .= '<option value="' . $option_id . '"' . ($selected ? ' selected="selected"' : '') . ' >' . $arrOption['value'] . $option_price . "</option>\n"; break; case Attribute::TYPE_TEXT_OPTIONAL: case Attribute::TYPE_TEXT_MANDATORY: // $option_price = ' '; $selectValues .= '<input type="text" name="productOption[' . $attribute_id . ']" id="productOption-' . $product_id . '-' . $attribute_id . '-' . $domId . '" value="' . $arrOption['value'] . '" style="width:180px;" />' . '<label for="productOption-' . $product_id . '-' . $attribute_id . '-' . $domId . '">' . $option_price . "</label><br />\n"; break; case Attribute::TYPE_EMAIL_OPTIONAL: case Attribute::TYPE_EMAIL_MANDATORY: // $option_price = ' '; $selectValues .= '<input type="text" name="productOption[' . $attribute_id . ']" id="productOption-' . $product_id . '-' . $attribute_id . '-' . $domId . '" value="' . $arrOption['value'] . '" style="width:180px;" />' . '<label for="productOption-' . $product_id . '-' . $attribute_id . '-' . $domId . '">' . $option_price . "</label><br />\n"; break; case Attribute::TYPE_URL_OPTIONAL: case Attribute::TYPE_URL_MANDATORY: // $option_price = ' '; $selectValues .= '<input type="text" name="productOption[' . $attribute_id . ']" id="productOption-' . $product_id . '-' . $attribute_id . '-' . $domId . '" value="' . $arrOption['value'] . '" style="width:180px;" />' . '<label for="productOption-' . $product_id . '-' . $attribute_id . '-' . $domId . '">' . $option_price . "</label><br />\n"; break; case Attribute::TYPE_DATE_OPTIONAL: case Attribute::TYPE_DATE_MANDATORY: // $option_price = ' '; // Passed by reference $element_id = 'productOption-' . $product_id . '-' . $attribute_id . '-' . $domId; $selectValues .= \Html::getDatepicker('productOption[' . $attribute_id . ']', array('defaultDate' => $arrOption['value']), 'style="width:180px;"', $element_id) . '<label for="productOption-' . $product_id . '-' . $attribute_id . '-' . $domId . '">' . $option_price . "</label><br />\n"; break; case Attribute::TYPE_NUMBER_INT_OPTIONAL: case Attribute::TYPE_NUMBER_INT_MANDATORY: // $option_price = ' '; $selectValues .= '<input type="text" name="productOption[' . $attribute_id . ']" id="productOption-' . $product_id . '-' . $attribute_id . '-' . $domId . '" value="' . $arrOption['value'] . '" style="width:180px;" />' . '<label for="productOption-' . $product_id . '-' . $attribute_id . '-' . $domId . '">' . $option_price . "</label><br />\n"; break; case Attribute::TYPE_NUMBER_FLOAT_OPTIONAL: case Attribute::TYPE_NUMBER_FLOAT_MANDATORY: // $option_price = ' '; $selectValues .= '<input type="text" name="productOption[' . $attribute_id . ']" id="productOption-' . $product_id . '-' . $attribute_id . '-' . $domId . '" value="' . $arrOption['value'] . '" style="width:180px;" />' . '<label for="productOption-' . $product_id . '-' . $attribute_id . '-' . $domId . '">' . $option_price . "</label><br />\n"; break; case Attribute::TYPE_UPLOAD_OPTIONAL: case Attribute::TYPE_UPLOAD_MANDATORY: // $option_price = ' '; $selectValues .= '<input type="file" name="productOption[' . $attribute_id . ']" id="productOption-' . $product_id . '-' . $attribute_id . '-' . $domId . '" style="width:180px;" />' . '<label for="productOption-' . $product_id . '-' . $attribute_id . '-' . $domId . '">' . $option_price . "</label><br />\n"; break; case Attribute::TYPE_TEXTAREA_OPTIONAL: case Attribute::TYPE_TEXTAREA_MANDATORY: // $valuePrice = ' '; $selectValues .= '<textarea name="productOption[' . $attribute_id . ']" id="productOption-' . $product_id . '-' . $attribute_id . '-' . $domId . '" style="width:300px;">' . contrexx_input2xhtml($arrOption['value']) . '</textarea>' . '<label for="productOption-' . $product_id . '-' . $attribute_id . '-' . $domId . '">' . $option_price . "</label><br />\n"; break; } ++$i; ++$domId; } // create foot of option menu/checkbox/radiobutton switch ($objAttribute->getType()) { case Attribute::TYPE_MENU_OPTIONAL: $selectValues .= "</select><br />"; break; case Attribute::TYPE_RADIOBUTTON: $selectValues .= "<br />"; break; case Attribute::TYPE_CHECKBOX: $selectValues .= ""; break; case Attribute::TYPE_MENU_MANDATORY: $selectValues .= "</select><br />"; break; // Set enctype in form if one of these is present // Set enctype in form if one of these is present case Attribute::TYPE_UPLOAD_OPTIONAL: case Attribute::TYPE_UPLOAD_MANDATORY: // Avoid code analyzer warning $flagUpload = true || $flagUpload; break; /* Nothing to to case Attribute::TYPE_TEXT_OPTIONAL: case Attribute::TYPE_TEXT_MANDATORY: case Attribute::TYPE_TEXTAREA_OPTIONAL: case Attribute::TYPE_TEXTAREA_MANDATORY: case Attribute::TYPE_EMAIL_OPTIONAL: case Attribute::TYPE_EMAIL_MANDATORY: case Attribute::TYPE_URL_OPTIONAL: case Attribute::TYPE_URL_MANDATORY: case Attribute::TYPE_DATE_OPTIONAL: case Attribute::TYPE_DATE_MANDATORY: case Attribute::TYPE_NUMBER_INT_OPTIONAL: case Attribute::TYPE_NUMBER_INT_MANDATORY: case Attribute::TYPE_NUMBER_FLOAT_OPTIONAL: case Attribute::TYPE_NUMBER_FLOAT_MANDATORY: */ } $selectValues .= "\n"; self::$objTemplate->setVariable(array('SHOP_PRODCUT_OPTION' => $selectValues, 'SHOP_PRODUCT_OPTION' => $selectValues, 'SHOP_PRODUCT_OPTIONS_NAME' => $objAttribute->getName(), 'SHOP_PRODUCT_OPTIONS_TITLE' => '<a href="javascript:{}" onclick="toggleOptions(' . $product_id . ', this)" title="' . $_ARRAYLANG['TXT_OPTIONS'] . '">' . $_ARRAYLANG['TXT_OPTIONS'] . "</a>\n")); if ($mandatory && self::$objTemplate->blockExists('product_attribute_mandatory')) { self::$objTemplate->touchBlock('product_attribute_mandatory'); } self::$objTemplate->parse('shopProductOptionsValuesRow'); } self::$objTemplate->parse('shopProductOptionsRow'); } } return "return checkProductOption('shopProductForm{$formName}', " . "{$product_id}, '" . substr($checkOptionIds, 0, strlen($checkOptionIds) - 1) . "');"; }
/** * Partial view of the Attributes for a Product being edited * * Only called by {@see view_product_edit()}. * Mind that the $product_id may be empty (usually zero) for new Products. * @access private * @param integer $product_id The ID of the Product being edited * @return void */ private static function viewpart_product_attributes($product_id = null) { $i = 0; $count = 0; // If a Product is selected, check those Product Attribute values // associated with it $arrRelation = Attributes::getRelationArray($product_id); foreach (Attributes::getArray($count) as $attribute_id => $objAttribute) { // All options available for this Product Attribute $arrOptions = Attributes::getOptionArrayByAttributeId($attribute_id); $nameSelected = false; $order = 0; foreach ($arrOptions as $option_id => $arrOption) { $valueSelected = false; if (in_array($option_id, array_keys($arrRelation))) { $valueSelected = true; $nameSelected = true; $order = $arrRelation[$option_id]; } self::$objTemplate->setVariable(array('SHOP_PRODUCTS_ATTRIBUTE_ID' => $attribute_id, 'SHOP_PRODUCTS_ATTRIBUTE_VALUE_ID' => $option_id, 'SHOP_PRODUCTS_ATTRIBUTE_VALUE_TEXT' => $arrOption['value'] . ' (' . $arrOption['price'] . ' ' . Currency::getDefaultCurrencySymbol() . ')', 'SHOP_PRODUCTS_ATTRIBUTE_VALUE_SELECTED' => $valueSelected ? \Html::ATTRIBUTE_CHECKED : '')); self::$objTemplate->parse('optionList'); } self::$objTemplate->setVariable(array('SHOP_PRODUCTS_ATTRIBUTE_ROW_CLASS' => 'row' . (++$i % 2 + 1), 'SHOP_PRODUCTS_ATTRIBUTE_ID' => $attribute_id, 'SHOP_PRODUCTS_ATTRIBUTE_NAME' => $objAttribute->getName(), 'SHOP_PRODUCTS_ATTRIBUTE_SELECTED' => $nameSelected ? \Html::ATTRIBUTE_CHECKED : '', 'SHOP_PRODUCTS_ATTRIBUTE_DISPLAY_TYPE' => $nameSelected ? 'block' : 'none', 'SHOP_PRODUCTS_ATTRIBUTE_SORTID' => $order)); self::$objTemplate->parse('attributeList'); } }