public static function refresh($force = false) { $settings = \Shop\Models\Settings::fetch(); if (empty($settings->{'currency.openexchangerates_api_id'})) { static::log('Could not refresh list of valid currencies. Please provide an open exchange rates API ID in the Shop Configuration page', 'ERROR'); return false; } // once a day is enough if (!empty($settings->currencies_last_refreshed) && $settings->currencies_last_refreshed > time() - 24 * 60 && empty($force)) { return false; } $oer = new \Shop\Lib\OpenExchangeRates($settings->{'currency.openexchangerates_api_id'}); if ($response = $oer->currencies()) { if ($currencies = \Dsc\ArrayHelper::fromObject($response)) { foreach ($currencies as $code => $title) { $currency = (new static())->setParam('conditions', array('code' => $code))->getItem(); if (empty($currency->id)) { $currency = new static(); } $currency->code = $code; $currency->title = $title; $currency->store(); } $settings->currencies_last_refreshed = time(); $settings->save(); } } return true; }
public static function defaultList() { $conditions = array('enabled' => 1); $settings = \Shop\Models\Settings::fetch(); if ($settings->countries_sort == 'name') { $conditions['sort'] = array('name' => 1); } $result = \Shop\Models\Countries::find($conditions); return $result; }
public static function passes(\Modules\Models\Modules $module, $route = null, $options = array()) { // if this ruleset is ignored, return null if (!in_array($module->{'assignment.groups.method'}, array('one', 'all', 'none'))) { return null; } $groups_method = $module->{'assignment.groups.method'}; $assigned_groups = $module->{'assignment.groups.list'}; $identity_id = \Dsc\System::instance()->get('auth')->getIdentity()->id; if (!empty($assigned_groups)) { $groups = array(); $user = (new \Users\Models\Users())->setState('filter.id', $identity_id)->getItem(); if (empty($identity_id) || empty($user->id)) { // Get the default group $group_id = \Shop\Models\Settings::fetch()->{'users.default_group'}; if (!empty($group_id)) { $groups[] = (new \Users\Models\Groups())->setState('filter.id', (string) $group_id)->getItem(); } } elseif (!empty($user->id)) { $groups = $user->groups(); } $group_ids = array(); foreach ($groups as $group) { $group_ids[] = (string) $group->id; } switch ($groups_method) { case "none": $intersection = array_intersect($assigned_groups, $group_ids); if (!empty($intersection)) { return false; } break; case "all": // $missing_groups == the ones from $assigned_groups that are NOT in $group_ids $missing_groups = array_diff($assigned_groups, $group_ids); if (!empty($missing_groups)) { return false; } break; case "one": default: $intersection = array_intersect($assigned_groups, $group_ids); if (empty($intersection)) { return false; } break; } } return true; }
/** * Simply formats a number according to the currency's rules * * @param unknown $number * @param string $currency_code * @param unknown $options */ public static function format($number, $currency_code = 'USD', $options = array()) { $settings = \Shop\Models\Settings::fetch(); // TODO Support custom formatting switch ($settings->{'currency.default'}) { case "INR": $formatted = 'Rs.' . number_format((double) $number, 0, ".", ","); break; case "USD": default: $formatted = '$' . number_format((double) $number, 2, ".", ","); break; } return $formatted; }
/** * Gets the customer's highest-ordered Users\Group * to be used for determining pricing and primary group status * * @return \Users\Models\Groups */ public static function primaryGroup(\Users\Models\Users $user = null) { $group = new \Users\Models\Groups(); if (!empty($user)) { if ($groups = $user->groups()) { $group = $groups[0]; } } if (empty($group->id)) { // Set this to be a default group, as configured in the Shop config $group_id = \Shop\Models\Settings::fetch()->{'users.default_group'}; if (!empty($group_id)) { $group = $group->setState('filter.id', (string) $group_id)->getItem(); } } return $group; }
public static function diagnostics() { if (class_exists('\\Modules\\Factory')) { \Modules\Models\Conditions::register('\\Shop\\ModuleConditions\\Orders', array('title' => 'Orders', 'icon' => 'fa fa-shopping-cart', 'type' => 'shop', 'slug' => 'shop-orders')); } $settings = \Shop\Models\Settings::fetch(); // TODO When did we last pull down the currency list? if (empty($settings->currencies_last_refreshed) || $settings->currencies_last_refreshed < time() - 24 * 60) { /* \Dsc\Queue::task('\Shop\Models\Currencies::refresh', array(), array( 'title' => 'Refresh currencies from OpenExchangeRates.org' )); */ } // TODO When did we last pull down the exchange rates? if (empty($settings->exchangerates_last_refreshed) || $settings->exchangerates_last_refreshed < time() - 24 * 60) { } }
break; } ?> <span class="label <?php echo $label_class; ?>"> <?php echo \Dsc\ArrayHelper::get($item, 'fulfillment_status', 'n/a'); ?> </span> */ ?> </div> </div> <?php } ?> </div> </div> </div> <div class="order-footer"> <?php echo \Shop\Models\Settings::fetch()->{'orders.printing.footer'}; ?> </div> </div> </body> </html>
public function currencies() { $this->settings_route = '/admin/shop/settings/currencies'; switch ($this->app->get('VERB')) { case "POST": case "post": // do the save and redirect to $this->settings_route return $this->save(); break; } $flash = \Dsc\Flash::instance(); $this->app->set('flash', $flash); $settings = \Shop\Models\Settings::fetch(); $flash->store($settings->cast()); $this->app->set('meta.title', 'Currencies | Shop'); echo $this->theme->render('Shop/Admin/Views::settings/currencies.php'); }
</div> <hr/><?php } ?> <?php } ?> </div> <?php } ?> </div> </div> </div> <?php $settings = \Shop\Models\Settings::fetch(); ?> <?php if ($settings->{'reviews.enabled'}) { ?> <?php echo $this->renderView('Shop/Site/Views::product/fragment_reviews.php'); ?> <?php } ?> </div>
/** * Determines whether or not a user qualifies for this campaign * * @param \Users\Models\Users $user * @throws \Exception * @return \Shop\Models\Campaigns */ public function customerQualifies(\Shop\Models\Customers $customer) { // Set $this->__is_validated = true if YES, user qualifies for this campaign. // throw an Exception if NO, user does not qualify. /** * is the campaign published? */ if (!$this->published()) { throw new \Exception('This campaign is not valid for today'); } $period_start = null; $period_end = null; switch ($this->period_type) { case "variable": $period_start = date('Y-m-d', strtotime('today -' . (int) $this->variable_period_days . ' days')); $period_end = date('Y-m-d', strtotime('tomorrow')); break; case "fixed": $period_start = $this->fixed_period_start; $period_end = $this->fixed_period_end; break; default: throw new \Exception('Invalid period type'); break; } // has the minimum spend amount for the qualification period been met? if (!empty($this->rule_min_spent)) { // Get the total amount spent by the customer during the qualification period $total = $customer->fetchTotalSpent($period_start, $period_end); if ($total < $this->rule_min_spent) { throw new \Exception('Customer has not spent enough during the qualification period'); } } /** * evaluate shopper groups against $this->groups */ if (!empty($this->groups)) { $groups = array(); if (empty($customer->id)) { // Get the default group $group_id = \Shop\Models\Settings::fetch()->{'users.default_group'}; if (!empty($group_id)) { $groups[] = (new \Users\Models\Groups())->setState('filter.id', (string) $group_id)->getItem(); } } elseif (!empty($customer->id)) { $groups = $customer->groups(); } $group_ids = array(); foreach ($groups as $group) { $group_ids[] = (string) $group->id; } switch ($this->groups_method) { case "none": $intersection = array_intersect($this->groups, $group_ids); if (!empty($intersection)) { // TODO Chagne the error messages!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! throw new \Exception('You do not qualify for this campaign.'); } break; case "all": // $missing_groups == the ones from $this->groups that are NOT in $group_ids $missing_groups = array_diff($this->groups, $group_ids); if (!empty($missing_groups)) { throw new \Exception('You do not qualify for this campaign.'); } break; case "one": default: $intersection = array_intersect($this->groups, $group_ids); if (empty($intersection)) { throw new \Exception('You do not qualify for this campaign.'); } break; } } /** * if we made it this far, the user qualifies */ $this->__is_validated = true; return $this; }
/** * Gets the billing country, default one if not set * * @param string $default * @return string */ public function billingCountry($default = null) { if ($this->{'checkout.billing_address.country'}) { return $this->{'checkout.billing_address.country'}; } return $default ? $default : \Shop\Models\Settings::fetch()->{'country'}; }
public static function sendEmailForOrder($order_id) { $settings = \Shop\Models\Settings::fetch(); if (empty($settings->{'reviews.enabled'})) { return; } $days_from_now = $settings->{'reviews.email_days'}; if (empty($days_from_now)) { return; } // load the order $order = (new \Shop\Models\Orders())->setState('filter.id', $order_id)->getItem(); if (empty($order->id)) { return; } // check which products from the order have not been reviewed. // If all have been reviewed, don't send the email. $product_ids = array(); foreach ($order->items as $item) { $key = (string) $item['product_id']; $product_ids[$key] = $item['product_id']; } $products = array_values($product_ids); $product_reviews = static::collection()->find(array('product_id' => array('$in' => $products), 'user_id' => $order->user_id)); foreach ($product_reviews as $doc) { $key = (string) $doc['product_id']; unset($product_ids[$key]); } // at this point, $product_ids should have the list of unreviewed products from this order if (empty($product_ids)) { return; } // so get an array of actual products $products = array(); foreach ($product_ids as $product_id) { foreach ($order->items as $item) { if ($item['product_id'] == $product_id) { $products[] = $item; } } } if (empty($products)) { return; } // get the recipient's email and send the email $recipients = array($order->user_email); if (empty($recipients)) { return; } $subject = $settings->get('reviews.email_subject'); if (empty($subject)) { $subject = "Please review your recent purchases!"; } $user = $order->user(); \Base::instance()->set('user', $user); \Base::instance()->set('products', $products); $html = \Dsc\System::instance()->get('theme')->renderView('Shop/Views::emails_html/review_products.php'); $text = \Dsc\System::instance()->get('theme')->renderView('Shop/Views::emails_text/review_products.php'); foreach ($recipients as $recipient) { \Dsc\System::instance()->get('mailer')->send($recipient, $subject, array($html, $text)); } }
/** * Send out new order emails to admins * * @param array $recipients */ public function sendEmailNewOrderNotifications(array $recipients = array()) { if (empty($recipients)) { $recipients = (array) \Shop\Models\Settings::fetch()->{'notifications.orders.emails'}; } \Base::instance()->set('order', $this); \Base::instance()->set('settings', \Shop\Models\Settings::fetch()); $html = \Dsc\System::instance()->get('theme')->renderView('Shop/Views::emails_html/new_order_notification.php'); $text = \Dsc\System::instance()->get('theme')->renderView('Shop/Views::emails_text/new_order_notification.php'); $order_number = $this->number; $subject = 'New Order #' . $order_number; foreach ($recipients as $recipient) { $this->__sendEmailNewOrder = \Dsc\System::instance()->get('mailer')->send($recipient, $subject, array($html, $text)); } return $this; }
/** * * @param unknown $cart_id * @param unknown $notification_idx */ public static function sendAbandonedEmailNotification($cart_id, $notification_idx) { $settings = \Shop\Models\Settings::fetch(); if (empty($settings->abandoned_cart_emails_enabled)) { return; } $cart = (new static())->setState('filter.id', $cart_id)->getItem(); // cart was deleted so dont do anything if (empty($cart->id)) { return; } // Has the cart been updated recently? if so, don't send this email $abandoned_time = $settings->get('abandoned_cart_time') * 60; $abandoned_time = time() - $abandoned_time; if ($cart->{'metadata.last_modified.time'} > $abandoned_time) { return; } if ($cart->quantity() == 0) { return; } $user = $cart->user(); if (empty($user->id) || $user->id != $cart->user_id || $user->guest) { return; } // get correct user email $recipients = array(); if (empty($cart->{'user_email'})) { if (!empty($user->email)) { $recipients = array($user->email); } } else { $recipients = array($cart->{'user_email'}); } if (empty($recipients)) { return; } $token = \Dsc\System::instance()->get('auth')->getAutoLoginToken($user, true); \Base::instance()->set('cart', $cart); \Base::instance()->set('user', $user); \Base::instance()->set('idx', $notification_idx); \Base::instance()->set('token', $token); $subject = $settings->get('abandoned_cart_emails.' . $notification_idx . '.subject'); if (empty($subject)) { $subject = $settings->get('abandoned_cart_subject'); if (empty($subject)) { $subject = "Complete your purchase"; } } $notification = $settings->get('abandoned_cart_emails.' . $notification_idx); if (empty($notification)) { $notification = array('text' => array('html' => '', 'plain' => '')); } \Base::instance()->set('notification', $notification); $html = \Dsc\System::instance()->get('theme')->renderView('Shop/Views::emails_html/abandoned_cart.php'); $text = \Dsc\System::instance()->get('theme')->renderView('Shop/Views::emails_text/abandoned_cart.php'); foreach ($recipients as $recipient) { \Dsc\System::instance()->get('mailer')->send($recipient, $subject, array($html, $text)); } $num = $notification_idx + 1; \Dsc\Activities::trackActor($user->email, 'Received abandoned cart email notification #' . $num, array('cart_value' => (string) $cart->total(), 'cart_items_count' => (string) $cart->quantity())); }
/** * Determines if this coupon is valid for a cart * * @param \Shop\Models\Carts $cart * @throws \Exception */ public function cartValid(\Shop\Models\Carts $cart) { // Set $this->__is_validated = true if YES, cart can use this coupon // throw an Exception if NO, cart cannot use this coupon /** * is the coupon published? */ if (!$this->published()) { throw new \Exception('This coupon is expired.'); } /** * Only 1 user-submitted coupon per cart, * and if the auto-coupon is exclusive, it can't be added with others */ // If this is a user-submitted coupon && there are other user-submitted coupons in the cart, fail if (empty($this->usage_automatic) && $cart->userCoupons() && $cart->userCoupons()[0]['code'] != $this->code) { throw new \Exception('Only one coupon allowed per cart'); } // if this is an automatic coupon && usage_with_others == 0 && there are other automatic coupons in the cart if ($this->usage_automatic && empty($this->usage_with_others) && $cart->autoCoupons()) { throw new \Exception('This coupon cannot be combined with others'); } // TODO take min_subtotal_amount_currency into account once we have currencies sorted if (!empty($this->min_subtotal_amount) && $cart->subtotal() < $this->min_subtotal_amount) { throw new \Exception('Cart has not met the minimum required subtotal'); } // TODO take min_order_amount_currency into account once we have currencies sorted $total = $cart->subtotal() - $cart->giftCardTotal() - $cart->discountTotal() - $cart->creditTotal(); // Add back the value of this coupon in case it is already applied foreach ($cart->allCoupons() as $coupon) { if ((string) $coupon['_id'] == (string) $this->id) { $total = $total + $coupon['amount']; break; } } if (!empty($this->min_order_amount) && $total < $this->min_order_amount) { throw new \Exception('Cart has not met the minimum required amount'); } /** * check that at least one of the $this->required_products is in the cart */ if (!empty($this->required_products)) { // get the IDs of all products in this cart $product_ids = array(); foreach ($cart->items as $cartitem) { $product_ids[] = (string) \Dsc\ArrayHelper::get($cartitem, 'product_id'); } $intersection = array_intersect($this->required_products, $product_ids); if (empty($intersection)) { throw new \Exception('Coupon does not apply to any products in your cart.'); } } /** * check that at least one of the $this->required_coupons is in the cart */ if (!empty($this->required_coupons)) { // get the IDs of all coupons in this cart $coupon_ids = array(); foreach ($cart->userCoupons() as $coupon) { $coupon_ids[] = (string) $coupon['_id']; } foreach ($cart->autoCoupons() as $coupon) { $coupon_ids[] = (string) $coupon['_id']; } $intersection = array_intersect($this->required_coupons, $coupon_ids); if (empty($intersection)) { throw new \Exception('Cart does not have any of the required coupons'); } } /** * check that at least one of the products from $this->required_collections is in the cart */ if (!empty($this->required_collections)) { // get the IDs of all products in this cart $product_ids = array(); foreach ($cart->items as $cartitem) { $product_ids[] = (string) \Dsc\ArrayHelper::get($cartitem, 'product_id'); } $found = false; foreach ($this->required_collections as $collection_id) { $collection_product_ids = \Shop\Models\Collections::productIds($collection_id); $intersection = array_intersect($collection_product_ids, $product_ids); if (!empty($intersection)) { $found = true; break; // if its found, break the foreach loop } } if (!$found) { throw new \Exception('Coupon does not apply to any products in your cart.'); } } /** * evaluate shopper groups against $this->groups */ if (!empty($this->groups)) { $groups = array(); $user = (new \Users\Models\Users())->setState('filter.id', $cart->user_id)->getItem(); if (empty($cart->user_id) || empty($user->id)) { // Get the default group $group_id = \Shop\Models\Settings::fetch()->{'users.default_group'}; if (!empty($group_id)) { $groups[] = (new \Users\Models\Groups())->setState('filter.id', (string) $group_id)->getItem(); } } elseif (!empty($user->id)) { $groups = $user->groups(); } $group_ids = array(); foreach ($groups as $group) { $group_ids[] = (string) $group->id; } switch ($this->groups_method) { case "none": $intersection = array_intersect($this->groups, $group_ids); if (!empty($intersection)) { throw new \Exception('Your order does not qualify for this discount.'); } break; case "all": // $missing_groups == the ones from $this->groups that are NOT in $group_ids $missing_groups = array_diff($this->groups, $group_ids); if (!empty($missing_groups)) { throw new \Exception('Your order does not qualify for this discount.'); } break; case "one": default: $intersection = array_intersect($this->groups, $group_ids); if (empty($intersection)) { throw new \Exception('Your order does not qualify for this discount.'); } break; } } /** * using geo_address_type (shipping/billing) from the cart, check that it is in geo_countries | geo_regions (if either is set) */ if (!empty($this->geo_countries) || !empty($this->geo_regions)) { // ok, so which of the addresses should we evaluate? switch ($this->geo_address_type) { case "billing": $region = $cart->billingRegion(); $country = $cart->billingCountry(); break; case "shipping": default: $region = $cart->shippingRegion(); $country = $cart->shippingCountry(); break; } if (is_null($region) && !empty($this->geo_regions) || is_null($country) && !empty($this->geo_countries)) { throw new \Exception('Customer cannot use this coupon until we know your address'); } if (!empty($this->geo_countries)) { // eval the country if (!in_array($country, $this->geo_countries)) { throw new \Exception('Shipping address is invalid'); } } if (!empty($this->geo_regions)) { // eval the region if (!in_array($region, $this->geo_regions)) { throw new \Exception('Shipping address is invalid'); } } } /** * Check the usage of the coupon */ if (strlen($this->usage_max)) { // usage_max = number of times TOTAL that the coupon may be used // count the orders with coupon.code $total_count = (new \Shop\Models\Orders())->collection()->count(array('coupons.code' => $this->code)); if ((int) $this->usage_max <= (int) $total_count) { throw new \Exception('Coupon cannot be used any more'); } } if (strlen($this->usage_max_per_customer)) { // usage_max_per_customer = number of times this customer may use this coupon // count the orders with coupon.code for user.id $user_count = (new \Shop\Models\Orders())->collection()->count(array('coupons.code' => $this->code, 'user_id' => $cart->user_id)); if ((int) $this->usage_max_per_customer <= (int) $user_count) { throw new \Exception('You cannot use this coupon any more'); } } /** * Check, if this isn't generated code */ if (!empty($this->generated_code)) { $key = new \MongoRegex('/' . $this->generated_code . '/i'); $result = \Shop\Models\Coupons::collection()->aggregate(array('$match' => array('_id' => new \MongoId((string) $this->id))), array('$unwind' => '$codes.list'), array('$match' => array("codes.list.code" => $key)), array('$group' => array('_id' => '$title', 'used_code' => array('$sum' => '$codes.list.used')))); if (count($result['result'])) { if ($result['result'][0]['used_code']) { throw new \Exception('You cannot use this coupon any more'); } } else { throw new \Exception('Coupon "' . $this->generated_code . '" is no longer available.'); } } /** * if we made it this far, the cart is valid for this coupon */ $this->__is_validated = true; return $this; }
public function productsXml() { $settings = \Shop\Models\Settings::fetch(); if (!$settings->{'feeds.gm_products.enabled'}) { return; } $this->app->set('CACHE', true); $cache = \Cache::instance(); $cache_period = 3600 * 24; if ($cache->exists('googlemerchant.products_xml', $string)) { header('Content-Type: application/xml; charset=utf-8'); echo $string; exit; } $base = \Dsc\Url::base(); $model = (new \Shop\Models\Products())->setState('filter.published_today', true)->setState('filter.inventory_status', 'in_stock')->setState('filter.publication_status', 'published'); $conditions = $model->conditions(); $conditions['product_type'] = array('$nin' => array('giftcard', 'giftcards')); $cursor = \Shop\Models\Products::collection()->find($conditions)->sort(array('title' => 1)); //->limit(10); /** * Generate XML */ $x = new \XMLWriter(); $x->openMemory(); $x->setIndent(true); $x->setIndentString(" "); $x->startDocument('1.0', 'UTF-8'); $x->startElement('rss'); $x->writeAttribute('version', '2.0'); $x->writeAttribute('xmlns:g', 'http://base.google.com/ns/1.0'); $x->startElement('channel'); $title = $settings->{'feeds.gm_products.title'} ? $settings->{'feeds.gm_products.title'} : 'Product Feed'; $x->startElement('title'); $x->text($title); $x->endElement(); // title $link = $base; $x->startElement('link'); $x->text($link); $x->endElement(); // link if ($description = $settings->{'feeds.gm_products.description'}) { $x->startElement('description'); $x->text($description); $x->endElement(); // description } foreach ($cursor as $product_doc) { $product = new \Shop\Models\Products($product_doc); foreach ($product->variantsInStock() as $variant) { $price = $product->price($variant['id']); // Skip products where price == 0.00 if (empty($price)) { continue; } $x->startElement('item'); $x->startElement('title'); $x->text($product->title); $x->endElement(); // title $x->startElement('description'); $x->text(strip_tags($product->getAbstract())); $x->endElement(); // description $x->startElement('g:link'); $x->text($base . 'shop/product/' . $product->slug); $x->endElement(); // g:link // image_link if ($image = $variant['image'] ? $variant['image'] : $product->{'featured_image.slug'}) { $x->startElement('g:image_link'); $x->text($base . 'asset/' . $image); $x->endElement(); // g:image_link } // google_product_category if ($product->{'gm_product_category'}) { $x->startElement('g:google_product_category'); $x->text($product->{'gm_product_category'}); $x->endElement(); // g:google_product_category } // TODO product_type // gender = female (or male, unisex) $gender = $settings->{'feeds.gm_products.gender'}; if ($product->{'gm_products.gender'}) { $gender = $product->{'gm_products.gender'}; } if ($gender) { $x->startElement('g:gender'); $x->text($gender); $x->endElement(); // g:gender } // age_group = adult (or newborn, infanct, toddler, kids) $age_group = $settings->{'feeds.gm_products.age_group'}; if ($product->{'gm_products.age_group'}) { $age_group = $product->{'gm_products.age_group'}; } if ($age_group) { $x->startElement('g:age_group'); $x->text($age_group); $x->endElement(); // g:age_group } // following handles color, size, pattern, material (if they are set as attributes) foreach ($product->attributes as $attribute) { $att_title = strtolower($attribute['title']); if (in_array($att_title, array('color', 'material', 'pattern', 'size'))) { $att_id = $attribute['id']; // get the attribute options $options = array(); foreach ($attribute['options'] as $option) { $options[] = $option['id']; } if ($found = array_intersect($options, $variant['attributes'])) { $key = array_search($found, $variant['attributes']); if (!empty($variant['attribute_titles'][$key])) { $x->startElement('g:' . $att_title); $x->text($variant['attribute_titles'][$key]); $x->endElement(); // g:$att_title } } } } // since we do variants: item_group_id $x->startElement('g:item_group_id'); $x->text($product->{'tracking.sku'}); $x->endElement(); // g:item_group_id $sku = $variant['sku'] ? $variant['sku'] : $product->{'tracking.sku'}; if (!$sku) { $sku = $variant['id']; } $x->startElement('g:id'); $x->text($sku); $x->endElement(); // g:id if ($brand = $settings->{'feeds.gm_products.brand'}) { $x->startElement('g:brand'); $x->text($brand); $x->endElement(); // g:brand } $x->startElement('g:mpn'); $x->text($sku); $x->endElement(); // g:mpn $x->startElement('g:price'); $x->text($price . ' USD'); $x->endElement(); // g:price $x->startElement('g:condition'); $x->text('new'); $x->endElement(); // g:condition $x->startElement('g:availability'); $x->text('in stock'); $x->endElement(); // g:availability $x->endElement(); // item } } $x->endElement(); // channel $x->endElement(); // rss $x->endDocument(); $string = $x->outputMemory(); $cache->set('googlemerchant.products_xml', $string, $cache_period); header('Content-Type: application/xml; charset=utf-8'); echo $string; }
/** * \T (tab) delimited feed of products * * http://www.pepperjamnetwork.com/doc/product_feed_advanced.html * */ public function productsTxt() { $settings = \Shop\Models\Settings::fetch(); if (!$settings->{'feeds.pepperjam_products.enabled'}) { return; } $this->app->set('CACHE', true); $cache = \Cache::instance(); $cache_period = 3600 * 24; if ($cache->exists('pepperjam.products_text', $string)) { header('Content-Type: text/plain; charset=utf-8'); echo $string; exit; } $base = \Dsc\Url::base(); $model = (new \Shop\Models\Products())->setState('filter.published_today', true)->setState('filter.inventory_status', 'in_stock')->setState('filter.publication_status', 'published'); $conditions = $model->conditions(); $conditions['product_type'] = array('$nin' => array('giftcard', 'giftcards')); $cursor = \Shop\Models\Products::collection()->find($conditions)->sort(array('title' => 1)); //->limit(10); /** * name sku buy_url image_url description_short description_long price manufacturer */ $column_headers = array('name', 'sku', 'buy_url', 'image_url', 'description_short', 'description_long', 'price', 'manufacturer'); $string = implode("\t", $column_headers) . "\r\n"; foreach ($cursor as $product_doc) { $product = new \Shop\Models\Products($product_doc); foreach ($product->variantsInStock() as $variant) { $valid = true; $price = $product->price($variant['id']); // Skip products where price == 0.00 if (empty($price)) { continue; } $pieces = array('name' => null, 'sku' => null, 'buy_url' => null, 'image_url' => null, 'description_short' => null, 'description_long' => null, 'price' => null, 'manufacturer' => null); $pieces['name'] = $product->title; $sku = $variant['sku'] ? $variant['sku'] : $product->{'tracking.sku'}; if (!$sku) { $sku = $variant['id']; } $pieces['sku'] = $sku; $pieces['buy_url'] = $base . 'shop/product/' . $product->slug . '?variant_id=' . $variant['id']; // image_link if ($image = $variant['image'] ? $variant['image'] : $product->{'featured_image.slug'}) { $pieces['image_url'] = $base . 'asset/' . $image; } $pieces['description_short'] = $product->title . ' '; if ($attribute_title = \Dsc\ArrayHelper::get($variant, 'attribute_title')) { $pieces['description_short'] .= $attribute_title; } $pieces['description_short'] = trim($pieces['description_short']); $pieces['description_long'] = strip_tags($product->getAbstract()); $pieces['price'] = $price; if ($brand = $settings->{'feeds.pepperjam_products.brand'}) { $pieces['manufacturer'] = $brand; } global $product; //walk peices logging empty values and omiting them array_walk($pieces, function (&$value, $key) { global $product; if (empty($value)) { \Dsc\Mongo\Collections\Logs::add($product->title . ' | ID: ' . $product->id . ' is missing ' . $key, 'WARNING', 'PepperJam'); $valid = false; } }); if ($valid) { $string .= implode("\t", $pieces) . "\r\n"; } } } $cache->set('pepperjam.products_text', $string, $cache_period); header('Content-Type: text/plain; charset=utf-8'); echo $string; exit; }
/** * User-aware price of the product, * accounting for user group, date, specials, etc. * Defaults to the product's default price. * * @param \Users\Models\Users $user * @return unknown */ public function price($variant_id = null, \Users\Models\Users $user = null) { $price = $this->get('prices.default'); if (empty($user)) { $identity = \Dsc\System::instance()->get('auth')->getIdentity(); if (!empty($identity->id)) { $user = $identity; } } $settings = \Shop\Models\Settings::fetch(); // find the first user group that has special price override in settings and use it $settings_price_override = null; $settings_override = false; if (!empty($user)) { foreach ($user->groups() as $group) { $settings_override = $settings->exists('special_group_default_prices.' . $group['slug']); if ($settings_override) { // found it, so get the correct number and leave $type_price = 'regular'; if (!empty($this->{'prices.list'})) { $type_price = 'sale'; } $settings_price_override = 'special_group_default_prices.' . $group['slug'] . '.' . $type_price; break; } } } // Get the product price for the user's primary group // primaryGroup defaults to the site-wide default user group $primaryGroup = \Shop\Models\Customers::primaryGroup($user); if ($group_slug = $primaryGroup->{'slug'}) { if (!$settings_override && $this->exists('prices.' . $group_slug)) { $price = $this->get('prices.' . $group_slug); } } if (!empty($variant_id) && $this->{'policies.variant_pricing.enabled'} && ($variant = $this->variant($variant_id))) { $price = $variant['price']; } // adjust price based on date ranges too $using_special_price = false; $now = strtotime('now'); $today = date('Y-m-d', $now); foreach ((array) $this->{'prices.special'} as $special_price) { if (empty($special_price['group_id']) || $special_price['group_id'] == (string) $primaryGroup->id) { if (!empty($special_price['start']['time']) && $special_price['start']['time'] <= $now && (empty($special_price['end']['time']) || $special_price['end']['time'] > $now)) { $price = $special_price['price']; $using_special_price = true; break; } } } // don't discount special prices if (!$using_special_price && $settings_override) { $ratio = 1.0 - (double) $settings->{$settings_price_override} / 100.0; $price = $price * $ratio; } return $price; }
<?php $selected_country = $flash->old('country') ? $flash->old('country') : \Shop\Models\Settings::fetch()->{'store_address.country'}; ?> <div id="address" class="well well-sm"> <div class="form-group"> <input type="text" class="form-control name" data-required="true" name="name" value="<?php echo $flash->old('name'); ?> " placeholder="Full Name" autocomplete="name"> </div> <div class="form-group"> <input type="text" class="form-control address" data-required="true" name="line_1" value="<?php echo $flash->old('line_1'); ?> " placeholder="Address Line 1" autocomplete="address-line1"> </div> <div class="form-group"> <input type="text" class="form-control address" name="line_2" value="<?php echo $flash->old('line_2'); ?> " placeholder="Address Line 2" autocomplete="address-line2"> </div> <div class="form-group"> <input type="text" class="form-control city" data-required="true" name="city" value="<?php echo $flash->old('city'); ?> " placeholder="City" autocomplete="locality"> </div> <div class="row">
public function sendEmailShareGiftCard($data) { \Base::instance()->set('data', $data); \Base::instance()->set('giftcard', $this); \Base::instance()->set('settings', \Shop\Models\Settings::fetch()); $html = \Dsc\System::instance()->get('theme')->renderView('Shop/Views::emails_html/share_gift_card.php'); $text = \Dsc\System::instance()->get('theme')->renderView('Shop/Views::emails_text/share_gift_card.php'); $subject = 'A gift card from ' . $data['sender_name']; $this->__sendEmailShareGiftCard = \Dsc\System::instance()->get('mailer')->send($data['recipient_email'], $subject, array($html, $text)); // Add the entry to the gift card's internal history log $this->history[] = array('created' => \Dsc\Mongo\Metastamp::getDate('now'), 'subject' => $data['sender_name'] . ' (' . $data['sender_email'] . ')', 'verb' => 'shared', 'object' => $data['recipient_name'] . ' (' . $data['recipient_email'] . ')'); return $this->save(); }