public function action() { /** @var Order $order */ $order = $this->orderService->find((int) $this->wp->getQueryParameter('pay')); if ($order->getKey() !== $_GET['key']) { $this->messages->addError(__('Invalid security key. Unable to process order.', 'jigoshop')); $this->wp->redirectTo($this->options->getPageId(Pages::ACCOUNT)); } if (isset($_POST['action']) && $_POST['action'] == 'purchase') { try { if ($this->options->get('advanced.pages.terms') > 0 && (!isset($_POST['terms']) || $_POST['terms'] != 'on')) { throw new Exception(__('You need to accept terms & conditions!', 'jigoshop')); } if (!isset($_POST['payment_method'])) { throw new Exception(__('Please select one of available payment methods.', 'jigoshop')); } $payment = $this->paymentService->get($_POST['payment_method']); $order->setPaymentMethod($payment); if (!$payment->isEnabled()) { throw new Exception(__('Selected payment method is not available. Please select another one.', 'jigoshop')); } $this->orderService->save($order); $url = $payment->process($order); // Redirect to thank you page if (empty($url)) { $url = $this->wp->getPermalink($this->wp->applyFilters('jigoshop\\checkout\\redirect_page_id', $this->options->getPageId(Pages::THANK_YOU))); $url = $this->wp->getHelpers()->addQueryArg(array('order' => $order->getId(), 'key' => $order->getKey()), $url); } $this->wp->wpRedirect($url); exit; } catch (Exception $e) { $this->messages->addError($e->getMessage()); } } }
/** * Creates new product properly based on POST variable data. * * @param $id int Post ID to create object for. * * @return \Jigoshop\Entity\Product */ public function create($id) { $coupon = new Entity(); $coupon->setId($id); if (!empty($_POST)) { $helpers = $this->wp->getHelpers(); $coupon->setTitle($helpers->sanitizeTitle($_POST['post_title'])); $_POST['jigoshop_coupon']['individual_use'] = $_POST['jigoshop_coupon']['individual_use'] == 'on'; $_POST['jigoshop_coupon']['free_shipping'] = $_POST['jigoshop_coupon']['free_shipping'] == 'on'; $_POST['jigoshop_coupon']['products'] = array_filter(explode(',', $_POST['jigoshop_coupon']['products'])); $_POST['jigoshop_coupon']['excluded_products'] = array_filter(explode(',', $_POST['jigoshop_coupon']['excluded_products'])); $_POST['jigoshop_coupon']['categories'] = array_filter(explode(',', $_POST['jigoshop_coupon']['categories'])); $_POST['jigoshop_coupon']['excluded_categories'] = array_filter(explode(',', $_POST['jigoshop_coupon']['excluded_categories'])); if (!empty($_POST['jigoshop_coupon']['from'])) { $_POST['jigoshop_coupon']['from'] = strtotime($_POST['jigoshop_coupon']['from']); } else { $_POST['jigoshop_coupon']['from'] = false; } if (!empty($_POST['jigoshop_coupon']['to'])) { $_POST['jigoshop_coupon']['to'] = strtotime($_POST['jigoshop_coupon']['to']); } else { $_POST['jigoshop_coupon']['to'] = false; } $coupon->restoreState($_POST['jigoshop_coupon']); } return $coupon; }
/** * Creates new product properly based on POST variable data. * * @param $id int Post ID to create object for. * * @return \Jigoshop\Entity\Product */ public function create($id) { $email = new Entity(); $email->setId($id); if (!empty($_POST)) { $helpers = $this->wp->getHelpers(); $email->setTitle($helpers->sanitizeTitle($_POST['post_title'])); $email->setText($helpers->parsePostBody($_POST['content'])); $availableActions = $this->getActions(); $_POST['jigoshop_email']['actions'] = array_intersect($_POST['jigoshop_email']['actions'], array_keys($availableActions)); $email->restoreState($_POST['jigoshop_email']); } return $email; }
/** * Save the settings */ private function save() { // We need to save the options ourselves; settings api does not trigger save for the permalinks page if (isset($_POST['permalink_structure']) || isset($_POST['category_base']) && isset($_POST['product_permalink'])) { // Cat and tag bases $categorySlug = trim(strip_tags($_POST['jigoshop_product_category_slug'])); $tagSlug = trim(strip_tags($_POST['jigoshop_product_tag_slug'])); $permalinks = $this->options->get('permalinks'); $helpers = $this->wp->getHelpers(); $permalinks['category'] = $helpers->untrailingslashit($categorySlug); $permalinks['tag'] = $helpers->untrailingslashit($tagSlug); // Product base $product_permalink = trim(strip_tags($_POST['product_permalink'])); if ($product_permalink == 'custom') { // Get permalink without slashes $product_permalink = trim(strip_tags($_POST['product_permalink_structure']), '/'); // This is an invalid base structure and breaks pages if ('%' . Types::PRODUCT_CATEGORY . '%' == $product_permalink) { $product_permalink = _x('product', 'slug', 'jigoshop') . '/' . $product_permalink; } } elseif (empty($product_permalink)) { $product_permalink = false; } $permalinks['product'] = $helpers->untrailingslashit($product_permalink); // Shop base may require verbose page rules if nesting pages $shopPageId = $this->options->getPageId(FrontendPages::SHOP); $shop_permalink = urldecode($shopPageId > 0 && $this->wp->getPost($shopPageId) ? $this->wp->getPageUri($shopPageId) : _x('shop', 'default-slug', 'jigoshop')); if ($shopPageId && trim($permalinks['product'], '/') === $shop_permalink) { $permalinks['verbose'] = true; } $this->options->update('permalinks', $permalinks); $this->options->saveOptions(); $this->wp->getRewrite()->flush_rules(); } }
public function ajaxSaveAttributeOption() { $errors = array(); if (!isset($_POST['attribute_id']) || !is_numeric($_POST['attribute_id'])) { $errors[] = __('Respective attribute is not set.', 'jigoshop'); } if (!isset($_POST['label']) || empty($_POST['label'])) { $errors[] = __('Option label is not set.', 'jigoshop'); } if (!empty($errors)) { echo json_encode(array('success' => false, 'error' => join('<br/>', $errors))); exit; } $attribute = $this->productService->getAttribute((int) $_POST['attribute_id']); if (isset($_POST['id'])) { $option = $attribute->removeOption($_POST['id']); } else { $option = new Attribute\Option(); } $option->setLabel(trim(htmlspecialchars(strip_tags($_POST['label'])))); if (isset($_POST['slug']) && !empty($_POST['slug'])) { $option->setValue(trim(htmlspecialchars(strip_tags($_POST['value'])))); } else { $option->setValue($this->wp->getHelpers()->sanitizeTitle($option->getLabel())); } $attribute->addOption($option); $this->productService->saveAttribute($attribute); echo json_encode(array('success' => true, 'html' => Render::get('admin/product_attributes/option', array('id' => $attribute->getId(), 'option_id' => $option->getId(), 'option' => $option)))); exit; }
/** * Adds a note to the order. * * @param $order Order The order. * @param $note string Note text. * @param $private bool Is note private? * * @return int Note ID. */ public function addNote($order, $note, $private = true) { $comment = array('comment_post_ID' => $order->getId(), 'comment_author' => __('Jigoshop', 'jigoshop'), 'comment_author_email' => '', 'comment_author_url' => '', 'comment_content' => $note, 'comment_type' => 'order_note', 'comment_agent' => __('Jigoshop', 'jigoshop'), 'comment_parent' => 0, 'comment_date' => $this->wp->getHelpers()->currentTime('mysql'), 'comment_date_gmt' => $this->wp->getHelpers()->currentTime('mysql', true), 'comment_approved' => true); $comment = $this->wp->applyFilters('jigoshop\\service\\order\\add_note', $comment, $order, $note, $private); $comment_id = $this->wp->wpInsertComment($comment); $this->wp->addCommentMeta($comment_id, 'private', $private); return $comment_id; }
/** * @param $result string Current email message. * @param $item Order\Item Item to display. * @param $order Order Order being displayed. * * @return string */ public function emailLink($result, $item, $order) { $product = $item->getProduct(); if ($product instanceof Product\Downloadable && in_array($order->getStatus(), array(Order\Status::COMPLETED, Order\Status::PROCESSING))) { $url = $this->wp->getHelpers()->addQueryArg(array('file' => $order->getKey() . '.' . $order->getId() . '.' . $item->getKey(), Api::getUrl(DownloadFile::NAME))); $result .= PHP_EOL . __('Your download link for this file is:', 'jigoshop'); $result .= PHP_EOL . ' - ' . $url; } return $result; }
public function displayTitle($actions) { $post = $this->wp->getGlobalPost(); // Remove "Quick edit" as we won't use it. unset($actions['inline hide-if-no-js']); if ($post->post_type == Types::ORDER) { $fullFormat = _x('Y/m/d g:i:s A', 'time', 'jigoshop'); $format = _x('Y/m/d', 'time', 'jigoshop'); $fullDate = $this->wp->getHelpers()->mysql2date($fullFormat, $post->post_date); $date = $this->wp->getHelpers()->mysql2date($format, $post->post_date); echo '<time title="' . $fullDate . '">' . $this->wp->applyFilters('post_date_column_time', $date, $post) . '</time>'; } return $actions; }
/** * Check PayPal IPN validity */ private function isResponseValid() { $values = $this->wp->getHelpers()->stripSlashesDeep($_POST); $values['cmd'] = '_notify-validate'; // Send back post vars to PayPal $params = array('body' => $values, 'sslverify' => false, 'timeout' => 30, 'user-agent' => 'Jigoshop/' . Core::VERSION); // Get url if ($this->settings['test_mode']) { $url = self::TEST_URL; } else { $url = self::LIVE_URL; } // Post back to get a response $response = $this->wp->wpSafeRemotePost($url, $params); // check to see if the request was valid if (!$this->wp->isWpError($response) && $response['response']['code'] >= 200 && $response['response']['code'] < 300 && strcmp($response['body'], "VERIFIED") == 0) { return true; } Registry::getInstance(JIGOSHOP_LOGGER)->addWarning('Received invalid response from PayPal!', array('response' => $response)); return false; }
/** * Fetches product from database. * * @param $post \WP_Post Post to fetch product for. * * @return \Jigoshop\Entity\Product */ public function fetch($post) { $type = $post ? $this->wp->getPostMeta($post->ID, 'type', true) : ''; if (empty($type)) { $type = Simple::TYPE; } $product = $this->get($type); $state = array(); if ($post) { $state = array_map(function ($item) { return $item[0]; }, $this->wp->getPostMeta($post->ID)); $state['attributes'] = $this->getAttributes($post->ID); $state['attachments'] = $this->getAttachments($post->ID); $state['id'] = $post->ID; $state['name'] = $post->post_title; $state['description'] = $this->wp->getHelpers()->parsePostBody($post->post_content); $state['categories'] = $this->getTerms($post->ID, Types::PRODUCT_CATEGORY); $state['tags'] = $this->getTerms($post->ID, Types::PRODUCT_TAG); if (isset($state['tax_classes'])) { $state['tax_classes'] = unserialize($state['tax_classes']); } if (isset($state['attribute_order']) && $state['attribute_order']) { $state['attribute_order'] = maybe_unserialize($state['attribute_order']); $attributes = array(); foreach ($state['attribute_order'] as $attributeId) { $attributes[$attributeId] = $state['attributes'][$attributeId]; } foreach ($state['attributes'] as $attributeId => $attribute) { if (!isset($attributes[$attributeId])) { $attributes[$attributeId] = $attribute; } } $state['attributes'] = $attributes; } $product->restoreState($state); } return $this->wp->applyFilters('jigoshop\\find\\product', $product, $state); }
public function action() { if (isset($_REQUEST['action'])) { switch ($_REQUEST['action']) { case 'cancel_order': if ($this->wp->getHelpers()->verifyNonce($_REQUEST['nonce'], 'cancel_order')) { /** @var Order $order */ $order = $this->orderService->find((int) $_REQUEST['id']); if ($order->getKey() != $_REQUEST['key']) { $this->messages->addError(__('Invalid order key.', 'jigoshop')); return; } if ($order->getStatus() != Status::PENDING) { $this->messages->addError(__('Unable to cancel order.', 'jigoshop')); return; } $order->setStatus(Status::CANCELLED); $cart = $this->cartService->createFromOrder($this->cartService->getCartIdForCurrentUser(), $order); $this->orderService->save($order); $this->cartService->save($cart); $this->messages->addNotice(__('The order has been cancelled', 'jigoshop')); } break; case 'update-shipping': $customer = $this->customerService->getCurrent(); $this->updateCustomer($customer); break; case 'checkout': try { $cart = $this->cartService->getCurrent(); // Update quantities $this->updateQuantities($cart); // Update customer (if needed) if ($this->options->get('shipping.calculator')) { $customer = $this->customerService->getCurrent(); $this->updateCustomer($customer); } if (isset($_POST['jigoshop_order']['shipping_method'])) { // Select shipping method $method = $this->shippingService->get($_POST['jigoshop_order']['shipping_method']); $cart->setShippingMethod($method); } if ($cart->getShippingMethod() && !$cart->getShippingMethod()->isEnabled()) { $cart->removeShippingMethod(); $this->messages->addWarning(__('Previous shipping method is unavailable. Please select different one.', 'jigoshop')); } if ($this->options->get('shopping.validate_zip')) { $address = $cart->getCustomer()->getShippingAddress(); if ($address->getPostcode() && !Validation::isPostcode($address->getPostcode(), $address->getCountry())) { throw new Exception(__('Postcode is not valid!', 'jigoshop')); } } do_action('jigoshop\\cart\\before_checkout', $cart); $this->cartService->save($cart); $this->messages->preserveMessages(); $this->wp->redirectTo($this->options->getPageId(Pages::CHECKOUT)); } catch (Exception $e) { $this->messages->addError(sprintf(__('Error occurred while updating cart: %s', 'jigoshop'), $e->getMessage())); } break; case 'update-cart': if (isset($_POST['cart']) && is_array($_POST['cart'])) { try { $cart = $this->cartService->getCurrent(); $this->updateQuantities($cart); $this->cartService->save($cart); $this->messages->addNotice(__('Successfully updated the cart.', 'jigoshop')); } catch (Exception $e) { $this->messages->addError(sprintf(__('Error occurred while updating cart: %s', 'jigoshop'), $e->getMessage())); } } } } if (isset($_GET['action']) && isset($_GET['item']) && $_GET['action'] === 'remove-item' && is_numeric($_GET['item'])) { $cart = $this->cartService->getCurrent(); $cart->removeItem((int) $_GET['item']); $this->cartService->save($cart); $this->messages->addNotice(__('Successfully removed item from cart.', 'jigoshop'), false); } }
/** * Executes actions associated with selected page. */ public function action() { $cart = $this->cartService->getCurrent(); if ($cart->isEmpty()) { $this->messages->addWarning(__('Your cart is empty, please add products before proceeding.', 'jigoshop')); $this->wp->redirectTo($this->options->getPageId(Pages::SHOP)); } if (!$this->isAllowedToEnterCheckout()) { $this->messages->addError(__('You need to log in before processing to checkout.', 'jigoshop')); $this->wp->redirectTo($this->options->getPageId(Pages::CART)); } if (isset($_POST['action']) && $_POST['action'] == 'purchase') { try { $allowRegistration = $this->options->get('shopping.allow_registration'); if ($allowRegistration && !$this->wp->isUserLoggedIn()) { $this->createUserAccount(); } if (!$this->isAllowedToCheckout($cart)) { if ($allowRegistration) { throw new Exception(__('You need either to log in or create account to purchase.', 'jigoshop')); } throw new Exception(__('You need to log in before purchasing.', 'jigoshop')); } if ($this->options->get('advanced.pages.terms') > 0 && (!isset($_POST['terms']) || $_POST['terms'] != 'on')) { throw new Exception(__('You need to accept terms & conditions!', 'jigoshop')); } $this->cartService->validate($cart); $this->customerService->save($cart->getCustomer()); if (!Country::isAllowed($cart->getCustomer()->getBillingAddress()->getCountry())) { $locations = array_map(function ($location) { return Country::getName($location); }, $this->options->get('shopping.selling_locations')); throw new Exception(sprintf(__('This location is not supported, we sell only to %s.'), join(', ', $locations))); } $shipping = $cart->getShippingMethod(); if ($this->isShippingRequired($cart) && (!$shipping || !$shipping->isEnabled())) { throw new Exception(__('Shipping is required for this order. Please select shipping method.', 'jigoshop')); } $payment = $cart->getPaymentMethod(); $isPaymentRequired = $this->isPaymentRequired($cart); $this->wp->doAction('jigoshop\\checkout\\payment', $payment); if ($isPaymentRequired && (!$payment || !$payment->isEnabled())) { throw new Exception(__('Payment is required for this order. Please select payment method.', 'jigoshop')); } $order = $this->orderService->createFromCart($cart); /** @var Order $order */ $order = $this->wp->applyFilters('jigoshop\\checkout\\order', $order); $this->orderService->save($order); $this->cartService->remove($cart); $url = ''; if ($isPaymentRequired) { $url = $payment->process($order); } else { $order->setStatus(\Jigoshop\Helper\Order::getStatusAfterCompletePayment($order)); $this->orderService->save($order); } // Redirect to thank you page if (empty($url)) { $url = $this->wp->getPermalink($this->wp->applyFilters('jigoshop\\checkout\\redirect_page_id', $this->options->getPageId(Pages::THANK_YOU))); $url = $this->wp->getHelpers()->addQueryArg(array('order' => $order->getId(), 'key' => $order->getKey()), $url); } $this->wp->wpRedirect($url); exit; } catch (Exception $e) { $this->messages->addError($e->getMessage()); } } }
/** * Migrates data from old format to new one. * @param array $products * @return bool migration product status: success or not */ public function migrate($products) { $wpdb = $this->wp->getWPDB(); // Open transaction for save migration products $var_autocommit_sql = $wpdb->get_var("SELECT @@AUTOCOMMIT"); try { $this->checkSql(); $wpdb->query("SET AUTOCOMMIT=0"); $this->checkSql(); $wpdb->query("START TRANSACTION"); $this->checkSql(); // Register product type taxonomy to fetch old product types $this->wp->registerTaxonomy('product_type', array('product'), array('hierarchical' => false, 'show_ui' => false, 'query_var' => true, 'show_in_nav_menus' => false)); $this->checkSql(); if ($this->wp->getOption('jigoshop_migration_product_first', false) == false) { // Update product_cat into product_category $wpdb->query($wpdb->prepare("UPDATE {$wpdb->term_taxonomy} SET taxonomy = %s WHERE taxonomy = %s", array('product_category', 'product_cat'))); $this->checkSql(); $wpdb->query($wpdb->prepare("UPDATE {$wpdb->postmeta} SET meta_value = %s WHERE meta_key = %s AND meta_value = %s", array('product_category', '_menu_item_object', 'product_cat'))); $this->checkSql(); foreach ($wpdb->get_results("SELECT * FROM {$wpdb->prefix}jigoshop_termmeta", ARRAY_A) as $termMeta) { $wpdb->insert($wpdb->prefix . 'jigoshop_term_meta', $termMeta); } $this->wp->updateOption('jigoshop_migration_product_first', true); } $productIds = array(); $attributes = array(); $productAttributes = array(); $globalAttributes = array(); foreach ($wpdb->get_results("SELECT * FROM {$wpdb->prefix}jigoshop_attribute_taxonomies") as $attribute) { $this->checkSql(); $globalAttributes[$this->wp->getHelpers()->sanitizeTitle($attribute->attribute_name)] = $attribute; } foreach ($wpdb->get_results("SELECT id AS attribute_id, slug AS attribute_name, label AS attribute_label, type AS attribute_type FROM {$wpdb->prefix}jigoshop_attribute") as $attribute) { $this->checkSql(); $globalAttributes[$attribute->attribute_name] = $attribute; } for ($i = 0, $endI = count($products); $i < $endI;) { $product = $products[$i]; $productIds[] = $product->ID; $productAttributes[$product->ID] = array('attributes' => array(), 'variations' => array()); // Add product types $types = $this->wp->getTheTerms($product->ID, 'product_type'); $this->checkSql(); $productType = Product\Simple::TYPE; if (is_array($types)) { if (!in_array($types[0]->slug, array(Product\Simple::TYPE, Product\Virtual::TYPE, Product\Downloadable::TYPE, Product\External::TYPE, Product\Variable::TYPE))) { Migration::saveLog(sprintf(__('We detected a product <a href="%s" target="_blank">(#%d) %s </a> of type "subscription" - this type is not supported by Jigoshop without an additional plugin. We changed its type to "simple" and set it as private.', 'jigoshop'), get_permalink($product->ID), $product->ID, get_the_title($product->ID), $types[0]->slug)); $wpdb->query($wpdb->prepare("UPDATE {$wpdb->posts} SET post_status = 'private' WHERE ID = %d", $product->ID)); $types[0]->slug = 'simple'; } $productType = $types[0]->slug; $wpdb->query($wpdb->prepare("INSERT INTO {$wpdb->postmeta} VALUES (NULL, %d, %s, %s)", array($product->ID, 'type', $types[0]->slug))); $this->checkSql(); } $regularPrice = 0.0; $taxClasses = array(); // Update columns do { // Sales support if ($products[$i]->meta_key == 'sale_price' && !empty($products[$i]->meta_value)) { $wpdb->query($wpdb->prepare("INSERT INTO {$wpdb->postmeta} (post_id, meta_key, meta_value) VALUES (%d, %s, %s)", array($product->ID, 'sales_enabled', true))); $this->checkSql(); } // Product attributes support if ($products[$i]->meta_key == 'product_attributes') { $attributeData = unserialize($products[$i]->meta_value); if (is_array($attributeData)) { foreach ($attributeData as $slug => $source) { if (empty($source['value'])) { continue; } $changeLocalToGlobal = isset($source['variation']) && $source['variation'] == true && $source['is_taxonomy'] != true && $productType == Product\Variable::TYPE; $productAttributes[$product->ID]['attributes'][$slug] = array('is_visible' => $source['visible'], 'is_variable' => isset($source['variation']) && $source['variation'] == true, 'values' => $changeLocalToGlobal ? str_replace(',', '|', $source['value']) : $source['value']); if (!isset($attributes[$slug])) { $type = isset($globalAttributes[$slug]) ? $this->_getAttributeType($globalAttributes[$slug]) : Text::TYPE; if ($changeLocalToGlobal) { $type = Multiselect::TYPE; } $label = isset($globalAttributes[$slug]) ? !empty($globalAttributes[$slug]->attribute_label) ? $globalAttributes[$slug]->attribute_label : $globalAttributes[$slug]->attribute_name : $source['name']; $attribute = $this->productService->createAttribute($type); $attribute->setSlug($slug); $attribute->setLabel($label); $attribute->setLocal($source['is_taxonomy'] != true && $changeLocalToGlobal != true); if ($changeLocalToGlobal) { foreach (explode('|', $productAttributes[$product->ID]['attributes'][$slug]['values']) as $attributeOption) { $option = new Option(); $option->setLabel($attributeOption); $option->setValue(sanitize_title($attributeOption)); $attribute->addOption($option); } $productAttributes[$product->ID]['attributes'][$slug]['values'] = array_map(function ($item) { return sanitize_title($item); }, explode('|', $productAttributes[$product->ID]['attributes'][$slug]['values'])); } $attributes[$slug] = $attribute; } } } } // Product variation data if ($products[$i]->meta_key == 'variation_data') { $variations = unserialize($products[$i]->meta_value); foreach ($variations as $variation => $value) { $productAttributes[$product->ID]['variations'][str_replace('tax_', '', $variation)] = sanitize_title($value); } } $key = $this->_transformKey($products[$i]->meta_key); if ($key !== null) { $value = $this->_transform($products[$i]->meta_key, $products[$i]->meta_value); if ($key == 'regular_price') { $regularPrice = $value; } if ($key == 'tax_classes') { $taxClasses = $value; } $wpdb->query($wpdb->prepare("UPDATE {$wpdb->postmeta} SET meta_value = %s, meta_key = %s WHERE meta_id = %d", array($value, $key, $products[$i]->meta_id))); $this->checkSql(); } $i++; } while ($i < $endI && $products[$i]->ID == $product->ID); // Update regular price if it includes tax if (!empty($this->taxes)) { $taxClasses = maybe_unserialize($taxClasses); foreach ($taxClasses as $taxClass) { if (isset($this->taxes['__compound__' . $taxClass])) { $regularPrice = $regularPrice / (100 + $this->taxes['__compound__' . $taxClass]['rate']) * 100; } } foreach ($taxClasses as $taxClass) { if (isset($this->taxes[$taxClass])) { $regularPrice = $regularPrice / (100 + $this->taxes[$taxClass]['rate']) * 100; } } $wpdb->query($wpdb->prepare("UPDATE {$wpdb->postmeta} SET meta_value = %s WHERE meta_key = %s AND post_id = %d", array($regularPrice, 'regular_price', $product->ID))); $this->checkSql(); } } foreach ($globalAttributes as $slug => $attributeData) { if (isset($attributes[$slug])) { continue; } $type = $this->_getAttributeType($attributeData); $label = !empty($attributeData->attribute_label) ? $attributeData->attribute_label : $attributeData->attribute_name; $attribute = $this->productService->createAttribute($type); $attribute->setSlug($slug); $attribute->setLabel($label); $attribute->setLocal(false); $attributes[$slug] = $attribute; } foreach ($attributes as $slug => $attribute) { /** @var $attribute Product\Attribute */ $antiDuplicateAttributes = unserialize($this->wp->getOption('jigoshop_attributes_anti_duplicate', serialize(array()))); if (!isset($antiDuplicateAttributes[$attribute->getSlug()]) || $attribute->isLocal()) { if (!$attribute->isLocal()) { // Fetch options if attribute is a taxonomy $options = $wpdb->get_results("\n\t\t\t\t\t\tSELECT t.name, t.slug FROM {$wpdb->terms} t\n\t\t\t\t\t\t\tLEFT JOIN {$wpdb->term_taxonomy} tt ON tt.term_id = t.term_id\n\t\t\t\t\t\t WHERE tt.taxonomy = 'pa_{$slug}'\n\t\t\t\t \t "); $this->checkSql(); $createdOptions = array(); foreach ($options as $source) { $option = new Option(); $option->setLabel($source->name); $option->setValue($source->slug); $attribute->addOption($option); $createdOptions[] = $source->slug; } } $this->productService->saveAttribute($attribute); $this->checkSql(); if (!$attribute->isLocal()) { $antiDuplicateAttributes[$attribute->getSlug()] = $attribute->getId(); $this->wp->updateOption('jigoshop_attributes_anti_duplicate', serialize($antiDuplicateAttributes)); $this->checkSql(); } } else { //merge attributes $attribute = $this->productService->getAttribute($antiDuplicateAttributes[$attribute->getSlug()]); if ($attribute instanceof Product\Attribute) { $savedOptions = array_map(function ($item) { return $item->getValue(); }, $attribute->getOptions()); foreach ($attributes[$slug]->getOptions() as $option) { if (!in_array($option->getValue(), $savedOptions)) { $attribute->addOption($option); } } $attributes[$slug] = $attribute; $this->productService->saveAttribute($attribute); } } // Add attribute to the products if ($attribute instanceof Product\Attribute) { foreach ($productIds as $id) { if (isset($productAttributes[$id]['attributes'][$attribute->getSlug()])) { $data = $productAttributes[$id]['attributes'][$attribute->getSlug()]; $value = array(); if (is_array($data['values'])) { foreach ($attribute->getOptions() as $option) { /** @var $option Option */ if (in_array($option->getValue(), $data['values'])) { $value[] = $option->getId(); } } } if (empty($value)) { $value = $data['values']; } $wpdb->insert($wpdb->prefix . 'jigoshop_product_attribute', array('product_id' => $id, 'attribute_id' => $attribute->getId(), 'value' => is_array($value) ? join('|', $value) : $value)); $this->checkSql(); $query = array('product_id' => $id, 'attribute_id' => $attribute->getId(), 'meta_key' => 'is_visible', 'meta_value' => $data['is_visible']); $wpdb->insert($wpdb->prefix . 'jigoshop_product_attribute_meta', $query); $this->checkSql(); if ($data['is_variable']) { $query = array('product_id' => $id, 'attribute_id' => $attribute->getId(), 'meta_key' => 'is_variable', 'meta_value' => true); $wpdb->insert($wpdb->prefix . 'jigoshop_product_attribute_meta', $query); $this->checkSql(); } } } } } foreach ($productIds as $id) { foreach ($productAttributes[$id]['variations'] as $taxonomy => $value) { if (!isset($attributes[$taxonomy])) { continue; } $attribute = $attributes[$taxonomy]; $option = $this->_findOption($attribute->getOptions(), $value); $query = array('variation_id' => $id, 'attribute_id' => $attribute->getId(), 'value' => $option); $wpdb->insert($wpdb->prefix . 'jigoshop_product_variation_attribute', $query); $this->checkSql(); } } // Add found tax classes $currentTaxClasses = $this->options->get('tax.classes'); $currentTaxClassesKeys = array_map(function ($item) { return $item['class']; }, $currentTaxClasses); $this->taxClasses = array_filter(array_unique($this->taxClasses), function ($item) use($currentTaxClassesKeys) { return !in_array($item, $currentTaxClassesKeys); }); foreach ($this->taxClasses as $class) { $currentTaxClasses[] = array('label' => ucfirst($class), 'class' => $class); } $this->options->update('tax.classes', $currentTaxClasses); // commit sql transation and restore value of autocommit $wpdb->query("COMMIT"); $wpdb->query("SET AUTOCOMMIT=" . $var_autocommit_sql); return true; } catch (Exception $e) { // rollback sql transation and restore value of autocommit if (WP_DEBUG) { \Monolog\Registry::getInstance(JIGOSHOP_LOGGER)->addDebug($e); } $wpdb->query("ROLLBACK"); $wpdb->query("SET AUTOCOMMIT=" . $var_autocommit_sql); Migration::saveLog(__('Migration products end with error: ', 'jigoshop') . $e); return false; } }
/** * @param $order Order The order. * * @return array Available arguments with proper values. */ private function getOrderEmailArguments($order) { $billingAddress = $order->getCustomer()->getBillingAddress(); $shippingAddress = $order->getCustomer()->getShippingAddress(); return $this->wp->applyFilters('jigoshop\\emails\\order_variables', array('blog_name' => $this->wp->getBloginfo('name'), 'order_number' => $order->getNumber(), 'order_date' => $this->wp->getHelpers()->dateI18n($this->wp->getOption('date_format')), 'shop_name' => $this->options->get('general.company_name'), 'shop_address_1' => $this->options->get('general.company_address_1'), 'shop_address_2' => $this->options->get('general.company_address_2'), 'shop_tax_number' => $this->options->get('general.company_tax_number'), 'shop_phone' => $this->options->get('general.company_phone'), 'shop_email' => $this->options->get('general.company_email'), 'customer_note' => $order->getCustomerNote(), 'order_items' => $this->formatItems($order), 'subtotal' => ProductHelper::formatPrice($order->getSubtotal()), 'shipping' => ProductHelper::formatPrice($order->getShippingPrice()), 'shipping_cost' => ProductHelper::formatPrice($order->getShippingPrice()), 'shipping_cost_raw' => $order->getShippingPrice(), 'shipping_method' => $order->getShippingMethod() ? $order->getShippingMethod()->getName() : '', 'discount' => ProductHelper::formatPrice($order->getDiscount()), 'total_tax' => ProductHelper::formatPrice($order->getTotalTax()), 'total' => ProductHelper::formatPrice($order->getTotal()), 'is_local_pickup' => $order->getShippingMethod() && $order->getShippingMethod()->getId() == LocalPickup::NAME ? true : null, 'checkout_url' => $order->getStatus() == Order\Status::PENDING ? OrderHelper::getPayLink($order) : null, 'payment_method' => $order->getPaymentMethod()->getName(), 'billing_first_name' => $billingAddress->getFirstName(), 'billing_last_name' => $billingAddress->getLastName(), 'billing_company' => $billingAddress instanceof CompanyAddress ? $billingAddress->getCompany() : '', 'billing_address_1' => $billingAddress->getAddress(), 'billing_address_2' => '', 'billing_postcode' => $billingAddress->getPostcode(), 'billing_city' => $billingAddress->getCity(), 'billing_country' => Country::getName($billingAddress->getCountry()), 'billing_country_raw' => $billingAddress->getCountry(), 'billing_state' => Country::hasStates($billingAddress->getCountry()) ? Country::getStateName($billingAddress->getCountry(), $billingAddress->getState()) : $billingAddress->getState(), 'billing_state_raw' => $billingAddress->getState(), 'billing_email' => $billingAddress->getEmail(), 'billing_phone' => $billingAddress->getPhone(), 'shipping_first_name' => $shippingAddress->getFirstName(), 'shipping_last_name' => $shippingAddress->getLastName(), 'shipping_company' => $shippingAddress instanceof CompanyAddress ? $shippingAddress->getCompany() : '', 'shipping_address_1' => $shippingAddress->getAddress(), 'shipping_address_2' => '', 'shipping_postcode' => $shippingAddress->getPostcode(), 'shipping_city' => $shippingAddress->getCity(), 'shipping_country' => Country::getName($shippingAddress->getCountry()), 'shipping_country_raw' => $shippingAddress->getCountry(), 'shipping_state' => Country::hasStates($shippingAddress->getCountry()) ? Country::getStateName($shippingAddress->getCountry(), $shippingAddress->getState()) : $shippingAddress->getState(), 'shipping_state_raw' => $shippingAddress->getState()), $order); }
public function fill(OrderInterface $order, array $data) { if (!empty($data['customer']) && is_numeric($data['customer'])) { $data['customer'] = $this->customerService->find($data['customer']); } if (isset($data['customer'])) { if (!empty($data['customer'])) { $data['customer'] = $this->wp->getHelpers()->maybeUnserialize($data['customer']); } else { $data['customer'] = new CustomerEntity\Guest(); } if (isset($data['billing_address'])) { $data['billing_address'] = array_merge(array_flip(array_keys(ProductHelper::getBasicBillingFields())), $data['billing_address']); /** @var CustomerEntity $customer */ $customer = $data['customer']; $customer->setBillingAddress($this->createAddress($data['billing_address'])); } if (isset($data['shipping_address'])) { $data['shipping_address'] = array_merge(array_flip(array_keys(ProductHelper::getBasicShippingFields())), $data['shipping_address']); /** @var CustomerEntity $customer */ $customer = $data['customer']; $customer->setShippingAddress($this->createAddress($data['shipping_address'])); } $order->setCustomer($data['customer']); unset($data['customer']); } /** @var OrderInterface $order */ $order = $this->wp->applyFilters('jigoshop\\factory\\order\\fetch\\after_customer', $order); if (isset($data['items'])) { $order->removeItems(); } //We do not want to add coupons and from directly, without validation. $coupons = null; if (isset($data['coupons'])) { $coupons = $data['coupons']; unset($data['coupons']); } if (isset($data['discount'])) { unset($data['discount']); } $order->restoreState($data); if ($coupons) { $coupons = $this->wp->getHelpers()->maybeUnserialize($coupons); if (isset($coupons[0]) && is_array($coupons[0])) { $codes = array_map(function ($coupon) { return $coupon['code']; }, $coupons); } else { $codes = $coupons; } $coupons = $this->couponService->getByCodes($codes); foreach ($coupons as $coupon) { /** @var Coupon $coupon */ try { $order->addCoupon($coupon); } catch (Exception $e) { $this->messages->addWarning($e->getMessage(), false); } } } return $this->wp->applyFilters('jigoshop\\factory\\order\\fill', $order); }
public function processResponse() { if (isset($_GET['file'])) { try { $data = explode('.', $_GET['file']); if (count($data) != 3) { throw new Exception(__('Invalid download key. Unable to download file.', 'jigoshop')); } list($key, $id, $itemKey) = $data; $order = $this->orderService->find((int) $id); /** @var $order Order */ if ($order->getKey() !== $key) { throw new Exception(__('Invalid security key. Unable to download file.', 'jigoshop')); } if (!in_array($order->getStatus(), array(Order\Status::COMPLETED, Order\Status::PROCESSING))) { throw new Exception(__('Invalid order.', 'jigoshop')); } $item = $order->getItem($itemKey); if ($item === null) { throw new Exception(__('Product not found.', 'jigoshop')); } if ($item->getType() !== Downloadable::TYPE) { throw new Exception(__('Invalid file to download.', 'jigoshop')); } $downloads = $item->getMeta('downloads')->getValue(); if (!empty($downloads) && $downloads == 0) { throw new Exception(__('Sorry, you have reached your download limit for this file.', 'jigoshop')); } if ($this->options->get('shopping.login_for_downloads')) { if (!$this->wp->isUserLoggedIn()) { throw new Exception(__('You have to log in before you can download a file.', 'jigoshop')); } else { if ($order->getCustomer()->getId() != $this->wp->getCurrentUserId()) { throw new Exception(__('This is not your download link.', 'jigoshop')); } } } $file = $item->getMeta('file')->getValue(); if (!$file) { throw new Exception(__('File not found.', 'jigoshop')); } if (!empty($downloads)) { $item->getMeta('downloads')->setValue($downloads - 1); $this->orderService->saveItemMeta($item, $item->getMeta('downloads')); } if (!$this->wp->isMultisite()) { $site_url = $this->wp->siteUrl(); $site_url = str_replace('https:', 'http:', $site_url); $file = str_replace($this->wp->getHelpers()->trailingslashit($site_url), ABSPATH, $file); } else { $network_url = $this->wp->networkAdminUrl(); $network_url = str_replace('https:', 'http:', $network_url); $upload_dir = $this->wp->wpUploadDir(); // Try to replace network url $file = str_replace($this->wp->getHelpers()->trailingslashit($network_url), ABSPATH, $file); // Now try to replace upload URL $file = str_replace($upload_dir['baseurl'], $upload_dir['basedir'], $file); } $file = $this->wp->applyFilters('jigoshop\\downloadable\\file_path', $file, $itemKey, $order); // See if its local or remote if (strstr($file, 'http:') || strstr($file, 'https:') || strstr($file, 'ftp:')) { $isRemote = true; } else { $isRemote = false; $file = realpath($file); } // Download the file $extension = strtolower(substr(strrchr($file, '.'), 1)); switch ($extension) { case 'pdf': $type = 'application/pdf'; break; case 'exe': $type = 'application/octet-stream'; break; case 'zip': $type = 'application/zip'; break; case 'doc': $type = 'application/msword'; break; case 'xls': $type = 'application/vnd.ms-excel'; break; case 'ppt': $type = 'application/vnd.ms-powerpoint'; break; case 'gif': $type = 'image/gif'; break; case 'png': $type = 'image/png'; break; case 'jpe': case 'jpeg': case 'jpg': $type = 'image/jpg'; break; default: $type = 'application/force-download'; } $this->wp->doAction('jigoshop\\downloadable\\before_download', $file, $order); @session_write_close(); @set_time_limit(0); @ob_end_clean(); // required for IE, otherwise Content-Disposition may be ignored if (ini_get('zlib.output_compression')) { ini_set('zlib.output_compression', 'Off'); } header('Pragma: no-cache'); header('Expires: 0'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header('Robots: none'); header('Content-Type: ' . $type); header('Content-Description: File Transfer'); header('Content-Transfer-Encoding: binary'); if (strstr($_SERVER['HTTP_USER_AGENT'], 'MSIE')) { // workaround for IE filename bug with multiple periods / multiple dots in filename header('Content-Disposition: attachment; filename="' . preg_replace('/\\./', '%2e', basename($file), substr_count(basename($file), '.') - 1) . '";'); } else { header('Content-Disposition: attachment; filename="' . basename($file) . '";'); } if ($isRemote) { header('Location: ' . $file); } else { if (file_exists($file)) { header('Content-Length: ' . filesize($file)); readfile($file); } else { throw new Exception(__('File not found.', 'jigoshop')); } } } catch (Exception $e) { $this->messages->addError($e->getMessage()); $this->wp->redirectTo($this->options->getPageId(Pages::SHOP)); } exit; } }
public function ajaxSaveAttribute() { try { if (!isset($_POST['product_id']) || empty($_POST['product_id'])) { throw new Exception(__('Product was not specified.', 'jigoshop')); } if (!is_numeric($_POST['product_id'])) { throw new Exception(__('Invalid product ID.', 'jigoshop')); } if (!isset($_POST['attribute_id']) || empty($_POST['attribute_id'])) { throw new Exception(__('Attribute was not specified.', 'jigoshop')); } if (!is_numeric($_POST['attribute_id'])) { throw new Exception(__('Invalid attribute ID.', 'jigoshop')); } /** @var \Jigoshop\Entity\Product $product */ $product = $this->productService->find((int) $_POST['product_id']); if (!$product->getId()) { throw new Exception(__('Product does not exists.', 'jigoshop')); } $id = (int) $_POST['attribute_id']; if ($product->hasAttribute($id)) { $attribute = $product->removeAttribute($id); $attributeExists = true; } else { if ($id == -1) { $attribute = new Attribute\Custom(); $label = trim(strip_tags($_POST['attribute_label'])); if (empty($label)) { throw new Exception(__('Custom attribute requires label to be set.', 'jigoshop')); } $attribute->setLabel($label); $attribute->setSlug($this->wp->getHelpers()->sanitizeTitle($label)); $this->productService->saveAttribute($attribute); $attributeExists = false; } else { $attribute = $this->productService->getAttribute($id); $attributeExists = false; } } if ($attribute === null) { throw new Exception(__('Attribute does not exists.', 'jigoshop')); } if (isset($_POST['value'])) { $attribute->setValue(trim(htmlspecialchars(wp_kses_post($_POST['value'])))); } else { if ($attributeExists) { throw new Exception(sprintf(__('Attribute "%s" already exists.', 'jigoshop'), $attribute->getLabel())); } else { $attribute->setValue(''); } } if (isset($_POST['options']) && isset($_POST['options']['display'])) { $attribute->setVisible($_POST['options']['display'] === 'true'); } $this->wp->doAction('jigoshop\\admin\\product_attribute\\add', $attribute, $product); $product->addAttribute($attribute); $this->productService->save($product); echo json_encode(array('success' => true, 'html' => Render::get('admin/product/box/attributes/attribute', array('attribute' => $attribute)))); } catch (Exception $e) { echo json_encode(array('success' => false, 'error' => $e->getMessage())); } exit; }