<?php
/**
 * Set session language based on:
 * - Cookie 'lang' (if exists)
 * - Browser language (if not present among website languages, use website main language)
 * - Form field 'language' (if present)
 *
 * The function also updates the product labels of the products in the session
 * to match the current language.
 *
 * @return bool
 */
function setSessionLang() {
   global $langs, $website, $weblangs, $db;
    // Get available langs for the website
    $website_langs = getAvailableLangs();
    $available_langs = $website_langs['langs'];
    $langs_code_shortcode = $website_langs['langs_code_shortcode'];

    // If no language is set or if a new language is selected (via form field)
    if (!isset($_COOKIE['lang']) || GETPOST('language', 'alpha')) {
        // Get browser language
        $browser_lang = $weblangs->getDefaultLang(1);

        // Change used lang
        $new_lang = GETPOST('language', 'alpha');
        if ($new_lang && array_key_exists ($new_lang, $available_langs)) {
            setcookie('lang', $new_lang, time() + (86400 * 30), '/');
            $session_lang = $new_lang;
        }

        // If no language is set in cookie and browser language is not present among available languages
        // use website main language as default
        if (!isset($_COOKIE['lang'])) {
            if (array_key_exists ($browser_lang, $available_langs)){
                // The browser language is present among the available languages
                setcookie('lang', $browser_lang, time() + (86400 * 30), '/');
                $session_lang = $browser_lang;
            } else {
                // The browser language is not present among the available languages
                setcookie('lang', $website->lang, time() + (86400 * 30), '/');
                $session_lang = $website->lang;
            }
        }

        // Set session lang
        if (!empty($session_lang)) {
            $_SESSION['lang']['shortcode'] = $session_lang;
            $_SESSION['lang']['code'] = $langs_code_shortcode[$session_lang];

            // Update product labels in session to match current language
            if (isset($_SESSION['products'])) {
                $langs->setDefaultLang($_SESSION['lang']['code']);
                // Loop over products in session and update label
                foreach ($_SESSION['products'] as $key => $value) {
                    $object = new Product($db);
                    $get_product = $object->fetch($key);
                    $_SESSION['products'][$key]['product_name'] = $object->label;
                }
            }
        }

    }

    // If session language is not set, use cookie language
    if (empty($_SESSION['lang']['shortcode']) || empty($_SESSION['lang']['code'])) {
        $_SESSION['lang']['shortcode'] = $_COOKIE['lang'];
        $_SESSION['lang']['code'] = $langs_code_shortcode[$_COOKIE['lang']];
    }

    // Set Dolibarr default language
    $langs->setDefaultLang($_SESSION['lang']['code']);
    $weblangs->setDefaultLang($_SESSION['lang']['code']);
    $langs->loadLangs(array("main", "website"));
    $weblangs->loadLangs(array("main", "website", "marketplace@marketplace"));

    return true;
}

/**
 * The function loops through the languages of the website configuration and
 * checks if they exist in the list of supported languages. If they do, they
 * are added to the $available_langs array, along with their corresponding
 * shortcode in the $langs_code_shortcode array.
 *
 * The function returns an array with two keys: 'langs' containing the list
 * of available languages and 'langs_code_shortcode' containing the list
 * of corresponding shortcodes.
 *
 * @return array
 */
function getAvailableLangs() {
    global $website, $weblangs;

    $available_langs = array();
    $langs_code_shortcode = array();
    $ws_langs_list = explode(',', $website->lang.','.$website->otherlang);
    $dol_available_langs = $weblangs->get_available_languages(DOL_DOCUMENT_ROOT, 1, 2, 1);
    foreach ($ws_langs_list as $lang) {
        foreach ($dol_available_langs as $key => $value) {
            if (strpos($key, $lang) === 0) {
                $available_langs[$lang] = $value;
                $langs_code_shortcode[$lang] = $key;
                break;
            }
        }
    }
    
    return array('langs' => $available_langs, 'langs_code_shortcode' => $langs_code_shortcode);
}

function getOrganizedTree($id,$sort = 'position')
{
    global $db;
    $root_cat_object = new Categorie($db);
    $result = $root_cat_object->fetch($id);
    $root_category_id = $root_cat_object->id;
    $root_category_type = $root_cat_object->type;
    $cats = $root_cat_object->get_filles();
    if (count($cats) < 1) {
        return array();
    } else {
        $categstatic = new Categorie($db);
        $fulltree = $categstatic->get_full_arbo($root_category_type, $root_category_id, 1);
        $organized_tree = buildTree($fulltree, $root_category_id);
        usort($organized_tree, build_sorter($sort));
        return $organized_tree;
    }
}

function buildTree(array &$elements, $parentId = 0)
{
  $branch = array();
  foreach ($elements as $element) {
    if ($element['fk_parent'] == $parentId) {
      $children = buildTree($elements, $element['id']);
      if ($children) {
        $element['children'] = $children;
      }
      $branch[$element['rowid']] = $element;
    }
  }
  return $branch;
}

function build_sorter($key)
{
  return function ($a, $b) use ($key) {
    return strnatcmp($a[$key], $b[$key]);
  };
}


function ws_login($customer_email, $customer_passwd) {
    global $db, $website;

    $sql  = "select lsa.rowid, lsa.pass_encoding, lsa.pass_crypted, ls.nom, fk_soc, lsa.login ";
    $sql .= "from ".MAIN_DB_PREFIX."societe_account lsa ";
    $sql .= "left join ".MAIN_DB_PREFIX."societe ls on ls.rowid = lsa.fk_soc ";
    $sql .= "where lsa.login = '" . $db->escape($customer_email) . "' ";
    $sql .= "and lsa.fk_website = " . (int) $website->id . " ";
    $sql .= "limit 1";

    $result = $db->query($sql);
    $objsql = $db->fetch_object($result);

    $is_logged = 0;
    $check_accaount = 0;
    $check_password = 0;
    $is_preferred_member = 0;
    if (!empty($objsql)) {
        $check_accaount = 1;
        if ($objsql->pass_encoding == 'dolibarr') {
            $check_password = dol_verifyHash ($customer_passwd, $objsql->pass_crypted);
        }
        if ($objsql->pass_encoding == 'dolistore') {
            $dolistore_key = getDolGlobalString("MARKETPLACE_SECRET_KEY");
            $to_check = md5($dolistore_key.$customer_passwd);
            if ($objsql->pass_crypted === $to_check){
                $check_password = 1;
            }
        }
        $is_logged = $check_accaount && $check_password;
    }
    
    if ($is_logged > 0) {
        $preferredCustomersCatId = getDolGlobalInt("MARKETPLACE_PROSPECTCUSTOMER_PREFERRED_ID");
        if (!empty($preferredCustomersCatId)) {
            $category = new Categorie($db);
            $user_categories = $category->getListForItem($objsql->fk_soc);

            foreach ($user_categories as $user_categorie) {
                if (!empty($user_categorie['id']) && $user_categorie['id'] == $preferredCustomersCatId) {
                    $is_preferred_member = 1;
                    break;
                }
            }
        }
    }

    return array(
        'status' => $is_logged,
        'userid' => $objsql->rowid,
        'pseudo' => $objsql->nom,
        'email' => $objsql->login,
        'socid' => $objsql->fk_soc,
        'is_preferred_member' => $is_preferred_member
    );
}


function ws_refreshCart($fk_soc) {
    global $db;
    // Find last validated, unpaid order of this user
    $sql_find_order = "SELECT c.rowid, c.fk_statut, c.fk_soc, c.date_creation, c.module_source ";
    $sql_find_order .= "FROM ".MAIN_DB_PREFIX."commande as c ";
    $sql_find_order .= "WHERE c.fk_soc = " . $fk_soc . " and c.fk_statut= 1 and c.facture = 0 and c.module_source = 'Marketplace' ";
    $sql_find_order .= "order by c.date_creation desc ";
    $sql_find_order .= "limit 1";

    $find_order = $db->query($sql_find_order);
    $obj_order = $db->fetch_object($find_order);

    // If there is an order, replace the current cart articles (fetched from SESSION) with the last validated, unpaid order.
    if (!empty($obj_order)) {
        $order_id = $obj_order->rowid;
        require_once DOL_DOCUMENT_ROOT."/commande/class/commande.class.php";
        $commande = new Commande($db);
        $ret = $commande->fetch($order_id);

        $commande->fetch_lines();
        $lines = $commande->lines;

        foreach ($lines as $line){
            $product = new Product($db);
            $ret = $product->fetch($line->fk_product);
            
            // check discount and calculate discounted price
		    $discount = marketplace_check_discount($product->id);
		    $discounted_price = marketplace_calculate_discounted_price($product->price_ttc, $discount);
		    
		    if ($discounted_price != $product->price_ttc) {
		        $price_to_display = $discounted_price;
		    } else {
		        $price_to_display = $product->price_ttc;
		    }
            
            $session_product['product_id'] = $product->id;
            $session_product['product_thumb'] = getImagePublicURLOfObject($product,1);
            $session_product['product_name'] = $product->label;
            $session_product['product_ref'] = $product->ref;
            $session_product['product_price'] = $price_to_display;
            $session_product['product_qty'] = $line->qty;

            if(isset($_SESSION['products'])){
                if(isset($_SESSION['products'][$session_product['product_id']]))
                {
                    unset($_SESSION['products'][$session_product['product_id']]);
                }
            }
            $_SESSION['products'][$session_product['product_id']] = $session_product;
        }
    }

    return 1;
}

/**
 * Check the validity of a module (rules must match the one in htdocs/admin/modules
 *
 * @return  array   Array of results
 */
function checkZipFile()
{
	global $weblangs;

	$error=0;
	$return = array(
		'product_file_path' => null,
		'upload' => 1,
		'errormsg' => null
	);

	$originalfilename=$_FILES['virtual_product_file']['name'];

	if (strlen($originalfilename) > 48)
	{
		$error++;
		$return['errormsg'] = $weblangs->trans("fileNameLengthError");
		///$return['errormsg'] = $this->l('Name of file must not be longer than 48 characters,  including the prefix ("module_", "theme_" or "website_"), the version suffix and the extension (".zip" for example) !');
	}

	dol_syslog("Upload or reupload file " . $originalfilename);

	if ($_FILES['virtual_product_file']['error'])
	{
		switch ($_FILES['virtual_product_file']['error'])
		{
			case 1: // UPLOAD_ERR_INI_SIZE
				$return['errormsg'] = $weblangs->trans("fileSizeHigherServerLimit");
				///$return['errormsg'] = $this->l('File size is higher than server limit !');
				break;
			case 2: // UPLOAD_ERR_FORM_SIZE
				$return['errormsg'] = $weblangs->trans("fileSizeHigherHtmlFormLimit");
				///$return['errormsg'] = $this->l('File size if higher than limit in HTML form !');
				break;
			case 3: // UPLOAD_ERR_PARTIAL
				$return['errormsg'] = $weblangs->trans("uploadAborted");
				///$return['errormsg'] = $this->l('File transfert was aborted !');
				break;
			case 4: // UPLOAD_ERR_NO_FILE
				$return['errormsg'] = $weblangs->trans("noFileOrSizeZero");
				///$return['errormsg'] = $this->l('File name was not defined or file size is null !');
				break;
		}
		$return['upload'] = -1;
		$error++;
	}

	if (! $error && ! preg_match('/(\.apk|\.odt|\.pdf|\.svg|\.zip|\.txt)$/i',$originalfilename))
	{
		$return['errormsg'] = $weblangs->trans("packageRuleViolation") . '<br>';
		$return['errormsg'].= $weblangs->trans("packageFileNameExtension");
		///$return['errormsg'] = $this->l('Package seems to not respect some rules:').'<br>';
		///$return['errormsg'].= $this->l('Package file name must end with extension .odt, .pdf, .svg, .zip, .txt or .apk');
		$return['upload'] = -1;
		$error++;
	}

	if (! $error && preg_match('/(\.txt)$/i',$originalfilename) && ! preg_match('/(README)\.txt$/i',$originalfilename))
	{
		$return['errormsg'] = $weblangs->trans("packageRuleViolation") . '<br>';
		$return['errormsg'].= $weblangs->trans("packageReadmeTxt");
		$return['upload'] = -1;
		$error++;
	}

	if (! $error && preg_match('/(\.zip)$/i',$originalfilename))
	{
		if (! preg_match('/^(module[a-zA-Z0-9]*|theme|website)_/', $originalfilename))
		{
			$return['errormsg'] = $weblangs->trans("packageRuleViolation") . '<br>';
			$return['errormsg'].= $weblangs->trans("packageFileNamePrefix") . '<br>';
			$return['errormsg'].= $weblangs->trans("packageBuildTool");
			$return['upload'] = -1;
			$error++;
		}

		if (! preg_match('/\-([0-9][0-9\.]*)\.zip$/i',$originalfilename))
		{
			$return['errormsg'] = $weblangs->trans("packageRuleViolation") . '<br>';
			$return['errormsg'].= $weblangs->trans("packageFileNameVersion") . '<br>';
			$return['errormsg'].= $weblangs->trans("packageBuildTool");
			$return['upload'] = -1;
			$error++;
		}

		// Example of allowed values:
		// module_mymodule-x.y.zip, moduleprestashop_mymodule-x.y.zip
		// theme_mytheme-x.y.zip
		// website_mytemplate-123456.zip
		if (! preg_match('/^module([a-zA-Z0-9]*)_([-a-zA-Z0-9_]+)\-([0-9][0-9\.]*)\.zip$/i',$originalfilename)
			&& ! preg_match('/^theme_([a-zA-Z0-9_]+)\-([0-9][0-9\.]*)\.zip$/i',$originalfilename)
			&& ! preg_match('/^website_([a-zA-Z0-9_]+)\-([0-9][0-9\.]*)\.zip$/i',$originalfilename)
			)
		{
			$return['errormsg'] = $weblangs->trans("packageRuleViolation") . '<br>';
			$return['errormsg'].= $weblangs->trans("packageFileNameRules") . '<br>';
			$return['errormsg'].= $weblangs->trans("packageBuildTool");
			$return['upload'] = -1;
			$error++;
		}
	}

	if (! $error && preg_match('/(\.zip)$/i',$originalfilename))
	{
		$zip = new ZipArchive();
		$res = $zip->open($_FILES['virtual_product_file']['tmp_name']);
		if ($res === TRUE)
		{
			$resarray = validateZipFile($zip,$originalfilename,$_FILES['virtual_product_file']['tmp_name']);
			//$zip->close();        // already close by validateZipFile
			$error=$resarray['error'];
			$return['upload']=$resarray['upload'];
			$return['errormsg'] = $resarray['errormsg'];
		}
		else
		{
			$return['errormsg'] = $weblangs->trans("fileNotAnalyzed") . '<br>';
			$return['errormsg'].= $weblangs->trans("emailIfError");
			$return['upload'] = -1;
			$error++;
		}
	}

	if (! $error)
	{
		$return['errormsg'] = '';
		$return['upload'] = 1;
	}

	return $return;
}

/**
 * Check that a zip file is Dolibarr rule compliant
 */
function validateZipFile(&$zip,$originalfilename,$zipfile)
{
	global $count, $results, $weblangs;

	$error=0;
	$return = array(
		'error' => 0,
		'errormsg'=> null,
		'upload' => 0
	);

	dol_syslog("Validate zip file " . $originalfilename);
	$subdir=basename($zipfile);
	//$dir='/home/dolibarr/dolistore.com/tmp/'.$subdir;
	$dir=sys_get_temp_dir().'/unzip-dir-'.$subdir;
	mkdir($dir, 0777, true);
	$zip->extractTo($dir.'/');
	$zip->close();

	// Zip content of a module should be ./mymodule or ./htdocs/mymodule

	// But we first we check if we need to change dir (for zip that are ./module/htdocs/module instead of ./htdocs/module)
	if (! $error && $dh = opendir($dir))
	{
		$nbofsubdirs=0;
		while (($file = readdir($dh)) !== false)
		{
			if ($file == '.' || $file == '..') continue;
			dol_syslog("We check if dir ".$dir.'/'.$file.'/htdocs exists');
			if (is_dir($dir.'/'.$file.'/htdocs'))
			{
				dol_syslog('Dir '.$dir.'/'.$file.'/htdocs exists. So we use dir='.$dir.'/'.$file.' as root for package to analyse.');
				$dir=$dir.'/'.$file;
				break;
			}
		}
		closedir($dh);
	}

	// Now $dir contains root of zip, so mymodule or htdocs/mymodule
	// Analyze files
	$ismodule=$istheme=0;

	if (preg_match('/^module([a-zA-Z0-9]*)_([-a-zA-Z0-9]+)\-([0-9][0-9\.]*)\.zip$/i',$originalfilename,$reg))
	{
		$ismodule=$reg[2];
		$extmoduleornot=$reg[1];
		if ($extmoduleornot) $ismodule=0;
	}
	if (preg_match('/^theme_([-a-zA-Z0-9]+)\-([0-9][0-9\.]*)\.zip$/i',$originalfilename,$reg)) $istheme=$reg[1];


	dol_syslog("Now dir is the directory with root of the zip = ".$dir, LOG_DEBUG);

	$dirmoduletheme = $dir.'/'.($ismodule?$ismodule:($istheme?$istheme:''));
	if (is_dir($dir.'/htdocs')) $dirmoduletheme = $dir.'/htdocs/'.($ismodule?$ismodule:($istheme?$istheme:''));
	$dirmodulethemeroot = dirname($dirmoduletheme);
	dol_syslog("Now dirmodulethemeroot = dir where is the module dir = ".$dirmodulethemeroot." and dirmoduletheme = dir with name of the module = ".$dirmoduletheme, LOG_DEBUG);

	if (! empty($ismodule) || ! empty($istheme))
	{
		dol_syslog("file ismodule=".$ismodule." istheme=".$istheme);
		// It's a module or theme file
		if (! $error && (! empty($ismodule) || ! empty($istheme)) && $dh = opendir($dir))
		{
			$nbofsubdirs=0; $direrror='';
			while (($file = readdir($dh)) !== false)
			{
				if ($file == '.' || $file == '..' || $file == 'README' || $file == 'README.txt' || $file == 'README.md') continue;
				dol_syslog("subdirs found for package:".$file);
				$nbofsubdirs++;
				$alloweddirs=array('htdocs', 'docs', 'scripts', 'test', 'build', ($ismodule?$ismodule:($istheme?$istheme:'')));
				if (! in_array($file,$alloweddirs))
				{
					$error++;
					$direrror=$file;
					break;
				}
			}
			if ($error)
			{
				$return['errormsg'].= $weblangs->trans("validationFail") . '<br>';
				$return['errormsg'].= $weblangs->trans("moduleContents") . '<br>';
				$return['errormsg'].= $weblangs->trans("moduleDirectoryRule1") . '<br>';
				$return['errormsg'].= $weblangs->trans("moduleDirectoryRule2") . '<br>';
				$return['errormsg'].= $weblangs->trans("directoryFound").' '.$direrror.'<br><br>'."\n";
			}
			closedir($dh);
		}

		// It's a module or theme file (check htdocs directory)
		if (! $error && ! empty($ismodule) && is_dir($dirmodulethemeroot) && $dh = opendir($dirmodulethemeroot))
		{
			dol_syslog("we scan module dir ".$dirmodulethemeroot." to be sure there is only one directory (with name of your module) into root");
			$nbofsubdir=0; $lastdirfound='';
			dol_syslog("check there is only one dir into root");
			while (($file = readdir($dh)) !== false)
			{
				if ($file == '.' || $file == '..' || $file == 'README' || $file == 'README.txt' || $file == 'README.md') continue;
				$lastdirfound = $file;
				dol_syslog("we found file or dir ".$file);
				$nbofsubdir++;
			}
			closedir($dh);
			if ($nbofsubdir >= 2 && ! is_file($dirmoduletheme.'/metapackage.conf'))
			{
				$return['errormsg'].= $weblangs->trans("rootDirWarning", $nbofsubdir, basename($dirmoduletheme)) . '<br><br>';
				$error++;
			}

			if ($ismodule != $lastdirfound)
			{
				if (is_file($dirmoduletheme.'/metapackage.conf'))
				{
					// TODO Check each dir found is inside list of modules

				} else {
					$return['errormsg'].= $weblangs->trans("moduleNameMismatch", $lastdirfound, $ismodule) .'<br><br>';
					$error++;
				}
			}
		}
		// Check "custom" compatibility
		if (! $error && ! empty($ismodule))
		{
			dol_syslog("check the good practice of code");
			$count = 0;
			$results = array();

			$search = array(
				0 => array(
					'name'          => 'main',
					'types'         => array('php'),
					'pattern'       => '(require|include).*(main|master)\.inc\.php',
					'multiple'      => true     // Means we must find 0 or several times the pattern. Error if found 1 occurrence.
				),
				/*2 => array(
				 'name'          => 'dol_include_once',
				 'types'         => array('php', 'class.php', 'lib.php', 'modules.php'),
				 'pattern'       => 'dol\_include\_once\([\"\']\/([^\/]*)\/.*;',
				 'contain'       => array($ismodule)     // error if it contains
				 ),*/
				1 => array(
					'name'                  => 'dol_document_root',
					'types'                 => array('php', 'class.php', 'lib.php', 'modules.php'),
					'pattern'               => '(require|include)(_once)?\(?(.*)[\"\']+\)?;',
					'id'                    => 3,           // eg. Use $regs[3] for test instead $regs[1]
					'contain'               => array('DOL_DOCUMENT_ROOT'),
					'notcontain'            => array($ismodule),
					'strict'                => true         // if true ('contain' && 'notcontain'), if false or not use ('contain' || 'notcontain')
				)
			);

			getDirContents($dir, $search, $results);     // This include a global $count

			dol_syslog("count of errors = ".$count);

			if (!empty($count)) // count of errors is not null
			{
				foreach($results as $result)
				{
					if ($result['testname'] == 'main')
					{
						$return['errormsg'].= $weblangs->trans("mainIncludeError", $result['filename'], $ismodule) .'<br><br>';
					}
					else if ($result['testname'] == 'dol_include_once')
					{
						$return['errormsg'].= $weblangs->trans("dolIncludeError", $result['filename'], $ismodule) .'<br>';
						$return['errormsg'].= $result['line'].'<br><br>';
					}
					else if ($result['testname'] == 'dol_document_root')
					{
						$return['errormsg'].= $weblangs->trans("docRootError", $result['filename'], $ismodule) .'<br>';
						$return['errormsg'].= $result['line'].'<br><br>';
					}
				}

				dol_syslog("file ".$originalfilename." is not compatible with custom directory!", LOG_ERR);

				$error++;
			}
		}
	}
	else
	{
		dol_syslog("file ".$originalfilename." is not a module and not a theme!", LOG_WARNING);    // It can be a doc, android app, ...
	}

	if (!empty($error))
	{
		dol_syslog("validateZipFile Error");

		$link = '<a target="_blank" class="linktowiki" href="https://wiki.dolibarr.org/index.php/Modules - Packaging rules and Dolistore validation rules">Dolibarr wiki developer documentation</a>';
		$return['errormsg'].= $weblangs->trans("invalidZipFile") .'<br>';
		$return['errormsg'].= $weblangs->trans("seeDocumentation", $link).'<br>';
		$return['errormsg'].= "<br>\n";
		$return['errormsg'].= $weblangs->trans("contactDolistore");
		$return['upload'] = -1;
		$error++;
	}
	else
	{
		dol_syslog("validateZipFile OK");
	}

	$return['error'] = $error;

	return $return;
}

function getDirContents($dir, $search = array(), &$results = array())
{
	global $count;

	$files = scandir($dir);

	foreach ($files as $key => $value)
	{
		$path = realpath($dir . DIRECTORY_SEPARATOR . $value);
		if (!is_dir($path))
		{
			$content = file_get_contents($path);
			$fileName = basename($path);
			$fileNameWithoutTmp = preg_replace('/\/tmp\/unzip[^\/]+\//', '', $path);

			$file_array = explode(".", $fileName);

			foreach ($search as $pattern)
			{
				if (count($file_array) > 1)
				{
					$ext = $file_array[1];
					if (!empty($file_array[2])) {
						$ext = $file_array[1] . '.' . $file_array[2];
					}

					if (in_array($ext, $pattern['types']))
					{

						if (strpos($content, '<?php') !== 0) continue;  // We discard files that are not php pages (we discard scripts)
						if (strpos($path, 'htdocs_') > 0) continue;  // We discard files that are files into htdocs_... because it is files for core, so no need to be compatible with custom
						if (strpos($path, 'phpunit') > 0) continue;  // We discard files that are files into phpunit because it is files for core, so no need to be compatible with custom

						$regs = array();
						if (!empty($pattern['multiple']))
						{
							preg_match_all('/' . $pattern['pattern'] . '/', $content, $regs);
							// Error if only one result (0 is ok, >1 is ok)
							if (!empty($regs) && count($regs[0]) == 1)
							{
								$results[] = array(
									'testname'      => $pattern['name'],
									'filename'      => $fileNameWithoutTmp
								);
								$count++;
							}
						}
						else
						{
							$id = (!empty($pattern['id']) ? $pattern['id'] : 1);
							preg_match_all('/' . $pattern['pattern'] . '/', $content, $regs);

							if (!empty($regs) && !empty($regs[$id]))
							{
								foreach($regs[$id] as $i => $string)
								{
									if (!empty($pattern['contain']) && is_array($pattern['contain']))
									{
										foreach ($pattern['contain'] as $contain)
										{
											// Mode strict true : doit contenir && ne pas contenir
											if (!empty($pattern['notcontain']) && !empty($pattern['strict']) && is_array($pattern['notcontain']))
											{
												foreach ($pattern['notcontain'] as $notcontain)
												{
													if (strstr($string, $contain) && strstr($string, $notcontain))
													{
														$results[] = array(
															'testname'      => $pattern['name'],
															'filename'      => $fileName,
															'line'          => $regs[0][$i]
														);
														$count++;
													}
												}
											}
											// Mode strict false : doit contenir. Note strstr return false if not found
											else if (!strstr($string, $contain))        // If found
											{
												// We found $contain into $string
												$results[] = array(
													'testname'      => $pattern['name'],
													'filename'      => $fileName,
													'line'          => $regs[0][$i]
												);
												$count++;
											}
										}
									}
									// Ou ne doit pas contenir
									if (empty($count) && !empty($pattern['notcontain']) && empty($pattern['strict']) && is_array($pattern['notcontain']))
									{
										foreach ($pattern['notcontain'] as $notcontain)
										{
											if (strstr($string, $notcontain))
											{
												$results[] = array(
													'testname'      => $pattern['name'],
													'filename'      => $fileName,
													'line'          => $regs[0][$i]
												);
												$count++;
											}
										}
									}
								}
							}
						}
					}
				}
			}

		}
		else if ($value != "." && $value != "..") {
			getDirContents($path, $search, $results);
		}
	}
}

function checkImage($image)
{
	global $weblangs;
	$flagError = false;

	if ($image['error'])
	{
		switch ($image['error'])
		{
			case 1: // UPLOAD_ERR_INI_SIZE
				$flagError = $weblangs->trans("fileSizeHigherServerLimit");
				break;
			case 2: // UPLOAD_ERR_FORM_SIZE
				$flagError = $weblangs->trans("fileSizeHigherHtmlFormLimit");
				break;
			case 3: // UPLOAD_ERR_PARTIAL
				$flagError = $weblangs->trans("uploadAborted");
				break;
			case 4: // UPLOAD_ERR_NO_FILE
				$flagError = $weblangs->trans("noFileOrSizeZero");
				break;
		}
	}
	else
	{
		//Check exctention
		preg_match('/\.([a-zA-Z0-9]+)$/', $image['name'], $reg);
		$extention_image = strtolower($reg[1]);
		if (! in_array($extention_image, array("jpg","png","gif","jpeg"))) {
			$flagError = $weblangs->trans("errorImageFormat", strtoupper($extention_image));
		}
	}

	return $flagError;
}
/*
* @param array 		$product 		Selected value
* @param int	 	$id 			Id of the product
*/
function addProduct($object, $id = null) {

	global $langs, $db, $user, $conf, $weblangs;
	$error = 0;
    $error_messages = array();

	include_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
	include_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
	include_once DOL_DOCUMENT_ROOT . '/ecm/class/ecmfiles.class.php';
	require_once DOL_DOCUMENT_ROOT . "/core/lib/files.lib.php";
	include_once DOL_DOCUMENT_ROOT . '/core/lib/security.lib.php';
	require_once DOL_DOCUMENT_ROOT . '/core/class/html.formbarcode.class.php';
	require_once DOL_DOCUMENT_ROOT . '/fourn/class/fournisseur.product.class.php';
	include_once DOL_DOCUMENT_ROOT .'/societe/class/societeaccount.class.php';


	// Load user and its permissions
	$result = $user->fetch('', 'admin'); // Load user for login 'admin'. Comment line to run as anonymous user.
	if (!($result > 0)) {
		dol_print_error(null, $user->error);
		exit;
	}
	$user->getrights();

	// Get Account ID.
	$user_id = $_SESSION['user']['id_user'];
	$supplier_account = new SocieteAccount($db);
	$result = $supplier_account->fetch($user_id);
	$supplier_id = $supplier_account->fk_soc;

	// Get customer ID.
	$supplier = new Societe($db);
	$supplier->fetch($supplier_id);

	// Update customer to vendor
	$supplier->fournisseur = '1';
	$supplier->code_fournisseur = 'auto';
	$supplier->update($supplier_id, $user);
	$result = $supplier->fetch($supplier_id);
	
	// We enable recursive category assignement (we use it for search and filter purposes)
    $conf->global->CATEGORIE_RECURSIV_ADD = 1;

	// Start of transaction
	$db->begin();

	//add one product
	$product = new Product($db);

	if ($id > 0) {
		$result = $product->fetch($id);
	} else {
		$dateRef = date ("YmdHis");
		$reference = 'c'.$supplier->id.'d'.$dateRef;
		$product->ref = $reference;
		$product->barcode = 'auto';
	}

	$product->type = $product::TYPE_SERVICE;
	$product->status = 0;
	
	// New Products will be status 0
	if ($id) {
	    $product->status = $object['status'];
	}
	$product->status_buy = 0;

	$product->label = $object['name'];
	$product->description = $object['short_description'];
	$product->other = $object['description'];
	$product->ref_ext = 'Marketplace';
	$product->price = price2num($object['sale_price']);
	$product->price_base_type = 'HT';
	$product->tva_tx = "20";
	$product->mandatory_period = !empty(GETPOST("mandatoryperiod", 'alpha')) ? 1 : 0;

	// Extrafields
	$product->array_options['options_marketplace_module_keywords'] = $object['keywords'];
	$product->array_options['options_marketplace_module_version'] = $object['version'];
	if (!empty($object['version_min'])) {
    	$version_min_object = new Categorie($db);
    	$result = $version_min_object->fetch($object['version_min']);
    	if ($result > 0) {
    	    $product->array_options['options_marketplace_min_version'] = $version_min_object->label;
    	}
	}
	if (!empty($object['version_max'])) {
    	$version_max_object = new Categorie($db);
    	$result = $version_max_object->fetch($object['version_max']);
    	if ($result > 0) {
    	    $product->array_options['options_marketplace_max_version'] = $version_max_object->label;
    	}
	}
	$product->array_options['options_marketplace_contact_support'] = $object['contact_support'];
	$object['dolibarr_core_include'] = $object['dolibarr_core_include'] ? 1 : 0;
	$product->array_options['options_marketplace_allow_source_in_core'] = $object['dolibarr_core_include'];
	//$product->array_options['options_marketplace_short_description'] = $object['resume'];
	//$product->array_options['options_marketplace_reason_disabled'] = $obj->dolibarr_disable_info;

	if ($id > 0) {
		$result = $product->update($id, $user);
	} else {
		$result = $product->create($user);
	}
	//$result = $product->create($user);

	if ($result < 0) {
		dol_syslog("Create Error => " . $result . " - " . $product->errorsToString());
		$error++;
	} else {
		dol_syslog("Product id=".$product->id." successfully");
	}
	
	// Add langs, categories, versions and photos
	if (!$error && 1) {
	    
	    // Update Price
	    if ($id) {
	        $product->updatePrice($product->price, 'HT', $user);
	    }

		// Add alternative languages
		if ($object['multilangs']) {
			foreach ($object['multilangs'] as $key => $value) {
				$availableLangsShortCode = getAvailableLangs()['langs_code_shortcode'];
				$product->multilangs[$availableLangsShortCode[$key]] = array(
					'label' => $value['name'],
					'description' => $value['short_description'],
					'other' => $value['description'],
				);
			}
		}
		$product->multilangs;
		$langs->setDefaultLang('en_US');
		$ret = $product->setMultiLangs($user);
		if ($ret < 0) {
			dol_syslog("Error in setMultiLangs result code = " . $ret . " - " . $product->errorsToString());
			$error++;
		} else {
			dol_syslog("Set MultiLangs OK");
		}

		// Add owner of a module by adding supplier price
		if (!$id) {
		    $object_ProductFournisseur = new ProductFournisseur($db);
		    $object_ProductFournisseur->fetch($product->id);
		    $object_ProductFournisseur->add_fournisseur($user, $supplier->id, $product->ref, 1);
		    $object_ProductFournisseur->update_buyprice(1, 0, $user, 'HT', $supplier, 1, $supplier->ref, 20, 0, '', 0, 0, '', '', array(), '', 0, 'HT');
		    dol_syslog("Adding supplier prices (id_fourn=".$supplier->id." ref_product_fourn=".$product->ref.") OK");
		}
		
		

		// Add  categories and versions
		if (!empty($object['version_min']) && !empty($object['version_max'])) {
			$version_tags = get_all_tags_between($version_min_object->label,$version_max_object->label);
			$version_ids = array();
			foreach ($version_tags as $key => $value) {
				$version_object = new Categorie($db);
				$result = $version_object->fetch('', $value);
				$version_ids[$version_object->id] = $version_object->id;
			}
		}
		if (!empty($object['categories'])) {
		    $marketplaceMainCat = array(getDolGlobalInt("MARKETPLACE_ROOT_CATEGORY_ID") => getDolGlobalInt("MARKETPLACE_ROOT_CATEGORY_ID"));
		    $object['categories'] = array_merge($marketplaceMainCat, $object['categories']);
			if (!empty($version_ids)) {
				$object['categories'] = array_merge($version_ids, $object['categories']); // Add versions to categories
			}
			$ret_cat = $product->setCategories($object['categories']);
			if ($ret_cat < 0) {
				dol_syslog("Error in setCategories result code = " . $ret_cat . " - " . $product->errorsToString().' '.join(',', $object['categories']));
				$error++;
			} else {
				dol_syslog("Set Categories and versions OK");
			}
		}


		// Add pictures AND package
		$upload_dir = $conf->product->multidir_output[1] . '/' . get_exdir(0, 0, 0, 1, $product, 'product');
		if (!is_dir($upload_dir)) {
			mkdir($upload_dir);
		}
		if (!empty($object['image_cover']['name'])) {
			$images['image_cover'] = $object['image_cover'];
		}
		if (!empty($object['other_images'])) {
			$other_images = $object['other_images'];
			foreach ($other_images as $key => $value) {
				$images[$key] = $value;
			}
		}
		if (!empty($images)) {
			foreach ($images as $key_image => $value_image) {
				$img = $upload_dir . '/' . $product->ref . '-' . $key_image . '.jpg';
	
				if (move_uploaded_file($value_image['tmp_name'], $img) != true){
					$error++;
					dol_syslog("file copy impossible for the moment, please try again later");
				} else {
					// Add thumb
					$product->addThumbs($img);
					
					$filename = basename($product->ref . '-' . $key_image  . '.jpg');
					$rel_dir = preg_replace('/^' . preg_quote(DOL_DATA_ROOT, '/') . '/', '', $upload_dir);
					$rel_dir = preg_replace('/^[\\/]/', '', $rel_dir);

					$ref = dol_hash($rel_dir . '/' . $filename, 3);

					// Add index to db
					if (empty ($id)) {
						addFileIntoDatabaseIndex($upload_dir, $filename, 'MARKETPLACE', 'uploaded', 1, $product);
					}
					
	
					// Update index to put position
					$ecmfile = new EcmFiles($db);
					$result_get_ecmfile = $ecmfile->fetch('', $ref);
					if ($key_image == 'image_cover'){
						$ecmfile->position = 0;
					} else {
						$position = preg_match('/_(\d+)$/', $key_image, $matches) ? $matches[1] : 100;
						$ecmfile->position = $position;
					}
					
					$result_update_ecmfile = $ecmfile->update($user);
	
					if ($result_update_ecmfile < 0) {
						dol_syslog("Error in set image " . $key_image . " result code = " . $result_update_ecmfile . " - " . $ecmfile->errorsToString());
						$error++;
					} else {
						dol_syslog("Set Image " . $key_image . " OK");
					}
				}
			}
		}		
		


		// Add package
		if (!empty($object['virtual_product_file']['name'])) {
			$package = $upload_dir . '/' . basename($object['virtual_product_file']['name']);

			if (move_uploaded_file($object['virtual_product_file']['tmp_name'], $package) != true){
				dol_syslog('Error: Failed to move uploaded file. ');
				$error++;
			} else {
				// Add index to db
				$filename = basename($object['virtual_product_file']['name']);
				addFileIntoDatabaseIndex($upload_dir, $filename, 'MARKETPLACE', 'uploaded', 1, $product);

				// Update index to put position
				$rel_dir = preg_replace('/^' . preg_quote(DOL_DATA_ROOT, '/') . '/', '', $upload_dir);
				$rel_dir = preg_replace('/^[\\/]/', '', $rel_dir);
				$ref = dol_hash($rel_dir . '/' . $filename, 3);

				$ecmfile = new EcmFiles($db);
				$result_get_ecmfile = $ecmfile->fetch('', $ref);
				$ecmfile->position = 100;
				$result_update_ecmfile = $ecmfile->update($user);

				if ($result_update_ecmfile < 0) {
					dol_syslog("Error in setPackage result code = " . $result_update_ecmfile . " - " . $ecmfile->errorsToString());
					$error++;
				} else {
					dol_syslog("Set Package OK");
				}
			}
		}
	}
    
    //$langs->setDefaultLang($_SESSION['lang']['code']);
	if ($error == 0) {
		$db->commit();
		dol_syslog("Product id=".$product->ref." successfully");
		return 1;
	} else {
		$db->rollback();
		dol_syslog('--- end error nb=' . $error);
		return $weblangs->trans("errorOccurred");
	}
}

function get_all_tags_between($start, $end) {
    $start_num = intval(substr($start, 1));
    $end_num = intval(substr($end, 1));
    
    $result = array();
    
    for ($i = $start_num; $i <= $end_num; $i++) {
        $result[] = 'V' . $i;
    }
    
    return $result;
}

// Send an email
function marketplace_send_email($id_template, $type_template, $object, $to, $additionalSubstitutionArray) {
    global $db, $conf, $user;
    
    $subject = '';
	$msg = '';

	// Send email
	include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
	$formmail = new FormMail($db);
	// Set output language
	$outputlangs = new Translate('', $conf);
	$outputlangs->setDefaultLang($_SESSION['lang']['code']);
	// Load traductions files required by page
	$outputlangs->loadLangs(array("main", "website", "marketplace@marketplace"));

	// Get email content from template
	$arraydefaultmessage = null;

	$arraydefaultmessage = $formmail->getEMailTemplate($db, $type_template, $user, $outputlangs, $id_template, 1, '');

	if (!empty($id_template) && is_object($arraydefaultmessage) && $arraydefaultmessage->id > 0) {
		$subject = $arraydefaultmessage->topic;
		$msg     = $arraydefaultmessage->content;
	}

    //$substitutionarray = $additionalSubstitutionArray;
	$substitutionarray = getCommonSubstitutionArray($outputlangs, 0, null, $object);
	$substitutionarray = array_merge($substitutionarray, $additionalSubstitutionArray);
	complete_substitutions_array($substitutionarray, $outputlangs, $object);
	$subjecttosend = make_substitutions($subject, $substitutionarray, $outputlangs);
	$texttosend = make_substitutions($msg, $substitutionarray, $outputlangs);


	$moreinheader = 'X-Dolibarr-Info: send_an_email by Marketplace'."\r\n";

	//$result = $customer->sendEmail($texttosend, $subjecttosend, array(), array(), array(), "", "", 0, -1, '', $moreinheader);
	
	
	// Detect if message is HTML
	if (dol_textishtml($texttosend, 0)) {
		$texttosend = dol_htmlentitiesbr($texttosend);
	}


	// Envoi mail confirmation
	$from = $conf->email_from;
	if (getDolGlobalString('MAIN_MAIL_EMAIL_FROM')) {
		$from = getDolGlobalString('MAIN_MAIL_EMAIL_FROM');
	}

	$trackid = 'conf'.$object->id;

	// Send email (substitutionarray must be done just before this)
	include_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
	$mailfile = new CMailFile($subjecttosend, $to, $from, $texttosend, array(), array(), array(), '', '', 0, -1, '', '', $trackid, $moreinheader);
	if ($mailfile->sendfile()) {
		return 1;
	} else {
		return 0;
	}
}

function marketplace_check_discount($id_product) {
    global $db;
    
    include_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';

    $discount = 0;
    $mode = "";
    
    $canBeDiscounted = 1;
    // Check if this product is allowed for discount
    $noDiscountProductCat = getDolGlobalInt("MARKETPLACE_DISCOUNT_EXCLUDE_PRODUCTS_CATEGORY_ID");
    if (!empty($noDiscountProductCat)) {
        $category = new Categorie($db);
        $prod_categories = $category->getListForItem($id_product, 'product');

        foreach ($prod_categories as $prod_categorie) {
            if (!empty($prod_categorie['id']) && $prod_categorie['id'] == $noDiscountProductCat) {
                $canBeDiscounted = 0;
                break;
            }
        }
    }
    
    // Check discount for preferred members
    if ($canBeDiscounted == 1 && !empty($_SESSION['user']['is_preferred_member']) && $_SESSION['user']['is_preferred_member'] == 1) {
        $discountValue = getDolGlobalInt("MARKETPLACE_PROSPECTCUSTOMER_PREFERRED_DISCOUNT");
        if (!empty($discountValue)) {
            $discount = $discountValue;
            $mode = "percent";
        }
    }
    
    // TODO Check discount for other cases
    
    return array(
        'value' => $discount,
        'mode' => $mode
    );
}

function marketplace_calculate_discounted_price($price, $discount) {
    $discounted_price = $price;
    if ($discount['value'] && $discount['mode']) {
        if ($discount['mode'] === "percent") {
            $discounted_price = $price * ((1 - $discount['value'] / 100));
        }
        
        if ($discount['mode'] === "amount") {
            $discounted_price = $price - $discount['value'];
        }
    }
    
    return $discounted_price;
}

function marketplaceNotifySellersBuyerByEmail ($order_id) {
	global $db;

	// Get order
	require_once DOL_DOCUMENT_ROOT."/commande/class/commande.class.php";
	$order = new Commande($db);
	$result = $order->fetch($order_id);

	// Get customer
	$customer = new SocieteAccount($db);
	$result = $customer->fetch($_SESSION['user']['id_user']);

	$products_list = '<ol>';

	// Find sellers
	$sql_get_order_products = "select cd.fk_product, cd.qty 
	from ".MAIN_DB_PREFIX."commandedet  cd 
	where cd.fk_commande =" .$order_id;
	if ($result_commande_det = $db->query($sql_get_order_products)) {
		while ($commande_det = $result_commande_det->fetch_object()) {
			// Get product
			$product = new Product($db);
			$result = $product->fetch($commande_det->fk_product);

			// Add product to list
			$products_list .= '<li>'.$product->label.' (x'.$commande_det->qty.')</li>';

			// Get product seller
			$sql_get_seller_id = "select lpfp.fk_soc 
				from ".MAIN_DB_PREFIX."product_fournisseur_price lpfp 
				where lpfp.fk_product =" .$product->id. " LIMIT 1";
			$resql = $db->query($sql_get_seller_id);
			$objsql = $db->fetch_object($resql);
			
			if(!empty($objsql->fk_soc)){
				// Get seller email
				$societeaccount = new SocieteAccount($db);
				$result = $societeaccount->fetch($objsql->fk_soc);
				$seller_email = $societeaccount->login;

				// Get seller name
				$seller = new Societe($db);
				$result = $seller->fetch($objsql->fk_soc);
				$seller_name = $seller->name;
				
				if ($result > 0) {
					$substitutionarray = array(
						'__SELLER_NAME__' => $seller_name,
						'__BUYER_NAME__' => strtoupper($_SESSION['user']['pseudo']),
						'__ORDER_REF__' => $order->ref,
						'__ORDER_DATE__' => dol_print_date($order->date, 'day'),
						'__PRODUCT__' => $product->label,
						'__QTY__' => $commande_det->qty
					);
					//marketplace_send_email(150, $societeaccount, $seller_email, $substitutionarray);
					marketplace_send_email(getDolGlobalInt("MARKETPLACE_SELLERS_ORDER_CONFIRMATION_TEMPLATE"), 'order_send', $societeaccount, $seller_email, $substitutionarray);
				}
			}
		}
	}
	$products_list .= "</ol>";
	
	// Send buyer email
	$substitutionarray = array(
		'__BUYER_NAME__' => strtoupper($_SESSION['user']['pseudo']),
		'__ORDER_REF__' => $order->ref,
		'__ORDER_DATE__' => dol_print_date($order->date, 'day'),
		'__PRODUCTS__' => $products_list
	);
	//marketplace_send_email(151, $customer, $customer->login, $substitutionarray);
	return marketplace_send_email(getDolGlobalInt("MARKETPLACE_BUYER_ORDER_CONFIRMATION_TEMPLATE"), 'order_send', $customer, $customer->login, $substitutionarray);
}

?>