/** * Upgrades the module to version 2.4.0. * * Adds admin tab for PS 1.5+. * Registers hook `displayBackOfficeHeader`. * * @param NostoTagging $object * @return bool */ function upgrade_module_2_4_0($object) { if (_PS_VERSION_ < '1.5') { return true; } return Nosto::helper('nosto_tagging/admin_tab')->install() && $object->registerHook('displayBackOfficeHeader'); }
/** * @inheritdoc */ public function getJson() { $array = array(); /** @var NostoProductInterface $item */ foreach ($this->getArrayCopy() as $item) { $data = array('url' => $item->getUrl(), 'product_id' => $item->getProductId(), 'name' => $item->getName(), 'image_url' => $item->getImageUrl(), 'price' => Nosto::helper('price')->format($item->getPrice()), 'price_currency_code' => strtoupper($item->getCurrencyCode()), 'availability' => $item->getAvailability(), 'categories' => $item->getCategories()); // Optional properties. if ($item->getFullDescription()) { $data['description'] = $item->getFullDescription(); } if ($item->getListPrice()) { $data['list_price'] = Nosto::helper('price')->format($item->getListPrice()); } if ($item->getBrand()) { $data['brand'] = $item->getBrand(); } foreach ($item->getTags() as $type => $tags) { if (is_array($tags) && count($tags) > 0) { $data[$type] = $tags; } } if ($item->getDatePublished()) { $data['date_published'] = Nosto::helper('date')->format($item->getDatePublished()); } if ($item->getVariationId()) { $data['variation_id'] = $item->getVariationId(); } $array[] = $data; } return json_encode($array); }
/** * Sends the product re-crawl request to nosto. * * @return bool true on success, false otherwise. * @throws NostoException if the request fails or cannot be made. */ public function send() { $request = $this->initApiRequest(); $response = $request->post($this->getCollectionAsJson()); if ($response->getCode() !== 200) { throw Nosto::createHttpException('Failed to send product re-crawl to Nosto.', $request, $response); } return true; }
/** * Sends an order confirmation to Nosto. * * @param NostoOrderInterface $order the order to confirm. * @param null $customerId the Nosto customer ID of the user who placed the order. * @throws NostoException on failure. * @return true on success. */ public function confirm(NostoOrderInterface $order, $customerId = null) { $request = $this->initApiRequest($customerId); $response = $request->post($this->getOrderAsJson($order)); if ($response->getCode() !== 200) { throw Nosto::createHttpException('Failed to send order confirmation to Nosto.', $request, $response); } return true; }
/** * Redirects the user to the module admin url if the current user is logged in as an admin in the back office. * If the url cannot be found, then show the 404 page. * * @param array $query_params */ protected function redirectToModuleAdmin(array $query_params) { $admin_url = Nosto::helper('nosto_tagging/config')->getAdminUrl(); if (!empty($admin_url)) { $admin_url = NostoHttpRequest::replaceQueryParamsInUrl($query_params, $admin_url); Tools::redirect($admin_url, ''); die; } $this->notFound(); }
/** * Encrypts and outputs the data and ends the application flow. * Only send the response if we can encrypt it, i.e. we have an shared encryption secret with nosto. * * @param NostoExportCollectionInterface $collection the data collection to output as encrypted response. */ public function encryptOutput(NostoExportCollectionInterface $collection) { /** @var NostoAccount $account */ $account = Nosto::helper('nosto_tagging/account')->find($this->module->getContext()->language->id); if ($account && $account->isConnectedToNosto()) { $cipher_text = NostoExporter::export($account, $collection); echo $cipher_text; } // It is important to stop the script execution after the export, // in order to avoid any additional data being outputted. die; }
/** * @inheritdoc */ public function getJson() { $array = array(); /** @var NostoOrderInterface $item */ foreach ($this->getArrayCopy() as $item) { $data = array('order_number' => $item->getOrderNumber(), 'order_status_code' => $item->getOrderStatus()->getCode(), 'order_status_label' => $item->getOrderStatus()->getLabel(), 'created_at' => Nosto::helper('date')->format($item->getCreatedDate()), 'buyer' => array('first_name' => $item->getBuyerInfo()->getFirstName(), 'last_name' => $item->getBuyerInfo()->getLastName(), 'email' => $item->getBuyerInfo()->getEmail()), 'payment_provider' => $item->getPaymentProvider(), 'external_order_ref' => $item->getExternalOrderRef(), 'purchased_items' => array()); foreach ($item->getPurchasedItems() as $orderItem) { $data['purchased_items'][] = array('product_id' => $orderItem->getProductId(), 'quantity' => (int) $orderItem->getQuantity(), 'name' => $orderItem->getName(), 'unit_price' => Nosto::helper('price')->format($orderItem->getUnitPrice()), 'price_currency_code' => strtoupper($orderItem->getCurrencyCode())); } $array[] = $data; } return json_encode($array); }
/** * Loads meta data from the given context and language. * * @param Context $context the context to use as data source. * @param int $id_lang the language to use as data source. */ public function loadData($context, $id_lang) { $language = new Language($id_lang); if (!Validate::isLoadedObject($language)) { return; } $id_lang = (int) $context->language->id; $id_shop = (int) $context->shop->id; $params = array('language_id' => (int) $language->id); /** @var NostoTaggingHelperUrl $url_helper */ $url_helper = Nosto::helper('nosto_tagging/url'); $this->redirect_url = $url_helper->getModuleUrl($this->module_name, $this->module_path, 'oauth2', $id_lang, $id_shop, $params); $this->language_iso_code = $language->iso_code; }
/** * Loads the cart data from supplied cart object. * * @param Cart $cart the cart object. */ public function loadData(Cart $cart) { if (!Validate::isLoadedObject($cart) || ($products = $cart->getProducts()) === array()) { return; } $currency = new Currency($cart->id_currency); if (!Validate::isLoadedObject($currency)) { return; } // Cart rules are available from prestashop 1.5 onwards. if (_PS_VERSION_ >= '1.5') { $cart_rules = (array) $cart->getCartRules(CartRule::FILTER_ACTION_GIFT); $gift_products = array(); foreach ($cart_rules as $cart_rule) { if ((int) $cart_rule['gift_product']) { foreach ($products as $key => &$product) { if (empty($product['gift']) && (int) $product['id_product'] === (int) $cart_rule['gift_product'] && (int) $product['id_product_attribute'] === (int) $cart_rule['gift_product_attribute']) { $product['cart_quantity'] = (int) $product['cart_quantity']; $product['cart_quantity']--; if (!($product['cart_quantity'] > 0)) { unset($products[$key]); } $gift_product = $product; $gift_product['cart_quantity'] = 1; $gift_product['price_wt'] = 0; $gift_product['gift'] = true; $gift_products[] = $gift_product; break; // One gift product per cart rule } } unset($product); } } $items = array_merge($products, $gift_products); } else { $items = $products; } foreach ($items as $item) { $name = $item['name']; if (isset($item['attributes_small'])) { $name .= ' (' . $item['attributes_small'] . ')'; } $this->line_items[] = array('product_id' => (int) $item['id_product'], 'quantity' => (int) $item['cart_quantity'], 'name' => (string) $name, 'unit_price' => Nosto::helper('price')->format($item['price_wt']), 'price_currency_code' => (string) $currency->iso_code); } }
/** * Reads the file system and finds any new upgrade scripts that can be applied for the module. * These scripts located in the modules `upgrade` directory, with versions above the current installed version. * * @param Module $module the module to find the upgrade files for. * @return array the list of upgrade scripts. */ protected function findUpgradeScripts($module) { $scripts = array(); $path = _PS_MODULE_DIR_ . $module->name . '/upgrade/'; $installed_version = (string) Nosto::helper('nosto_tagging/config')->getInstalledVersion(); $new_version = $module->version; if (file_exists($path) && ($files = scandir($path))) { foreach ($files as $file) { if (!in_array($file, array('.', '..', 'index.php'))) { $parts = explode('-', $file); $script_version = isset($parts[1]) ? basename($parts[1], '.php') : ''; if (count($parts) == 2 && !empty($script_version) && version_compare($script_version, self::$from_version, '>=') && version_compare($script_version, $new_version, '<=') && version_compare($script_version, $installed_version, '>')) { $scripts[] = array('file' => $path . $file, 'version' => $script_version, 'upgrade_function' => 'upgrade_module_' . str_replace('.', '_', $script_version)); } } } } usort($scripts, array('NostoTaggingUpdater', 'sortUpgradeScriptsByVersion')); return $scripts; }
/** * @inheritdoc */ public function getJson() { $array = array(); /** @var Nosto_Tagging_Model_Meta_Order $item */ foreach ($this->getArrayCopy() as $item) { /** @var NostoHelperDate $dateHelper */ $dateHelper = Nosto::helper('date'); $data = array('order_number' => $item->getOrderNumber(), 'external_order_ref' => $item->getExternalOrderRef(), 'order_statuses' => array(), 'created_at' => $dateHelper->format($item->getCreatedDate()), 'buyer' => array(), 'payment_provider' => $item->getPaymentProvider(), 'purchased_items' => array()); if ($item->getOrderStatus()) { $data['order_status_code'] = $item->getOrderStatus()->getCode(); $data['order_status_label'] = $item->getOrderStatus()->getLabel(); } /** @var NostoHelperPrice $priceHelper */ $priceHelper = Nosto::helper('price'); foreach ($item->getPurchasedItems() as $orderItem) { $data['purchased_items'][] = array('product_id' => $orderItem->getProductId(), 'quantity' => (int) $orderItem->getQuantity(), 'name' => $orderItem->getName(), 'unit_price' => $priceHelper->format($orderItem->getUnitPrice()), 'price_currency_code' => strtoupper($orderItem->getCurrencyCode())); } foreach ($item->getOrderStatuses() as $status) { if ($status->getCreatedAt()) { if (!isset($data['order_statuses'][$status->getCode()])) { $data['order_statuses'][$status->getCode()] = array(); } $data['order_statuses'][$status->getCode()][] = date('Y-m-d\\TH:i:s\\Z', strtotime($status->getCreatedAt())); } } if ($item->getBuyerInfo()) { if ($item->getBuyerInfo()->getFirstName()) { $data['buyer']['first_name'] = $item->getBuyerInfo()->getFirstName(); } if ($item->getBuyerInfo()->getLastName()) { $data['buyer']['last_name'] = $item->getBuyerInfo()->getLastName(); } if ($item->getBuyerInfo()->getEmail()) { $data['buyer']['email'] = $item->getBuyerInfo()->getEmail(); } } $array[] = $data; } return json_encode($array); }
/** * Sends the order confirmation to Nosto. * * @param NostoOrderInterface $order the placed order model. * @param NostoAccountInterface $account the Nosto account for the shop where the order was placed. * @param null $customerId the Nosto customer ID of the user who placed the order. * @throws NostoException on failure. * @return true on success. */ public static function send(NostoOrderInterface $order, NostoAccountInterface $account, $customerId = null) { if (!empty($customerId)) { $path = NostoApiRequest::PATH_ORDER_TAGGING; $replaceParams = array('{m}' => $account->getName(), '{cid}' => $customerId); } else { $path = NostoApiRequest::PATH_UNMATCHED_ORDER_TAGGING; $replaceParams = array('{m}' => $account->getName()); } $request = new NostoApiRequest(); $request->setPath($path); $request->setContentType('application/json'); $request->setReplaceParams($replaceParams); $orderData = array('order_number' => $order->getOrderNumber(), 'order_status_code' => $order->getOrderStatus()->getCode(), 'order_status_label' => $order->getOrderStatus()->getLabel(), 'buyer' => array('first_name' => $order->getBuyerInfo()->getFirstName(), 'last_name' => $order->getBuyerInfo()->getLastName(), 'email' => $order->getBuyerInfo()->getEmail()), 'created_at' => Nosto::helper('date')->format($order->getCreatedDate()), 'payment_provider' => $order->getPaymentProvider(), 'external_order_ref' => $order->getExternalOrderRef(), 'purchased_items' => array()); foreach ($order->getPurchasedItems() as $item) { $orderData['purchased_items'][] = array('product_id' => $item->getProductId(), 'quantity' => (int) $item->getQuantity(), 'name' => $item->getName(), 'unit_price' => Nosto::helper('price')->format($item->getUnitPrice()), 'price_currency_code' => strtoupper($item->getCurrencyCode())); } $response = $request->post(json_encode($orderData)); if ($response->getCode() !== 200) { Nosto::throwHttpException('Failed to send order confirmation to Nosto.', $request, $response); } return true; }
/** * Authenticates the application with the given code to receive an access token. * * @param string $code code sent by the authorization server to exchange for an access token. * @return NostoOAuthToken * @throws NostoException */ public function authenticate($code) { if (empty($code)) { throw new NostoException('Invalid authentication token'); } $request = new NostoHttpRequest(); $request->setUrl(self::$baseUrl . self::PATH_TOKEN); $request->setReplaceParams(array('{cid}' => $this->clientId, '{sec}' => $this->clientSecret, '{uri}' => $this->redirectUrl, '{cod}' => $code)); $response = $request->get(); $result = $response->getJsonResult(true); if ($response->getCode() !== 200) { Nosto::throwHttpException('Failed to authenticate with code.', $request, $response); } if (empty($result['access_token'])) { throw new NostoException('No "access_token" returned after authenticating with code'); } if (empty($result['merchant_name'])) { throw new NostoException('No "merchant_name" returned after authenticating with code'); } return NostoOAuthToken::create($result); }
/** * Finds and returns an account for given criteria. * * @param null|int $lang_id the ID of the language. * @param null|int $id_shop_group the ID of the shop context. * @param null|int $id_shop the ID of the shop. * @return NostoAccount|null the account with loaded API tokens, or null if not found. */ public function find($lang_id = null, $id_shop_group = null, $id_shop = null) { /** @var NostoTaggingHelperConfig $helper_config */ $helper_config = Nosto::helper('nosto_tagging/config'); $account_name = $helper_config->getAccountName($lang_id, $id_shop_group, $id_shop); if (!empty($account_name)) { $account = new NostoAccount($account_name); $tokens = array(); foreach (NostoApiToken::getApiTokenNames() as $token_name) { $token_value = $helper_config->getToken($token_name, $lang_id, $id_shop_group, $id_shop); if (!empty($token_value)) { $tokens[$token_name] = $token_value; } } if (!empty($tokens)) { foreach ($tokens as $name => $value) { $account->addApiToken(new NostoApiToken($name, $value)); } } return $account; } return null; }
/** * Finds purchased items for the order. * * @param Context $context the context. * @param Order $order the order object. * @return NostoTaggingOrderPurchasedItem[] the purchased items. */ protected function findPurchasedItems(Context $context, Order $order) { $purchased_items = array(); $currency = new Currency($order->id_currency); if (!Validate::isLoadedObject($currency)) { return $purchased_items; } $products = array(); $total_discounts_tax_incl = 0; $total_shipping_tax_incl = 0; $total_wrapping_tax_incl = 0; $total_gift_tax_incl = 0; // Cart rules and split orders are available from prestashop 1.5 onwards. if (_PS_VERSION_ >= '1.5') { // One order can be split into multiple orders, so we need to combine their data. $order_collection = Order::getByReference($order->reference); foreach ($order_collection as $item) { /** @var $item Order */ $products = array_merge($products, $item->getProducts()); $total_discounts_tax_incl = Tools::ps_round($total_discounts_tax_incl + $item->total_discounts_tax_incl, 2); $total_shipping_tax_incl = Tools::ps_round($total_shipping_tax_incl + $item->total_shipping_tax_incl, 2); $total_wrapping_tax_incl = Tools::ps_round($total_wrapping_tax_incl + $item->total_wrapping_tax_incl, 2); } // We need the cart rules used for the order to check for gift products and free shipping. // The cart is the same even if the order is split into many objects. $cart = new Cart($order->id_cart); if (Validate::isLoadedObject($cart)) { $cart_rules = (array) $cart->getCartRules(); } else { $cart_rules = array(); } $gift_products = array(); foreach ($cart_rules as $cart_rule) { if ((int) $cart_rule['gift_product']) { foreach ($products as $key => &$product) { if (empty($product['gift']) && (int) $product['product_id'] === (int) $cart_rule['gift_product'] && (int) $product['product_attribute_id'] === (int) $cart_rule['gift_product_attribute']) { $product['product_quantity'] = (int) $product['product_quantity']; $product['product_quantity']--; if (!($product['product_quantity'] > 0)) { unset($products[$key]); } $total_gift_tax_incl = Tools::ps_round($total_gift_tax_incl + $product['product_price_wt'], 2); $gift_product = $product; $gift_product['product_quantity'] = 1; $gift_product['product_price_wt'] = 0; $gift_product['gift'] = true; $gift_products[] = $gift_product; break; // One gift product per cart rule } } unset($product); } } $items = array_merge($products, $gift_products); } else { $products = $order->getProducts(); $total_discounts_tax_incl = $order->total_discounts; $total_shipping_tax_incl = $order->total_shipping; $total_wrapping_tax_incl = $order->total_wrapping; $items = $products; } $id_lang = (int) $context->language->id; foreach ($items as $item) { $p = new Product($item['product_id'], false, $context->language->id); if (Validate::isLoadedObject($p)) { $product_name = $p->name; $id_attribute = (int) $item['product_attribute_id']; $attribute_combinations = $this->getProductAttributeCombinationsById($p, $id_attribute, $id_lang); if (!empty($attribute_combinations)) { $attribute_combination_names = array(); foreach ($attribute_combinations as $attribute_combination) { $attribute_combination_names[] = $attribute_combination['attribute_name']; } if (!empty($attribute_combination_names)) { $product_name .= ' (' . implode(', ', $attribute_combination_names) . ')'; } } $purchased_item = new NostoTaggingOrderPurchasedItem(); $purchased_item->setProductId((int) $p->id); $purchased_item->setQuantity((int) $item['product_quantity']); $purchased_item->setName((string) $product_name); $purchased_item->setUnitPrice(Nosto::helper('price')->format($item['product_price_wt'])); $purchased_item->setCurrencyCode((string) $currency->iso_code); $purchased_items[] = $purchased_item; } } if ($this->include_special_items && !empty($purchased_items)) { // Add special items for discounts, shipping and gift wrapping. if ($total_discounts_tax_incl > 0) { // Subtract possible gift product price from total as gifts are tagged with price zero (0). $total_discounts_tax_incl = Tools::ps_round($total_discounts_tax_incl - $total_gift_tax_incl, 2); if ($total_discounts_tax_incl > 0) { $purchased_item = new NostoTaggingOrderPurchasedItem(); $purchased_item->setProductId(-1); $purchased_item->setQuantity(1); $purchased_item->setName('Discount'); // Note the negative value. $purchased_item->setUnitPrice(Nosto::helper('price')->format(-$total_discounts_tax_incl)); $purchased_item->setCurrencyCode((string) $currency->iso_code); $purchased_items[] = $purchased_item; } } // Check is free shipping applies to the cart. $free_shipping = false; if (isset($cart_rules)) { foreach ($cart_rules as $cart_rule) { if ((int) $cart_rule['free_shipping']) { $free_shipping = true; break; } } } if (!$free_shipping && $total_shipping_tax_incl > 0) { $purchased_item = new NostoTaggingOrderPurchasedItem(); $purchased_item->setProductId(-1); $purchased_item->setQuantity(1); $purchased_item->setName('Shipping'); $purchased_item->setUnitPrice(Nosto::helper('price')->format($total_shipping_tax_incl)); $purchased_item->setCurrencyCode((string) $currency->iso_code); $purchased_items[] = $purchased_item; } if ($total_wrapping_tax_incl > 0) { $purchased_item = new NostoTaggingOrderPurchasedItem(); $purchased_item->setProductId(-1); $purchased_item->setQuantity(1); $purchased_item->setName('Gift Wrapping'); $purchased_item->setUnitPrice(Nosto::helper('price')->format($total_wrapping_tax_incl)); $purchased_item->setCurrencyCode((string) $currency->iso_code); $purchased_items[] = $purchased_item; } } return $purchased_items; }
/** * Turns an order object into a JSON structure. * * @param Nosto_Tagging_Model_Meta_Order $order the order object. * @return string the JSON structure. */ protected function getOrderAsJson(Nosto_Tagging_Model_Meta_Order $order) { $data = array('order_number' => $order->getOrderNumber(), 'external_order_ref' => $order->getExternalOrderRef(), 'order_status_code' => $order->getOrderStatus()->getCode(), 'order_status_label' => $order->getOrderStatus()->getLabel(), 'buyer' => array('first_name' => $order->getBuyerInfo()->getFirstName(), 'last_name' => $order->getBuyerInfo()->getLastName(), 'email' => $order->getBuyerInfo()->getEmail()), 'created_at' => Nosto::helper('date')->format($order->getCreatedDate()), 'payment_provider' => $order->getPaymentProvider(), 'purchased_items' => array()); foreach ($order->getPurchasedItems() as $item) { $data['purchased_items'][] = array('product_id' => $item->getProductId(), 'quantity' => (int) $item->getQuantity(), 'name' => $item->getName(), 'unit_price' => Nosto::helper('price')->format($item->getUnitPrice()), 'price_currency_code' => strtoupper($item->getCurrencyCode())); } return json_encode($data); }
/** * Returns the base url for the Nosto iframe. * * @return string the url. */ protected function getBaseUrl() { return Nosto::getEnvVariable('NOSTO_WEB_HOOK_BASE_URL', NostoHttpRequest::$baseUrl); }
/** * Returns the account administration iframe url. * If there is no account the "front page" url will be returned where an * account can be created from. * * @param Mage_Core_Model_Store $store the store view to get the url for. * @param NostoAccount $account the Nosto account to get the iframe url for. * @param array $params optional extra params for the url. * * @return string the iframe url. */ public function getIframeUrl(Mage_Core_Model_Store $store, NostoAccount $account = null, array $params = array()) { $meta = new Nosto_Tagging_Model_Meta_Account_Iframe(); $meta->loadData($store); return Nosto::helper('iframe')->getUrl($meta, $account, $params); }
/** * Loads the meta-data from context. * * @param Context $context the context to get the meta-data from. * @param int $id_lang the language ID of the shop for which to get the meta-data. */ public function loadData($context, $id_lang) { $shop_language = new Language($id_lang); if (!Validate::isLoadedObject($shop_language)) { return; } /** @var NostoTaggingHelperUrl $url_helper */ $url_helper = Nosto::helper('nosto_tagging/url'); $this->first_name = $context->employee->firstname; $this->last_name = $context->employee->lastname; $this->email = $context->employee->email; $this->language_iso_code = $context->language->iso_code; $this->language_iso_code_shop = $shop_language->iso_code; $this->preview_url_product = $url_helper->getPreviewUrlProduct(null, $id_lang); $this->preview_url_category = $url_helper->getPreviewUrlCategory(null, $id_lang); $this->preview_url_search = $url_helper->getPreviewUrlSearch($id_lang); $this->preview_url_cart = $url_helper->getPreviewUrlCart($id_lang); $this->preview_url_front = $url_helper->getPreviewUrlHome($id_lang); $this->shop_name = $shop_language->name; }
/** * Sends the re-crawl API request to Nosto. * * @param NostoAccountInterface $account the account to re-crawl the product(s) for. * @param array $payload the request payload as an array that will be json encoded. * @return bool true on success. * @throws NostoException if the request fails or cannot be made. */ protected static function sendRequest(NostoAccountInterface $account, array $payload) { $token = $account->getApiToken('products'); if ($token === null) { throw new NostoException('Failed to send product re-crawl to Nosto. No `products` API token found for account.'); } $request = new NostoApiRequest(); $request->setPath(NostoApiRequest::PATH_PRODUCT_RE_CRAWL); $request->setContentType('application/json'); $request->setAuthBasic('', $token->getValue()); $response = $request->post(json_encode($payload)); if ($response->getCode() !== 200) { Nosto::throwHttpException('Failed to send product re-crawl to Nosto.', $request, $response); } return true; }
/** * Serializes the product into an array structure. * * Example: * * array( * 'url' => 'http://www.example.com/product/CANOE123', * 'product_id' => 'CANOE123', * 'name' => 'ACME Foldable Canoe', * 'image_url' => 'http://www.example.com/product/images/CANOE123.jpg', * 'price' => '1269.00', * 'price_currency_code' => 'EUR', * 'availability' => 'InStock', * 'categories' => array('/Outdoor/Boats/Canoes', '/Sales/Boats'), * 'description' => 'This foldable canoe is easy to travel with.', * 'list_price' => '1299.00', * 'brand' => 'ACME', * 'tag1' => array('Men'), * 'tag2' => array('Foldable'), * 'tag3' => array('Brown', 'Black', 'Orange'), * 'date_published' => '2011-12-31', * 'variation_id' => 'EUR' * ) * * @param NostoProductInterface $product the product to serialize. * @return array the serialized product array. */ public function serialize(NostoProductInterface $product) { /** @var NostoFormatterDate $dateFormatter */ $dateFormatter = Nosto::formatter('date'); /** @var NostoFormatterPrice $priceFormatter */ $priceFormatter = Nosto::formatter('price'); $data = array('url' => $product->getUrl(), 'product_id' => $product->getProductId(), 'name' => $product->getName(), 'image_url' => $product->getImageUrl(), 'categories' => array()); if ($product->getAvailability() instanceof NostoProductAvailability) { $data['availability'] = $product->getAvailability()->getAvailability(); } elseif (is_string($product->getAvailability())) { $data['availability'] = $product->getAvailability(); } else { $data['availability'] = ''; } if ($product->getPrice() instanceof NostoPrice) { $data['price'] = $priceFormatter->format($product->getPrice()); } elseif (is_numeric($product->getPrice())) { $data['price'] = $product->getPrice(); } else { $data['price'] = ''; } if ($product->getCurrency() instanceof NostoCurrencyCode) { $data['price_currency_code'] = $product->getCurrency()->getCode(); } elseif (is_string($product->getCurrency())) { $data['price_currency_code'] = $product->getCurrency(); } else { $data['price_currency_code'] = ''; } foreach ($product->getCategories() as $category) { if ($category instanceof NostoCategoryInterface) { $data['categories'][] = $category->getPath(); } elseif (is_string($category) || is_numeric($category)) { $data['categories'][] = $category; } } // Optional properties. if ($product->getThumbUrl()) { $data['thumb_url'] = $product->getThumbUrl(); } if ($product->getDescription()) { $data['description'] = $product->getDescription(); } if ($product->getListPrice() instanceof NostoPrice) { $data['list_price'] = $priceFormatter->format($product->getListPrice()); } elseif (is_numeric($product->getListPrice())) { $data['list_price'] = $product->getListPrice(); } else { $data['list_price'] = ''; } if ($product->getBrand()) { $data['brand'] = $product->getBrand(); } foreach ($product->getTags() as $type => $tags) { if (is_array($tags) && count($tags) > 0) { $data[$type] = $tags; } } if ($product->getDatePublished() instanceof NostoDate) { $data['date_published'] = $dateFormatter->format($product->getDatePublished()); } if ($product->getVariationId()) { $data['variation_id'] = $product->getVariationId(); } if (count($product->getVariations()) > 0) { $data['variations'] = array(); foreach ($product->getVariations() as $variation) { $variationData = array(); if ($variation->getCurrency()) { $variationData['price_currency_code'] = $variation->getCurrency()->getCode(); } if ($variation->getPrice() instanceof NostoPrice) { $variationData['price'] = $priceFormatter->format($variation->getPrice()); } if ($variation->getListPrice() instanceof NostoPrice) { $variationData['list_price'] = $priceFormatter->format($variation->getListPrice()); } if ($variation->getAvailability() instanceof NostoProductAvailability) { $variationData['availability'] = $variation->getAvailability()->getAvailability(); } elseif (is_string($variation->getAvailability())) { $variationData['availability'] = $variation->getAvailability(); } if ($variation->getId()) { $variationData['variation_id'] = $variation->getId(); $data['variations'][$variation->getId()] = $variationData; } else { $data['variations'][] = $variationData; } } } return $data; }
/** * Signs the user in to Nosto via SSO. * * Requires that the account has a valid sso token associated with it. * * @param NostoAccount $account the account to sign into. * @param NostoAccountMetaSingleSignOnInterface $meta the SSO meta-data. * @return string a secure login url. * * @throws NostoException on failure. */ public function sso(NostoAccount $account, NostoAccountMetaSingleSignOnInterface $meta) { $token = $account->getApiToken(NostoApiToken::API_SSO); if (is_null($token)) { throw new NostoException(sprintf('No `%s` API token found for account "%s".', NostoApiToken::API_SSO, $account->getName())); } $request = new NostoHttpRequest(); $request->setUrl(NostoHttpRequest::$baseUrl . NostoHttpRequest::PATH_SSO_AUTH); $request->setReplaceParams(array('{platform}' => $meta->getPlatform(), '{email}' => $meta->getEmail())); $request->setContentType('application/x-www-form-urlencoded'); $request->setAuthBasic('', $token->getValue()); $response = $request->post(http_build_query(array('fname' => $meta->getFirstName(), 'lname' => $meta->getLastName()))); if ($response->getCode() !== 200) { throw Nosto::createHttpException('Failed to sign into Nosto using Single Sign On.', $request, $response); } $result = $response->getJsonResult(); if (empty($result->login_url)) { throw new NostoException('No "login_url" returned when logging in employee to Nosto'); } return $result->login_url; }
/** * Turn the currencyCode exchange rate collection into a JSON structure. * * Format: * * { * "rates": { * "EUR": { * "rate": "0.706700000000", * "price_currency_code": "EUR" * } * }, * "valid_until": "2015-02-27T12:00:00Z" * } * * @return string the JSON structure. * @throws NostoException of the rate collection is empty. */ protected function getCollectionAsJson() { $data = array('rates' => array(), 'valid_until' => null); /** @var NostoExchangeRate $item */ foreach ($this->collection as $item) { $data['rates'][$item->getName()] = array('rate' => $item->getExchangeRate(), 'price_currency_code' => $item->getCurrencyCode()); } if (empty($data['rates'])) { Nosto::throwException(sprintf('Failed to update currencyCode exchange rates for account %s. No rates found in collection.', $this->account->getName())); } return json_encode($data); }
/** * Serializes the order into an array structure. * * @param NostoOrderInterface $order the order to serialize. * @return array the serialized data. */ public function serialize(NostoOrderInterface $order) { /** @var NostoFormatterDate $dateFormatter */ $dateFormatter = Nosto::formatter('date'); /** @var NostoFormatterPrice $priceFormatter */ $priceFormatter = Nosto::formatter('price'); $data = array('order_number' => $order->getOrderNumber(), 'buyer' => array(), 'purchased_items' => array()); if ($order->getCreatedDate() instanceof NostoDate) { $data['created_at'] = $dateFormatter->format($order->getCreatedDate()); } else { $data['created_at'] = ''; } if ($order->getStatus() instanceof NostoOrderStatusInterface) { $data['order_status_code'] = $order->getStatus()->getCode(); $data['order_status_label'] = $order->getStatus()->getLabel(); } elseif (is_string($order->getStatus()) || is_numeric($order->getStatus())) { $data['order_status_code'] = $order->getStatus(); $data['order_status_label'] = $order->getStatus(); } if ($order->getPaymentProvider() instanceof NostoOrderPaymentProviderInterface) { $data['payment_provider'] = $order->getPaymentProvider()->getProvider(); } elseif (is_string($order->getPaymentProvider()) || is_numeric($order->getPaymentProvider())) { $data['payment_provider'] = $order->getPaymentProvider(); } foreach ($order->getItems() as $item) { $itemData = array('product_id' => $item->getItemId(), 'quantity' => (int) $item->getQuantity(), 'name' => $item->getName()); if ($item->getUnitPrice() instanceof NostoPrice) { $itemData['unit_price'] = $priceFormatter->format($item->getUnitPrice()); } elseif (is_numeric($item->getUnitPrice())) { $itemData['unit_price'] = $item->getUnitPrice(); } else { $itemData['unit_price'] = ''; } if ($item->getCurrency() instanceof NostoCurrencyCode) { $itemData['price_currency_code'] = $item->getCurrency()->getCode(); } elseif (is_string($item->getCurrency())) { $itemData['price_currency_code'] = $item->getCurrency(); } else { $itemData['price_currency_code'] = ''; } $data['purchased_items'][] = $itemData; } // Add optional order reference if set. if ($order->getExternalRef()) { $data['external_order_ref'] = $order->getExternalRef(); } // Add optional buyer info. if ($order->getBuyer() instanceof NostoOrderBuyerInterface) { $data['buyer']['first_name'] = $order->getBuyer()->getFirstName(); $data['buyer']['last_name'] = $order->getBuyer()->getLastName(); $data['buyer']['email'] = $order->getBuyer()->getEmail(); } // Add optional order status history if set. if ($order->getHistoryStatuses() !== array()) { $dateFormat = new NostoDateFormat(NostoDateFormat::ISO_8601); $statuses = array(); foreach ($order->getHistoryStatuses() as $status) { if ($status instanceof NostoOrderStatusInterface && $status->getCreatedAt()) { if (!isset($statuses[$status->getCode()])) { $statuses[$status->getCode()] = array(); } $statuses[$status->getCode()][] = $dateFormatter->format($status->getCreatedAt(), $dateFormat); } } if (count($statuses) > 0) { $data['order_statuses'] = $statuses; } } return $data; }
/** * Calculates the price (including tax if applicable) and returns it. * * We need to check if taxes are to be included in the prices, given that they are configured. * This is determined by the "Price display method" setting of the active user group. * Possible values are 1, tax excluded, and 0, tax included. * * @param Product $product the product model. * @param Context $context the context to calculate the price on (currency conversion). * @param bool $discounted_price if discounts should be applied. * @return string the calculated price. */ protected function calcPrice(Product $product, Context $context, $discounted_price = true) { $incl_tax = (bool) (!Product::getTaxCalculationMethod((int) $context->cookie->id_customer)); $specific_price_output = null; $value = Product::getPriceStatic((int) $product->id, $incl_tax, null, 6, null, false, $discounted_price, 1, false, null, null, null, $specific_price_output, true, true, $context, true); return Nosto::helper('price')->format($value); }
/** * Returns Nosto accounts based on active shops. * * The result is formatted as follows: * * array( * array(object(NostoAccount), int(id_shop), int(id_lang)) * ) * * @return NostoAccount[] the account data. */ protected function getAccountData() { $data = array(); /** @var NostoTaggingHelperAccount $account_helper */ $account_helper = Nosto::helper('nosto_tagging/account'); foreach ($this->getContextShops() as $shop) { $id_shop = (int) $shop['id_shop']; $id_shop_group = (int) $shop['id_shop_group']; foreach (LanguageCore::getLanguages(true, $id_shop) as $language) { $id_lang = (int) $language['id_lang']; $account = $account_helper->find($id_lang, $id_shop_group, $id_shop); if ($account === null || !$account->isConnectedToNosto()) { continue; } $data[] = array($account, $id_shop, $id_lang); } } return $data; }
/** * Returns the account administration iframe url. * If there is no account the "front page" url will be returned where an * account can be created from. * * @param Mage_Core_Model_Store $store the store view to get the url for. * @param NostoAccount $account the Nosto account to get the iframe url for. * @param array $params optional extra params for the url. * * @return string the iframe url. */ public function getIframeUrl(Mage_Core_Model_Store $store, NostoAccount $account = null, array $params = array()) { /** @var Nosto_Tagging_Model_Meta_Account_Iframe $meta */ $meta = Mage::getModel('nosto_tagging/meta_account_iframe'); $meta->loadData($store); return Nosto::helper('iframe')->getUrl($meta, $account, $params); }
/** * Turn the currency exchange rate collection into a JSON structure. * * Format: * * { * "rates": { * "EUR": { * "rate": "0.706700000000", * "price_currency_code": "EUR" * } * }, * "valid_until": "2015-02-27T12:00:00Z" * } * * @param NostoCurrencyExchangeRateCollection $collection the rate collection. * @return string the JSON structure. * @throws NostoException of the rate collection is empty. */ protected function getCollectionAsJson(NostoCurrencyExchangeRateCollection $collection) { $data = array('rates' => array(), 'valid_until' => null); $validUntil = $collection->getValidUntil(); if (!is_null($validUntil)) { /** @var NostoFormatterDate $formatter */ $formatter = Nosto::formatter('date'); $data['valid_until'] = $formatter->format($validUntil, new NostoDateFormat(NostoDateFormat::ISO_8601)); } /** @var NostoCurrencyExchangeRate $item */ foreach ($collection->getArrayCopy() as $item) { $data['rates'][$item->getCurrency()->getCode()] = array('rate' => $item->getExchangeRate(), 'price_currency_code' => $item->getCurrency()->getCode()); } if (empty($data['rates'])) { throw new NostoException(sprintf('Failed to update currency exchange rates for account %s. No rates found in collection.', $this->account->getName())); } return json_encode($data); }
/** * @inheritdoc */ public function ssoLogin(NostoAccountMetaDataIframeInterface $meta) { $token = $this->getApiToken('sso'); if ($token === null) { return false; } $request = new NostoHttpRequest(); $request->setUrl(NostoHttpRequest::$baseUrl . NostoHttpRequest::PATH_SSO_AUTH); $request->setReplaceParams(array('{platform}' => $meta->getPlatform(), '{email}' => $meta->getEmail())); $request->setContentType('application/x-www-form-urlencoded'); $request->setAuthBasic('', $token->getValue()); $response = $request->post(http_build_query(array('fname' => $meta->getFirstName(), 'lname' => $meta->getLastName()))); $result = $response->getJsonResult(); if ($response->getCode() !== 200) { Nosto::throwHttpException('Unable to login employee to Nosto with SSO token.', $request, $response); } if (empty($result->login_url)) { throw new NostoException('No "login_url" returned when logging in employee to Nosto'); } return $result->login_url; }
/** * Converts the product object into an array and returns it. * * Example: * * array( * 'url' => 'http://www.example.com/product/CANOE123', * 'product_id' => 'CANOE123', * 'name' => 'ACME Foldable Canoe', * 'image_url' => 'http://www.example.com/product/images/CANOE123.jpg', * 'price' => '1269.00', * 'price_currency_code' => 'EUR', * 'availability' => 'InStock', * 'categories' => array('/Outdoor/Boats/Canoes', '/Sales/Boats'), * 'description' => 'This foldable canoe is easy to travel with.', * 'list_price' => '1299.00', * 'brand' => 'ACME', * 'tag1' => array('Men'), * 'tag2' => array('Foldable'), * 'tag3' => array('Brown', 'Black', 'Orange'), * 'date_published' => '2011-12-31' * ) * * @param NostoProductInterface $product the object. * @return array the newly created array. */ protected function getProductAsArray(NostoProductInterface $product) { $data = array('url' => $product->getUrl(), 'product_id' => $product->getProductId(), 'name' => $product->getName(), 'image_url' => $product->getImageUrl(), 'price' => Nosto::helper('price')->format($product->getPrice()), 'price_currency_code' => strtoupper($product->getCurrencyCode()), 'availability' => $product->getAvailability(), 'categories' => $product->getCategories()); // Optional properties. if ($product->getFullDescription()) { $data['description'] = $product->getFullDescription(); } if ($product->getListPrice()) { $data['list_price'] = Nosto::helper('price')->format($product->getListPrice()); } if ($product->getBrand()) { $data['brand'] = $product->getBrand(); } foreach ($product->getTags() as $type => $tags) { if (is_array($tags) && count($tags) > 0) { $data[$type] = $tags; } } if ($product->getDatePublished()) { $data['date_published'] = Nosto::helper('date')->format($product->getDatePublished()); } return $data; }