<?php
/**
 * Workshop class
 * 
 * Provides methods related to workshop (workgroups) module
 * 
 * @package linea21\modules\workshop
 * @author $Author$ - linea21 <info@linea21.com>
 * @version $Id$ 
 * @access public
 * @license http://opensource.org/licenses/gpl-3.0.html
 * Work group Management
 */

class workshop {
  /* @param
   * */
  var $TDB_WORKSHOP = T_WORK; // nom de la table.
  var $ID;
  var $DENOMINATION;
  var $RESUME;
  var $LEVEL;
  var $COMMENT;
  var $RESTRICTED;
  var $DATE_CREA;
  var $LAST_MODIFY;
  var $STATUT;
  protected $dispatcher = null;

  public function __construct()
  {
    $this->dispatcher = $GLOBALS['dispatcher'];
  }

  public function __call($method, $arguments)
  {
    $event = $this->dispatcher->notifyUntil(new sfEvent($this, 'workshop.extensible_function', array(
      'method'    => $method,
      'arguments' => $arguments
    )));
    if (!$event->isProcessed())
    {
      throw new Exception(sprintf('Call to undefined method %s::%s.', get_class($this), $method));
    }

    return $event->getReturnValue();
  }

  /**
   * workshop::CheckDataIntegrity()
   * Vérification intégrité des données
   *
   * @access public
   * @param array $table contient les composants d'un groupe de travail
   * @return boolean true
   * si verifié, sinon string 'message d'erreur'
   */
  function CheckDataIntegrity($table, $sql_object)
  {
  	// Filter data event + return value
  	$r = $this->dispatcher->filter(new sfEvent($this, 'workshop.before_datacheck', array('data' => $table)), $table);
  	$table = $r->getReturnValue();

    if (strlen($table[0]) < 3) return _t('workshop','no_title');
    if (strlen($table[1]) < 3) return _t('workshop','no_resume');

    if (substr($table[5], -1) == ',') {
      $table[5] = substr($table[5], 0, -1);
    }
    $table_organizer = @explode(',', $table[5]);
    for ($i = 0;$i < count($table_organizer);$i++) {
      $table_organizer[$i] = trim($table_organizer[$i]);
      if (strlen(trim($table_organizer[$i])) < 2) $return = _t('workshop','no_author');
      $result = $this->_CheckUserValidity($table_organizer[$i], $sql_object);
      if (!is_numeric($result)) $return = _t('workshop','author_not_valid') . " : " . $table_organizer[$i];
      else $return = $result;
      $result_admin = $this->_CheckAdmin($sql_object, -1, $table_organizer[$i]);
      if ($result_admin == false) $return = _t('workshop','author_not_admin') . " : " . $table_organizer[$i];
      if (!is_numeric($return)) return $return;
    }

    // Notify the beginning of the current method
    $this->dispatcher->notify(new sfEvent($this, 'workshop.after_datacheck', array('data' => $table)));

    return $return;
  }

  /**
   * workshop::_CheckAdmin()
   * Vérification droits d'utilisation avancé Admin ou Animateur
   *
   * @access private
   * @param object $sql_object
   * @return integer $user_id (option)
   * @param string $user_login (option)
   * @return integer id de l'utilisateur si verifié, sinon false
   */
  function _CheckAdmin($sql_object, $user_id = -1, $user_login = -1)
  {
  	// Notify the beginning of the current method
  	$this->dispatcher->notify(new sfEvent($this, 'workshop.is_admin', array('user_id' => $user_id, 'user_login' => $user_login)));

    if ($user_id <> -1) {
      $q = "SELECT rights_workshop, U.user_id FROM " . T_USER . " AS U LEFT OUTER JOIN " . T_RIGHT . " AS R on U.user_rights=R.rights_id  WHERE user_id='" . $user_id . "' AND user_validity='Y';";
    }
    if ($user_login <> -1) {
      $q = "SELECT rights_workshop, U.user_id FROM " . T_USER . " AS U LEFT OUTER JOIN " . T_RIGHT . " AS R on U.user_rights=R.rights_id  WHERE lower(user_login)= '" . strtolower($user_login) . "' AND user_validity='Y';";
    }
    $result = $sql_object->DBSelect($q);
    if ($result[0]['rights_workshop'] == 'A' || $result[0]['rights_workshop'] == 'O') return $result[0]['user_id'];
    else return false;
  }

  /**
   * workshop::_CheckUserValidity()
   * Vérification validité de l'utilisateur
   *
   * @access private
   * @param string $login
   * @param object $sql_object
   * @return integer si $login existe
   * sinon renvoie false
   */
  function _CheckUserValidity($login, $sql_object)
  {
  	// Notify the beginning of the current method
  	$this->dispatcher->notify(new sfEvent($this, 'workshop.is_user_valid', array('login' => $login)));

    $q = "SELECT user_id FROM " . T_USER . " WHERE lower(user_login)= '" . strtolower($login) . "' AND user_validity='Y';";
    $result = $sql_object->DBSelect($q);
    if ($result == 0) return false;
    if (count($result) > 1) exit();
    else return (int)$result[0]['user_id'];
  }

  /**
   * workshop::CheckUsersIntegrity()
   * Vérification pour ajout d'utilisateurs
   *
   * @access public
   * @param string $logins
   * @param integer $id
   * @param object $sql_object
   * @param string $statut
   * @return string $result
   */
  function CheckUsersIntegrity($logins, $id, $sql_object, $statut)
  {
  	// Notify the beginning of the current method
  	$this->dispatcher->notify(new sfEvent($this, 'workshop.check_users_integrity', array('logins' => $logins, 'workshop_id' => $id, 'statut' => $statut)));

    if (strlen(trim($logins)) < 2) return _t('workshop','no_author');

    if (substr($logins, -1) == ',') {
      $logins = substr($logins, 0, -1);
    }
    $users = @explode(',', $logins);

    foreach ($users as $user) {
      $user = trim($user);
      // check if user exists
      $result = $this->_CheckUserValidity($user, $sql_object);
      if ($result== false) return _t('workshop','author_not_valid') . " : " . $user;
      // check if user has rights enough
      if ($statut == 'O') {
        $result = $this->_CheckAdmin($sql_object, -1, $user);
        if ($result == false) return _t('workshop','author_not_admin') . " : " . $user;
      }
      // check if user is already member of the workgroup
      $q = "SELECT user_id FROM " . T_USER . " WHERE lower(user_login)= '" . strtolower($user) . "' AND user_validity='Y';";
      $data = $sql_object->DBSelect($q);

      $q = "SELECT COUNT(jwu_id) AS nb FROM " . J_WORK_USERS . " WHERE jwu_user_id=" . $data[0]['user_id'] . " AND jwu_workshop_id=" . $id . ";";
      $data = $sql_object->DBSelect($q, 'OBJECT');
      if ($data[0]->nb != 0) return _t('workshop','yet_author') . " : " . $user;
    }

    return true;
  }

  /**
   * workshop::AddWorkshop()
   * Ajout d'un groupe de travail
   *
   * @access public
   * @param array $table_workshop contient les composants d'un workshop
   * @param object $sql_object
   * @return integer $last_id
   */
  function AddWorkshop($table_workshop, $sql_object)
  {
  	global $l21auth;
  	
  	// Filter data event + return value
  	$r = $this->dispatcher->filter(new sfEvent($this, 'workshop.before_add', array('data' => $table_workshop)), $table_workshop);
  	$table_workshop = $r->getReturnValue();
  	
  	// image 64 encoded conversion if enabled before escaping content
  	$table_workshop[1] = convertBase64Images($table_workshop[1], 'wg-');
  	$table_workshop[3] = convertBase64Images($table_workshop[3], 'wg-');

    $table_workshop=$sql_object->DBescape($table_workshop);

    $this->DENOMINATION = strip_input(trim($table_workshop[0]));
    $this->RESUME = strip_input(trim($table_workshop[1]), true);
    $this->LEVEL = $table_workshop[2];
    $this->COMMENT = strip_input(trim($table_workshop[3]), true);
    $this->STATUT = $table_workshop[4];
    $this->RESTRICTED = $table_workshop[6];

    $q = "INSERT INTO " . $this->TDB_WORKSHOP . " (workshop_denomination, workshop_resume, workshop_level, workshop_comment, workshop_statut, workshop_restricted, workshop_date_crea) VALUES('" . $this->DENOMINATION . "', '" . $this->RESUME . "', " . $this->LEVEL . ", '" . $this->COMMENT . "', '" . $this->STATUT . "', " . $this->RESTRICTED . ", NOW());";
    $last_id = $sql_object->DBInsert ($q, 1);
    
    if(is_numeric($last_id))	logfile(LOG_MAINFILE, array('[action] add workgroup', 'ID='.$last_id, 'by_id='.$l21auth->GetSessionElement('id'), 'by_login='.$l21auth->GetSessionElement('login')));
    
    // automatically create workgroup dir in library
    if(is_numeric($last_id)) {
    	mkdir(SITE_PATH.'library/userfiles/workgroups/'. $last_id, 0755, true);
    }

    // Notify the end of the current method
    $this->dispatcher->notify(new sfEvent($this, 'workshop.after_add', array('data' => $table_workshop, 'id' => $last_id)));

    return $last_id;
  }

  /**
   * workshop::ModifyWorkshop()
   * modification d'un workshop
   *
   * @access public
   * @param int $ID identifiant d'un workshop
   * @param array $table_workshop contient les composants d'un workshop
   * @param object $sql_object
   * @return bool $result
   */
  function ModifyWorkshop($ID, $table_workshop, $sql_object)
  {
  	// Filter data event + return value
  	$r = $this->dispatcher->filter(new sfEvent($this, 'workshop.before_modify', array('data' => $table_workshop, 'id' => $ID)), $table_workshop);
  	$table_workshop = $r->getReturnValue();
  	
  	// image 64 encoded conversion if enabled before escaping content
  	$table_workshop[1] = convertBase64Images($table_workshop[1], 'wg-');
  	$table_workshop[3] = convertBase64Images($table_workshop[3], 'wg-');

    $table_workshop=$sql_object->DBescape($table_workshop);

    if (is_numeric($ID)) {
      $this->ID = $ID;
    }

    $this->DENOMINATION = strip_input(trim($table_workshop[0]));
    $this->RESUME = strip_input(trim($table_workshop[1]), true);
    $this->LEVEL = $table_workshop[2];
    $this->COMMENT = strip_input(trim($table_workshop[3]), true);
    $this->RESTRICTED = $table_workshop[6];

    $q = "UPDATE  " . $this->TDB_WORKSHOP . " set workshop_denomination='" . $this->DENOMINATION . "', workshop_resume='" . $this->RESUME . "' , workshop_level=" . $this->LEVEL . ", workshop_restricted=" . $this->RESTRICTED . ", workshop_comment='" . $this->COMMENT . "' WHERE workshop_id=" . $this->ID . ";";
    $result = $sql_object->DBQuery($q);

    // Notify the end of the current method
    $this->dispatcher->notify(new sfEvent($this, 'workshop.after_modify', array('data' => $table_workshop, 'id' => $this->ID)));

    return $result;
  }


  /**
   * Workshop::changeRanges()
   * changes Workshop range
   *
   * @access public
   * @param array : Id (key) and ranges (value)
   * @param object $sql_object
   * @return bool $result
   */

  function changeRanges($array, $sql_object)
  {

    foreach ($array as $key => $value) {
      $query = "UPDATE " . $this->TDB_WORKSHOP . " set workshop_range='".$value."' WHERE workshop_id='" . $key . "';";
      $result = $sql_object->DBQuery($query);
    }

    // Notify the beginning of the current method
    $this->dispatcher->notify(new sfEvent($this, 'workshop.change_ranges', array('data' => $array)));

    return $result;
  }

  /**
   * modification du statut d'un workshop
   *
   * @access public
   * @param int $id identifiant du workshop
   * @param string $state (facultatif) 'P' Public/'D' Draft/'AA' AdminArchive/'PA' PublicArchive/'E' Erase
   * @param object $sql_object
   * @return bool $result
   */

  function StateWorkshop($ID, $state, $sql_object)
  {
  	// Notify the end of the current method
  	$this->dispatcher->notify(new sfEvent($this, 'workshop.change_state', array('id' => $ID, 'state' => $state)));

    if (is_numeric($ID)) {
      $this->ID = $ID;
    }
    if ($state != '') {
      strtoupper($state);
      switch ($state) {
        case 'P':
          $this->STATUT = $state;
          break;
        case 'D':
          $this->STATUT = $state;
          break;
        case 'AA':
          $this->STATUT = $state;
          break;
        case 'PA':
          $this->STATUT = $state;
          break;
        case 'E':
          $this->STATUT = $state;
          break;
        default:
          $this->STATUT = 'D';
          break;
      }
    } else $this->STATUT = 'D';
    $q = "UPDATE  " . $this->TDB_WORKSHOP . " set workshop_statut='" . $this->STATUT . "' WHERE workshop_id=" . $this->ID . ";";
    $result = $sql_object->DBQuery($q);
    return $result;
  }

  /**
   * suppression d'un workshop
   *
   * @access public
   * @param int $id identifiant du workshop a supprimer
   * @param object $sql_object
   * @return bool $result
   */

  function DeleteWorkshop($ID, $sql_object)
  {
  	global $l21auth;
  	
  	// Notify the beginning of the current method
  	$this->dispatcher->notify(new sfEvent($this, 'workshop.delete', array('id' => $ID)));

    if (is_numeric($ID)) {
      $this->ID = $ID;
    }
    $result = $this->StateWorkshop($this->ID, 'E', $sql_object);

    // we log delete action
    if($result)	logfile(LOG_MAINFILE, array('[action] delete workgroup', 'ID='.$ID, 'by_id='.$l21auth->GetSessionElement('id'), 'by_login='.$l21auth->GetSessionElement('login')));
    
    return $result;
  }
  
  
  /**
   * workshop::importUsers()
   * Import users from another workgroup
   *
   * @access public
   * @param int $work_id identifiant du workshop
   * @param int $import_id import from that identifier
   * @param object $sql_object
   * @return integer $last_id
   */
  function importUsers($work_id, $import_id, $sql_object)
  {
  	// Notify the beginning of the current method
  	$this->dispatcher->notify(new sfEvent($this, 'workshop.import_users', array('id' => $work_id, 'import_id' => $import_id)));

  	$users = array();
  	
	// we select users from current workshop
	$users = $this->getWorkshopUsers($work_id, $sql_object);
	
	// we select users from imported workgroup
	$q = "SELECT user_id, jwu_user_right FROM " . T_USER . " U LEFT OUTER JOIN " . J_WORK_USERS . " J ON user_id = jwu_user_id WHERE jwu_workshop_id = ".$import_id." AND user_validity = 'Y' ";
	$import = $sql_object->DBSelect($q);
	
	if(!isset($import[0]['user_id'])) {
		logfile(LOG_MAINFILE, array('Workgroup import ['.$import_id.' to '.$work_id.'] - no records found'));
		return true;
	}
	
	$cnt = 0;
	foreach ($import as $item) {
	  // we ensure user is not already in the database
	  if(!in_array($item['user_id'], $users)) {
		$q = "INSERT INTO " . J_WORK_USERS . " (jwu_workshop_id, jwu_user_id, jwu_user_right) VALUES(" . $work_id . ", " . $item['user_id'] . ",'" . $item['jwu_user_right'] . "');";
		$last_id = $sql_object->DBInsert ($q, 1);
		$cnt++;
	  }
	}
	logfile(LOG_MAINFILE, array('Workgroup import ['.$import_id.' to '.$work_id.'] - done with success ! ('. $cnt. ' entries imported)'));

    return true;
  }
  
    /**
   * workshop::getWorkshopUsers()
   *Récuperation des utilisateurs du groupe de travail
   *
   * @access public
   * @param int $work_id identifiant du workshop
   * @param object $sql_object
   * @return array $users
   */
  function getWorkshopUsers($work_id, $sql_object) {
	  
	$users = array();
  	
	// we select users from current workshop
	$q = "SELECT user_id, jwu_user_right FROM " . T_USER . " U LEFT OUTER JOIN " . J_WORK_USERS . " J ON user_id = jwu_user_id WHERE jwu_workshop_id = ". $work_id ." AND user_validity = 'Y' ";
	$current = $sql_object->DBSelect($q);
	
	if(isset($current[0]['user_id'])) {
		foreach ($current as $item) {
			array_push($users, $item['user_id']);
		}
	}
	
	return $users;
  }

  /**
   * workshop::AddUserWorkshop()
   * Ajout d'un ou plusieurs utilisateurs au workshop
   *
   * @access public
   * @param int $work_id identifiant du workshop
   * @param string $user_login login(s) utilisateur(s)
   * @param array $user_right droit confié a l'utilisateur sur le workshop
   * @param object $sql_object
   * @return integer $last_id
   */
  function AddUserWorkshop($work_id, $user_login, $user_right , $sql_object)
  {
  	// Notify the beginning of the current method
  	$this->dispatcher->notify(new sfEvent($this, 'workshop.add_user', array('id' => $work_id, 'user_login' => $user_login, 'user_right' => $user_right)));

	// we select users from current workshop
	$users = $this->getWorkshopUsers($work_id, $sql_object);
	
    if (is_numeric($work_id)) {
      $this->ID = $work_id;
    } else return false;
    if (substr($user_login, -1) == ',') {
      $user_login = substr($user_login, 0, -1);
    }
    $user_login = @explode(',', $user_login);
    
    for ($i = 0;$i < count($user_login);$i++) {
		$username = trim($user_login[$i]);
		$q = "SELECT user_id FROM " . T_USER . " WHERE lower(user_login) = '" . strtolower($username) . "' AND user_validity='Y';";
		$data = $sql_object->DBSelect($q);
		$user_id = $data[0]['user_id'];
		
		// we ensure user is not already in the database
		if(!in_array($user_id, $users)) {
			$q = "INSERT INTO " . J_WORK_USERS . " (jwu_workshop_id, jwu_user_id, jwu_user_right) VALUES(" . $this->ID . ", " . $user_id . ",'" . $user_right . "');";
			$last_id = $sql_object->DBInsert ($q, 1);
		}
    }

    return $last_id;
  }

  /**
   * workshop::DeleteUserWorkshop()
   * suppression d'un utilisateur au workshop
   *
   * @access public
   * @param int $user_id identifiant du workshop
   * @param string $work_id login de l'utilisateur
   * @param object $sql_object
   * @return bool $result
   */
  function DeleteUserWorkshop($user_id, $work_id, $sql_object)
  {
  	global $l21auth;
  	
  	// Notify the beginning of the current method
  	$this->dispatcher->notify(new sfEvent($this, 'workshop.delete_user', array('id' => $work_id, 'user_id' => $user_id)));

    if (is_numeric($work_id) && is_numeric($user_id)) {
      $q = "DELETE FROM " . J_WORK_USERS . " WHERE jwu_workshop_id=" . $work_id . " AND jwu_user_id=" . $user_id . ";";
      $result = $sql_object->DBQuery($q);
      
      // we log delete action
      if($result)	logfile(LOG_MAINFILE, array('[action] delete user from workgroup', 'ID='.$work_id, 'user_ID='.$user_id, 'by_id='.$l21auth->GetSessionElement('id'), 'by_login='.$l21auth->GetSessionElement('login')));
      
      return $result;
    } else return false;
  }

  /**
   * workshop::acceptUser()
   * acceptation d'un utilisateur au workshop
   *
   * @access public
   * @param int $work_id identifiant du workshop
   * @param string $user_id
   * @param object $sql_object
   * @return bool $result
   */
  function acceptUser($work_id, $user_id, $sql_object)
  {
  	// Notify the beginning of the current method
  	$this->dispatcher->notify(new sfEvent($this, 'workshop.accept_user', array('id' => $work_id, 'user_id' => $user_id)));
  	 
  	if (is_numeric($work_id)) {

  		$q = "UPDATE " . J_WORK_USERS . " SET jwu_user_right='U' WHERE jwu_user_id=" . $user_id . " AND jwu_workshop_id=" . $work_id . " ;";
  		$result = $sql_object->DBQuery($q);
  		
  		return $result;
  	} else return false;
  }
  
  /**
   * workshop::changeUserStatus()
   * Convertit un utilisateur simple en animateur
   * ou inversement
   *
   * @access public
   * @param int $work_id identifiant du workshop
   * @param int $user_id
   * @param string $convert_to
   * @param object $user
   * @param object $sql_object
   * @return bool $result
   */
  function changeUserStatus($work_id, $user_id, $convert_to, $user, $sql_object)
  {
  	// Notify the beginning of the current method
  	$this->dispatcher->notify(new sfEvent($this, 'workshop.accept_user', array('id' => $work_id, 'user_id' => $user_id, 'convert_to' => $convert_to, 'user' => $user)));
  
  	// if we convert user to simple workgroup subscriber
  	// we don't change current permissions
  	if ($convert_to == 'U') {
  
  		$q = "UPDATE " . J_WORK_USERS . " SET jwu_user_right='U' WHERE jwu_user_id=" . $user_id . " AND jwu_workshop_id=" . $work_id . " ;";
  		$r = $sql_object->DBQuery($q);
  
  	}
  	
  	// if we convert user to workgroup moderator
  	// we change permissions if needed
  	if ($convert_to == 'O') {
  	
  		$q = "UPDATE " . J_WORK_USERS . " SET jwu_user_right='O' WHERE jwu_user_id=" . $user_id . " AND jwu_workshop_id=" . $work_id . " ;";
  		$r = $sql_object->DBQuery($q);

  		// if we convert to animator we update rights array if needed
  		if($r) {
  		
  			$data = $user->GetUserRights($user_id, $sql_object);
  		  
  			if(!isset($data[0]['rights_id'])) system_error();
  		
  			$a = array();
  			$a['workshop'] = 'O';
  			$a['dashboard'] = $data[0]['rights_dashboard'];
  			$a['project'] = $data[0]['rights_project'];
  			$a['publication'] = $data[0]['rights_publication'];
  			$a['news'] = $data[0]['rights_news'];
  			$a['yellowpages'] = $data[0]['rights_yellowpages'];
  			$a['level'] = $data[0]['rights_level'];
  			$a['scale'] = $data[0]['rights_scale'];
  			$a['category_user'] = $data[0]['rights_category_user'];
  		
  			// we update user rights in db only if needed
  			if($data[0]['rights_workshop'] != 'A' && $data[0]['rights_workshop'] != 'O') $r = $user->ModifyRight($user_id, $a, $sql_object);
  		}
  	
  	}
  	
  	return $r;
  	
  }

  /**
   * workshop::ModifyOrganizerWorkshop()
   * modification des organisateurs d'un workshop
   *
   * @access public
   * @param int $work_id identifiant du workshop
   * @param string $table_login string des organisateurs séparés par ','
   * @param object $sql_object
   * @return int $last_id
   */
  function ModifyOrganizerWorkshop($work_id, $table_login, $sql_object)
  {
  	// Notify the beginning of the current method
  	$this->dispatcher->notify(new sfEvent($this, 'workshop.modify_organizer', array('id' => $work_id, 'logins' => $table_login)));

    if (substr($table_login, -1) == ',') {
      $table_login = substr($table_login, 0, -1);
    }
    $table_login = @explode(',', $table_login);
    $q = "DELETE FROM " . J_WORK_USERS . " WHERE jwu_workshop_id=" . $work_id . " AND jwu_user_right='O';";
    $result = $sql_object->DBQuery($q);
    for ($i = 0;$i < count($table_login);$i++) {
      $user_id = $this->_CheckUserValidity(trim($table_login[$i]), $sql_object);
      $q2 = "DELETE FROM " . J_WORK_USERS . " WHERE jwu_workshop_id=" . $work_id . " AND jwu_user_id=" . $user_id . ";";
      $result2 = $sql_object->DBQuery($q2);
      $q3 = "INSERT INTO " . J_WORK_USERS . " (jwu_workshop_id, jwu_user_id, jwu_user_right) VALUES(" . $work_id . ", " . $user_id . ",'O');";
      $last_id = $sql_object->DBInsert ($q3, 1);
    }
    return $last_id;
  }

}

?>