<?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  04/04/11, 09:32
  @author oscim <mail aurelien@oscim.fr> <www http://www.oscim.fr>
  @encode UTF-8
*/

/**
  @class products
  @brief master class for manage and edit products
*/
class products
    implements ExtModPage, InterfacedTJsonS, InterfacedInnerHtml{

  const FILENAME = FILENAME_PRODUCTS;

  /**
    @p string $code
  */
  public static $code;
  /**
    @p string $action
  */
  public static $action;
  /**
    @p array $modules
  */
  public static $list=array();
  /**
    @p array $modules
  */
  public static $modules;
  /**
    @p array $languages
  */
  public static $languages;
  /**
    @p objet $pInfo
  */
  public static $pInfo;
  /**
    @p array $tax_class_array
  */
  public static $tax_class_array;
  /**
    @p array $track_stock tableau gestion stock
  */
  public static $track_stock;

  /**
    @p bool $in_status
  */
  public static $in_status;
  /**
    @p bool $in_status
  */
  public static $out_status;
  /**
    @p array $product_investigation cf Qtpro
  */
  public static $product_investigation;
  /**
    @p array $DiversInfo transport var
  */
  public static $DiversInfo;
  /**
    @p array $actions
  */
  public static $actions;
  /**
    @p obj $box
  */
  public static $box;


  public static $cPath;
  public static $Vtype;

  public function  __construct(){
    self::GetConf();
  }

  /**
    @brief Load , adjust and define var environement exe for module
	Is use in module and class abstract for init value config this module
  */
  public static function GetConf(){
    global $languages_id;

    self::$code=__CLASS__;

    self::$action=(isset($_REQUEST['action'])? $_REQUEST['action'] : 'listing' );
    self::$cPath=(isset($_GET['cPath'])? (int)$_GET['cPath'] : 0);
    self::$Vtype=(isset($_GET['Vtype'])? (int)$_GET['Vtype'] : '');


    /**
      @remarks not load if not first init
    */
    if(defined('JSONSTATMENT')) return;


    //! active datatable in ajax, precise les GET necessaire
    if(!defined('JSONSTATMENT')) define('JSONSTATMENT', 'mod=page&type='.self::$code.(isset($_GET['expected'])?'&expected=true':'').(isset($_GET['cPath'])?'&cPath='.$_GET['cPath']:'').(isset($_GET['Vtype'])?'&Vtype='.$_GET['Vtype']:''));
    //! detail item in ajax
    if(!defined('AJAXSTATMENTDETAIL')) define('AJAXSTATMENTDETAIL', 'mod=page&type='.self::$code);



    self::$modules=new productsACA;
    self::$modules->set_image_handler();

    // check if the catalog image directory exists
    global $messageStack;
    if (is_dir(DIR_FS_CATALOG_IMAGES)) {
      if (!is_writeable(DIR_FS_CATALOG_IMAGES)) $messageStack->add(__('error catalog image directory not writeable'), 'error');
    }
    else  $messageStack->add(__('error catalog image directory does not exist'), 'error');

    self::$languages = tep_get_languages();
  }


/** public static ExtModPage */

  public function check_action($actionss){
    global $languages_id,$messageStack;

    self::$action=$actionss;
    $DB=Database::getInstance();

    // begin Extra Product Fields
      $epf_query = $DB->query("select e.epf_id, e.epf_uses_value_list, e.epf_show_parent_chain, e.epf_size, l.epf_label, l.languages_id, l.epf_active_for_language from " . TABLE_PRODUCTS_EXTRA_FIELDS . " e join " . TABLE_PRODUCTS_EXTRA_FIELDS_LABELS . " l where e.epf_status and (e.epf_id = l.epf_id) order by e.epf_order");
      $epf = array();
      $xfields = array();
      while ($e = tep_db_fetch_array($epf_query)) {  // retrieve all active extra fields for all languages
	$field = 'extra_value' . ($e['epf_uses_value_list'] ? '_id' : '') . $e['epf_id'];
	$epf[] = array('id' => $e['epf_id'],
		      'label' => $e['epf_label'],
		      'uses_list' => $e['epf_uses_value_list'],
		      'show_chain' => $e['epf_show_parent_chain'],
		      'size' => $e['epf_size'],
		      'language' => $e['languages_id'],
		      'language_active' => $e['epf_active_for_language'],
		      'field' => $field);
	if (!in_array( $field, $xfields))
	  $xfields[] = $field; // build list of distinct fields
      }
    // end Extra Product Fields


    self::$actions['action'] = self::$action;
    self::$actions['display_file']='';
    self::$actions['action_class']=(isset($_GET['action_class']))? $_GET['action_class'] : '';
    self::$actions['action_method']=(isset($_GET['action_method']))? $_GET['action_method'] : '';

  // Ask categories modules if want to change the action
    self::$actions = self::$modules->check_action(self::$actions);
    self::$action = self::$actions['action'];


    self::$DiversInfo['current_category_id']=((isset($_GET['cPath'])&& !empty($_GET['cPath']))  ? tep_db_prepare_input($_GET['cPath']) :  0);

    // added qtpro
    self::$product_investigation = qtpro_doctor_investigate_product(@$_GET['pID']);

    if ( empty(self::$actions['action_class']) ) {

    if ( preg_match("/(insert|update|setflag)/i", self::$action) ) tep_reset_cache_data_seo_urls('reset');

      switch (self::$action) {
	case 'setflag':
	  if ( ($_GET['flag'] == '0') || ($_GET['flag'] == '1') ) {
	    if (isset($_GET['pID']))  tep_set_product_status($_GET['pID'], $_GET['flag']);
	    osCSS_Cache::clear('also_purchased');
	  }

	  tep_redirect(tep_href_link(self::FILENAME, tep_get_all_get_params(array('action','cPath','pID','setflag','flag'), false) ));
	break;

	case 'delete_product_confirm':
	  if (isset($_POST['products_id']) && isset($_POST['product_categories']) && is_array($_POST['product_categories'])) {
	    $product_id = tep_db_prepare_input($_POST['products_id']);
	    $product_categories = $_POST['product_categories'];

	    for ($i=0, $n=sizeof($product_categories); $i<$n; $i++) {
	      $DB->query("delete from " . TABLE_PRODUCTS_TO_CATEGORIES . " where products_id = '" . (int)$product_id . "' and categories_id = '" . (int)$product_categories[$i] . "'");
	    }

	    $product_categories_query = $DB->query("select count(*) as total from " . TABLE_PRODUCTS_TO_CATEGORIES . " where products_id = '" . (int)$product_id . "'");
	    $product_categories = tep_db_fetch_array($product_categories_query);

	    if ($product_categories['total'] == '0') {
	      tep_remove_product($product_id);
	      $DB->query("delete from " . TABLE_PRODUCTS_VIRTUAL . " where productsID = '" . (int)$product_id . "'");
	    }
	  }

	  osCSS_Cache::clear('categoriesBox');
	  osCSS_Cache::clear('category_tree');
	  osCSS_Cache::clear('also_purchased');

// 	  tep_redirect(tep_href_link(self::FILENAME));
	break;

	case 'insert_product_base':
	  $typeID = (int)tep_db_prepare_input($_POST['products_virtual_type_id']);

	  $sql_data_array = array('products_quantity' =>  0,
			  'products_price' => 0,
			  'products_date_added' => 'now()',
			  'manufacturers_id' =>  '',
			  'track_stock' =>  ( ($typeID == 1) ? 1 : 0 )
			    );
	  $resobj=tep_db_perform(TABLE_PRODUCTS, $sql_data_array);
	  $products_id = tep_db_insert_id($resobj);



	  if ($typeID == 1) // being changed to Physical, so delete it from the Virtual Products table
	    $DB->query("delete from " . TABLE_PRODUCTS_VIRTUAL . " where productsID = '" . (int)$products_id . "'");
	  else // update by replacement
	    $DB->query("replace into " . TABLE_PRODUCTS_VIRTUAL . "(productsID, typeID) values ('" . (int)$products_id . "', '" . $typeID . "')");

	  $DB->query("insert into " . TABLE_PRODUCTS_TO_CATEGORIES . " (products_id, categories_id) values ('" . (int)$products_id . "', '".ORPHELIN_COLLECTOR."')");


	  for ($i=0, $n=sizeof(self::$languages); $i<$n; $i++) {
	    $language_id = self::$languages[$i]['id'];

	    $sql_data_array = array('products_name' => '','products_id' => $products_id, 'language_id' => $language_id);
	    tep_db_perform(TABLE_PRODUCTS_DESCRIPTION, $sql_data_array);
	  }

	  tep_redirect(tep_href_link(self::FILENAME, tep_get_all_get_params(array('action','cPath','pID'),false).'pID=' . $products_id.'&action=new_product'));
	break;


	case 'insert_product':
	case 'update_product':
	  if (isset($_GET['pID'])) $products_id = tep_db_prepare_input($_GET['pID']);
	  $products_date_available = (isset($_POST['products_date_available'])) ? tep_db_prepare_input($_POST['products_date_available']) : '';
	  $products_date_available = (date('Y-m-d') < tep_date_raw($products_date_available)) ? tep_date_raw($products_date_available) : 'null';

	  $sql_data_array = array('products_quantity' => (isset($_POST['products_quantity']) ?tep_db_prepare_input($_POST['products_quantity']) : 0),
				  'products_model' =>  (isset($_POST['products_model'])?tep_db_prepare_input($_POST['products_model']) : ''),
				  'products_price' => tep_db_prepare_input($_POST['products_price']),
				  'products_date_available' => $products_date_available,
				  'products_weight' =>  (isset($_POST['products_weight'])? tep_db_prepare_input($_POST['products_weight']) : 0) ,
				  'products_status' => tep_db_prepare_input($_POST['products_status']),
				  'products_tax_class_id' => tep_db_prepare_input($_POST['products_tax_class_id']),
				  'manufacturers_id' => (isset($_POST['manufacturers_id']) ?tep_db_prepare_input($_POST['manufacturers_id']) : ''),
				  'track_stock' => (isset($_POST['track_stock']) ? tep_db_prepare_input($_POST['track_stock']) :  ((self::$modules->type_flag==1 ) ? 1 : 0) ),
				  'products_ordered' => (isset($_POST['products_ordered']) ? tep_db_prepare_input($_POST['products_ordered']) :  '0' )
				    );

	  //! added qtpro
	  if(self::$product_investigation['has_tracked_options'] or self::$product_investigation['stock_entries_count'] > 0){
	  //Do not modify the stock from this page if the product has database entries or has tracked options
	  unset($sql_data_array['products_quantity']);
	  }

	  if (isset($_POST['products_image']) && tep_not_null($_POST['products_image']) && ($_POST['products_image'] != 'none')){
	    if( substr($_POST['products_image'], 0,strlen( DIR_WS_CATALOG_IMAGES)) ==DIR_WS_CATALOG_IMAGES )
	      $sql_data_array['products_image'] = tep_db_prepare_input(substr($_POST['products_image'], strlen( DIR_WS_CATALOG_IMAGES)  ) );
	    else
	      $sql_data_array['products_image'] = tep_db_prepare_input($_POST['products_image']);
	  }



	  if (self::$action == 'insert_product') {
	    // ACA START INSERT PRODUCT TABLE
	    self::$modules->load_post_values($_POST);
	    $sql_data_array = array_merge($sql_data_array, self::$modules->get_insert_table_products ());

	    tep_db_perform(TABLE_PRODUCTS, $sql_data_array);
	  } elseif (self::$action == 'update_product') {
	    $sql_data_array['products_last_modified'] ='now()';
	    // ACA START UPDATE PRODUCT TABLE
	    self::$modules->load_post_values($_POST);
	    $sql_data_array = array_merge($sql_data_array, self::$modules->get_update_table_products ());

	    tep_db_perform(TABLE_PRODUCTS, $sql_data_array, 'update', "products_id = '" . (int)$products_id . "'");
	  }

	    $DB->query("delete from " . TABLE_PRODUCTS_TO_CATEGORIES . " where products_id='" . (int)$products_id . "' ");
	    if(!isset($_POST['categories']) || !is_array($_POST['categories'])) $DB->query("insert into " . TABLE_PRODUCTS_TO_CATEGORIES . " (products_id, categories_id) values ('" . (int)$products_id . "', '1')");
	    else
	    foreach($_POST['categories'] as $value)
	      $DB->query("insert into " . TABLE_PRODUCTS_TO_CATEGORIES . " (products_id, categories_id) values ('" . (int)$products_id . "', '" . (int)$value. "')");

	    // BOF Separate Pricing Per Customer
	    $customers_group_query = $DB->query("select customers_group_id, customers_group_name from " . TABLE_CUSTOMERS_GROUPS . " where customers_group_id != '0' order by customers_group_id");
	    while ($customers_group = tep_db_fetch_array($customers_group_query)) // Gets all of the customers groups
	      {
	      $attributes_query = $DB->query("select customers_group_price from " . TABLE_PRODUCTS_GROUPS . " where products_id = '" . $products_id . "' and customers_group_id = '" . $customers_group['customers_group_id'] . "'");
	      $attributes = tep_db_fetch_array($attributes_query);

	      if (tep_db_num_rows($attributes_query) > 0) {
		if (isset($_POST['sppcoption'][$customers_group['customers_group_id']]) && isset($_POST['sppcprice'][$customers_group['customers_group_id']]) && $_POST['sppcprice'][$customers_group['customers_group_id']]!= '') { // this is checking if the check box is checked and the price is not null
		  if ( $_POST['sppcprice'][$customers_group['customers_group_id']] != $attributes['customers_group_price'])
		    $DB->query("update " . TABLE_PRODUCTS_GROUPS . " set customers_group_price = '" . $_POST['sppcprice'][$customers_group['customers_group_id']] . "' where customers_group_id = '" . $customers_group['customers_group_id'] . "' and products_id = '" . $products_id . "'");
		}
		else
		  $DB->query("delete from " . TABLE_PRODUCTS_GROUPS . " where customers_group_id = '" . $customers_group['customers_group_id'] . "' and products_id = '" . $products_id . "'");
	      }
	      elseif (isset($_POST['sppcoption'][$customers_group['customers_group_id']]) && isset($_POST['sppcprice'][$customers_group['customers_group_id']]) && $_POST['sppcprice'][$customers_group['customers_group_id']] != '')
		$DB->query("insert into " . TABLE_PRODUCTS_GROUPS . " (products_id, customers_group_id, customers_group_price) values ('" . $products_id . "', '" . $customers_group['customers_group_id'] . "', '" . $_POST['sppcprice'][$customers_group['customers_group_id']] . "')");
	    }
	    // EOF Separate Pricing Per Customer


	  for ($i=0, $n=sizeof(self::$languages); $i<$n; $i++) {
	    $language_id = self::$languages[$i]['id'];

	    $sql_data_array = array('products_name' => tep_db_prepare_input($_POST['products_name'][$language_id]) );

	    if (self::$action == 'insert_product') {
	      $insert_sql_data = array('products_id' => $products_id, 'language_id' => $language_id);

	      $sql_data_array = array_merge($sql_data_array, $insert_sql_data);
	      // ACA START INSERT IN PRODUCT_DESCRIPTION TABLE
	      $sql_data_array = array_merge($sql_data_array, self::$modules->get_insert_table_products_description ($language_id));

	      tep_db_perform(TABLE_PRODUCTS_DESCRIPTION, $sql_data_array);
	    } elseif (self::$action == 'update_product') {
	      // ACA START UPDATE PRODUCT_DESCRIPTION TABLE
	      $sql_data_array = array_merge($sql_data_array, self::$modules->get_update_table_products_description ($language_id));
	      tep_db_perform(TABLE_PRODUCTS_DESCRIPTION, $sql_data_array, 'update', "products_id = '" . (int)$products_id . "' and language_id = '" . (int)$language_id . "'");
	    }
	  }

	  self::$modules->after_update ($products_id);

	  osCSS_Cache::clear('categoriesBox');
	  osCSS_Cache::clear('category_tree');
	  osCSS_Cache::clear('also_purchased');

	  if(isset($_POST['up_and_close']) ) tep_redirect(tep_href_link(self::FILENAME, 'pID=' . $products_id));
	  else tep_redirect(tep_href_link(self::FILENAME, 'pID=' . $products_id.'&action=new_product' ));

	break;
	case 'copy_to_confirm':
	  if (isset($_POST['products_id']) && isset($_POST['categories_id'])) {
	    $products_id = tep_db_prepare_input($_POST['products_id']);
	    $categories_id = tep_db_prepare_input($_POST['categories_id']);

	    if ($_POST['copy_as'] == 'link') {
	      if ($categories_id != self::$DiversInfo['current_category_id']) {
		$check_query = $DB->query("select count(*) as total from " . TABLE_PRODUCTS_TO_CATEGORIES . " where products_id = '" . (int)$products_id . "' and categories_id = '" . (int)$categories_id . "'");
		$check = $check_query->fetchAssoc();
		if ($check['total'] < '1') {
		  $DB->query("insert into " . TABLE_PRODUCTS_TO_CATEGORIES . " (products_id, categories_id) values ('" . (int)$products_id . "', '" . (int)$categories_id . "')");
		}
	      } else {
		$messageStack->add_session(ERROR_CANNOT_LINK_TO_SAME_CATEGORY, 'error');
	      }
	    } elseif ($_POST['copy_as'] == 'duplicate') {
	      $qu=$DB->query("SELECT typeID FROM " . TABLE_PRODUCTS_VIRTUAL . " WHERE productsID='".$products_id."' ");
	      if(tep_db_num_rows($qu)){
		$virt=$qu->fetchAssoc();
		$typeID=$virt['typeID'];
	      }
	      else $typeID=false;

	      $product_query = $DB->query("select products_quantity, products_model, products_image, products_price, products_date_available, products_weight, products_tax_class_id, manufacturers_id from " . TABLE_PRODUCTS . " where products_id = '" . (int)$products_id . "'");
	      $product = $product_query->fetchAssoc();

	      $resobj=$DB->query("insert into " . TABLE_PRODUCTS . " (products_quantity, products_model,products_image, products_price, products_date_added, products_date_available, products_weight, products_status, products_tax_class_id, manufacturers_id) values ('" . tep_db_input($product['products_quantity']) . "', '" . tep_db_input($product['products_model']) . "', '" . tep_db_input($product['products_image']) . "', '" . tep_db_input($product['products_price']) . "',  now(), " . (empty($product['products_date_available']) ? "null" : "'" . tep_db_input($product['products_date_available']) . "'") . ", '" . tep_db_input($product['products_weight']) . "', '0', '" . (int)$product['products_tax_class_id'] . "', '" . (int)$product['manufacturers_id'] . "')");

	      $dup_products_id = tep_db_insert_id($resobj);

	      if($typeID !=false)
		$DB->query("insert into " . TABLE_PRODUCTS_VIRTUAL . "(productsID, typeID) values ('" . (int)$dup_products_id . "', '" . (int)$typeID . "')");

	      $description_query = $DB->query("select language_id, products_name, products_description, products_url from " . TABLE_PRODUCTS_DESCRIPTION . " where products_id = '" . (int)$products_id . "'");
	      while ($description =$description_query->fetchAssoc()) {
		$DB->query("insert into " . TABLE_PRODUCTS_DESCRIPTION . " (products_id, language_id, products_name, products_description, products_url, products_viewed) values ('" . (int)$dup_products_id . "', '" . (int)$description['language_id'] . "', '" . tep_db_input($description['products_name']) . "', '" . tep_db_input($description['products_description']) . "', '" . tep_db_input($description['products_url']) . "', '0')");
	      }

	      $DB->query("insert into " . TABLE_PRODUCTS_TO_CATEGORIES . " (products_id, categories_id) values ('" . (int)$dup_products_id . "', '" . (int)$categories_id . "')");

	      // BOF Separate Pricing Per Customer
	      $cg_price_query = $DB->query("select customers_group_id, customers_group_price from " . TABLE_PRODUCTS_GROUPS . " where products_id = '" . $products_id . "' order by customers_group_id");

	      // insert customer group prices in table products_groups when there are any for the copied product
	      if ($cg_price_query->__get('numRows') > 0) {
		while ( $cg_prices = $cg_price_query->fetchAssoc()) {
		  $DB->query("insert into " . TABLE_PRODUCTS_GROUPS . " (customers_group_id, customers_group_price, products_id) values ('" . (int)$cg_prices['customers_group_id'] . "', '" . tep_db_input($cg_prices['customers_group_price']) . "', '" . (int)$dup_products_id . "')");
		}
	      }

	      // ACA START DUPLICATE PRODUCT
	      self::$modules->duplicate_product($products_id,$dup_products_id);


	      $products_id = $dup_products_id;
	    }

	    osCSS_Cache::clear('also_purchased');

	  }

	  tep_redirect(tep_href_link(self::FILENAME, 'cPath=' . $categories_id . '&pID=' . $products_id));
	break;
	case 'new':
	  self::$DiversInfo['products_virtual_typeID'] = 1; // default, "Physical"
	break;
	case 'edit':
	case 'new_product':
	  $parameters = array('products_name' => '',
			      'products_description' => '',
			      'products_url' => '',
			      'products_id' => '',
			      'products_quantity' => '',
			      'products_model' => '',
			      'products_image' => '',
			      'products_price' => '',
			      'products_weight' => '',
			      'products_date_added' => '',
			      'products_last_modified' => '',
			      'products_date_available' => '',
			      'products_status' => '',
			      'products_tax_class_id' => '',
			      'manufacturers_id' => '',
			      'products_ordered' => ''
			      );

	  self::$pInfo = new objectInfo($parameters);

	  if (isset ($_GET['pID']) && (!$_POST) ) self::load_db_values($_GET['pID']);

	  self::$tax_class_array = array(array('id' => '0', 'text' => TEXT_NONE));
	  $tax_class_query = $DB->query("select tax_class_id, tax_class_title from " . TABLE_TAX_CLASS . " order by tax_class_title");
	  while ($tax_class = tep_db_fetch_array($tax_class_query)) {
	    self::$tax_class_array[] = array('id' => $tax_class['tax_class_id'],'text' => $tax_class['tax_class_title']);
	  }



	  if (!isset(self::$pInfo->products_status)) self::$pInfo->products_status = '1';
	  switch (self::$pInfo->products_status) {
	    case '0': self::$in_status = false; self::$out_status = true; break;
	    case '1':
	    default: self::$in_status = true; self::$out_status = false;
	  }

	  self::$track_stock = array(
				    array('id'=>0, 'text'=>__('pas de suivi de stock') ),
				    array('id'=>1, 'text'=>__('en stock') ),
				    array('id'=>2, 'text'=>__('hors stock') )
				    );


	  // ACA START LOAD VALUES FROM DB
	  self::$modules->load_db_values ($_GET['pID']);

	  break;

	default:


	  //! entretient
	  $DB->query("update " . TABLE_PRODUCTS . " set products_date_available = '' where to_days(now()) > to_days(products_date_available)");

	  //! Entretient liens avec  description
	    $product_query = $DB->query("SELECT  p.products_id FROM " . TABLE_PRODUCTS . " p LEFT OUTER JOIN  " . TABLE_PRODUCTS_DESCRIPTION . " pd ON p.products_id =pd.products_id  WHERE  pd.products_id is null");
	    while ($product = tep_db_fetch_array($product_query)){
	      $DB->query("insert into " . TABLE_PRODUCTS_DESCRIPTION . " (products_id,language_id) values ('" . (int)$product['products_id'] . "','".(int)$languages_id."')");
	    }

	   //! Entretient liens avec  categorie
	  self::UpdateOrphelin();
      }


    } else {
      /**
	A module has asked to privately take care of this action, check if class and method exist and run it.
      */
	if (!empty(self::$actions['action_method']) && method_exists(self::$modules->modules[self::$actions['action_class']],self::$actions['action_method'] )){
	  $metho=self::$actions['action_method'];
	  self::$box = new box;
	  self::$box=self::$modules->modules[self::$actions['action_class']]->$metho(self::$box,(int)$_GET['pID']);
	}
    }


  }
  public function get_header(){
    ?>
    <script type="text/javascript"><!--
    /* Appel des pages, et execution de commande*/
    function get_ajax(id,vars,lib){
      var ter = document.getElementById(id);
      ter.innerHTML = '<p style="text-align:center"><img src="<?php echo DIR_WS_IMAGES ?>loading.gif"/></p>';
      $.ajax({
	type: "GET",
	url: lib,
	data: "<?php echo tep_session_name().'='.tep_session_id() ?>&" + vars,
	success: function(msg){
	  ter.innerHTML = msg;
	}
      });
      return false;
    }
    $(function() {
      $("a.fancyajax.manufacturers").fancybox({
	'overlayOpacity': 0.6,
	'callbackOnClose': function() {
	  get_ajax('manufacturers_id','forceajax=true&exe=in_manufacturers&param=<?php echo  self::$pInfo->manufacturers_id ?>&lib=lib.categories','ajax.php');
	}
      });
      $("a.fancyajax.stock").fancybox({
	'overlayOpacity': 0.6,
	'callbackOnClose': function() {
	  get_ajax('manufacturers_id','forceajax=true&exe=in_manufacturers&param=<?php echo  self::$pInfo->manufacturers_id ?>&lib=lib.categories','ajax.php');
	}
      });
      $("a.fancyajax").fancybox({
	'overlayOpacity': 0.6,
	'callbackOnClose': function() {
	  get_ajax('manufacturers_id','forceajax=true&exe=in_manufacturers&param=<?php echo  self::$pInfo->manufacturers_id ?>&lib=lib.categories','ajax.php');
	}
      });
    });
    // --></script>

    <?php if (self::$action == 'new_product'): ?>
    <script type="text/javascript"><!--
    function disabled_input(inputs){ $(inputs).attr('disabled', 'disabled'); }

    function activ_input(inputs){ $(inputs).removeAttr('disabled'); }

    $(function() {
      $.datepicker.setDefaults($.extend({
	duration: '',
	changeMonth: true,
	changeYear: true,
	showOn: 'button',
	buttonImage: '<?php echo DIR_WS_ICONS . 'calendar.gif';?>',
	buttonImageOnly: true
      }
      <?php if (($lng=language::LangueSelected())&&  $lng != 'en') echo ",\n"."$.datepicker.regional['".$lng."']"."\n";  ?>
      ));
      $('#bt_products_date_available').datepicker({altField: '#products_date_available'});

    });

    var tax_rates = new Array();
    <?php
    for ($i=0, $n=sizeof(self::$tax_class_array); $i<$n; $i++) {
      if (self::$tax_class_array[$i]['id'] > 0)  echo 'tax_rates["' . self::$tax_class_array[$i]['id'] . '"] = ' . tep_get_tax_rate_value(self::$tax_class_array[$i]['id']) . ';' . "\n";
    }
    ?>
    function doRound(x, places) { return Math.round(x * Math.pow(10, places)) / Math.pow(10, places); }

    function getTaxRate() {
      var selected_value = document.forms["new_product"].products_tax_class_id.selectedIndex;
      var parameterVal = document.forms["new_product"].products_tax_class_id[selected_value].value;

      if ( (parameterVal > 0) && (tax_rates[parameterVal] > 0) ) { return tax_rates[parameterVal]; }
      else { return 0; }
    }

    function updateGross() {
      var taxRate = getTaxRate();
      var grossValue = document.forms["new_product"].products_price.value;

      if (taxRate > 0) { grossValue = grossValue * ((taxRate / 100) + 1); }

      document.forms["new_product"].products_price_gross.value = doRound(grossValue, 6);
      document.forms["new_product"].products_price_final.value = doRound(grossValue, 6);
    }

    function updateNet() {
      var taxRate = getTaxRate();

      var netValue = document.forms["new_product"].products_price_gross.value;
      document.forms["new_product"].products_price_final.value = doRound(netValue, 6);

      if (taxRate > 0) { netValue = netValue / ((taxRate / 100) + 1); }

      document.forms["new_product"].products_price.value = doRound(netValue, 6);
    }

    //--></script>
    <?php /** aca */     self::$modules->get_header_js('new_product');  ?>
    <?php endif;

  }


  public static function load_db_values($ID){
    global $languages_id;
    $DB=Database::getInstance();

    $product_query = $DB->query("select pd.products_name, pd.products_description, pd.products_url, p.products_id, p.products_quantity, p.products_model, p.products_image, p.products_price, p.products_weight, p.track_stock,  p.products_date_added, p.products_last_modified,  products_date_available, p.products_status, p.products_tax_class_id, p.manufacturers_id,p.products_ordered from " . TABLE_PRODUCTS . " p, " . TABLE_PRODUCTS_DESCRIPTION . " pd where p.products_id = '" . (int)$ID . "' and p.products_id = pd.products_id and pd.language_id = '" . (int)$languages_id . "'");
    $product = tep_db_fetch_array($product_query);
    tep_db_free_result($product_query);

    $cat_query = $DB->query("select categories_id  from " . TABLE_PRODUCTS_TO_CATEGORIES . " where products_id='" . (int)$ID . "' ");
    while($cat_l = tep_db_fetch_array($cat_query)){ $cat_list[$cat_l['categories_id']]=$cat_l; }
    $product['categories']=$cat_list;
    tep_db_free_result($cat_query);

    $sql = "select * from ".TABLE_PRODUCTS_VIRTUAL." where productsID=".(int)$ID;
    $result = $DB->query($sql);
    if (tep_db_num_rows($result) > 0) { // this product is in the virtual table
      $virtual = tep_db_fetch_array($result);
      $product['products_virtual_typeID']= $virtual['typeID'];
    }
    else $product['products_virtual_typeID']= 1;
    tep_db_free_result($result);

    $product['products_date_available']=(tep_not_null($product['products_date_available'])? tep_date_short($product['products_date_available']) : '');

    // <!-- BOF Separate Pricing Per Customer -->
    $customers_group_query = $DB->query("select customers_group_id, customers_group_name from " . TABLE_CUSTOMERS_GROUPS . " where customers_group_id != '0' order by customers_group_id");
    while ($customers_group = tep_db_fetch_array($customers_group_query)) {
      $attributes_query = $DB->query("select customers_group_price from " . TABLE_PRODUCTS_GROUPS . " where products_id = '" . self::$pInfo->products_id . "' and customers_group_id = '" . $customers_group['customers_group_id']. "'");
      $attributes = tep_db_fetch_array($attributes_query);
      if (!isset($attributes['customers_group_price'])) $attributes['customers_group_price'] = '';

      $product['products_sppc'][$customers_group['customers_group_id']] = array('sppcname' => $customers_group['customers_group_name'], 'sppcprice' => $attributes['customers_group_price']);
    }
    //<!-- EOF Separate Pricing Per Customer -->

    self::$pInfo=new objectInfo($product);

    //! descative gestion de stock, si stock composé avec attributes
    $attributes_stock_query = $DB->query("SELECT products_stock_quantity FROM " . TABLE_PRODUCTS_STOCK . " WHERE  products_id = '" . (int)$ID . "'");
    if($attributes_stock_query->__get('numRows')>0 && !defined('CLASS_STOCK')) define('CLASS_STOCK',true);
  }

  /**
  */
  public function display_view() {
    $action=self::$action;

    switch(self::$action){
      case 'new':
	$action='delete';
      break;
      case 'delete_product':
	self::load_db_values($_GET['pID']);
	$action='delete';
      break;
      case 'edit':
      case 'new_product':
	$action='edit';
      case 'copy_to':
	self::load_db_values($_GET['pID']);
      break;
      default:

      if(!empty(self::$actions['action_method']) )
	$action='aca_actions';
      else {
	self::tep_get_list();
	$action='listing';
      }
    }
    /// use master gabarit
    return MGabCont::CallGab($action,__FUNCTION__,__CLASS__);
  }

/** public static InterfacedTJsonS */

  /**
    @fn get_item_action($products)
    @brief fonction qui construit l'affichage de la colonne action
      La mise en forme est contenu dans les ressource xml du template en cours
    @param $products array
    @return string
  */
  private static function get_item_action($products){
    return  sprintf(
		  CsrtAction::getFormat('row_action'),
		  self::$modules->display_ColumnRowAction($products['products_id']) ,
		  sprintf(CsrtAction::getLink('row_action_right', IMAGE_COPY_TO, 'copyto'), 'fancy',  tep_href_link(self::FILENAME, 'pID=' . $products['products_id'] . '&amp;action=copy_to') ,'' ).
		  sprintf(CsrtAction::getLink('row_action_right', IMAGE_EDIT, 'edit'), '',  tep_href_link(self::FILENAME,  'pID=' . $products['products_id'] . '&amp;action=new_product') ,'' ).
		  sprintf(CsrtAction::getLink('row_action_right', IMAGE_DELETE, 'delete'), 'fancy',  tep_href_link(self::FILENAME,  'pID=' . $products['products_id'] . '&amp;action=delete_product') ,'' ).
		  sprintf(CsrtAction::getLink('row_action_right', __('txt stock') , 'stock'), 'fancyView',  tep_href_link(FILENAME_STOCK, 'product_id=' . $products['products_id'].'&amp;origin='.self::FILENAME) ,'' ).
		  sprintf(CsrtAction::getLink('row_action_right', __('image view public') , 'publiclink'), '',  tep_catalog_href_link('product_info.php', 'products_id=' . $products['products_id']) ,' target="blank"' )
	      );
  }

  private static function get_status_product($products){
    $exclude=array('action','pID','forceajax','type','class','function','funct', 'mod');
    $query_s='action=setflag&amp;pID=' . $products['products_id'].'&amp;flag=';

    if ($products['products_status'] == '1')
      return  tep_image(DIR_WS_ICONS . 'icon_status_green.gif', IMAGE_ICON_STATUS_GREEN) . '&nbsp;<a href="' . tep_href_link(self::FILENAME, tep_get_all_get_params($exclude).$query_s.'0' ) . '">' . tep_image(DIR_WS_ICONS . 'icon_status_red_light.gif', IMAGE_ICON_STATUS_RED_LIGHT) . '</a>';
    else
      return '<a href="' . tep_href_link(self::FILENAME,  tep_get_all_get_params($exclude).$query_s.'1') . '">' . tep_image(DIR_WS_ICONS . 'icon_status_green_light.gif', IMAGE_ICON_STATUS_GREEN_LIGHT) . '</a>&nbsp;' . tep_image(DIR_WS_ICONS . 'icon_status_red.gif', IMAGE_ICON_STATUS_RED);
  }

  private static function emptyResult(){
    return array(  'null',
	      'id',
	      'image',
	      'pv.typeID',
	      'model',
	      'name',
	      'categorie',
	      'quantity',
	      'price',
	      'status',
	      'action'
	  );
  }

  public static function tep_get_modele(){
      return array( 0 =>false,
		    'products_id'=>true,
		    'products_image'=>true,
		    'pv.typeID'=>true,
		    'products_model'=>true,
		    'products_name'=>true,
		    'categories_name'=>false,
		    'products_quantity'=>true,
		    'products_price'=>true,
		    'products_status'=>true,
		    'action'=>false
	      );
  }

  public static function tep_get_list($page=1,$rowbyp=10,$sOrder='',$sWhere='',$options=''){
    global $languages_id,$query_numrows;
    new  self();
    if(self::$cPath>0) self::$DiversInfo['current_category_id']=self::$cPath;
    else self::$DiversInfo['current_category_id']=(isset($options['current_category_id'])?$options['current_category_id'] :'');

    $sta=(!empty(self::$Vtype)? " AND pv.typeID ='".(int)self::$Vtype."' " : '' );

    $DB=Database::getInstance();
    $listing_products=array();
    $add_tbl='';
    $cat= (tep_not_null(self::$DiversInfo['current_category_id']))?" and p2c.categories_id = '" . (int)self::$DiversInfo['current_category_id'] . "' " : "" ;
    $avenir=(isset($_GET['expected']) && tep_not_null($_GET['expected'])) ? " and p.products_date_available IS NOT NULL " : " and p.products_date_available IS NULL ";

    if(tep_not_null($sWhere)){
      $sWhere=str_replace(array('products_id'),array('p.products_id'), $sWhere);

      if(strpos($sWhere, 'categories_name') >0 ) {
	$add_tbl=" ,  " . TABLE_CATEGORIES_DESCRIPTION . " cd  ";
	$sWhere .=" AND cd.categories_id=p2c.categories_id ";
      }
    }

    $products_query = "select distinct  p.products_id, p.products_image, pv.typeID  , p.products_model,pd.products_name, p.products_quantity, p.products_price, p.products_status  from " . TABLE_PRODUCTS . " p LEFT JOIN ".TABLE_PRODUCTS_VIRTUAL." pv on(p.products_id = pv.productsID) LEFT JOIN  ".TABLE_STATUS." s on(pv.typeID = s.status_id and s.status_type='products_virtual_types' and s.language_id='" . (int)$languages_id . "') , " . TABLE_PRODUCTS_DESCRIPTION . " pd, " . TABLE_PRODUCTS_TO_CATEGORIES . " p2c  ".$add_tbl." where p.products_id = pd.products_id and pd.language_id = '" . (int)$languages_id . "' and p.products_id = p2c.products_id    ".$cat." ".$avenir." ".$sta." ".$sWhere." order by  ".((!empty($sOrder)) ? $sOrder : 'pd.products_name  ASC');

    $products_split = new splitPageResults($page, $rowbyp, $products_query,$query_numrows);

    $pq=$DB->query($products_query);

    while ($products = tep_db_fetch_array($pq)) {
      $products['pv.typeID']=(!empty($products['typeID'])? $products['typeID']: '0');
      $products['products_image']=(!empty($products['products_image']))
				     ? tep_info_image($products['products_image'], $products['products_name'], TEMP_BO_SMALL_IMAGE_WIDTH, TEMP_BO_SMALL_IMAGE_HEIGHT)
				     : tep_info_image(IMAGE_NONEXISTENT, $products['products_name'], TEMP_BO_SMALL_IMAGE_WIDTH, TEMP_BO_SMALL_IMAGE_HEIGHT) ;
      $products['products_status']=self::get_status_product($products);


      $objres=$DB->query("SELECT categories_name FROM " . TABLE_CATEGORIES . " c,  " . TABLE_CATEGORIES_DESCRIPTION . " cd , " . TABLE_PRODUCTS_TO_CATEGORIES . " p2c    WHERE c.categories_id=cd.categories_id AND cd.language_id = '" . (int)$languages_id . "' AND c.categories_id=p2c.categories_id and products_id='".$products['products_id']."' ");
      $res=$objres->fetchAllAssoc();

      $products['categories_name']='';
      foreach($res as $cat)
	$products['categories_name'] .=$cat['categories_name'].',';

      if(strlen($products['categories_name'])>25)$products['categories_name']= substr($products['categories_name'],0 ,20).'...';

      self::$list[]=$products;
    }

    $li=$res=array();
    foreach(self::$list as $item){
      foreach(self::tep_get_modele() as $k=>$v) $li[$k]=(isset($item[$k]) && !empty($item[$k]))? $item[$k] : '&nbsp;';
      $li[0]=$item['products_id'];
      $li['action']=self::get_item_action($item);
      $res[]=$li;
    }

    if(count($res)===0) $res[]= self::emptyResult();
    return $res;
  }

 /** static InterfacedInnerHtml */

  public static function detail_row_page($id){

    new  self();
    self::load_db_values((int)$id);
    self::$modules->display_detail_row_page($id);
    return tep_get_include_contents(__CLASS__.'.inline');
  }



  /** methode specific module */

  public static function NameVirtualID($id){
    foreach(tep_get_status_array('products_virtual_types') as $row)
      if($id==$row['id']) return  $row['text'];
  }


  /**
    deactive/active les class (defini dans les gabarit) autorisé pour ce type de produit
    Control en 2 temps si la class est deja defini

    @param
      @a string Non class testé
      @a int $flag_type, peut être homis
    @return true/false
  */
  public static function CheckClassProduct($string_class, $flag_type=''){
    $virtual_type=(tep_not_null($flag_type)?$flag_type : self::$modules->type_flag);
    $class = 'CFG_CLASS_VIRTUAL_TYPE_'.$virtual_type;
    if(defined($class) && in_array($string_class, explode(';',constant($class)))) return false;
    if(_cst_bool($string_class)) return false;
    return true;
  }


  /**
    @fn UpdateOrphelin()
    @brief call method for update in cat , the products in not category
  */
  private static function UpdateOrphelin(){
    $DB=Database::getInstance();
    $product_query = $DB->query("SELECT  p.products_id FROM " . TABLE_PRODUCTS . " p LEFT OUTER JOIN  " . TABLE_PRODUCTS_TO_CATEGORIES . " p2c ON p.products_id =p2c.products_id  WHERE  p2c.products_id is null");
    while ($product = tep_db_fetch_array($product_query)){
      $DB->query("insert into " . TABLE_PRODUCTS_TO_CATEGORIES . " (products_id, categories_id) values ('" . (int)$product['products_id'] . "', '".ORPHELIN_COLLECTOR."')");
    }
  }
}




/**
  @class productsACA
*/
class productsACA
  extends aca
    implements mod_aca{
  var $modules=array();
  var $products_id;
  var $image_handler;

  /**
    class constructor
  */
  function __construct() {
    global $language, $languages_id,$language_code2, $lang,$oscss;

    $this->name='products';
    $this->products_id='';
    $this->image_handler='';
    $this->type_flag=1;

    $this->modules=array();
    foreach(parent::initialise_type('MODULE_ACAPRO_INSTALLED_BO','products') as $class){
	$cl[$class]=new $class ();
	// test flag type module, si aucun, produist base
	if(!isset($cl[$class]->flag_type_virtual)) $cl[$class]->flag_type_virtual=0;
	// incremente tableau module unqiuement si flag ok
	if($this->control_type_mod($cl[$class]->flag_type_virtual)) $list_mod[$class] = $cl[$class]->sort_order;
	asort($list_mod);
	foreach($list_mod as $class=>$s){
	  $this->modules[$class] =$cl[$class];
	}
	unset($cl);unset($list_mod);
    }
  }


  /**
    Appel magic
  */
  public function __call($method, $attrs) {
    $r=array();
    foreach ($this->modules as $key=>$module) {
      if (( isset($attrs['flag']) &&  isset($module->$attrs['flag']) &&  (bool)$module->$attrs['flag']) /// control flag
	  and (method_exists($module, $method )) /// control presence method
	  )
	$r[]=$this->modules[$key]->$method($attrs);
    }

    return $r;
  }

  /**
    Activation/ descative les modules en focntion du type de produits
    @param
      @a int $flag le type falg de modules
    @return boolean
  */
  private function control_type_mod($flag){
    $this->load_type_product();
    if(in_array($flag,explode(',',$this->type_flag) ) || $flag==0) return true;
    else return false;
  }

  /**
    Recup db type flag
    @return int, Id du type ou 1
  */
  private function load_type_product(){
    if(!isset($_GET['pID'])) return ;
    $sql = "select * from ".TABLE_PRODUCTS_VIRTUAL." where productsID=".(int)$_GET['pID'];
    $result = tep_db_query($sql);
    if (tep_db_num_rows($result) > 0) { // this product is in the virtual table
      $virtual = tep_db_fetch_array($result);
      $this->type_flag= $virtual['typeID'];
    }
    else $this->type_flag=1;
    tep_db_free_result($result);
  }


  /**
    Find which module will take care of saving images
    $handler is optional and can be used to force an image handler
  */
  public function set_image_handler ($handler='') {
    if ($handler=='') {
      foreach ($this->modules as $key=>$module)
	if (($module->enabled) and (method_exists($module,'get_products_image_handler' )))
	  $handler= $this->modules[$key]->get_products_image_handler($handler);
    }
    $this->image_handler = $handler;
    if ($handler!='') $this->modules[$handler]->is_image_handler = true;
  }


  /**
    Ask each module what to insert into products table
  */
  public function get_insert_table_products () {
    $sql_data_array=array();
    foreach ($this->modules as $key=>$module) {
      if (($module->enabled) and (method_exists($module, 'insert_table_products' ))) {
	$sql_module= $this->modules[$key]->insert_table_products();
	$sql_data_array=array_merge ($sql_data_array, $sql_module);
      }
    }
    return $sql_data_array;
  }

  public function get_update_table_products (){
    $sql_data_array=array ();
    foreach ($this->modules as $key=>$module) {
      if (($module->enabled) and (method_exists($module,'update_table_products' ))) {
	$sql_data_array= (array)$this->modules[$key]->update_table_products();

      }
    }
    return $sql_data_array;
  }

  public function get_insert_table_products_description ($language_id) {
    $sql_data_array=array();
    foreach ($this->modules as $key=>$module) {
	if (($module->enabled) and (method_exists($module,'insert_table_products_description' ))) {
	  $sql_module= $this->modules[$key]->insert_table_products_description($language_id);
	  $sql_data_array=array_merge ($sql_data_array, $sql_module);
	}
    }
    return $sql_data_array;
  }

  public function get_update_table_products_description ($language_id) {

    $sql_data_array = array();
    foreach ($this->modules as $key=>$module) {
      if (($module->enabled) and (method_exists($module,'update_table_products_description' ))) {
	$sql_module= $this->modules[$key]->update_table_products_description($language_id);
	$sql_data_array=array_merge ($sql_data_array, $sql_module);
      }
    }
    return $sql_data_array;
  }


  /**
  */
  public function after_update ($Id){
    foreach ($this->modules as $key=>$module) {
      if (($module->enabled) and (method_exists($module,'after_update' )))
	$this->modules[$key]->after_update($Id);
    }
    $languages = tep_get_languages();
    for ($i=0, $n=sizeof($languages); $i<$n; $i++) {
      $language_id = $languages[$i]['id'];
      foreach ($this->modules as $key=>$module) {
	if (($module->enabled) and (method_exists($module,'after_update_lang' )))
	  $this->modules[$key]->after_update_lang($language_id, $Id);
      }
    }
  }

  public function duplicate_product($products_id,$dup_products_id){

    // Duplicate products and put in other category
    // Load values of current product from database
    $this->load_db_values($products_id);
    // Ask if module must do something before duplication of the product
    foreach ($this->modules as $key=>$module) {
      if (($module->enabled) and  method_exists($module, 'duplicate_product'))
	$this->modules[$key]->duplicate_product($products_id, $dup_products_id);
    }
    // Update just created (duplicated) product with modules datas
    $sql_data_array = $this->get_insert_table_products();
    if (sizeof($sql_data_array)>0)
      tep_db_perform(TABLE_PRODUCTS, $sql_data_array, 'update', "products_id = '" . (int)$dup_products_id . "'");
  // Update informations into the products_description table
    $languages = tep_get_languages();
    for ($i=0, $n=sizeof($languages); $i<$n; $i++) {
      $language_id = $languages[$i]['id'];
//       $sql_data_array = $this->get_insert_table_products_description($language_id);
/*      if (sizeof($sql_data_array)>0)
	tep_db_perform(TABLE_PRODUCTS_DESCRIPTION, $sql_data_array, 'update', "products_id = '" . (int)$dup_products_id . "' and language_id = '" . (int)$language_id . "'");*/
    }
    $this->products_id=$dup_products_id;
    // Do what have to do after the update of the new product
    $this->after_update($this->products_id);
  }

  /**
    Suppression apres confirmation
  */
  public function delete_product ($products_id){
    foreach ($this->modules as $key=>$module)
      if (($module->enabled) and  method_exists($module, 'delete_product' ))
	$this->modules[$key]->delete_product($products_id);
  }

  /**
    products_restock apres confirmation
  */
  public function products_restock ($products_id,$cID,$Qt,$finalprice){
    foreach ($this->modules as $key=>$module)
      if (method_exists($module, 'products_restock' ))
	  $this->modules[$key]->products_restock($products_id,$cID,$Qt,$finalprice);
  }

  /**
    Load each module parameters from database
  */
  public function load_db_values ($Id) {
    global $language, $languages_id;
    $this->products_id=$Id;
    foreach ( $this->modules as $key=>$module) {
      if (($module->enabled) and  method_exists($module, 'load_db_values' ))  $this->modules[$key]->load_db_values($Id);
    }
  }

  /**
    Load each module parameters from the  POST variables
  */
  public function load_post_values ($post) {
    $post = $this->check_post_array ($post);
    $this->products_id = @$_GET['pID']; // Save the product ID
    foreach ($this->modules as $key=>$module) {
      if (($module->enabled) and (method_exists($module, 'load_post_values' )) and (isset($post[$module->code])))
	$this->modules[$key]->load_post_values($post[$module->code]);
    }
  }

//   public function display_ColumnRowAction($id){
//     $st='';
//     foreach ($this->modules as $key=>$module)
//       if (($module->enabled) and (method_exists($module,'display_ColumnRowAction' )))
// 	$st .=$this->modules[$key]->display_ColumnRowAction($id);
//     return $st;
//   }

  /**
    Tabs in products
    Ask each module about what to dispay in the product editor of each module.
  */
//   function display_edit (&$contents) {
//   }

  public function display_image_preview (){
    // Returns the image path and name to show in the product preview
    return $this->modules[$this->image_handler]->display_image_preview ();
  }

  /**
    Affichage en mode liste, detail, colonne droite
    Ask each product module about what to dispay in the listing left column.
  */
//   public function display_right_column ($contents, $products_id) {
//   }


  /**
    Vue etat et list specifique modules
  */
  function display_view (&$contents) {
  }

  /**
    Return tableau complet des element à insrére dans la clause sql
  */
  public function shearch_in_product(){
    foreach ($this->modules as $key=>$module)
	if ($module->enabled && method_exists($module, 'shearch_in_product' ))
	  $contents[$key]=$this->modules[$key]->shearch_in_product();
   return $contents;
  }

}


?>