<?php if (!defined('HTTP_SERVER')) die('You can not access this file directly!');
/**
 *\licence GPL 2005-2011  The osCSS developers - osCSS Open Source E-commerce
 *\portion code Copyright (c) 2002 osCommerce
 *\package osCSS-2 <www http://www.oscss.org>
 *\version 2.1.0
 *\date  28/11/10, 22:44
 *\author oscim <mail aurelien@oscim.fr> <www http://www.oscim.fr>
 *\encode UTF-8
 *\file
 *\dir common/classes/
 *\class shoppingCart
*/

class shoppingCart {
  /**
  */
  var $contents;
  /**
    Total panier
    @a numeric
  */
  var $total;
  /**
    Poids du panier
    @a numeric
  */
  var $weight;
  /**
    ID du panier, unique
    @a int
  */
  var $cartID;
  /**
  */
  var $content_type;

  function shoppingCart() {
    $this->reset();
  }

  /**
    \brief Chargement dans les header de pages
  */
  public function get_header(){
    return false;
  }

  /**
  */
  private function calculate() {
    global $price;
    $this->total = 0;
    $this->weight = 0;
    $incart=$this->get_products();

    if (!is_array($incart)) return ;

    foreach($incart as $product) {
      $qty = $product['quantity'];
      $products_weight = $product['weight'];

      $this->total += tep_round($product['total_line_ttc'], $price->get_round(true));
      $this->weight += ($qty * $products_weight);

    }

    if(!isset($this->cartID )) $this->cartID = $this->generate_cart_id();
  }

  /**
  */
  public function cleanup() {
    reset($this->contents);
    while (list($key,) = each($this->contents)) {
      if (!isset($this->contents[$key]['qty']) ||$this->contents[$key]['qty'] < 1) {
	unset($this->contents[$key]);
	// remove from database
	if (tep_session_is_registered('customer_id')) {
	  tep_db_query("delete from " . TABLE_CUSTOMERS_BASKET . " where customers_id = '" . (int)$customer_id . "' and products_id = '" . tep_db_input($key) . "'");
	  tep_db_query("delete from " . TABLE_CUSTOMERS_BASKET_ATTRIBUTES . " where customers_id = '" . (int)$customer_id . "' and products_id = '" . tep_db_input($key) . "'");
	}
      }
    }
    $this->contents=array();
  }

  /**
  */
  private function generate_cart_id($length = 5) {
    return tep_create_random_value($length, 'digits');
  }



  /**
  */
  public function restore_contents() {
    global $customer_id;

    if (!tep_session_is_registered('customer_id')) return false;
    $DB=Database::getInstance();

    // insert current cart contents in database
    if (is_array($this->contents)) {
      reset($this->contents);
      while (list($products_id, ) = each($this->contents)) {
        $qty = $this->contents[$products_id]['qty'];
        $product_query = $DB->query($sql="select products_id from " . TABLE_CUSTOMERS_BASKET . " where customers_id = '" . (int)$customer_id . "' and products_id = '" . tep_db_input($products_id) . "'");

        if (!$product_query->__get('numRows')) {
          $DB->query("insert into " . TABLE_CUSTOMERS_BASKET . " (customers_id, products_id, customers_basket_quantity, customers_basket_date_added) values ('" . (int)$customer_id . "', '" . tep_db_input($products_id) . "', '" . $qty . "', '" . date('Ymd') . "')");
          if (isset($this->contents[$products_id]['attributes'])) {
            reset($this->contents[$products_id]['attributes']);
            while (list($option, $value) = each($this->contents[$products_id]['attributes'])) {
              $DB->query("insert into " . TABLE_CUSTOMERS_BASKET_ATTRIBUTES . " (customers_id, products_id, products_options_id, products_options_value_id) values ('" . (int)$customer_id . "', '" . tep_db_input($products_id) . "', '" . (int)$option . "', '" . (int)$value . "')");
            }
          }
        } else {
          $DB->query("update " . TABLE_CUSTOMERS_BASKET . " set customers_basket_quantity = '" . $qty . "' where customers_id = '" . (int)$customer_id . "' and products_id = '" . tep_db_input($products_id) . "'");
        }
      }
    }

    // reset per-session cart contents, but not the database contents
    $this->reset(false);

    $products_query = $DB->query("select products_id, customers_basket_quantity from " . TABLE_CUSTOMERS_BASKET . " where customers_id = '" . (int)$customer_id . "'");
    while ($products = $products_query->fetchAssoc()) {
      $this->contents[$products['products_id']] = array('qty' => $products['customers_basket_quantity']);
      // attributes
      $attributes_query = $DB->query("select products_options_id, products_options_value_id, products_options_value_text from " . TABLE_CUSTOMERS_BASKET_ATTRIBUTES . " where customers_id = '" . (int)$customer_id . "' and products_id = '" . tep_db_input($products['products_id']) . "'");
      while ($attributes = $attributes_query->fetchAssoc()) {
	if ($attributes['products_options_value_id'] == PRODUCTS_OPTIONS_VALUE_TEXT_ID)  $this->contents[$products['products_id']]['attributes'][$attributes['products_options_id']] = $attributes['products_options_value_text'];
        else $this->contents[$products['products_id']]['attributes'][$attributes['products_options_id']] = $attributes['products_options_value_id'];
      }
    }

    $this->cartID = $this->generate_cart_id();
  }


  function reset($reset_database = false) {
    global $customer_id;

    $this->contents = array();
    $this->total = 0;
    $this->weight = 0;
    $this->content_type = false;

    if (tep_session_is_registered('customer_id') && ($reset_database == true)) {
      tep_db_query("delete from " . TABLE_CUSTOMERS_BASKET . " where customers_id = '" . (int)$customer_id . "'");
      tep_db_query("delete from " . TABLE_CUSTOMERS_BASKET_ATTRIBUTES . " where customers_id = '" . (int)$customer_id . "'");
    }

    unset($this->cartID);
    if (tep_session_is_registered('cartID')) tep_session_unregister('cartID');
  }

  /**
    Add item

    @param $products_id \a string/int  19 || product Id vace option 19{1}1{3}10
    @param $qty \a int
    @param $attributes \a string
    @param $notify \a  boolean
    @param $special_class \a  string , permet d'ajouter element supplementaire , class de promo,
  */
  public function add_cart($products_id, $qty = '1', $attributes = '', $notify = true,$special_class='') {
    global $new_products_id_in_cart, $customer_id;

    $products_id_string = tep_get_uprid($products_id, $attributes);
    $products_id = tep_get_prid($products_id_string);

    if (is_numeric($products_id) && is_numeric($qty)) {
      $product_obj=product::get_item($products_id);

      if($product_obj !=false){
	if ($notify == true) {
	  $new_products_id_in_cart = $products_id;
	  tep_session_register('new_products_id_in_cart');
	}

	if ($this->in_cart($products_id_string)==true) {
 	  $this->update_quantity($products_id_string, $qty, $attributes);
	}
	else {
	  $this->contents[$products_id_string] = array('qty' => $qty);
	  if(!empty($special_class)) $this->contents[$products_id_string]['special_class'] = $special_class;
  // insert into database
	  if (tep_session_is_registered('customer_id')) tep_db_query("insert into " . TABLE_CUSTOMERS_BASKET . " (customers_id, products_id, customers_basket_quantity, customers_basket_date_added) values ('" . (int)$customer_id . "', '" . tep_db_input($products_id_string) . "', '" . $qty . "', '" . date('Ymd') . "')");
	  if (is_array($attributes)) {
	    reset($attributes);
	    while (list($option, $value) = each($attributes)) {
	      $attr_value = NULL;
	      $blank_value = FALSE;
	      if (strstr($option, TEXT_PREFIX)) {
		if (trim($value) == NULL) {
		  $blank_value = TRUE;
		} else {
		  $option = substr($option, strlen(TEXT_PREFIX));
		  $attr_value = htmlspecialchars(stripslashes($value), ENT_QUOTES);
		  $value = $_POST['Valueid'][$option];
		  $this->contents[$products_id_string]['attributes_values'][$option] = $attr_value;
		}
	      }

	      if (!$blank_value) {
              $this->contents[$products_id_string]['attributes'][$option] = $value;
  // insert into database
	      if (tep_session_is_registered('customer_id')) tep_db_query("insert into " . TABLE_CUSTOMERS_BASKET_ATTRIBUTES . " (customers_id, products_id, products_options_id, products_options_value_id,products_options_value_text) values ('" . (int)$customer_id . "', '" . tep_db_input($products_id_string) . "', '" . (int)$option . "', '" . (int)$value . "', '" . tep_db_input($attr_value) . "')");
	      }
	    }
	  }
	}
	// assign a temporary unique ID to the order contents to prevent hack attempts during the checkout procedure
	$this->cartID = $this->generate_cart_id();
      }

    }
  }

  /**
    \brief Mise a jour quantite one item
    @param $products_id 19 || product Id vace option 19{1}1{3}10 \a string/int
    @param $quantity int
    @param $attributes string
  */
  public function update_quantity($products_id, $quantity = '', $attributes = '') {
    global $customer_id;

    $products_id_string = tep_get_uprid($products_id, $attributes);
    $products_id = tep_get_prid($products_id_string);

    if (is_numeric($products_id) && isset($this->contents[$products_id_string]) && is_numeric($quantity)) {
      $this->contents[$products_id_string] = array('qty' => $quantity);
  // update database
      if (tep_session_is_registered('customer_id')) tep_db_query("update " . TABLE_CUSTOMERS_BASKET . " set customers_basket_quantity = '" . $quantity . "' where customers_id = '" . (int)$customer_id . "' and products_id = '" . tep_db_input($products_id_string) . "'");
      if (is_array($attributes)) {
	reset($attributes);
	while (list($option, $value) = each($attributes)) {
          $attr_value = NULL;
          $blank_value = FALSE;
          if (strstr($option, TEXT_PREFIX)) {
            if (trim($value) == NULL) {
              $blank_value = TRUE;
            } else {
              $option = substr($option, strlen(TEXT_PREFIX));
              $attr_value = htmlspecialchars(stripslashes($value), ENT_QUOTES);
              $value = (isset($_POST['Valueid'][$products_id_string][$option])? $_POST['Valueid'][$products_id_string][$option]:  $option); // PRODUCTS_OPTIONS_VALUE_TEXT_ID;
              $this->contents[$products_id_string]['attributes_values'][$option] = $attr_value;
            }
          }

          if (!$blank_value) {
            $this->contents[$products_id_string]['attributes'][$option] = $value;
  // update database
	    if (tep_session_is_registered('customer_id')) tep_db_query("update " . TABLE_CUSTOMERS_BASKET_ATTRIBUTES . " set products_options_value_id = '" . (int)$value . "', products_options_value_text = '" . tep_db_input($attr_value) . "' where customers_id = '" . (int)$customer_id . "' and products_id = '" . tep_db_input($products_id_string) . "' and products_options_id = '" . (int)$option . "'");
	  }
	}
      }
    }
  }



  /**
    \brief get total number of items in cart
  */
  public function count_contents() {
    $total_items = 0;
    if (is_array($this->contents)) {
      reset($this->contents);
      while (list($products_id, ) = each($this->contents))  $total_items += $this->get_quantity($products_id);
    }
    return $total_items;
  }

  /**
    Recup qty
    @param $products_id \a int
    @return numeric
  */
  public function get_quantity($products_id) {
    if (isset($this->contents[$products_id]))  return $this->contents[$products_id]['qty'];
    else return 0;
  }

  /**
    @param $products_id_string \a string/int
    @return boolean
  */
  public function in_cart($products_id_string) {
    if (isset($this->contents[$products_id_string]))  return true;
    else  return false;
  }

  /**
    @param $products_id int
    @return boolean
  */
  public function remove($products_id) {
      global $customer_id;

      unset($this->contents[$products_id]);
      if (tep_session_is_registered('customer_id')) {
        tep_db_query("delete from " . TABLE_CUSTOMERS_BASKET . " where customers_id = '" . (int)$customer_id . "' and products_id = '" . tep_db_input($products_id) . "'");
        tep_db_query("delete from " . TABLE_CUSTOMERS_BASKET_ATTRIBUTES . " where customers_id = '" . (int)$customer_id . "' and products_id = '" . tep_db_input($products_id) . "'");
      }

      // assign a temporary unique ID to the order contents to prevent hack attempts during the checkout procedure
      $this->cartID = $this->generate_cart_id();
      return true;
    }

    function remove_all() {
      $this->reset();
    }

  /**
   *
  */
  public function get_product_id_list() {
    $product_id_list = '';
    if (is_array($this->contents)) {
      reset($this->contents);
      while (list($products_id, ) = each($this->contents)) {
	$product_id_list .= ', ' . $products_id;
      }
    }

    return substr($product_id_list, 2);
  }


  /**
   * \fn get_products()
    \brief Boucle qui recupere les produist de $content
    Utilisé dans tous les recap panier/order/checkcout
  */
  function get_products() {
    global $languages_id,$price;
    if (!is_array($this->contents)) return false;
    $products_array = array();
    reset($this->contents);

    foreach($this->contents as $products_id=>$product){
      $pid = tep_get_prid($products_id);
      $product_obj=product::get_item($pid);

      if($product_obj !=false){
	$prid = $product_obj->products_id;

	$res_price=$price->get_products_price($products_id,(int)$product['qty']);
	$special=( ($res_price['price_ht'] !=$res_price['sprice_ht'] && $res_price['sprice_ht']>0)? true : false);

	$products_array[] = array('id' => $products_id,
				  'name' => $product_obj->products_name,
				  'model' => $product_obj->products_model,
				  'image' => $product_obj->products_image,
				  'track_stock' => $product_obj->track_stock,
				  'price' =>  (($special)? $res_price['sprice_ht'] :$res_price['price_ht']),
				  'quantity' => $product['qty'],
				  'weight' => $product_obj->products_weight +( isset($this->contents[$products_id]['attributes']) ?(float)product::get_attributes_weight($products_id, $this->contents[$products_id]['attributes']) : 0) ,
				  'final_price' => (($special)? $res_price['sprice_ht'] :$res_price['price_ht']),
				  'final_price_ttc' => (($special)? $res_price['sprice_ttc'] :$res_price['price_ttc']),
				  'total_line' => $res_price['total_line'],
				  'total_line_ttc' => $res_price['total_line_ttc'],
				  'tax_class_id' => $product_obj->products_tax_class_id,
				  'attributes' => (isset($this->contents[$products_id]['attributes']) ? $this->contents[$products_id]['attributes'] : ''),
				  'attributes_values' => (isset($this->contents[$products_id]['attributes_values']) ? $this->contents[$products_id]['attributes_values'] : ''),
				  'special_class'=> (isset($this->contents[$products_id]['special_class'])? $this->contents[$products_id]['special_class'] : ''),
				  );
      }
    }
    return $products_array;
  }


  /**
    \brief Renvoi du total panier
  */
  public function show_total() {
    $this->calculate();
    return $this->total;
  }

  /**
    \brief Renvoi du poids total du panier
  */
  public function show_weight() {
    $this->calculate();
    return $this->weight;
  }

  /**
  */
  public function get_content_type() {
    $this->content_type = 'physical';

    $array_content_type=array();

    if ($this->count_contents() > 0) {
      reset($this->contents);
      while (list($products_id, ) = each($this->contents)) {
	$virtual_products_result = tep_db_query("select * from ".TABLE_PRODUCTS_VIRTUAL." where productsID=".(int)$products_id);
	if (tep_db_num_rows($virtual_products_result) > 0) {
	  $res=tep_db_fetch_array($virtual_products_result);

	  $array_content_type[] = (in_array($res['typeID'], explode(';',TYPE_VIRTUAL_PRODUCTS)))? 'virtual' : 'physical';
	}
	else $array_content_type[] = 'physical';
      }
    }

    if(in_array('virtual',$array_content_type) && in_array('physical',$array_content_type)) $this->content_type =  'mixed';
    elseif(in_array('virtual',$array_content_type)) $this->content_type =  'virtual';

    if ( (_cst_bool('DOWNLOAD_ENABLED')) && ($this->count_contents() > 0) ) {
      reset($this->contents);
      while (list($products_id, ) = each($this->contents)) {
	if (isset($this->contents[$products_id]['attributes'])) {
	  reset($this->contents[$products_id]['attributes']);
	  while (list(, $value) = each($this->contents[$products_id]['attributes'])) {
	    $virtual_check_query = tep_db_query("select count(*) as total from " . TABLE_PRODUCTS_ATTRIBUTES . " pa, " . TABLE_PRODUCTS_ATTRIBUTES_DOWNLOAD . " pad where pa.products_id = '" . (int)$products_id . "' and pa.options_values_id = '" . (int)$value . "' and pa.products_attributes_id = pad.products_attributes_id");
	    $virtual_check = tep_db_fetch_array($virtual_check_query);

	    if ($virtual_check['total'] > 0) {
	      switch ($this->content_type) {
		case 'mixed':
		case 'physical':
		  $this->content_type = 'mixed';
		  break;
		default:
		 $this->content_type = 'virtual';
		break;
	      }
	    }
	  }
	}
      }
    }

    return $this->content_type;
  }

  /**
  */
  function unserialize($broken) {
    for(reset($broken);$kv=each($broken);) {
      $key=$kv['key'];
      if (isset($this->$key) && gettype($this->$key)!="user function")
      $this->$key=$kv['value'];
    }
  }


  /**
    \brief Inititalisation des moduel order_total
  */
  private function init_ot(){
    global $page,$cart,$languages_id;

    if( ($order_total_modules=$page->return_object('order_total_modules')) ===false){
      $order_total_modules = new order_total;
      $page->add_object('order_total_modules',$order_total_modules);
    }
    $this->otm=$order_total_modules;
  }

  /**
    \brief Init base module actif pour la page shopping_cart
    Report de l'entete de la page
    @return object
  */
  public function init_draw(){
    global $page,$cart,$languages_id;

    $this->init_ot();
    $res=$this->otm->_extents('init_draw');

    $this->DC = new objectInfo(array());
    $products=array();
    $any_out_of_stock = 0;
    $hidden='';

    if ($this->count_contents() > 0) {

      $products = $this->get_products();
      for ($i=0, $n=sizeof($products); $i<$n; $i++) {
	$pid = tep_get_prid($products[$i]['id']);
	// Push all attributes information in an array
	if (isset($products[$i]['attributes']) && is_array($products[$i]['attributes'])) {
	  while (list($option, $value) = each($products[$i]['attributes'])) {
	      $attributes = tep_db_query("select popt.products_options_name, poval.products_options_values_name, pa.options_values_price, pa.price_prefix, pa.products_options_values_url
					  from " . TABLE_PRODUCTS_OPTIONS . " popt, " . TABLE_PRODUCTS_OPTIONS_VALUES . " poval, " . TABLE_PRODUCTS_ATTRIBUTES . " pa
					  where pa.products_id = '" . $pid . "'
					  and pa.options_id = '" . $option . "'
					  and pa.options_id = popt.products_options_id
					  and pa.options_values_id = '" . $value . "'
					  and pa.options_values_id = poval.products_options_values_id
					  and popt.language_id = '" . $languages_id . "'
					  and poval.language_id = '" . $languages_id . "'");
	      $attributes_values = tep_db_fetch_array($attributes);

	    if(isset($products[$i]['attributes_values'][$option]) ) {
	    /* Specifique option type texte / file champ personnalisé par le client */
	      $hidden .=tep_draw_hidden_field('Valueid[' . $products[$i]['id'] . '][' . $option . ']', $value);
	      $hidden .=tep_draw_hidden_field('id[' . $products[$i]['id'] . '][' . TEXT_PREFIX . $option . ']',  $products[$i]['attributes_values'][$option]);
	      $products[$i][$option]['products_options_values_name'] = '('.$products[$i]['attributes_values'][$option].')';
	    } else{
	      $products[$i][$option]['products_options_values_name'] = $attributes_values['products_options_values_name'];
	      $hidden .=tep_draw_hidden_field('id[' . $products[$i]['id'] . '][' . $option . ']', $value);
	    }
	    $products[$i][$option]['options_values_id'] = $value;
	    $products[$i][$option]['products_options_name'] = $attributes_values['products_options_name'];
	    $products[$i][$option]['options_values_price'] = $attributes_values['options_values_price'];
	    $products[$i][$option]['price_prefix'] = $attributes_values['price_prefix'];
	    $products[$i][$option]['img_url'] = $attributes_values['products_options_values_url'];

	  }
	}

	$products[$i]['name'] = $products[$i]['name'] ;

	//! Stock check
	if( Stock::check_inline($products[$i]) ) {
	  $any_out_of_stock = 1;
	  $products[$i]['name']  .= Stock::mark_inline();
	}

	if (isset($products[$i]['attributes']) && is_array($products[$i]['attributes'])) {
	  reset($products[$i]['attributes']);
	  while (list($option, $value) = each($products[$i]['attributes'])) {
	    $products[$i]['name'] .= "<br />".'<span class="cartAttributes"> - ' . $products[$i][$option]['products_options_name'] . ' ' . $products[$i][$option]['products_options_values_name'] . '</span>';
	    if(tep_not_null($products[$i][$option]['img_url']))
	      $products[$i]['image'] = '<a class="tn" href="' . tep_href_link(FILENAME_PRODUCT_INFO, 'products_id=' . $products[$i]['id']) . '">' . tep_image(DIR_WS_IMAGES .  $products[$i][$option]['img_url'], $products[$i]['name'],  $page->_conf_value('SMALL_IMAGE_WIDTH'), $page->_conf_value('SMALL_IMAGE_HEIGHT')) . '</a>';
	  }
	}
	//! modification par les modules order total
	$products[$i]=$this->process_cart($products[$i]);
      }
    }
    $this->DC->products=$products;
    $this->DC->hidden=$hidden;
    $this->DC->any_out_of_stock=$any_out_of_stock;
    return $this->DC;
  }

  /**
    \brief Init base module actif pour la page shopping_cart
    Intervention boucle definiton des produits
  */
  private function process_cart($product){
    $this->init_ot();
    return $this->otm->process_cart('',$product);
  }

  /**
    \brief Init base module actif pour la page shopping_cart
  */
  public function draw_cart($product){
    $this->init_ot();
    return $this->otm->draw_cart('',$product);
  }

  /**
    \brief Init base module actif pour la page shopping_cart
  */
  public function show_list_total(){
    $list=array();
    $this->init_ot();

    $this->ListTotal = strip_tags($this->show_total());
    foreach($this->otm->_extents('show_list_total') as $k=>$mod){
      $list[]=$mod;
    }
    return $list;
  }


}
?>