/** * Fetches product from database. * * @param $post \WP_Post Post to fetch product for. * * @return \Jigoshop\Entity\Product */ public function fetch($post) { $coupon = new Entity(); $state = array(); if ($post) { $state = array_map(function ($item) { return $item[0]; }, $this->wp->getPostMeta($post->ID)); $coupon->setId($post->ID); $coupon->setTitle($post->post_title); $coupon->setCode($post->post_name); if (isset($state['products'])) { $state['products'] = unserialize($state['products']); } if (isset($state['excluded_products'])) { $state['excluded_products'] = unserialize($state['excluded_products']); } if (isset($state['categories'])) { $state['categories'] = unserialize($state['categories']); } if (isset($state['excluded_categories'])) { $state['excluded_categories'] = unserialize($state['excluded_categories']); } if (isset($state['payment_methods'])) { $state['payment_methods'] = unserialize($state['payment_methods']); } $coupon->restoreState($state); } return $this->wp->applyFilters('jigoshop\\find\\coupon', $coupon, $state); }
/** * @return bool Whether current method is enabled and able to work. */ public function isEnabled() { $cart = $this->cartService->getCurrent(); $post = $this->wp->getGlobalPost(); if ($post === null || $post->post_type != Types::ORDER) { $customer = $cart->getCustomer(); } else { // TODO: Get rid of this hack for customer fetching $customer = unserialize($this->wp->getPostMeta($post->ID, 'customer', true)); } return $this->options['enabled'] && ($this->options['available_for'] === 'all' || in_array($customer->getShippingAddress()->getCountry(), $this->options['countries'])); }
/** * @return bool Whether current method is enabled and able to work. */ public function isEnabled() { $cart = $this->cartService->getCurrent(); $post = $this->wp->getGlobalPost(); if ($post === null || $post->post_type != Types::ORDER) { $customer = $cart->getCustomer(); } else { // TODO: Get rid of this hack for customer fetching $customer = maybe_unserialize($this->wp->getPostMeta($post->ID, 'customer', true)); } if (empty($customer)) { return $this->options['enabled']; } return $this->options['enabled'] && $customer->getShippingAddress()->getCountry() == $this->baseCountry; }
/** * Fetches product from database. * * @param $post \WP_Post Post to fetch product for. * * @return \Jigoshop\Entity\Product */ public function fetch($post) { $email = new Entity(); $state = array(); if ($post) { $state = array_map(function ($item) { return $item[0]; }, $this->wp->getPostMeta($post->ID)); $email->setId($post->ID); $email->setTitle($post->post_title); $email->setText($post->post_content); $state['actions'] = unserialize($state['actions']); $email->restoreState($state); } return $this->wp->applyFilters('jigoshop\\find\\email', $email, $state); }
/** * @return bool Whether current method is enabled and able to work. */ public function isEnabled() { $cart = $this->cartService->getCurrent(); $post = $this->wp->getGlobalPost(); if ($post === null || $post->post_type != Types::ORDER) { $customer = $cart->getCustomer(); } else { // TODO: Get rid of this hack for customer fetching $customer = unserialize($this->wp->getPostMeta($post->ID, 'customer', true)); } $freeShippingCoupon = array_reduce($cart->getCoupons(), function ($value, $coupon) { /** @var $coupon Coupon */ return $value || $coupon->isFreeShipping(); }, false); return $this->options['enabled'] && ($freeShippingCoupon || $cart->getProductSubtotal() >= $this->options['minimum'] && ($this->options['available_for'] === 'all' || in_array($customer->getShippingAddress()->getCountry(), $this->options['countries']))); }
/** * 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); }
/** * Fetches order from database. * * @param $post \WP_Post Post to fetch order for. * * @return \Jigoshop\Entity\Order */ public function fetch($post) { $order = new Entity($this->options->get('tax.classes')); /** @var Entity $order */ $order = $this->wp->applyFilters('jigoshop\\factory\\order\\fetch\\before', $order); $state = array(); if ($post) { $state = array_map(function ($item) { return $item[0]; }, $this->wp->getPostMeta($post->ID)); $order->setId($post->ID); if (isset($state['customer'])) { // Customer must be unserialized twice "thanks" to WordPress second serialization. /** @var CustomerEntity */ $state['customer'] = unserialize(unserialize($state['customer'])); if ($state['customer'] instanceof CustomerEntity && !$state['customer'] instanceof CustomerEntity\Guest && $state['customer_id'] > 0) { $customer = $this->customerService->find($state['customer_id']); $customer->setBillingAddress($state['customer']->getBillingAddress()); $customer->setShippingAddress($state['customer']->getShippingAddress()); $state['customer'] = $customer; } } $state['customer_note'] = $post->post_excerpt; $state['status'] = $post->post_status; $state['created_at'] = strtotime($post->post_date); $state['items'] = $this->getItems($post->ID); if (isset($state['shipping'])) { $shipping = unserialize($state['shipping']); if (!empty($shipping['method'])) { $state['shipping'] = array('method' => $this->shippingService->findForState($shipping['method']), 'price' => $shipping['price'], 'rate' => isset($shipping['rate']) ? $shipping['rate'] : null); } } if (isset($state['payment'])) { $state['payment'] = $this->paymentService->get($state['payment']); } $order = $this->fill($order, $state); } return $this->wp->applyFilters('jigoshop\\find\\order', $order, $state); }
/** * Sends specified email to specified address. * * @param $hook string Email to send. * @param array $args Arguments to the email. * @param $to string Receiver address. */ public function send($hook, array $args = array(), $to) { if ($this->suppress) { $this->suppress = false; return; } $templates = $this->getTemplates(); if (!isset($templates[$hook]) || empty($templates[$hook])) { return; } foreach ($templates[$hook] as $postId) { $post = $this->wp->getPost($postId); if (!empty($post) && $post->post_status == 'publish') { $subject = $this->wp->getPostMeta($postId, 'subject', true); $post->post_title = empty($subject) ? $post->post_title : $subject; $post = $this->filterPost($post, $args); $headers = array('MIME-Version: 1.0', 'Content-Type: text/html; charset=UTF-8', 'From: "' . $this->options->get('general.emails.from') . '" <' . $this->options->get('general.email') . '>'); $footer = $this->options->get('general.emails.footer'); $post->post_content = $footer ? $post->post_content . '<br/><br/>' . $footer : $post->post_content; $this->wp->wpMail($to, $post->post_title, nl2br($post->post_content), $headers); } } }
/** * Migrates data from old format to new one. * @param array $orders * @return bool migration product status: success or not */ public function migrate($orders) { $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 order status taxonomy to fetch old statuses $this->wp->registerTaxonomy('shop_order_status', array('shop_order'), array('hierarchical' => true, 'update_count_callback' => '_update_post_term_count', 'labels' => array('name' => __('Order statuses', 'jigoshop'), 'singular_name' => __('Order status', 'jigoshop'), 'search_items' => __('Search Order statuses', 'jigoshop'), 'all_items' => __('All Order statuses', 'jigoshop'), 'parent_item' => __('Parent Order status', 'jigoshop'), 'parent_item_colon' => __('Parent Order status:', 'jigoshop'), 'edit_item' => __('Edit Order status', 'jigoshop'), 'update_item' => __('Update Order status', 'jigoshop'), 'add_new_item' => __('Add New Order status', 'jigoshop'), 'new_item_name' => __('New Order status Name', 'jigoshop')), 'public' => false, 'show_ui' => false, 'show_in_nav_menus' => false, 'query_var' => true, 'rewrite' => false)); for ($i = 0, $endI = count($orders); $i < $endI;) { $order = $orders[$i]; // Update central order data $status = $this->wp->getTheTerms($order->ID, 'shop_order_status'); $this->checkSql(); if (!empty($status)) { $status = $this->_transformStatus($status[0]->slug); } else { $status = Status::PENDING; } $query = $wpdb->prepare("UPDATE {$wpdb->posts} SET post_status = %s WHERE ID = %d", $status, $order->ID); $wpdb->query($query); $this->checkSql(); $wpdb->query($wpdb->prepare("INSERT INTO {$wpdb->postmeta} (post_id, meta_key, meta_value) VALUES (%d, %s, %s)", $order->ID, 'number', $order->ID)); $this->checkSql(); $wpdb->query($wpdb->prepare("INSERT INTO {$wpdb->postmeta} (post_id, meta_key, meta_value) VALUES (%d, %s, %s)", $order->ID, 'updated_at', time())); $this->checkSql(); // Update columns do { switch ($orders[$i]->meta_key) { case '_js_completed_date': $wpdb->query($wpdb->prepare("UPDATE {$wpdb->postmeta} SET meta_key = %s, meta_value = %d WHERE meta_id = %d", 'completed_at', strtotime($orders[$i]->meta_value), $orders[$i]->meta_id)); $this->checkSql(); break; case 'order_key': $wpdb->query($wpdb->prepare("UPDATE {$wpdb->postmeta} SET meta_key = %s WHERE meta_id = %d", 'key', $orders[$i]->meta_id)); $this->checkSql(); break; case 'order_data': $data = unserialize($orders[$i]->meta_value); $data = $this->_fetchOrderData($data); // Migrate customer if ($this->customer == null) { $customer = $this->wp->getPostMeta($order->ID, 'customer', true); $this->customer = $customer; } $this->customer = $this->_migrateCustomer($this->customer, $data); $wpdb->query($wpdb->prepare("INSERT INTO {$wpdb->postmeta} (post_id, meta_key, meta_value) VALUES (%d, %s, %s)", $order->ID, 'customer', serialize(serialize($this->customer)))); $this->checkSql(); // Migrate coupons $wpdb->query($wpdb->prepare("INSERT INTO {$wpdb->postmeta} (post_id, meta_key, meta_value) VALUES (%d, %s, %s)", $order->ID, 'coupons', serialize($data['order_discount_coupons']))); // TODO: HERE $this->checkSql(); // Migrate shipping method try { $method = $this->shippingService->get($data['shipping_method']); $wpdb->query($wpdb->prepare("INSERT INTO {$wpdb->postmeta} (post_id, meta_key, meta_value) VALUES (%d, %s, %s)", $order->ID, 'shipping', serialize(array('method' => $method->getState(), 'price' => $data['order_shipping'], 'rate' => '')))); $this->checkSql(); } catch (Exception $e) { $this->messages->addWarning(sprintf(__('Shipping method "%s" not found. Order with ID "%d" has no shipping method now.'), $data['shipping_method'], $order->ID)); } // Migrate payment method try { $method = $this->paymentService->get($data['payment_method']); $wpdb->query($wpdb->prepare("INSERT INTO {$wpdb->postmeta} (post_id, meta_key, meta_value) VALUES (%d, %s, %s)", $order->ID, 'payment', $method->getId())); $this->checkSql(); } catch (Exception $e) { $this->messages->addWarning(sprintf(__('Payment method "%s" not found. Order with ID "%d" has no payment method now.'), $data['payment_method'], $order->ID)); } // Migrate order totals $wpdb->query($wpdb->prepare("INSERT INTO {$wpdb->postmeta} (post_id, meta_key, meta_value) VALUES (%d, %s, %s)", $order->ID, 'subtotal', $data['order_subtotal'])); $this->checkSql(); $wpdb->query($wpdb->prepare("INSERT INTO {$wpdb->postmeta} (post_id, meta_key, meta_value) VALUES (%d, %s, %s)", $order->ID, 'discount', $data['order_discount'])); $this->checkSql(); $wpdb->query($wpdb->prepare("INSERT INTO {$wpdb->postmeta} (post_id, meta_key, meta_value) VALUES (%d, %s, %s)", $order->ID, 'total', $data['order_total'])); $this->checkSql(); // TODO: Add new meta for shipping total price /*$wpdb->query($wpdb->prepare("INSERT INTO {$wpdb->postmeta} (post_id, meta_key, meta_value) VALUES (%d, %s, %s)", $order->ID, 'shipping', $data['order_shipping'] )); $this->checkSql();*/ break; case 'customer_user': if ($this->customer == null) { $customer = $this->wp->getPostMeta($order->ID, 'customer', true); if ($customer !== false) { /** @var Customer $customer */ $customer = maybe_unserialize(maybe_unserialize($customer)); if (!$customer) { $customer = new Customer(); } } else { $customer = new Customer(); } $this->customer = $customer; } /** @var \WP_User $user */ if (($user = $this->wp->getUserBy('id', $orders[$i]->meta_value)) !== false) { $this->checkSql(); $this->customer->setId($user->ID); $this->customer->setLogin($user->get('login')); $this->customer->setEmail($user->get('user_email')); $this->customer->setName($user->get('display_name')); $wpdb->query($wpdb->prepare("UPDATE {$wpdb->postmeta} SET meta_value = %d WHERE post_id = %d AND meta_key = %s", serialize(serialize($this->customer)), $orders[$i]->meta_id, 'customer')); $this->checkSql(); $userId = $orders[$i]->meta_value; } else { $userId = 0; $guest = new Customer\Guest(); $guest->setBillingAddress($this->customer->getBillingAddress()); $guest->setShippingAddress($this->customer->getShippingAddress()); $this->customer = $guest; } $wpdb->query($wpdb->prepare("INSERT INTO {$wpdb->postmeta} (post_id, meta_key, meta_value) VALUES (%d, %s, %d)", $order->ID, 'customer_id', $userId)); break; case 'order_items': $data = unserialize($orders[$i]->meta_value); $globalTaxRate = 0.0; foreach ($data as $itemData) { /** @var Product $product */ $itemData = $this->_fetchItemData($itemData); $product = null; $productGetId = null; if ($wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM {$wpdb->posts} WHERE ID = %d", $itemData['id'])) > 0) { $product = $this->productService->find($itemData['id']); $productGetId = $product->getId(); } $tax = 0.0; $taxRate = 0; if ($itemData['qty'] == 0) { $itemData['qty'] = 1; } $price = $itemData['cost'] / $itemData['qty']; if (!empty($itemData['taxrate']) && $itemData['taxrate'] > 0) { $tax = $price * $itemData['taxrate'] / 100; $taxRate = $itemData['taxrate']; } else { if (isset($itemData['cost_inc_tax']) && $itemData['cost'] < $itemData['cost_inc_tax']) { $tax = ($itemData['cost_inc_tax'] - $itemData['cost']) / $itemData['qty']; $taxRate = $tax / $itemData['cost']; } } $globalTaxRate += $taxRate; $productGetType = false; if ($productGetId == null) { if (isset($itemData['variation_id']) && !empty($itemData['variation_id'])) { $productGetType = Product\Variable::TYPE; } else { $productGetType = Product\Simple::TYPE; } } else { $productGetType = $product->getType(); } $insertOrderData = array('order_id' => $order->ID, 'product_type' => $productGetType, 'title' => $itemData['name'], 'price' => $price, 'tax' => $tax, 'quantity' => $itemData['qty'], 'cost' => $itemData['cost']); if ($productGetId != null) { $insertOrderData['product_id'] = $productGetId; } $wpdb->insert($wpdb->prefix . 'jigoshop_order_item', $insertOrderData); $this->checkSql(); $itemId = $wpdb->insert_id; if (isset($itemData['variation_id']) && !empty($itemData['variation_id']) && ($productGetId == null || $product instanceof Product\Variable)) { $wpdb->query($wpdb->prepare("INSERT INTO {$wpdb->prefix}jigoshop_order_item_meta (item_id, meta_key, meta_value) VALUES (%d, %s, %s)", $itemId, 'variation_id', $itemData['variation_id'])); $this->checkSql(); if ($productGetId !== null) { /** @var Product\Variable\Variation $variationProduct */ /** @var Product\Variable $product */ $variationProduct = $product->getVariation($itemData['variation_id']); if (is_array($itemData['variation']) && $variationProduct && $variationProduct instanceof Product\Variable\Variation) { foreach ($itemData['variation'] as $variation => $variationValue) { $variation = str_replace('tax_', '', $variation); $attribute = $this->getAttribute($variationProduct, $variation); if ($attribute === null) { $this->messages->addWarning(sprintf(__('Attribute "%s" not found for variation ID "%d".', 'jigoshop'), $variation, $variationProduct->getId())); continue; } $option = $this->getAttributeOption($attribute, $variationValue); if ($option === null) { $this->messages->addWarning(sprintf(__('Attribute "%s" option "%s" not found for variation ID "%d".', 'jigoshop'), $variation, $variationValue, $variationProduct->getId())); continue; } $wpdb->query($wpdb->prepare("INSERT INTO {$wpdb->prefix}jigoshop_order_item_meta (item_id, meta_key, meta_value) VALUES (%d, %s, %s)", $itemId, $attribute->getAttribute()->getId(), $option->getId())); $this->checkSql(); } } } } } $wpdb->query($wpdb->prepare("INSERT INTO {$wpdb->prefix}jigoshop_order_tax (order_id, label, tax_class, rate, is_compound) VALUES (%d, %s, %s, %d, %d)", $order->ID, __('Standard', 'jigoshop'), 'standard', $globalTaxRate / (count($data) == 0 ? 1 : count($data)), false)); $this->checkSql(); break; } $i++; } while ($i < $endI && $orders[$i]->ID == $order->ID); } // 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 orders end with error: ', 'jigoshop') . $e); return false; } }