Пример #1
0
	/**
	 * Matches a Promo Code rule to a code submitted from the shopping cart
	 * 
	 * @since 1.1
	 *
	 * @param array $rule The promo code rule
	 * @return boolean
	 **/
	function promocode ($rule) {
		extract($rule);
		$promocode = strtolower($value);

		// Match previously applied codes
		if (isset($this->Cart->promocodes[$promocode])
			&& is_array($this->Cart->promocodes[$promocode])) return true;

		// Match new codes

		// No code provided, nothing will match
		if (empty($this->Cart->promocode)) return false;

		$subject = strtolower($this->Cart->promocode);
		return Promotion::match_rule($subject,$logic,$promocode,$property);
	}
Пример #2
0
	/**
	 * Match a rule to the item
	 *	 
	 * @since 1.1
	 *
	 * @param array $rule A structured rule array
	 * @return boolean
	 **/
	function match ($rule) {
		extract($rule);

		switch($property) {
			case "Any item name": $subject = $this->name; break;
			case "Any item quantity": $subject = (int)$this->quantity; break;
			case "Any item amount": $subject = $this->total; break;

			case "Name": $subject = $this->name; break;
			case "Category": $subject = $this->categories; break;
			case "Tag name": $subject = $this->tags; break;
			case "Variation": $subject = $this->option->label; break;

			// case "Input name": $subject = $Item->option->label; break;
			// case "Input value": $subject = $Item->option->label; break;

			case "Quantity": $subject = $this->quantity; break;
			case "Unit price": $subject = $this->unitprice; break;
			case "Total price": $subject = $this->total; break;
			case "Discount amount": $subject = $this->discount; break;

		}
		return Promotion::match_rule($subject,$logic,$value,$property);
	}
 /**
  * promotions()
  * Matches, calculates and applies promotion discounts */
 function promotions()
 {
     global $Shopp;
     $db = DB::get();
     $limit = $Shopp->Settings->get('promo_limit');
     // Load promotions if they've not yet been loaded
     if (empty($this->data->Promotions)) {
         $promo_table = DatabaseObject::tablename(Promotion::$table);
         // Add date-based lookup too
         $this->data->Promotions = $db->query("SELECT * FROM {$promo_table} WHERE scope='Order' AND ((status='enabled' AND UNIX_TIMESTAMP(starts) > 0 AND UNIX_TIMESTAMP(starts) < UNIX_TIMESTAMP() AND UNIX_TIMESTAMP(ends) > UNIX_TIMESTAMP()) OR status='enabled')", AS_ARRAY);
     }
     $PromoCodeFound = false;
     $PromoCodeExists = false;
     $PromoLimit = false;
     $this->data->PromosApplied = array();
     foreach ($this->data->Promotions as &$promo) {
         if (!is_array($promo->rules)) {
             $promo->rules = unserialize($promo->rules);
         }
         // Add quantity rule automatically for buy x get y promos
         if ($promo->type == "Buy X Get Y Free") {
             $promo->search = "all";
             if ($promo->rules[count($promo->rules) - 1]['property'] != "Item quantity") {
                 $qtyrule = array('property' => 'Item quantity', 'logic' => "Is greater than", 'value' => $promo->buyqty);
                 $promo->rules[] = $qtyrule;
             }
         }
         $items = array();
         $match = false;
         $rulematches = 0;
         foreach ($promo->rules as $rule) {
             $rulematch = false;
             switch ($rule['property']) {
                 case "Item name":
                     foreach ($this->contents as $id => &$Item) {
                         if (Promotion::match_rule($Item->name, $rule['logic'], $rule['value'], $rule['property'])) {
                             $items[$id] =& $Item;
                             $rulematch = true;
                         }
                     }
                     break;
                 case "Item quantity":
                     foreach ($this->contents as $id => &$Item) {
                         if (Promotion::match_rule(number_format($Item->quantity, 0), $rule['logic'], $rule['value'], $rule['property'])) {
                             $items[$id] =& $Item;
                             $rulematch = true;
                         }
                     }
                     break;
                 case "Item amount":
                     foreach ($this->contents as $id => &$Item) {
                         if (Promotion::match_rule(number_format($Item->total, 2), $rule['logic'], $rule['value'], $rule['property'])) {
                             $items[$id] =& $Item;
                             $rulematch = true;
                         }
                     }
                     break;
                 case "Total quantity":
                     if (Promotion::match_rule(number_format($this->data->Totals->quantity, 0), $rule['logic'], $rule['value'], $rule['property'])) {
                         $rulematch = true;
                     }
                     break;
                 case "Shipping amount":
                     if (Promotion::match_rule(number_format($this->data->Totals->shipping, 2), $rule['logic'], $rule['value'], $rule['property'])) {
                         $rulematch = true;
                     }
                     break;
                 case "Subtotal amount":
                     if (Promotion::match_rule(number_format($this->data->Totals->subtotal, 2), $rule['logic'], $rule['value'], $rule['property'])) {
                         $rulematch = true;
                     }
                     break;
                 case "Promo code":
                     // Match previously applied codes
                     if (is_array($this->data->PromoCodes) && in_array($rule['value'], $this->data->PromoCodes)) {
                         $rulematch = true;
                         break;
                     }
                     // Match a new code
                     if (!empty($this->data->PromoCode)) {
                         if (Promotion::match_rule($this->data->PromoCode, $rule['logic'], $rule['value'], $rule['property'])) {
                             if (is_array($this->data->PromoCodes) && !in_array($this->data->PromoCode, $this->data->PromoCodes)) {
                                 $this->data->PromoCodes[] = $rule['value'];
                                 $PromoCodeFound = $rule['value'];
                             } else {
                                 $PromoCodeExists = true;
                             }
                             $this->data->PromoCode = false;
                             $rulematch = true;
                         }
                     }
                     break;
             }
             if ($rulematch && $promo->search == "all") {
                 $rulematches++;
             }
             if ($rulematch && $promo->search == "any") {
                 $match = true;
                 break;
                 // One matched, no need to match any more
             }
         }
         // end foreach ($promo->rules)
         if ($promo->search == "all" && $rulematches == count($promo->rules)) {
             $match = true;
         }
         // Everything matches up, apply the promotion
         if ($match && !$PromoLimit) {
             // echo "Matched $promo->name".BR;
             if (!empty($items)) {
                 $freeshipping = 0;
                 // Apply promo calculation to specific cart items
                 foreach ($items as $item) {
                     switch ($promo->type) {
                         case "Percentage Off":
                             $this->data->Totals->discount += $item->total * ($promo->discount / 100);
                             break;
                         case "Amount Off":
                             $this->data->Totals->discount += $promo->discount;
                             break;
                         case "Buy X Get Y Free":
                             $this->data->Totals->discount += floor($item->quantity / ($promo->buyqty + $promo->getqty)) * $item->unitprice;
                             break;
                         case "Free Shipping":
                             $freeshipping++;
                             break;
                     }
                 }
                 if ($freeshipping == count($this->contents) && $promo->scope == "Order") {
                     $this->freeshipping = true;
                 } else {
                     $this->freeshipping = false;
                 }
             } else {
                 // Apply promo calculation to entire order
                 switch ($promo->type) {
                     case "Percentage Off":
                         $this->data->Totals->discount += $this->data->Totals->subtotal * ($promo->discount / 100);
                         break;
                     case "Amount Off":
                         $this->data->Totals->discount += $promo->discount;
                         break;
                     case "Free Shipping":
                         $this->freeshipping = true;
                         break;
                 }
             }
             $this->data->PromosApplied[] = $promo;
             if ($limit > 0 && count($this->data->PromosApplied) + 1 > $limit) {
                 $PromoLimit = true;
                 break;
             }
         }
         if ($match && $promo->exclusive == "on") {
             break;
         }
     }
     // end foreach ($Promotions)
     // Promo code found, but ran into promotion limits
     if (!empty($this->data->PromoCode) && $PromoLimit) {
         $this->data->PromoCodeResult = __("No additional codes can be applied.", "Shopp");
         $this->data->PromoCodes = array_diff($this->data->PromoCodes, array($PromoCodeFound));
         $this->data->PromoCode = false;
     }
     // Promo code not found
     if (!empty($this->data->PromoCode) && !$PromoCodeFound && !$PromoCodeExists) {
         $this->data->PromoCodeResult = $this->data->PromoCode . ' ' . __("is not a valid code.", "Shopp");
         $this->data->PromoCodes = array_diff($this->data->PromoCodes, array($this->data->PromoCode));
         $this->data->PromoCode = false;
     }
 }