<?php // project.php - Create and update projects
// ------------------------------------------------------------------------
// Copyright (c) 2001, 2002 The phpBugTracker Group
// Copyright (c) 2004, 2005 David Han Sze Chuen, Denis Guinnepain for Air Liquide Medical Systems (Taema)
// Copyright (c) 2005, 2006, 2015 Denis Guinnepain
// ------------------------------------------------------------------------
// This file is part of Diamentis

// Diamentis is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.

// Diamentis is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with phpBugTracker; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
// ------------------------------------------------------------------------

@include("field_builder.php");
@include("workflow.php");

chdir('..');
define('TEMPLATE_PATH', 'admin');
include("include.php");
@include("backup.php");

// //////////////////////////////////////////////////////////////////////////////
// ///////////////// GLOBALS
// //////////////////////////////////////////////////////////////////////////////

$do_edit_field = "edit_field";
$edit_field_listbox_name = 'edit_field_id';
$op_edit_selectbox = "edit_selectbox";
// //////////////////////////////////////////////////////////////////////////////
// ///////////////// FUNCTIONS
// //////////////////////////////////////////////////////////////////////////////
function del_version($versionid, $projectid) {
    global $db, $me;
    if (!$db->getOne('select count(*) from ' . TBL_BUG . " where version_id = $versionid")) {
        $db->query("delete from " . TBL_VERSION . " where version_id = $versionid");
    } 
    header("Location: $me?op=edit&id=$projectid&");
} // end of del_version($versionid, $projectid)
// //////////////////////////////////////////////////////////////////////////////
function save_version($version_id = 0) {
    global $db, $me, $_pv, $STRING, $now, $u, $t;
    $error = ''; 
    // Validation
    if (!$_pv['version_name'] = trim($_pv['version_name']))
        $error = $STRING['giveversion'];
    if ($error) {
        show_version($_pv['version_id'], $error);
        return;
    } 
    extract($_pv);
    if (!isset($active))
        $active = 0;
    if (!$version_id) {
        $db->query('insert into ' . TBL_VERSION . " (version_id, project_id, version_name, active, created_by, created_date)
				values (" . $db->nextId(TBL_VERSION) . ", $project_id, " . $db->quote(stripslashes($version_name)) . ", $active, $u, $now)");
    } else {
        $db->query('update ' . TBL_VERSION . " set project_id = $project_id, version_name = " . $db->quote(stripslashes($version_name)) . ", active = $active where version_id = '$version_id'");
    } 
    if ($use_js) {
        $t->display('admin/edit-submit.html');
    } else {
        header("Location:$me?op=edit&id=$project_id");
    } 
} // end of save_version($version_id = 0)
// //////////////////////////////////////////////////////////////////////////////
function show_version($versionid = 0, $error = '') {
    global $db, $t, $_pv, $STRING, $QUERY, $_gv;
    foreach ($_pv as $k => $v) $$k = $v;
    if ($versionid) {
        $t->assign($db->getRow(sprintf($QUERY['admin-show-version'], $versionid)));
    } else {
        if (!empty($_gv['project_id']))
            $t->assign('project_id', $_gv['project_id']);
        $t->assign($_pv);
    } 
    $t->assign('error', $error);
    $t->wrap('admin/version-edit.html', ($versionid ? 'editversion' : 'addversion'));
} // end of show_version($versionid = 0, $error = '')
// //////////////////////////////////////////////////////////////////////////////
function del_component($componentid, $projectid) {
    global $db, $me;
    if (!$db->getOne('select count(*) from ' . TBL_BUG . " where component_id = $componentid")) {
        $db->query("delete from " . TBL_COMPONENT . " where component_id = $componentid");
    } 
    header("Location: $me?op=edit&id=$projectid&");
} // end of del_component($componentid, $projectid)
// //////////////////////////////////////////////////////////////////////////////
function save_component($component_id = 0) {
    global $db, $me, $_pv, $u, $STRING, $now, $t;
    $error = ''; 
    // Validation
    if (!$_pv['component_name'] = trim($_pv['component_name']))
        $error = $STRING['givename'];
    elseif (!$_pv['component_desc'] = trim($_pv['component_desc'])) $error = $STRING['givedesc'];
    if ($error) {
        show_component($_pv['component_id'], $error);
        return;
    } 
    foreach ($_pv as $k => $v) $$k = $v;
    if (!$owner)
        $owner = 0;
    if (!$active)
        $active = 0;
    if (!$component_id) {
        $db->query('insert into ' . TBL_COMPONENT . " (component_id, project_id, component_name, component_desc, owner,
				active, created_by, created_date, last_modified_by, last_modified_date)
				values (" . $db->nextId(TBL_COMPONENT) . ", $project_id, " . $db->quote(stripslashes($component_name)) . ", " . $db->quote(stripslashes($component_desc)) . ", $owner, $active, $u, $now, $u, $now)");
    } else {
        $db->query('update ' . TBL_COMPONENT . " set component_name = " . $db->quote(stripslashes($component_name)) . ', component_desc = ' . $db->quote(stripslashes($component_desc)) . ", owner = $owner, active = $active, last_modified_by = $u, " . "last_modified_date = $now where component_id = $component_id");
    } 
    if ($use_js) {
        $t->display('admin/edit-submit.html');
    } else {
        header("Location: $me?op=edit&id=$project_id");
    } 
} // end of save_component($component_id = 0)
// //////////////////////////////////////////////////////////////////////////////
function show_component($componentid = 0, $error = '') {
    global $db, $t, $_pv, $STRING, $QUERY, $_gv;
    if ($componentid) {
        $t->assign($db->getRow(sprintf($QUERY['admin-show-component'], $componentid)));
    } else {
        if (!empty($_gv['project_id']))
            $t->assign('project_id', $_gv['project_id']);
        $t->assign($_pv);
    } 
    $t->assign('error', $error);
    $t->wrap('admin/component-edit.html', ($componentid ? 'editcomponent' : 'addcomponent'));
} // end of show_component($componentid = 0, $error = '')


function add_project_group_perm($project_id,$group_name,$perm_name)
{
	global $db;
	if (DB::isError($db->query("REPLACE INTO " . TBL_PROJECT_GROUP . " (project_id, group_id, perm_id) SELECT '$project_id',ag.group_id,ap.perm_id 
				FROM " . TBL_AUTH_GROUP . " ag, " . TBL_AUTH_PERM . " ap WHERE ag.group_name='$group_name' AND ap.perm_name='$perm_name' ") )) 
	{
		death("DBerror 01","permission attribution failed");
	}
}

function remove_project_group_perm($project_id,$group_name,$perm_name)
{
	global $db;
	if (DB::isError($db->query("DELETE pg.* FROM " . TBL_PROJECT_GROUP . " pg, " . TBL_AUTH_PERM . " ap , " . TBL_AUTH_GROUP . " ag 
				WHERE pg.project_id=$project_id AND pg.group_id=ag.group_id AND group_name='$group_name' AND pg.perm_id=ap.perm_id AND ap.perm_name='$perm_name'") )) 
	{
		death("DBerror 02","permission suppression failed");
	}
}

// //////////////////////////////////////////////////////////////////////////////
// FM 171 D.Guinnepain 24/02/04 Add project admin right management
// function save_project($projectid = 0)
// 06/09/04 : move to mementoPlus :
// Validation : verify project name, project desc, usergroup
// New project validation : remove component and version checks because fields are unknown at creation
function save_project($projectid = 0) {
    global $db, $me, $u, $STRING, $now, $_pv, $QUERY;
    $error = ''; 
    // Validation
    if (!$_pv['project_name'] = htmlspecialchars(trim($_pv['project_name']))) {
        $error = $STRING['givename'];
    } elseif (!$_pv['project_desc'] = htmlspecialchars(trim($_pv['project_desc']))) {
        $error = $STRING['givedesc'];
    } elseif (isset($_pv['usergroup']) and is_array($_pv['usergroup']) and in_array('all', $_pv['usergroup']) and count($_pv['usergroup']) > 1) {
        $error = $STRING['project_only_all_groups'];
    } 
    if ($error) {
        show_project($projectid, $error);
        return;
    } 
    if ($error) {
        show_project($projectid, $error);
        return;
    } 
    foreach ($_pv as $k => $v) $$k = $v;
    if (!isset($active))
        $active = 0;
    if (!isset($sequence))
        $sequence = 0;
    if (!isset($share_view_all))
        $share_view_all = 0;
    if (!isset($share_struct))
        $share_struct = 0;
    if (!isset($authorize_request))
        $authorize_request = 0;
    if (!isset($share_new))
        $share_new = 0;
    if (!isset($share_edit_log))
        $share_edit_log = 0;
    if (!$projectid) {
		$projectid = $db->nextId(TBL_PROJECT);
		$projectTableFileName=TBL_PREFIX . "file_prj_id_" . "$projectid";
		
		$default_status_id = get_open_status_ids();
		if (count($default_status_id)) {
			reset($default_status_id);
			$default_status_id = current($default_status_id);
		} else {
			$default_status_id = 0;
		}
		
		$sql=sprintf($QUERY['init_file_table'], $projectTableFileName, $default_status_id);
		$res=$db->query($sql);
		if (DB::isError($res)) {
			death("DBerror","file table creation failed");
		}
		if ($_pv['list_projects']=="none")
    		{
    			$_pv['list_projects']=PUBLIC_PROJECT_ID;
    		}
		//get all public fields which are non internally used by the system
		$db->query('insert into ' . TBL_PROJECT . " (project_id, project_name, project_desc, active, sequence, share_view_all, share_struct, authorize_request, share_new, share_edit_log, parent_project_id, created_by, created_date, file_table_name)
			values ($projectid , " . $db->quote(stripslashes($project_name)) . ", " . $db->quote(stripslashes($project_desc)) . ", $active, $sequence, $share_view_all, $share_struct, $authorize_request, $share_new, $share_edit_log, " . $_pv['list_projects'] . " , $u, $now, " . $db->quote($projectTableFileName) .")");
		$res=array();
		$myMPFile = & new MPFile($projectid);
		$res=$myMPFile->sp_cache;
		//add fields to the file table
		if (!empty($res)) {	
			foreach($res as $k => $v) {
				if (!isset($v->internal_system_use) or ($v->internal_system_use==false)) {
					$myMPFile->alterField($myMPFile->project_field_properties[$k]['field_conf_id'],'create');
				}	
			}
		}
    } else {
		$db->query('update ' . TBL_PROJECT . " set project_name = " . $db->quote(stripslashes($project_name)) . ", project_desc = " . $db->quote(stripslashes($project_desc)) . ", active = $active, sequence = $sequence, share_view_all = $share_view_all, share_struct = $share_struct, authorize_request = $authorize_request, share_new = $share_new, share_edit_log = $share_edit_log where project_id = $projectid");
    } 

	if ($share_view_all == 0)
	{
		remove_project_group_perm($projectid,'User','View');
	}
	else
	{
		add_project_group_perm($projectid,'User','View');
	}

	if ($share_edit_log == 0)
	{
		remove_project_group_perm($projectid,'User','Editbug');
	}
	else
	{
		add_project_group_perm($projectid,'User','Editbug');
	}

	if ($authorize_request == 0)
	{
		remove_project_group_perm($projectid,'User','Invite');
	}
	else
	{
		add_project_group_perm($projectid,'User','Invite');
	}


/*    // Handle project -> group relationship
    $old_usergroup = $db->getCol('select group_id from ' . TBL_PROJECT_GROUP . " where project_id = $projectid");
    if (isset($usergroup) and is_array($usergroup) and count($usergroup)) {
        if (in_array('all', $usergroup)) {
            // User selected 'All groups'
            if (count($old_usergroup)) {
                $db->query('delete from ' . TBL_PROJECT_GROUP . " where project_id = $projectid");
            } 
        } else {
            // Compute differences between old and new
            $remove_from = array_diff($old_usergroup, $usergroup);
            $add_to = array_diff($usergroup, $old_usergroup);
            if (count($remove_from)) {
                foreach ($remove_from as $group) {
                    $db->query('delete from ' . TBL_PROJECT_GROUP . " where project_id = $projectid
							 and group_id = $group");
                } 
            } 
            if (count($add_to)) {
                foreach ($add_to as $group) {
                    $db->query("insert into " . TBL_PROJECT_GROUP . " (project_id, group_id, created_by, created_date)
					  	values ('$projectid' ,'$group', $u, $now)");
                } 
            } 
        } 
    } elseif (count($old_usergroup)) {
        // User selected nothing, so consider it 'All groups'
        $db->query('delete from ' . TBL_PROJECT_GROUP . " where project_id = $projectid");
    } 
*/


header("Location: $me?op=edit&id=$projectid");
} // end of save_project($projectid = 0)
// //////////////////////////////////////////////////////////////////////////////
// FM 171 D.Guinnepain 24/02/04 Add project admin right management
function show_project($projectid = 0, $error = null,$extra_users=array()) {
    global $db, $me, $t, $TITLE, $_gv, $_pv, $QUERY, $perm,$restricted_projects,$DiaBackup;
    if (is_array($error))
        $t->assign($error);
    else
        $t->assign('error', $error);
    $t->assign('project_groups', $db->getCol('select group_id from ' . TBL_PROJECT_GROUP . " where project_id = $projectid")); 
    // FM 171
//    $ProjectPermAdmin = $db->getOne('select perm_id from ' . TBL_AUTH_PERM . " where perm_name ='Admin'");
//    $ProjectPermEdit = $db->getOne('select perm_id from ' . TBL_AUTH_PERM . " where perm_name ='Editbug'");
//    $t->assign('project_admins', $db->getCol('select user_id from ' . TBL_PROJECT_PERM . " where project_id = $projectid and perm_id = $ProjectPermAdmin")); 
//    $t->assign('extra_users', $db->getCol('select user_id from ' . TBL_PROJECT_PERM . " where project_id = $projectid and perm_id = $ProjectPermEdit")); 
    $t->assign('extra_users', $extra_users); 
    // EndOf FM 171
    if ($projectid) {
        // to access the dynamic fields configuration page
        $t->assign("edit_project_fields_url", "$me?op=edit_project_fields&id=$projectid");

        $t->assign($db->getRow('select * from ' . TBL_PROJECT . " where project_id = $projectid"));
		// TODO : do a better presentation of a project fields. One for viewing, and the other one for editing (which is already done)
        // $t->assign(array('components' => $db->getAll(sprintf($QUERY['admin-list-components'], $projectid)), 'versions' => $db->getAll(sprintf($QUERY['admin-list-versions'], $projectid))));
        $t->assign('Backup',$DiaBackup);
        $t->wrap('admin/project-edit.html', 'editproject');
    } else {
        if (!empty($_pv)) {
            $t->assign($_pv);
        } else {
            $t->assign('active', 1);
        } 
	$list_of_project = array();
//	$array_rest_pj=explode(',', $restricted_projects);
	foreach($db->getAll("SELECT * FROM " . TBL_PROJECT . " WHERE share_struct<>0" ) as $v) {
//		if (!in_array($v['project_id'], $array_rest_pj))
//		{
			$list_of_project[$v['project_id']] = htmlspecialchars($v['project_name']);
//		}
	}	
	$t->assign('list_of_project', $list_of_project);

	$t->wrap('admin/project-add.html', 'addproject');
    } 
} // end of show_project($projectid = 0, $error = null)
// //////////////////////////////////////////////////////////////////////////////
function list_projects() {
    global $me, $db, $t, $selrange, $_gv, $STRING, $TITLE, $perm, $restricted_projects,$u,$permValue;
    if (!isset($_gv['order'])) {
        $order = 'created_date';
        $sort = 'asc';
    } else {
        $order = $_gv['order'];
        $sort = $_gv['sort'];
    } 
    $db->page = isset($_gv['page']) ? $_gv['page'] : 1;
    $nr = $db->getOne("select count(*) from " . TBL_PROJECT);
    list ($selrange, $llimit) = multipages($nr, $page, "order=$order&sort=$sort"); 
    // Show only active projects with at least one component
	
	// if the user is the main admin
    if ($perm->have_perm('Admin')) { // Show admins all projects
        $p_query2 = '';
		
		// add support for public fields
		$configure_public_fields = true;
		$t->assign("configure_public_fields", $configure_public_fields);
    } else { // Filter out projects that can't be seen by this user
        $p_query2 = ", " . TBL_PROJECT_PERM . " pp where p.project_id = pp.project_id AND pp.user_id=$u AND pp.perm_id=" . $permValue['Admin'];
    } 
	
	$projects = $db->getAll($db->modifyLimitQuery("select * from " . TBL_PROJECT . " p $p_query2 order by $order $sort", $llimit, $selrange));
	//DEBUG
	//printarray($projects);	
    $t->assign('projects', $projects);
    
	$headers = array(
		'projectid' => 'project_id', 
		'name' => 'project_name', 
		'description' => 'project_desc', 
		'active' => 'active', 
		'createdby' => 'created_by', 
		'createddate' => 'created_date'
	);
    sorting_headers($me, $headers, $order, $sort);
    $t->wrap('admin/projectlist.html', 'project');
} // end of list_projects()
// //////////////////////////////////////////////////////////////////////////////
/**
Same as the function show_project_fields_manager(), only for the public project.
*/
function show_public_fields_manager() {
    return show_project_fields_manager(null, true);
} 
// //////////////////////////////////////////////////////////////////////////////
/**
Print a list of a project fields including public and private fields properties.
*/
function show_project_fields_manager($project_id = null, $is_public = false /*, $user_name_field=null*/) {
    // global $me, $db, $t, $selrange, $_gv, $STRING, $TITLE, $perm, $restricted_projects;
    global $perm, $me, $db, $t, $selrange, $_gv, $STRING, $TITLE, $do_edit_field, $edit_field_listbox_name;
	// create a MPFile instance
	$mpfile = &new MPFile($project_id);
	$project_id = $mpfile->project_data['project_id'];
	//if(empty($user_name_field))
	//	$user_name_field = "email"; // by default, print the email as the user name
	
	if (!isset($_gv['order'])) {
        $order = 'edit_order';
        $sort = 'asc';
    } else {
        $order = $_gv['order'];
        $sort = $_gv['sort'];
    } 	
	
	// prepare the sql query
	$options = array();
	$options['link'] = array();
	$options['link']['created_by'] = true;
	$options['link']['last_modified_by'] = true;
	$options['order'] = $order;
	$options['sort'] = $sort;
	$options['countRows'] = true;
	
	//DEBUG
	//println("options before : ");
	//printarray($options);
	
	$nr = $mpfile->getFieldsProperties($project_id, $options); // number of rows -> nb of project fields
	// list ($selrange, $llimit) = multipages($nr, $page, "order=$order&sort=$sort");

	// make sql query
	$options['countRows'] = false;
	$options['returnQuery'] = true;
	$sql = $mpfile->getFieldsProperties($project_id, $options);
	
	//DEBUG
	//println("sql = $sql");
	
	// search all fields, with user names
	// $fields = $db->getAll($db->modifyLimitQuery($sql, $llimit, $selrange));	
	$fields = $db->getAll($sql);	
    
	//DEBUG
	//println("\$sql = $sql");
	//println("\$nr = $nr");
	//println("\$selrange = $selrange");
	//println("\$llimit = $llimit");	
	//printarray($fields);
	
	$t->assign('fields', $fields);
    $headers = array('field_conf_id' => 'field_conf_id',
        'title' => 'title',
		'field_type_title' => 'field_type_title',
        'description' => 'description',
        'default_value' => 'default_value',
        'edit_order' => 'edit_order',
        'list_order' => 'list_order',
        'properties' => 'properties',
        'created_by' => 'created_by',
        'created_date' => 'created_date',
        'last_modified_by' => 'last_modified_by',
        'last_modified_date' => 'last_modified_date');
    sorting_headers($me, $headers, $order, $sort, "op=" . (($is_public)? 'edit_public_fields' : "edit_project_fields&id={$project_id}"));
	if ($is_public) {
	    $page_title = htmlspecialchars($STRING['configure_public_fields']);
	}
	else {
		$page_title = htmlspecialchars($STRING['configure_project_fields']);
		//$t->assign("project_name", $db->getOne("select project_name from " . TBL_PROJECT . " pj where pj.project_id = '$project_id'"));
		$t->assign("project_name", $mpfile->project_data['project_name']);
	}
	
	// what are the public fields ?
	// $public_field_names = $mpfile->getFieldName_by_SubProperty('internal_system_use', true, $cmp_type='bool');
	$parent_field_names = array();
	foreach ($mpfile->project_field_properties as $fname => $v) {
		if ($v['project_id'] != $project_id) {
			$parent_field_names[] = $fname;
		}
	}
	// are they editable ? need admin rights
	// public fields are editable only if the edited project is the public one and the user must be admin
	$allowed_to_edit_project_fields = false;//$perm->have_project_perm($project_id,'Admin');
	
	//DEBUG
	//println("public field names");
	//printarray($public_field_names);
	
	// get data for the option list at the bottom, it will be used to select a field for editing
	$field_to_select = array();
	foreach($fields as $k => $v) {
		if ($v['project_id']==$project_id){//$allowed_to_edit_project_fields or !in_array($v['field_name'], $public_field_names)) {
			$field_to_select[$v['field_conf_id']] = $v['title'];
		}
	}
	
	// prepare listbox
	$html_src = listbox($edit_field_listbox_name, $field_to_select, $cmdtype = 11);
	
	$t->assign('parent_field_names', $parent_field_names);
	$t->assign('allowed_to_edit_project_fields', $allowed_to_edit_project_fields);
	//$t->assign('current_project_id', $project_id); // the project id of the current edited project
	
	// build url link to add a new field
	$t->assign('add_new_field_url', $me  ."?op=add_field&step=1&id=" . (($project_id != null)? $project_id : "public"));

	$t->assign('back_url', $me . "?op=edit&id=" . (($project_id == null)? PUBLIC_PROJECT_ID : $project_id));
	$t->assign('select_field', $html_src);
	$t->assign('edit_field_url', "{$me}");
	$t->assign('do_edit_fields', 'do_edit_field');
	// $_SESSION['current_edited_project_id'] = $project_id; // save the current edited project
    $t->wrap('admin/project_edit_fields.html', $page_title);
} // end of show_project_fields_manager($project_id = null, $is_public = false /*, $user_name_field=null*/)
// //////////////////////////////////////////////////////////////////////////////
/** 
Prepare a form to edit a project field or treat its results
@param integer $field_conf_id the field_conf id
@param string $cmdtype the type of action to do : 'form' or 'treat'
@param boolean $verbose print debug info
@return void
*/
function edit_field_manager($field_conf_id, $cmdtype = 'form', $verbose = false) {
	global $t, $STRING, $db, $op_edit_selectbox, $me, $do_edit_field;
	//$do_edit = 'do_edit';
	$title_input = 'title'; // these are the column names
	$description_input = 'description';
	$default_value_input = 'default_value';
	$edit_order_input = 'edit_order';
	$list_order_input = 'list_order';	
	$subproperties_input = array(
		'maxlen' => 'sp[maxlen]', 
		'int_size' => 'sp[int_size]', 
		'decimal_size' => 'sp[decimal_size]', 
		'read_only' =>'sp[read_only]', 
		'declare' =>'sp[declare]', 
		'hidden' =>'sp[hidden]', 
		'dashAfter' =>'sp[dashAfter]', 
		'label' =>'sp[label]', 
		'unique' => 'sp[unique]', 
		'internal_system_use' => 'sp[internal_system_use]', 
		'highlight_url' => 'sp[highlight_url]', 
		'time_type' => 'sp[time_type]',
		'twin_ref_id' => 'sp[SB_twin_id]'
	);
	
	$time_type = array(
		"date" => "date", 
		"hour" => "hour", 
		"time" => "time"
	);
	
	$posted_keys = array($title_input, $description_input, $default_value_input, $edit_order_input, $list_order_input, $list_order_input, 'sp');
	
	/*
	vu dans MPSubProperty :
	    var $_type_numeric = array("maxlen", "int_size", "decimal_size");
    var $_type_bool = array("read_only", "unique", "internal_system_use", "highlight_url");
    var $_type_enum = array("time_type" => array("date", "hour", "time"));
	*/
	
	$project_id = MPFile::getProject_id_from_Field_Conf ($field_conf_id);	
	$mpfile = & new MPFile($project_id);
	
	$options = array();
	$options['link'] = array();
	$options['link']['created_by'] = true;
	$options['link']['last_modified_by'] = true;
	$options['order'] = $order;
	$options['sort'] = $sort;
	$options['field_conf_id'] = $field_conf_id;
	$res = $mpfile->getFieldsProperties($project_id, $options);
	$res = $res[0]; // there should be only one result
	// subproperties
	$prop = & $mpfile->sp_cache[$res['field_name']];
	/*
		0 :  	['0'] 	['field_conf_id']  	=	 1
		1 : 	['0'] 	['project_id'] 	=	17
		2 : 	['0'] 	['field_type_id'] 	=	2
		3 : 	['0'] 	['field_name'] 	=	title
		4 : 	['0'] 	['title'] 	=	Title
		5 : 	['0'] 	['description'] 	=	The title of the file.
		6 : 	['0'] 	['edit_order'] 	=	13
		7 : 	['0'] 	['list_order'] 	=	2
		8 : 	['0'] 	['default_value'] 	=	
		9 : 	['0'] 	['properties'] 	=	maxlen=255;
		10 : 	['0'] 	['created_by'] 	=	38
		11 : 	['0'] 	['created_date'] 	=	0
		12 : 	['0'] 	['last_modified_by'] 	=	38
		13 : 	['0'] 	['last_modified_date'] 	=	0
		14 : 	['0'] 	['field_type_title'] 	=	String
		15 : 	['0'] 	['field_type_description'] 	=	Accepts either a length limited or unlimited string
		16 : 	['0'] 	['_username1'] 	=	david.han-sze-chuen@airliquide.com
		17 : 	['0'] 	['_username2'] 	=	david.han-sze-chuen@airliquide.com
		*/
		
	if ($cmdtype == 'form') {
	
		// prepare edit form 
		$input = array();
		
		$input['title'] = text($title_input, $res['title'], 11);
		$input['description'] = textarea($description_input, 24, 5, $res['description'], 11);		
		
		// $input['default_value'] = text($default_value_input, htmlspecialchars($res['default_value']), 11);		
		
		$input['edit_order'] = text($edit_order_input, $res['edit_order'], 11);
		$input['list_order'] = text($list_order_input, $res['list_order'], 11);		
		
		$input['properties'] = array();
		$prop_html = &$input['properties'];
		
		//if(true || isset($prop->maxlen)) {
		if ($res['field_type_title'] == STRING_TYPE) {
			$prop_html['maxlen'] = htmlspecialchars($STRING['properties']['maxlen']) . " : " . text($subproperties_input['maxlen'], $prop->maxlen, 11);
			$prop_html['maxlen'] = htmlsurround($prop_html['maxlen'], $tag_name = "td", $tag_option = "");
			$prop_html['maxlen'] = htmlsurround($prop_html['maxlen'], $tag_name = "tr", $tag_option = "");
			
			$opt = (($prop->maxlen != 0)? "maxlength=\"$prop->maxlen\"" : '');			
			
			if ($prop->maxlen == 0)
			{
				$input['default_value'] = textarea($default_value_input, 24, 5, $res['default_value'], 11);		
			}
			else
			{
				$input['default_value'] = text($default_value_input, htmlspecialchars($res['default_value']), 11, $opt);
			}
		}
		if (($res['field_type_title'] == INTEGER_TYPE) || ($res['field_type_title'] == FLOAT_TYPE)) {
			$prop_html['int_size'] = htmlspecialchars($STRING['properties']['int_size']) . " : " . text($subproperties_input['int_size'], $prop->int_size, 11);
			$prop_html['int_size'] = htmlsurround($prop_html['int_size'], $tag_name = "td", $tag_option = "");
			$prop_html['int_size'] = htmlsurround($prop_html['int_size'], $tag_name = "tr", $tag_option = "");
			$input['default_value'] = text($default_value_input, $res['default_value'], 11);
		}
		if ($res['field_type_title'] == FLOAT_TYPE) {
			$prop_html['decimal_size'] = htmlspecialchars($STRING['properties']['decimal_size']) . " : " . text($subproperties_input['decimal_size'], $prop->decimal_size, 11);
			$prop_html['decimal_size'] = htmlsurround($prop_html['decimal_size'], $tag_name = "td", $tag_option = "");
			$prop_html['decimal_size'] = htmlsurround($prop_html['decimal_size'], $tag_name = "tr", $tag_option = "");
		}
		// always available
		$str = YesNoQuestion($subproperties_input['read_only'], $msg = htmlspecialchars($STRING['properties']['read_only'],ENT_QUOTES,$STRING['lang_charset']), $yes = $prop->read_only, $cmdtype = 11, $option = '');
		$str = htmlsurround($str, $tag_name = "td", $tag_option = "");
		$str = htmlsurround($str, $tag_name = "tr", $tag_option = "");
		$prop_html['read_only'] = $str;
		
		// always available
		$str = YesNoQuestion($subproperties_input['declare'], $msg = htmlspecialchars($STRING['properties']['declare'],ENT_QUOTES,$STRING['lang_charset']), $yes = $prop->declare, $cmdtype = 11, $option = '');
		$str = htmlsurround($str, $tag_name = "td", $tag_option = "");
		$str = htmlsurround($str, $tag_name = "tr", $tag_option = "");
		$prop_html['declare'] = $str;
		
		
		if ($res['field_name'] != SELECTBOX_STATUS) 
		{
			$t->assign('isStatus', false);
			$str = YesNoQuestion($subproperties_input['hidden'], $msg = htmlspecialchars($STRING['properties']['hidden'],ENT_QUOTES,$STRING['lang_charset']), $yes = $prop->hidden, $cmdtype = 11, $option = '');
			$str = htmlsurround($str, $tag_name = "td", $tag_option = "");
			$str = htmlsurround($str, $tag_name = "tr", $tag_option = "");
			$prop_html['hidden'] = $str;
		}
		else
		{
			$t->assign('isStatus', true);
		}
		//println("affichage variable débug $msg");
		//printarray($subproperties_input);
		// always available
		$str = YesNoQuestion($subproperties_input['dashAfter'], $msg = htmlspecialchars($STRING['properties']['dashAfter'],ENT_QUOTES,$STRING['lang_charset']), $yes = $prop->dashAfter, $cmdtype = 11, $option = '');
		$str = htmlsurround($str, $tag_name = "td", $tag_option = "");
		$str = htmlsurround($str, $tag_name = "tr", $tag_option = "");
		$prop_html['dashAfter'] = $str;


		// always available
		$str = YesNoQuestion($subproperties_input['label'], $msg = htmlspecialchars($STRING['properties']['label'],ENT_QUOTES,$STRING['lang_charset']), $yes = $prop->label, $cmdtype = 11, $option = '');
		$str = htmlsurround($str, $tag_name = "td", $tag_option = "");
		$str = htmlsurround($str, $tag_name = "tr", $tag_option = "");
		$prop_html['label'] = $str;
		
		
		if ($res['field_type_title'] == STRING_TYPE) {
			$str = YesNoQuestion($subproperties_input['highlight_url'], $msg = htmlspecialchars($STRING['properties']['highlight_url'],ENT_QUOTES,$STRING['lang_charset']), $yes = $prop->highlight_url, $cmdtype = 11, $option = '');
			$str = htmlsurround($str, $tag_name = "td", $tag_option = "");
			$str = htmlsurround($str, $tag_name = "tr", $tag_option = "");
			$prop_html['highlight_url'] = $str;
		}
		//if(true || isset($prop->time_type)) {
		if ($res['field_type_title'] == TIMESTAMP_TYPE) {
			$str = htmlspecialchars($STRING['properties']['time_type'] . " : ");
			//listbox($name, $value, $cmdtype = 1, $multiple = false, $selected = null, $option = '')
			$str .= listbox($subproperties_input['time_type'], $time_type, $cmdtype = 11, false, $selected = array_search($prop->time_type, $time_type));
			$str = htmlsurround($str, $tag_name = "td", $tag_option = "");
			$str = htmlsurround($str, $tag_name = "tr", $tag_option = "");			
			$prop_html['time_type'] = $str;
			
			$opt = "onChange=\"javascript:return checkDate(this)\"";
			$input['default_value'] = text($default_value_input, htmlspecialchars(date(DATE_FORMAT, $res['default_value']),ENT_QUOTES,$STRING['lang_charset']), 11, $opt);
		}
		if(isset($prop->internal_system_use)) { 		
			$str = "<b>" . htmlspecialchars($STRING['properties']['internal_system_use']) . "</b>";
			$str = htmlsurround($str, $tag_name = "td", $tag_option = "");
			$str = htmlsurround($str, $tag_name = "tr", $tag_option = "");
			$prop_html['internal_system_use'] = $str;
		}
		
		#if ($res['field_type_title'] == SELECT_TWINBOX_TYPE) {		
		#	$str = htmlsurround("", $tag_name = "input", $tag_option = "type=hidden value=". $prop->SB_twin_id . " name=sp[SB_twin_id]");
		#        $prop_html['SB_twin_id'] = $str;
		#			
		#}
		if ($res['field_type_title'] == SELECTBOX_TYPE) {		
			$str = YesNoQuestion($subproperties_input['unique'], $msg = htmlspecialchars($STRING['properties']['unique'],ENT_QUOTES,$STRING['lang_charset']), $yes = $prop->unique, $cmdtype = 11, $option = '');
			$str = htmlsurround($str, $tag_name = "td", $tag_option = "");
			$str = htmlsurround($str, $tag_name = "tr", $tag_option = "");
			$prop_html['unique'] = $str;
		
			$t->assign('edit_selectbox_url', "project.php?op={$op_edit_selectbox}&fid={$field_conf_id}");
			$t->assign('isSelectBox', true);
			
			if ($res['field_name'] != 'assigned_to') {
				// get the list of selectbox values
				$list_values = array();
				$list_titles = array();
				$sql = "SELECT * FROM " . TBL_SELECTBOX_VALUE . " WHERE field_conf_id = " . $db->quote($field_conf_id) . " ORDER BY sv_order asc";
				$result = $db->getAll($sql);
				foreach($result as $v) {
					$list_values[$v['sv_id']] = $v['sv_value'];
					$list_titles[$v['sv_id']] = $v['sv_description'];
				}
				
				$input['default_value'] = listbox($default_value_input, $list_values, 11, false, $res['default_value'], '', $list_titles);
			} else {
				$input['default_value'] = $STRING['disabled'];
			}
		}
		
		$t->assign('goto_url', "{$me}?" . array_to_getvars($_GET) . "&validate=1");
		$t->assign('back_url', $me . "?op=" . (($project_id == PUBLIC_PROJECT_ID)? 'edit_public_fields' : "edit_project_fields&id=$project_id"));
		$t->assign('workflow_url', $me  ."?op=advanced_list&message=" . rawurlencode($res['title'] . " : " . $STRING['define_visibility']) . "&id=" . $res['field_conf_id']);
		$t->assign('action', "field");
		$t->assign('input', $input);
		$t->assign('data', $res);
		$t->wrap('admin/field-edit.html');
		return;
	} // end of 'form'
	if ($cmdtype == 'treat') { // we have to treat the user's form
		//DEBUG
		//println("edit_field_manager() : Treat submit data");
		
		//DEBUG
		//println("Old field conf data : ");
		//printarray($res);
		//println("old sp : ");
		//$prop->toString(true, true);		
		
		if (isset($prop->SB_twin_id))
		{
			$new_sp = "SB_twin_id=" . $prop->SB_twin_id . ";";
		}
		else
		{
		$new_sp = '';
		}
		
		// for each posted value
		foreach($_POST as $k => $v) {
			if (in_array($k, $posted_keys)) { // if value name is to be used
				if ($k != 'sp') { // if it's a normal field conf value
					$res[$k] = stripslashes($v);
				} else { // if it's a subproperty
					// so, $v is an array
					foreach($v as $prop_name => $prop_value) {
						// if the property is known
						if (isset($subproperties_input[$prop_name])) {
							// assemble a subproperty string
							$new_sp .= "{$prop_name}=" . rawurlencode(stripslashes($prop_value)) .';';
						}
					}
				}
			}
		}
		
		$res['title'] = trim(strip_tags($res['title']));
		$res['description'] = trim(strip_tags($res['description']));
		$res['edit_order'] = intval($res['edit_order']);
		$res['list_order'] = intval($res['list_order']);
		
		switch($res['field_type_title']) {
			case SELECTBOX_TYPE :
				$res['default_value'] = trim(stripslashes($res['default_value']));
				break;
			case INTEGER_TYPE :
				$res['default_value'] = intval($res['default_value']);
				break;
			case FLOAT_TYPE :
				$res['default_value'] = floatval($res['default_value']);
				break;
			case STRING_TYPE :
				$res['default_value'] = trim(stripslashes($res['default_value']));
				break;
			case TIMESTAMP_TYPE :
				if (!empty($res['default_value'])) {
					$res['default_value'] = convertDate(stripslashes($res['default_value']), $verbose);
				} else $res['default_value'] = 0;
				break;
		}
		
		if (strlen($res['title']) == 0) {
			death('ERROR EMPTY TITLE', 'edit_field_manager() : the field title must not be empty.');
		}
		
		// who modified the field ?
		$res['last_modified_by'] = $_SESSION['uid'];
		
		// create a new subproperty if needed
		if ($new_sp != '') {
			//DEBUG
			//println("New sp : str : $new_sp");
			$new_sp = & new MPSubProperty($new_sp);
			$new_sp->internal_system_use = $prop->internal_system_use;
			$res['properties'] = $new_sp->toString(false, false);
		}
		//else $new_sp = false;
		
		// give this data to MPFile for field conf updating
		//DEBUG
		//println("New field conf data : ");
		//printarray($res);
		//if ($new_sp !== false) {
		//	println("new sp : ");
		//	$new_sp->toString(true, true);
		//}
		// update the field conf
		$mpfile->alterFieldConf($field_conf = $res, $selectbox_values = null, $action='update', false, $verbose);
		
		// prepare to update the file table
		// $mpfile->reloadCache($verbose);
		// update Memento Plus DB
		$ret = MPFile::alterFieldForAll($field_conf_id, 'change', $verbose);
		
		// go to project list
		redirection("project.php?op=" . (($project_id == PUBLIC_PROJECT_ID)? 'edit_public_fields' : "edit_project_fields&id=$project_id"));		
		//	((!empty($_SESSION['current_edited_project_id']))? 'edit_project_fields' : 'edit_public_fields') . 
		//	"&id=" . 
		//	(isset($_SESSION['current_edited_project_id'])? $_SESSION['current_edited_project_id'] : $project_id));		
	} // end of 'treat'
} // end of edit_field_manager($field_conf_id, $cmdtype = 'form', $verbose = false)
// //////////////////////////////////////////////////////////////////////////////
/** 
Prepare a form to edit the selectbox values of a project_field or treat its results
@param integer $field_conf_id the field_conf id
@param string $cmdtype the type of action to do : 'form' or 'treat'
@param boolean $verbose print debug info
@return void
*/
function edit_selectbox_manager($field_conf_id, $cmdtype = 'form', $verbose = false) {
	global $t, $STRING, $db, $do_edit_field;

	//DEBUG
	//println("edit_selectbox_manager()");
	
	$posted_keys = array(
		'value' => 'sv_value', // these are the column names
		'description' => 'sv_description',
		'order' => 'sv_order',	
		'options' => array(
				'reserved' => 'reserved',
				'closed' => 'closed',
			)
	);
	
	$cmdtype = strtolower($cmdtype);
	
	$project_id = MPFile::getProject_id_from_Field_Conf ($field_conf_id);	
	$mpfile = & new MPFile($project_id);
	
	$options = array();
	$options['link'] = array();
	$options['link']['created_by'] = true;
	$options['link']['last_modified_by'] = true;
	$options['order'] = $order;
	$options['sort'] = $sort;
	$options['field_conf_id'] = $field_conf_id;
	$res = $mpfile->getFieldsProperties($project_id, $options);
	$res = $res[0]; // there should be only one result
	$field_name = $res['field_name'];
	// subproperties
	$prop = & $mpfile->sp_cache[$field_name];
	// selectbox 
	$sb = $mpfile->sb_cache;
	
	// gather the sb for this field conf and reassign the sv_id to the sb data
	$temp = array();
	foreach($sb as $k => $v) {
		if ($v['field_conf_id'] == $field_conf_id) {
			$temp[$k] = $v;
			$temp[$k]['sv_id'] = $k;
		}
	}
	$mod_sb = $temp;
	
	if($verbose) {
		println('res = ');
		printarray($res);
		println('sb = ');
		printarray($mod_sb);
	}
	
	if ($cmdtype == 'form') {
	
		if (count($mod_sb) == 0) {
			$t->assign('noSb', true);
		} else {	
			// order the selectbox
			// see in functions.php for order_by_element_of_array() info
			$ordered_sb  = order_by_element_of_array('order', 'asc', $mod_sb);
			
			// prepare edit form 
			$input = array();
			
			foreach($ordered_sb as $osb_k => $osb_v) {
				$input[$osb_k] = array();
				$in = & $input[$osb_k];
				
				$in['sv_id'] = $osb_v['sv_id'];
				$in['sv_description'] = rawurlencode($osb_v['description']);
				$in['sv_value'] = $osb_v['value'];
				$in['value'] = text("sv[{$osb_v['sv_id']}][value]", htmlspecialchars($osb_v['value']), 11);
				$in['description'] = text("sv[{$osb_v['sv_id']}][description]", htmlspecialchars($osb_v['description']), 11);			
				$in['order'] = text("sv[{$osb_v['sv_id']}][order]", htmlspecialchars($osb_v['order']), 11);
				
				$in['options'] = array();
				$in['options']['reserved'] = checkbox("sv[{$osb_v['sv_id']}][reserved]", 'reserved', $checked = in_array('reserved', $osb_v['options']), $cmdtype = 11);
				$in['options']['closed'] = checkbox("sv[{$osb_v['sv_id']}][closed]", 'closed', $checked = in_array('closed', $osb_v['options']), $cmdtype = 11);
				$in['options']['sequenceFree'] = checkbox("sv[{$osb_v['sv_id']}][sequenceFree]", 'sequenceFree', $checked = in_array('sequenceFree', $osb_v['options']), $cmdtype = 11);
				$in['options']['expanded'] = checkbox("sv[{$osb_v['sv_id']}][expanded]", 'expanded', $checked = in_array('expanded', $osb_v['options']), $cmdtype = 11);
				$in['options']['hidden'] = checkbox("sv[{$osb_v['sv_id']}][hidden]", 'hidden', $checked = in_array('hidden', $osb_v['options']), $cmdtype = 11);
				// the delete link
				$in['del_url'] = "project.php?op=delete_selectbox_value&sv_id={$osb_v['sv_id']}";
			}
			
			if ($res['field_name'] == SELECTBOX_STATUS) {
				$t->assign('isStatus', true);
			}
		}
		$add_selectboxvalue_url = $me . "project.php?op=add_selectboxvalue&fid=$field_conf_id";
		$t->assign('add_selectboxvalue_url', $add_selectboxvalue_url);
		
		$t->assign('workflow_url', $me  ."project.php?op=advanced_list2&message=" . rawurlencode($STRING['define_followers'])) ;//. "&id=" . $res['field_conf_id'] );
		$t->assign('action', "status");
		$t->assign('back_url', $me . "project.php?op=do_edit_field&fid=$field_conf_id");
		$t->assign('input', $input);
		$t->assign('data', $res);		
		$t->wrap('admin/selectbox-edit.html');
		return;
	} // end of 'form'
	
	if ($cmdtype == 'treat') { // we have to treat the user's form
		//DEBUG
		if ($verbose) {
			println("edit_selectbox_manager() : Treat submit data");
		}
		
		// for each posted value
		foreach($_POST['sv'] as $sv_id => $v) {
			$mod_sb[$sv_id]['options'] = array();
			
			if (isset($v['value']))
				$mod_sb[$sv_id]['value'] = trim(stripslashes($v['value']));
			if (isset($v['description']))
				$mod_sb[$sv_id]['description'] = trim(stripslashes($v['description']));
			if (isset($v['order']))
				$mod_sb[$sv_id]['order'] = intval($v['order']);
			if (isset($v['closed']))
				$mod_sb[$sv_id]['options'][] = 'closed';			
			if (isset($v['sequenceFree']))
				$mod_sb[$sv_id]['options'][] = 'sequenceFree';			
			if (isset($v['reserved']))
				$mod_sb[$sv_id]['options'][] = 'reserved';
			if (isset($v['expanded']))
				$mod_sb[$sv_id]['options'][] = 'expanded';
			if (isset($v['hidden']))
				$mod_sb[$sv_id]['options'][] = 'hidden';
		}
		
		if($verbose) {
			if (isset($mpfile->sp_cache[$field_name ]->unique)) {
				println("edit_selectbox_manager() : check unique values : " . $mpfile->sp_cache[$field_name ]->unique);				
			} else println("edit_selectbox_manager() : check unique values : false, undefined");
		}
		// are the selectbox values unique ?
		if (isset($mpfile->sp_cache[$field_name ]->unique) && $mpfile->sp_cache[$field_name ]->unique) {
			// look for non unique values
			// copy all values into one array
			$temp = array();
			foreach($mod_sb as $k => $v) {			
				if(!isset($temp[$v['value']]))
					$temp[$v['value']] = 1;
				else {// it has already been created, so, the value isn't unique
						death('ERROR', 'edit_selectbox_manager() : this value (' . htmlspecialchars($v['value']) . ') already exists.');
					}
			}
		}
		
		$ret = $mpfile->alterSelectBoxValue($mod_sb, $action = "update", $verbose);
		
		// go to project edit form
		redirection("project.php?op=do_edit_field&fid=$field_conf_id");
	} // end of 'treat'
} // end of edit_selectbox_manager($field_conf_id, $cmdtype = 'form', $verbose = false)
// //////////////////////////////////////////////////////////////////////////////
/**
Prepare or treat a form to define a new selectbox value.
@param integer $field_conf_id the field_conf id
@param string $cmdtype the type of action to do : 'form' or 'treat'
@param boolean $verbose print debug info
@return void
*/
function add_selectbox_manager($field_conf_id, $cmdtype = 'form', $verbose=false) {
	global $t, $STRING, $db, $do_edit_field, $op_edit_selectbox, $me, $known_options;
	// Ordre  	Valeur  	Description  	Réservé  	Etat clos
	
	// load the MPFile object
	$project_id = MPFile::getProject_id_from_Field_Conf ($field_conf_id);
	if ($project_id  === false) {
		death('ERROR', 'Unable to find the project associated to this selectbox.');
	}
	$mpfile = &new MPFile($project_id);
	
	// get the field conf data
	$field_conf = null;
	foreach($mpfile->project_field_properties as $k => $v) {
		if ($v['field_conf_id'] == $field_conf_id) {
			$field_conf = $v;
			break;
		}
	}
	
	switch(strtolower($cmdtype)) {
		case 'form' :
			$t->assign('data', $field_conf); // store some data about the field conf
			// is it a status selectbox ?
			if ($field_conf['field_name'] == SELECTBOX_STATUS)
				$t->assign('isStatus', true);
			
			$t->wrap('admin/selectbox-add.html');
			break;
		case 'treat' :
			/*
			example of post data
			1 :  	['order']  	=	 1111
			2 : 	['value'] 	=	bababa
			3 : 	['description'] 	=	desccc
			4 : 	['reserved'] 	=	reserved
			5 : 	['closed'] 	=	closed
			*/
		
			// prepare parameters for alterSelectBoxValue()
			$selectbox_values = array(); // an array of sv values
			$sv = array(); // one of the sv values
			
			// copy filtered data in it
			$sv['value'] = trim(stripslashes($_POST['value']));
			$sv['description'] = trim(stripslashes($_POST['description']));
			$sv['order'] = intval($_POST['order']);
			$sv['field_conf_id'] = intval($_GET['fid']);
			
			// are the selectbox values unique ?
			if (isset($mpfile->sp_cache[$field_conf['field_name']]->unique) && $mpfile->sp_cache[$field_conf['field_name']]->unique) {
				//$mpfile->sb_cache[
				$check_sv = array(); // a temporary array
				$check_sv[$sv['value']] = 1; // store the new value first
				foreach($mpfile->sb_cache as $k => $v) { // for each sv
					if ($v['field_conf_id'] == $field_conf_id) {// if it's a sv of this field
						if (!isset($check_sv[$v['value']])) { // if value is not known yet
							$check_sv[$v['value']] = 1;
						}
						else {
							death('ERROR', 'add_selectbox_manager() : this value (' . htmlspecialchars($v['value']) . ') already exists.');
						}
					}
				}
				unset($check_sv);
			}
			
			// don't forget options
			$sv['options'] = array();
			
			// check if some options are set
			// TODO : should check if the user tries to use the 'closed' option, 
			//        which is reserved to the status field.
			foreach($known_options as $k=>$v) {
				if(isset($_POST[$v]))
					$sv['options'][] = stripslashes($_POST[$v]);
			}
			// affect the sv to the main array 
			$selectbox_values[0] = &$sv;
			// use the class function
			$mpfile->alterSelectBoxValue($selectbox_values, "insert", $verbose);
		
			// go to selectbox edit form
			redirection("project.php?op=$op_edit_selectbox&fid=" . $_GET['fid']);
			break;
		default : 
			death('INVALID PARAMETER VALUE', 'admin : project : field conf : selectbox : add_selectbox_manager() : \$cmd_type value cannot be handled.');
	}	
} // end of add_selectbox_manager($field_conf_id, $cmdtype = 'form', $verbose=false)
// //////////////////////////////////////////////////////////////////////////////
/**
Given the selectbox value id, delete it after having checked that it's no more used in any file table
@param integer $sv_id the selectbox id to delete
@param boolean $verbose Print debug info
@return void
*/
function delete_selectbox_value($sv_id, $verbose = false) {
	global $t, $db, $STRING, $me;

	$res = null;
	$field_conf_id = null;
	$project_id = null;
	$mpfile = null;
	$isPublic = null;
	$file_tables = null;
	$text = null;
	$isError = null;
	
	// get the field_conf_id of the sv and some other info
	$res = $db->query("SELECT sv.*, fc.field_name FROM " . TBL_SELECTBOX_VALUE . " sv, " . TBL_FIELD_CONF . " fc WHERE sv.field_conf_id = fc.field_conf_id AND sv.sv_id = " . $db->quote($sv_id));
	if (DB::isError($res)) {
		death("DB ERROR", "01 delete_selectbox_value()<br>" . $res->getMessage());
	}
	$sv = fetchall($res);
	$sv = $sv[0]; // reaffect data because there should be only one result row
	$field_conf_id = intval($sv['field_conf_id']);
	
	if($verbose){
		println("delete_selectbox_value() : get the field_conf_id of the sv and some other info :");
		println("sql = $db->last_query");	
		println("selectbox data and field name : ");
		printarray($sv);
	}
	
	$project_id = MPFile::getProject_id_from_Field_Conf ($field_conf_id);
	if ($project_id === false) {
		death("ERROR", "02 delete_selectbox_value() : can't find the project associated to this selectbox value.");
	}
	
	if($verbose){
		println("delete_selectbox_value() : project id of the sv : $project_id");
	}

	// use mpfile class
	$mpfile = & new MPFile($project_id);
	
	// is it a public selectbox field ?
	$isPublic = ($mpfile->project_data['project_name'] == PUBLICFIELDS_PROJECT_NAME)? true : false;
	
	if($verbose){
		println("delete_selectbox_value() : isPublic = $isPublic");
	}
	
	// gather the file tables to check
	$file_tables = array();
	if (!$isPublic) { // if it's a private field, we just have to check in one table
		$file_tables[] = $mpfile->project_data['file_table_name'];
	} else {
		// if public, check in every tables
		// gather file table names
		$res = $db->query("SELECT DISTINCT file_table_name FROM " . TBL_PROJECT . " WHERE project_id != " . PUBLIC_PROJECT_ID);
		if(DB::isError($res)) {
			death("DB ERROR", "03 delete_selectbox_value() : can't find the file tables associated to this public selectbox value.<br>" . $res->getMessage());
		}
		$tab = fetchall($res);
		foreach($tab as $k=>$v) {
			$file_tables[] = $v['file_table_name'];
		}
	}
	
	if($verbose){
		println("delete_selectbox_value() : file tables to check : ");
		printarray($file_tables);
	}
	
	$text = '';
	$isError = false;
	
	// check if a file is still using the selectbox value in necessary file tables	
	foreach($file_tables as $k => $tbl_name) {
		$sql = "SELECT count(*) FROM " . $tbl_name . " WHERE " . $sv['field_name'] . " = " . $db->quote($sv_id);
		$res = $db->getOne($sql);
		if (DB::isError($res)) {
			death("DB ERROR", "04 delete_selectbox_value() : can't determine if the selectbox value is still in use in a file table.<br>" . $res->getMessage());
		}
		
		if($verbose){
			println("delete_selectbox_value() : check in $tbl_name");
		}
		
		$nb = &$res;
		if($nb > 0) { // a file is still using the sv
			$isError = true;
			
			$text .= sprintf($STRING['unable_to_delete_selectbox_value2'], "<b>" . $mpfile->project_data['project_name']) . "</b><br>\n";
				
			if($verbose){
				println("delete_selectbox_value() : problem : a file is still using this selectbox value : project_id = $project_id, file_table_name = $tbl_name");
			}			
			break;
		}
	}
	
	// if no error, delete the sv
	if (!$isError) {
		// delete the selectbox value
		$sql = "DELETE FROM " . TBL_SELECTBOX_VALUE . " WHERE sv_id = " . $db->quote($sv_id);
		
		if($verbose){
			println("delete_selectbox_value() : delete the selectbox value in " . TBL_SELECTBOX_VALUE);
		}
		
		$res = $db->query($sql);
		if (DB::isError($res)) {
            death("DB ERROR", "05 delete_selectbox_value() : error when trying to delete the selectbox value.<br>" . $res->getMessage());
        }
        
		// check that the deletion is well done
		if ($db->affectedRows() == 1) {
			// delete the selectbox options
			$sql = "DELETE FROM " . TBL_SELECTBOX_OPTION . " WHERE sv_id = " . $db->quote($sv_id);
			if($verbose){
				println("delete_selectbox_value() : delete the selectbox options in " . TBL_SELECTBOX_OPTION);
			}
			$res = $db->query($sql);
			if (DB::isError($res)) {
				death("DB ERROR", "06 delete_selectbox_value() : error when trying to delete the selectbox options.<br>" . $res->getMessage());
			}
			$text = $STRING['selectbox_deletion_successful'];
		} else {
			$isError = true;
			$text = $STRING['unable_to_delete_selectbox_value3'];
		}
	}
	
	$t->assign('text', $text);
	$t->assign('iserror', $isError);
	$t->wrap('admin/error.html');	
} // end of delete_selectbox_value($sv_id, $verbose)


function getSubproperty($field_conf_id,$prop_name)
{
	$project_id = MPFile::getProject_id_from_Field_Conf ($field_conf_id);	
	$mpfile = & new MPFile($project_id);
	$res = $mpfile->getFieldsProperties($project_id, $options);
	foreach ($res as $k => $v) 
	{
		if ($v['field_conf_id']==$field_conf_id)
		{
			$field_conf = $v; // there should be only one result
			break;
		}
	}
	// subproperties
	$prop = & $mpfile->sp_cache[$field_conf['field_name']];
	return $prop->$prop_name;
}

function setSubproperty($field_conf_id,$prop_name,$value)
{
	$project_id = MPFile::getProject_id_from_Field_Conf ($field_conf_id);	
	$mpfile = & new MPFile($project_id);
	$res = $mpfile->getFieldsProperties($project_id, $options);
	foreach ($res as $k => $v) 
	{
		if ($v['field_conf_id']==$field_conf_id)
		{
			$field_conf = $v; // there should be only one result
			break;
		}
	}
	// subproperties
	//$prop = & $mpfile->sp_cache[$res['field_name']];
	if (!preg_match("/$prop_name.*;/",$field_conf['properties']))
	{
		$field_conf['properties'] .= $prop_name . "=" . $value . ";";
	}
	else
	{
		$field_conf['properties']=preg_replace("/(.*$prop_name=).*;/","$1$value;",$field_conf['properties']);
	}
	$mpfile->alterFieldConf($field_conf, $selectbox_values = null, $action='update', false);

	//printarray($prop);
	//$str_sp=convert_array_to_string($sp);

				
}

function manage_perm($permname='undefined',$action='undefine',$project_id,$selected_users)
{
	global $db,$perm;
	//verification of the $project_id parameter
	if (!$perm->have_project_perm($_gv['id'],'Admin')) 
	{
		$perm->perm_invalid('AdminProject', $_gv['id']);
		die;
	}
	$perm_id=$db->getOne("SELECT perm_id FROM " . TBL_AUTH_PERM . " WHERE perm_name='$permname'");
	//verification of the $permname parameter
	if (!isset($perm_id))
	{
		death("ERROR 01","Unknown permission name $permname");
	}
	if (isset($selected_users) and is_array($selected_users) and count($selected_users) > 0)
	{
		switch ($action)
		{
			case 'add':
				foreach ($selected_users as $user) 
				{
					$db->query("INSERT INTO " . TBL_PROJECT_PERM . " (project_id, user_id, perm_id) VALUES ($project_id, $user, $perm_id)");
				} 
				break;
			case 'remove':
				foreach ($selected_users as $user) 
				{
					$db->query("DELETE FROM " . TBL_PROJECT_PERM . " WHERE project_id=$project_id AND user_id=$user AND perm_id<=$perm_id");
				} 
				break;
			default:
				break;
		}
	}
}//end of manage_perm

function add_invite($project_id=NULL)
 {
	global $db, $t, $_pv, $STRING, $now, $u;
	
	$login_domain_admin=$db->getOne("SELECT login FROM " . TBL_AUTH_USER . " WHERE user_id=$u ");
	if (!isset($project_id) || $project_id==NULL)
	{
		$error=" internal system error : wrong domain reference";
		death("ERROR",$error);
	}
	if (!EMAIL_IS_LOGIN && !$_pv['login'] = trim($_pv['login'])) 
		$error = $STRING['givelogin'];
	elseif (!$_pv['email'] or !bt_valid_email($_pv['email'])) 
		$error = $STRING['giveemail'];
	elseif ($user_id=$db->getOne("select user_id from ".TBL_AUTH_USER.
		" where email = '{$_pv['email']}' ".
		(!empty($_pv['login']) ? "or login = '{$_pv['login']}'" : '')))
	{
		if ($_pv['stage']=="confirm_only_invite")
		{
		// ok
			$t->assign('stage',"creation_done");
			qp_mail($_pv['email'], $STRING['newinvitesubject'], sprintf($STRING['newinvitemessage'],$db->getOne("SELECT project_name FROM " . TBL_PROJECT . " WHERE project_id=$project_id") ,INSTALL_URL),
		    	sprintf("From: %s",$login_domain_admin));
			return $user_id;		
		}
		else
		{
			$error = $STRING['loginused'] . ". " . $STRING['confirm_loginused'];
			$t->assign('stage',"confirm_only_invite");		
		}
	}
	elseif ($_pv['stage']!="confirm_creation" )
	{
		$error = $STRING['loginnotused']; 
		$t->assign('stage',"confirm_creation");		
	}
	elseif (!isset($_pv['lastname']) || $_pv['lastname']=="")
	{
		$error = $STRING['loginnotused']; 
		$t->assign('stage',"confirm_creation");		
	}
	// else OK
	
	if (!empty($error)) 
	{ 
		$t->assign('error',$error);
		$t->assign('project_id',$project_id);
        	$t->wrap("admin/invite.html");
        	die;
	}
	$firstname = htmlspecialchars($_pv['firstname']);
	$lastname = htmlspecialchars($_pv['lastname']);
	$password = genpassword(10);
	if (ENCRYPT_PASS) {
		$mpassword = $db->quote(md5($password));
	} else {
		$mpassword = $db->quote(stripslashes($password));
	}
	if (EMAIL_IS_LOGIN) {
		$login = $_pv['email'];
	} else {
		$login = $_pv['login'];
	}
		$user_id = $db->nextId(TBL_AUTH_USER);
		$db->query("insert into ".TBL_AUTH_USER." (user_id, login, first_name, last_name, email, password, active, created_date, last_modified_date)"
				." values (".join(', ', array($user_id, $db->quote(stripslashes($login)), 
				$db->quote(stripslashes($firstname)), 
				$db->quote(stripslashes($lastname)), $db->quote($_pv['email']), 
				$mpassword, 1, $now, $now)).")");
		$db->query("insert into ".TBL_USER_GROUP.
			" (user_id, group_id, created_by, created_date)
			  select $user_id, group_id, $u, $now from ".TBL_AUTH_GROUP.
			" where group_name = 'User'"); 
		$db->query("insert into ".TBL_USER_PREF." (user_id) values ($user_id)");
		qp_mail($_pv['email'], $STRING['newacctsubject'], sprintf($STRING['newacctmessage'], $password),
	    	sprintf("From: %s",$login_domain_admin));
	    	return $user_id;

//		$t->wrap('newaccountsuccess.html', 'accountcreated');

}


// //////////////////////////////////////////////////////////////////////////////
// ////////////////////// ANALYSE GET AND POST VARS
// //////////////////////////////////////////////////////////////////////////////
$perm->check('AdminProject');

if (isset($_gv['op'])) {
    switch ($_gv['op']) {
        case 'add' :
            show_project();
            break;
        case 'edit' :
            if ($perm->have_project_perm($_gv['id'],'Admin')) {
                show_project($_gv['id']);
                break;
            } else {
                $perm->perm_invalid('AdminProject', $_gv['id']);
                break;
            } 
        case 'edit_public_fields' : 
            // show_component($_gv['id']);
            show_public_fields_manager();
            break;
        case 'edit_project_fields' : 
            // show_component($_gv['id']);
            show_project_fields_manager($_gv['id']);
            break;
        case 'edit_component' :
            show_component($_gv['id']);
            break;
        case 'edit_version' :
            show_version($_gv['id']);
            break;
        case 'del_component' :
            del_component($_gv['id'], $_gv['project_id']);
            break;
        case 'del_version' :
            del_version($_gv['id'], $_gv['project_id']);
            break;
		case 'do_edit_field' :
				if (isset($_GET['fid'])) {
					if (!isset($_GET['validate'])) {
						edit_field_manager(intval($_GET['fid']));
					} else {
						edit_field_manager(intval($_POST['field_conf_id']), 'treat');
					}
				} else death('ERROR', 'Access unavailable');			
			break;
		case $op_edit_selectbox :
			if (isset($_GET['fid']))
				edit_selectbox_manager(intval($_GET['fid']));
			else death('ERROR', 'Access unavailable');
			break;
		case 'add_selectboxvalue' :
			if (isset($_GET['fid'])) {
				add_selectbox_manager(intval($_GET['fid']));
			}
			else death('ERROR', 'Access unavailable');
			break;
		case 'delete_selectbox_value' :
			if (isset($_GET['sv_id']) && isset($_GET['is_confirmed'])) {
				if ($_GET['is_confirmed'] == 1)
					delete_selectbox_value(intval($_GET['sv_id']), $verbose);
				else 
					death('ERROR', 'Access unavailable. You have to go to the selectbox edition form to be able to delete a selectbox value.');
			} else death('ERROR', 'Access unavailable');
			break;
		case 'add_field' :
			if (isset($_GET['id']) && isset($_GET['step'])&&$DiaBuilder=="fee") {
				add_field($_GET['id'], intval($_GET['step']), 'form');
			}
			else death('ERROR', $STRING['missing_feature']);
			break;
		case 'advanced_list' :
			if (isset($_GET['message']) && isset($_GET['id']) && $DiaWorkflow=="fee") {
				$new_str_prop=getSubproperty($_GET['id'],'hidden_states');		
				$hidden=str_replace("_sep_",";", "$new_str_prop");
				list_workflow($_GET['message'], $_GET['id'],$hidden,"field");
			}
			else death('ERROR', $STRING['missing_feature']);
			break;
		case 'advanced_list2' :
			if (isset($_GET['message']) && isset($_GET['id'])  && isset($_GET['follow']) && $DiaWorkflow=="fee") 
			{
				$follow=rawurldecode($_GET['follow']);
				list_workflow($_GET['message'], $_GET['id'], $_GET['follow'],"status");
			}
			else death('ERROR', $STRING['missing_feature']);
			break;
		case 'mail' :
		        if ($perm->have_project_perm($_gv['id'],'Admin')) 
		        {
				$t->assign($error);
				$t->assign('project_id',$_gv['id']);
		        	$t->wrap("admin/invite.html");
		        	break;
		        }
             		else 
             		{
                		$perm->perm_invalid('AdminProject', $_gv['id']);
		                break;
            		} 
		default : 
			death('ERROR', 'Access unavailable');
			break;
    } 
} elseif (isset($_pv['do'])) {
    switch ($_pv['do']) {
        case 'project' :
            if ($perm->have_project_perm($_pv['id'],'Admin')) 
            {
            	save_project($_pv['id']);
            }else
            {
               $perm->perm_invalid('AdminProject', $_pv['id']);
            }
            break;
        case 'manage_invite' :
            if ($perm->have_project_perm($_pv['id'],'Admin')) 
            {
        	if (isset($_pv['Remove']))
        	{
            		manage_perm('Invite','remove',$_pv['id'],$_pv['user_invite']);
            		show_project($_pv['id'], $error = null,$_pv['user_invite']);
            	}
            	elseif (isset($_pv['Submit']))
            	{
            		$new_user_id=add_invite($_pv['id']);
            		manage_perm('Invite','add',$_pv['id'],array($new_user_id));
 	           	show_project($_pv['id'], $error = null,$_pv['user_invite']);
            	}
            	elseif (isset($_pv['Upgrade'])&& $perm->have_perm('Admin'))
            	{
	            	manage_perm('Request','add',$_pv['id'],$_pv['user_invite']);
        	    	show_project($_pv['id'], $error = null,$_pv['user_invite']);
            	}
            }else
            {
               $perm->perm_invalid('AdminProject', $_pv['id']);
            }
            break;
        case 'manage_request' :
            if ($perm->have_project_perm($_pv['id'],'Admin')) 
            {
	       	if (isset($_pv['Remove'])&& $perm->have_perm('Admin'))
        	{
            		manage_perm('Request','remove',$_pv['id'],$_pv['user_request']);
 	           	show_project($_pv['id'], $error = null,$_pv['user_request']);
            	}
            	elseif (isset($_pv['Submit']))
            	{
	            	manage_perm('View','add',$_pv['id'],$_pv['user_request']);
        	    	show_project($_pv['id'], $error = null,$_pv['user_request']);
            	}
            }
            else
            {
               $perm->perm_invalid('AdminProject', $_pv['id']);
            }
            break;
        case 'manage_view' :
            if ($perm->have_project_perm($_pv['id'],'Admin')) 
            {
        	if (isset($_pv['Remove']))
        	{
            		manage_perm('View','remove',$_pv['id'],$_pv['user_view']);
 	           	show_project($_pv['id'], $error = null,$_pv['user_view']);
            	}
            	elseif (isset($_pv['Submit']))
            	{
            		manage_perm('Editbug','add',$_pv['id'],$_pv['user_view']);
 	           	show_project($_pv['id'], $error = null,$_pv['user_view']);
            	}
            }else
            {
               $perm->perm_invalid('AdminProject', $_pv['id']);
            }
            break;
        case 'manage_edit' :
            if ($perm->have_project_perm($_pv['id'],'Admin')) 
            {
        	if (isset($_pv['Remove']))
        	{
            		manage_perm('Editbug','remove',$_pv['id'],$_pv['user_edit']);
 	           	show_project($_pv['id'], $error = null,$_pv['user_edit']);
            	}
            	elseif (isset($_pv['Submit']))
            	{
            		manage_perm('Admin','add',$_pv['id'],$_pv['user_edit']);
 	           	show_project($_pv['id'], $error = null,$_pv['user_edit']);
            	}
            }else
            {
               $perm->perm_invalid('AdminProject', $_pv['id']);
            }
            break;
        case 'manage_admin' :
            if ($perm->have_project_perm($_pv['id'],'Admin')) 
            {
            	manage_perm('admin','remove',$_pv['id'],$_pv['user_admin']);
 	        show_project($_pv['id'], $error = null,$_pv['user_admin']);
            }else
            {
               $perm->perm_invalid('AdminProject', $_pv['id']);
            }
            break;
		case 'edit_field_validate' :
			if (isset($_POST['field_conf_id'])) {
				edit_field_manager(intval($_POST['field_conf_id']), 'treat');
			}
			else death('ERROR', 'Access unavailable');
			break;		
		case 'edit_selectbox_validate' :
			if (isset($_POST['field_conf_id']) && isset($_POST['sv'])) {
				edit_selectbox_manager(intval($_POST['field_conf_id']), 'treat');
			}
			else death('ERROR', 'Access unavailable');
			break;			
		case 'add_selectbox_validate' :
			if (isset($_GET['fid'])) {
				add_selectbox_manager(intval($_GET['fid']), 'treat');
			} else death('ERROR', 'Access unavailable');
			break;
		case 'add_field_validate' :
			if (isset($_GET['id']) && isset($_GET['step'])) {
				add_field($_GET['id'], intval($_GET['step']), 'treat');
			}
			break;
		case 'advanced_update' :
			if (isset($_pv['id']) && isset($_pv['action']) && $DiaWorkflow=="fee") 
			{
			 	$selected=update_workflow($_pv['id']);
				if ($_pv['action']=="field")
				{
					$new_str_prop=str_replace(";", "_sep_","$selected");
					setSubproperty($_pv['id'],'hidden_states',$new_str_prop);		
					edit_field_manager($_pv['id']);
				}
				else // =="status"
				{
					$res = $db->query($do_query="UPDATE " . TBL_SELECTBOX_VALUE . " SET `sv_description` = '" . $selected . "' WHERE `sv_id` = " . $_pv['id']);		
					if(DB::isError($res))
					{
			
						echo ("<br>Error : " . $res->getMessage() . "<br>");
						print($do_query . "<br>");
						die();
					}
					edit_selectbox_manager(7);
				}
			}
			else death('ERROR', $STRING['missing_feature']);
			break;
		case 'do_edit_field' :
				if (isset($_pv['edit_field_id'])) {
						edit_field_manager(intval($_pv['edit_field_id']));
				} else death('ERROR', 'Access unavailable');			
			break;
			default :
			death('ERROR', 'Access unavailable');
			break;
    } 
} else list_projects();

?>