<?php
/**

 * File for groups

 *

 * @package eFront

*/
//This file cannot be called directly, only included.
if (str_replace(DIRECTORY_SEPARATOR, "/", __FILE__) == $_SERVER['SCRIPT_FILENAME']) {
    exit;
}
/**

 * EfrontGroupException class

 *

 * This class extends Exception class and is used to issue errors regarding groups

 * @package eFront

 * @author Antonellis Panagiotis

 * @version 1.0

 */
class EfrontGroupException extends Exception
{
    const NO_ERROR = 0;
    const GROUP_NOT_EXISTS = 301;
    const INVALID_ID = 302;
    const INVALID_USER = 303;
    const USER_NOT_EXISTS = 304;
    const USER_ALREADY_MEMBER = 305;
    const ASSIGNMENT_ERROR = 306;
}
/**

 * EfrontGroup class

 *

 * This class represents a group

 * @package eFront

 * @author Antonellis Panagiotis

 * @version 1.0

 */
class EfrontGroup
{
    /**

     * The group array.

     *

     * @since 3.5.0

     * @var array

     * @access protected

     */
    public $group = array();
    /**

     * The group users. Calling getUsers() initializes it; otherwise, it evaluates to false.

     *

     * @since 3.5.0

     * @var array

     * @access protected

     */
    protected $users = false;
    /*

     * The group lessons. Lessons correlated with this group can be either directly assigned to

     * all users of the group or be automatically assigned to every user joining the group

     */
    protected $lessons = false;
    /*

     * The group courses. Lessons correlated with this group can be either directly assigned to

     * all users of the group or be automatically assigned to every user joining the group

     */
    protected $courses = false;
    /**

     * Class constructor

     *

     * This function is used to instantiate the class. The instatiation is done

     * based on a group id. If an entry with this id is not found in the database,

     * an EfrontGroupException is thrown.

     * <br/>Example:

     * <code>

     * $group = new EfrontGroup(32);                     //32 is a group id

     * </code>

     *

     * @param int $group_id The group id or array with group's info array

     * @since 3.5.0

     * @access public

     */
    function __construct($group_id) {
        if (is_array($group_id)) {
            $group[0] = $group_id;
        } else {
         if (!eF_checkParameter($group_id, 'id')) {
             throw new EfrontGroupException(_INVALIDID.": $group_id", EfrontGroupException :: INVALID_ID);
         }
            $group = eF_getTableData("groups", "*", "id = $group_id");
        }
        if (sizeof($group) == 0) {
            throw new EfrontGroupException(_GROUPDOESNOTEXIST, EfrontGroupException :: GROUP_NOT_EXISTS);
        } else {
            $this -> group = $group[0];
        }
    }
    /**

     * Create group

     *

     * This function creates a new group. This involves creating

     * the database instance..

     * The function argument is an array with field values, corresponding to database

     * fields. All fields are optional, and if absent they are filled with default values,

     * but 'name' is strongly recommended to be defined

     * <br/>Example:

     * <code>

     * $fields = array('name' => 'Test group', 'description' => 'Description of the group');

     * try {

     *   $newGroup = EfrontGroup :: create($fields);                     //$newgroup is now a new group object

     * } catch (Exception $e) {

     *   echo $e -> getMessage();

     * }

     * </code><br/>

     *

     * @param array $fields The new group characteristics

     * @return EfrontGroup the new group object

     * @since 3.5.0

     * @access public

     * @static

     */
    public static function create($fields) {
        $fields['name'] = trim($fields['name']);
        !isset($fields['name']) ? $fields['name'] = 'Default name' : null;
        $group_id = eF_insertTableData("groups", $fields); //Insert the group to the database
        $newGroup = new EfrontGroup($group_id);
        return $newGroup;
    }
    public static function createDynamicGroup($fields) {
     self :: deleteDynamicGroup();
        $group = self::create($fields); //Insert the group to the database
        return $group;
    }
    public static function deleteDynamicGroup($group = false) {
     if ($group) {
      eF_deleteTableData("groups", "id=".$_SESSION['dynamic_group']);
      eF_deleteTableData("users_to_groups", "groups_id=".$_SESSION['dynamic_group']);
      unset($_SESSION['dynamic_group']);
     } else {
      eF_deleteTableData("groups", "dynamic=1 and created is not null and created < ".(time() - 360));
      eF_deleteTableData("users_to_groups", "groups_id in (select id from groups where dynamic=1 and created is not null and created < ".(time() - 360).")");
     }
    }
    /**

     * Delete group

     *

     * This function is used to delete an existing group. In order to do

     * this, it caclulates all the group dependendant elements, deletes them

     * and finally deletes the group itself.

     *

     * <br/>Example:

     * <code>

     * try {

     *   $group = new EfrontGroup(32);                     //32 is the group id

     *   $group -> delete();

     * } catch (Exception $e) {

     *   echo $e -> getMessage();

     * }

     * </code>

     *

     * @return boolean True if everything is ok

     * @since 3.5.0

     * @access public

     */
    public function delete() {
        eF_deleteTableData("lessons_to_groups", "groups_ID=".$this -> group['id']);
        eF_deleteTableData("courses_to_groups", "groups_ID=".$this -> group['id']);
     eF_deleteTableData("users_to_groups", "groups_ID=".$this -> group['id']);
        eF_deleteTableData("groups", "id=".$this -> group['id']);
        return true;
    }
    /**

     * Get group users

     *

     * This function returns an array with the group users. The array

     * has 2 sub-arrays, 'student' and 'professor', each of which holding

     * a list of user logins. If the optional $type is specified, then only

     * a one-dimensional array is returned, holding the group users of the

     * specified type.

     * <br/>Example:

     * <code>

     * try {

     *   $group     = new EfrontGroup(32);                     //32 is the group id

     *   $all_users  = $group -> getUsers();

     *   $professors = $group -> getUsers('professor');

     * } catch (Exception $e) {

     *   echo $e -> getMessage();

     * }

     * </code><br/>

     * One thing to note is that this function caches results throughout the life

     * cycle of the object. That is, if some other function updates the group users,

     * the function results will not be altered, unless $refresh is set to true

     *

     * @param string $type The group users type

     * @param boolean $refresh Whether to explicitly refresh the object cached data set

     * @return array A 2-dimensional array with group users per type, or a 1-dimensional array with group users of the specified type

     * @since 3.5.0

     * @access public

     */
    public function getUsers($type = false, $refresh = false) {
        if ($this -> users === false || $refresh) { //Make a database query only if the variable is not initialized, or it is explicitly asked
            $this -> users = array('professor' => array(), 'student' => array());
            $result = eF_getTableData("users_to_groups ug, users u", "ug.*, u.user_type", "u.login=ug.users_LOGIN and groups_ID=".$this -> group['id']);
            foreach ($result as $value) {
                $this -> users[$value['user_type']][] = $value['users_LOGIN'];
            }
         }
        if ($type) {
            return $this -> users[$type];
        } else {
            return $this -> users;
        }
    }
    /**

     * Add users to group

     *

     * This function is used to add users to the current group

     * <br>Example:

     * <code>

     * $group = new EfrontGroup(2);

     * $group -> addUsers(array('jdoe', 'doej'));

     * </code>

     *

     * @param mixed $users An array of user logins or EfrontUser objects, or a single login or EfrontUser object

     * @return boolean True if everything is ok

     * @since 3.5.2

     * @access public

     */
    public function addUsers($users) {
        if (!is_array($users)) {
            if ($users instanceof EfrontUser) {
                $users = $users -> user['login'];
            }
            $users = array($users);
        }
        $allUsers = eF_getTableDataFlat("users", "login", "archive=0"); //TODO: removed here the "active = 1 AND "
        // Optimization - get the lesson info extraciton out of the loop if you are to assign
        // them to new group users
        if ($this -> group['assign_profile_to_new']) {
            $groupLessons = $this -> getLessons();
            $lessonIds = array_keys($groupLessons);
            /*

            $lessonTypes = array();

            foreach ($groupLessons as $lesson) {

                $lessonTypes[] = $lesson['user_type'];

            }

			*/
            $groupCourses = $this -> getCourses(true, true);
            //$courseI = array_keys($groupCourses);
            /*

            $courseTypes = array();

            foreach ($groupCourses as $course) {

                $courseTypes[] = $course['user_type'];

            }

			*/
        }
        $errors = array();
        foreach ($users as $key => $user) {
            if ($user instanceof EfrontUser) {
                $user = $user -> user['login'];
            }
            if (in_array($user, $allUsers['login'])) {
                $fields = array('groups_ID' => $this -> group['id'],
                                'users_LOGIN' => $user);
                try {
                 eF_insertTableData("users_to_groups", $fields);
                 if ($this -> group['assign_profile_to_new']) {
                  $userObject = EfrontUserFactory::factory($user);
                  $userObjects[$user] = $userObject;
                  $fields = array();
                  if ($userObject -> getType() != 'administrator') {
                   // Update the user profile
                   if ($this -> group['user_types_ID']) {
                    if ($this -> group['user_types_ID'] != 'student' && $this -> group['user_types_ID'] != 'professor') {
                     $basic_type = eF_getTableData("user_types", "basic_user_type", "id = '" . $this -> group['user_types_ID']. "'");
                     if (sizeof($basic_type)) {
                      $fields["user_type"] = $basic_type[0]['basic_user_type'];
                      $fields["user_types_ID"] = $this -> group['user_types_ID'];
                     } else {
                      throw new EfrontGroupException(_INVALIDID, EfrontGroupException :: INVALID_ID);
                     }
                    } else {
                     // basic user type
                     $fields["user_type"] = $this -> group['user_types_ID'];
                     $fields["user_types_ID"] = 0;
                    }
                   }
                  }
                  if ($this -> group['languages_NAME']) {
                   $fields["languages_NAME"] = $this -> group['languages_NAME'];
                  }
                  if ($this -> group['users_active']) {
                   $fields["active"] = ($this -> group['users_active'] == 1)? 1:0;
                  }
                  if (sizeof($fields)) {
                   eF_updateTableData("users", $fields, "login = '". $user ."'");
                  }
                  // Add lessons - info acquired before entering the new user assignment loop
                  if ($userObject -> getType() != 'administrator') {
                   if (isset($fields["user_types_ID"])) {
                    $userTypeInCourses = $fields["user_types_ID"];
                   } elseif (isset($fields["user_type"])) {
                    $userTypeInCourses = $fields["user_type"];
                   } else {
                    $userTypeInCourses = $userObject -> getType();
                   }
                   if (!empty($lessonIds)) {
                    $userObject -> addLessons($lessonIds, $userTypeInCourses, 1); //active lessons
                   }
                  }
                 }
                } catch (Exception $e) {
                 // Don't throw here, so that mass assignments can continue to the next user
                 $errors[] = _USERALREADYEXISTSINGROUP.": $user";
                }
            } else {
             $errors[] = _USERDOESNOTEXIST.": $user";
             //throw new EfrontGroupException(_USERDOESNOTEXIST.": $user", EfrontGroupException :: USER_NOT_EXISTS);
            }
        }
//pr($groupCourses);exit;
        if (!empty($groupCourses)) {
         foreach ($groupCourses as $course) {
          $course -> addUsers($userObjects, $userTypeInCourses, 1);
         }
        }
        if (!empty($errors)) {
         throw new EfrontGroupException(implode("<br>", $errors), EfrontGroupException :: ASSIGNMENT_ERROR);
        }
    }
    /**

     * Remove users from group

     *

     * This function is used to remove users from the current group

     * <br>Example:

     * <code>

     * $group = new EfrontGroup(2);

     * $group -> removeUsers(array('jdoe', 'doej'));

     * </code>

     *

     * @param mixed $users An array of user logins or EfrontUser objects, or a single login or EfrontUser object

     * @return boolean True if everything is ok

     * @since 3.5.2

     * @access public

     */
    public function removeUsers($users) {
        if (!is_array($users)) {
            if ($users instanceof EfrontUser) {
                $users = $users -> user['login'];
            }
            $users = array($users);
        }
        foreach ($users as $user) {
            if ($user instanceof EfrontUser) {
                $user = $user -> user['login'];
            }
            if (eF_checkParameter($user, 'login')) {
                eF_deleteTableData("users_to_groups", "users_LOGIN='".$user."' and groups_ID=".$this -> group['id']);
            }
        }
        return true;
    }
    /**

     * Update group users

     *

     * This function is used to update ALL current group users

     * in terms of active/languages_NAME/user_type

     * <br>Example:

     * <code>

     * $group = new EfrontGroup(2);

     * $group -> group['active'] = 2; 	// deactivate users

     * $group -> updateUsers();

     * $group -> persist();

     * </code>

     *

     * @param optionally a single user login might be set to update only this user's records

     * @return boolean True if everything is ok

     * @since 3.5.2

     * @access public

     */
    public function updateUsers($login = false) {
        if ($login) {
            $users = array($login);
        } else {
            $users = $this -> getUsers();
            $users = array_merge($users['professor'], $users['student']);
        }
        //pr($users);
        if (sizeof($users)) {
         if ($this -> group['user_types_ID']) {
             // If we have a custom user type
             if ($this -> group['user_types_ID'] != 'student' && $this -> group['user_types_ID'] != 'professor') {
              $basic_type = eF_getTableData("user_types", "basic_user_type", "id = '" . $this -> group['user_types_ID'] . "'");
              if (sizeof($basic_type)) {
                  $fields["user_type"] = $basic_type[0]['basic_user_type'];
                  $fields["user_types_ID"] = $this -> group['user_types_ID'];
              }
             } else {
                 // basic user type
                 $fields["user_type"] = $this -> group['user_types_ID'];
                 $fields["user_types_ID"] = 0;
             }
         }
         if ($this -> group['languages_NAME']) {
             $fields["languages_NAME"] = $this -> group['languages_NAME'];
         }
         if ($this -> group['users_active']) {
             $fields["active"] = ($this -> group['users_active'] == 1)? 1:0;
         }
         // If at least one value greater than zero
         if (sizeof($fields)) {
             return eF_updateTableData("users", $fields, "login IN ('". implode("','", $users) ."')");
         }
        }
        return true;
    }
    /**

     * Get group lessons

     *

     * This function returns an array with the group lessons. Each record in

     * the array holds the lesson id, lesson name and the type ('student' or 'professor')

     * assosiated with that lesson.

     *

     * <br/>Example:

     * <code>

     * try {

     *   $group     = new EfrontGroup(32);                     //32 is the group id

     *   $group_lessons = $group -> getLessons();

     * } catch (Exception $e) {

     *   echo $e -> getMessage();

     * }

     * </code><br/>

     * One thing to note is that this function caches results throughout the life

     * cycle of the object. That is, if some other function updates the group users,

     * the function results will not be altered, unless $refresh is set to true

     *

     * @return array of lessons in the form [lessons_ID] => [lessons_ID, lessons_name, user_type, active]

     * @since 3.5.2

     * @access public

     */
    public function getLessons() {
        if ($this -> lessons === false) { //Make a database query only if the variable is not initialized, or it is explicitly asked
            $result = eF_getTableData("lessons_to_groups lg, lessons l", "lg.*, l.name, l.active", "lg.lessons_ID = l.id and lg.groups_ID=".$this -> group['id']);
            $this -> lessons = array();
            foreach ($result as $value) {
                $this -> lessons[$value['lessons_ID']] = array("lessons_ID" => $value['lessons_ID'], "lessons_name" => $value['name'], "user_type" => $this -> group['user_types_ID'], "active" => $value['active']);
            }
         }
        return $this -> lessons;
    }
     /**

     * Add lessons to group

     *

     * This function is used to add lessons to the current group

     * <br>Example:

     * <code>

     * $group = new EfrontGroup(2);

     * $group -> addLesson(3, 'professor'); // will add lesson with id 3 and role 'professor' to the group's lessons

     * </code>

     *

     * @param $lessons_ID and $user_type

     * @return boolean True if everything is ok

     * @since 3.5.2

     * @access public

     */
    public function addLesson($lessons_ID, $user_type = "student") {
        // Check if the lesson exists in the group's list
        $lessons = $this -> getLessons();
        if (in_array($lessons_ID, array_keys($lessons))) {
            // If the lesson is already assigned check if you need
            // to update the user type for this lesson
            if ($lessons[$lessons_ID]['user_type'] != $user_type) {
                $ok = eF_updateTableData("lessons_to_groups", array("user_type" => $user_type), "lessons_ID = " . $lessons_ID);
                $this -> lessons[$lessons_ID]['user_type'] = $user_type;
                return $ok;
            }
        } else {
            $fields = array('lessons_ID' => $lessons_ID,
                'user_type' => $user_type,
                'groups_ID' => $this -> group['id']);
            if ($ok = eF_insertTableData("lessons_to_groups", $fields)) {
                $newLesson = new EfrontLesson($lessons_ID);
                $this -> lessons[$lessons_ID] = array('lessons_ID' => $lessons_ID,'lessons_name'=> $newLesson -> lesson['name'], 'user_type' => $user_type);
            }
            return $ok;
        }
        // if control flow reaches here then the lesson was already assigned and with the same user_type
        return false;
    }
    /**

     * Remove lessons from group

     *

     * This function is used to remove lessons from the current group

     * <br>Example:

     * <code>

     * $group = new EfrontGroup(2);

     * $group -> removeLessons(array(21, 32));	// remove lessons with ids 21 and 32

     * </code>

     *

     * @param mixed $users An array of lesson ids or EfrontLesson objects, or a single id or EfrontLesson object

     * @return boolean True if everything is ok

     * @since 3.5.2

     * @access public

     */
    public function removeLessons($lessons) {
        if (!is_array($lessons)) {
            if ($lessons instanceof EfrontLesson) {
                $lessons = $lessons -> lesson['id'];
            }
            $lessons = array($lessons);
        }
        foreach ($lessons as $lesson) {
            if ($lesson instanceof EfrontLesson) {
                $lesson = $lesson -> lesson['id'];
            }
            if (eF_checkParameter($lesson, 'id')) {
                eF_deleteTableData("lessons_to_groups", "lessons_ID ='".$lesson."' and groups_ID=".$this -> group['id']);
            }
        }
        return true;
    }
    /**

     * Get group courses

     *

     * This function returns an array with the group courses. Each record in

     * the array holds the course id, course name and the type ('student' or 'professor')

     * assosiated with that course.

     *

     * <br/>Example:

     * <code>

     * try {

     *   $group     = new EfrontGroup(32);                     //32 is the group id

     *   $group_courses = $group -> getCourses();

     * } catch (Exception $e) {

     *   echo $e -> getMessage();

     * }

     * </code><br/>

     * One thing to note is that this function caches results throughout the life

     * cycle of the object. That is, if some other function updates the group users,

     * the function results will not be altered, unless $refresh is set to true

     *

     * @param boolean $returnObjects whether to return EfrontCourse objects

     * @param boolean $refresh whether to refresh data

     * @return array of courses in the form [courses_ID] => [courses_ID, courses_name, user_type]

     * @since 3.5.2

     * @access public

     */
    public function getCourses($returnObjects = false, $refresh = false) {
        if ($this -> courses === false || $refresh) { //Make a database query only if the variable is not initialized, or it is explicitly asked
            $result = eF_getTableData("courses_to_groups lg, courses l", "lg.*, l.*", "lg.courses_ID = l.id and lg.groups_ID=".$this -> group['id']);
            $this -> courses = array();
            foreach ($result as $value) {
             if ($returnObjects) {
                 $this -> courses[$value['courses_ID']] = new EfrontCourse($value);
             } else {
                 $this -> courses[$value['courses_ID']] = array("courses_ID" => $value['courses_ID'], "courses_name" => $value['courses_name'], "user_type" => $this -> group['user_types_ID']);
             }
            }
         }
        return $this -> courses;
    }
    public function getGroupUsers($constraints = array()) {
     !empty($constraints) OR $constraints = array('archive' => false, 'active' => true);
  list($where, $limit, $orderby) = EfrontUser :: convertUserConstraintsToSqlParameters($constraints);
  $where[] = "ug.users_LOGIN=u.login";
  $result = eF_getTableData("users u, users_to_groups ug", "u.*, 1 as has_group", implode(" and ", $where), $orderby, "", $limit);
  return EfrontUser :: convertDatabaseResultToUserObjects($result);
    }
    public function getGroupUsersIncludingUnassigned($constraints = array()) {
     !empty($constraints) OR $constraints = array('archive' => false, 'active' => true);
  list($where, $limit, $orderby) = EfrontUser :: convertUserConstraintsToSqlParameters($constraints);
     $result = eF_getTableData("users u left outer join users_to_groups ug on ug.users_LOGIN=u.login",
         implode(" and ", $where), $orderby, "", $limit);
  return EfrontUser :: convertDatabaseResultToUserObjects($result);
    }
    /*

     * Returns the courses of the group users only

     */
 public function getGroupUserCourses($constraints = array()) {
  $select['main'] = 'c.*';
  $select['has_instances'] = "(select count( * ) from courses l where instance_source=c.id) as has_instances";
  $select['num_lessons'] = "(select count( * ) from lessons_to_courses cl, lessons l where cl.courses_ID=c.id and l.archive=0 and l.id=cl.lessons_ID) as num_lessons";
  // num_students: assigned+completed
  $select['num_students'] = "(select count( * ) from users_to_courses uc, users u where uc.courses_ID=c.id and u.archive=0 and uc.archive=0 and u.login=uc.users_LOGIN and u.user_type='student') as num_students";
  $select['num_assigned'] = "(select count( * ) from users_to_courses uc, users u, users_to_groups ug where uc.courses_ID=c.id and u.archive=0 and uc.archive=0 and u.login=uc.users_LOGIN and u.user_type='student' and uc.completed=0 and u.login=ug.users_LOGIN and ug.groups_ID = ".$this -> group['id'].") as num_assigned";
  $select['num_completed'] = "(select count( * ) from users_to_courses uc, users u, users_to_groups ug where uc.courses_ID=c.id and u.archive=0 and uc.archive=0 and u.login=uc.users_LOGIN and u.user_type='student' and uc.completed=1 and u.login=ug.users_LOGIN and ug.groups_ID = ". $this -> group['id'].") as num_completed";
  $select = EfrontCourse :: convertCourseConstraintsToRequiredFields($constraints, $select);
  list($where, $limit, $orderby) = EfrontCourse :: convertCourseConstraintsToSqlParameters($constraints);
  $result = eF_getTableData("courses c", implode(",", $select), implode(" and ", $where), $orderby, false, $limit);
  if (!isset($constraints['return_objects']) || $constraints['return_objects'] == true) {
   return EfrontCourse :: convertDatabaseResultToCourseObjects($result);
  } else {
   return $result;
  }
 }
    /*

     * Returns the courses of the group users only plus any unassigned courses

     */
    public function getGroupCourses($constraints = array()) {
     !empty($constraints) OR $constraints = array('archive' => false, 'active' => true);
  list($where, $limit, $orderby) = EfrontCourse :: convertCourseConstraintsToSqlParameters($constraints);
  $select = "c.*, cg.user_type, 1 as has_course,
       (select count( * ) from courses c1, courses_to_groups cg1 where c1.instance_source=c.id and cg1.courses_ID=c1.id and cg.groups_ID=".$this -> group['id'].")
         as has_instances,
       (select count( * ) from lessons_to_courses cl, lessons l where cl.courses_ID=c.id and l.archive=0 and l.id=cl.lessons_ID)
         as num_lessons,
       (select count( * ) from users_to_courses uc, users u where uc.courses_ID=c.id and u.archive=0 and u.login=uc.users_LOGIN and u.user_type='student')
         as num_students";
  $where[] = "c.id=cg.courses_ID and cg.groups_ID=".$this -> group['id'];
     $result = eF_getTableData("courses c, courses_to_groups cg", $select,
         implode(" and ", $where), $orderby, $groupby, $limit);
  return EfrontCourse :: convertDatabaseResultToCourseObjects($result);
    }
    public function countGroupCourses($constraints = array()) {
     !empty($constraints) OR $constraints = array('archive' => false, 'active' => true);
     list($where, $limit, $orderby) = EfrontCourse :: convertCourseConstraintsToSqlParameters($constraints);
  $where[] = "c.id=cg.courses_ID and cg.groups_ID=".$this -> group['id'];
     $result = eF_getTableData("courses c, courses_to_groups cg", "c.id",
         implode(" and ", $where));
  return $result[0]['count'];
    }
    public function getGroupCoursesIncludingUnassigned($constraints = array()) {
     !empty($constraints) OR $constraints = array('archive' => false, 'active' => true);
  list($where, $limit, $orderby) = EfrontCourse :: convertCourseConstraintsToSqlParameters($constraints);
  $select = "c.*, r.courses_ID is not null as has_course,
       (select count( * ) from courses l where instance_source=c.id)
         as has_instances,
       (select count( * ) from lessons_to_courses cl, lessons l where cl.courses_ID=c.id and l.archive=0 and l.id=cl.lessons_ID)
         as num_lessons,
       (select count( * ) from users_to_courses uc, users u where uc.courses_ID=c.id and u.archive=0 and u.login=uc.users_LOGIN and u.user_type='student')
         as num_students";
  //$where[] = "d.id=c.directions_ID";
     $result = eF_getTableData("courses c left outer join (select courses_ID from courses_to_groups where groups_ID=".$this -> group['id'].") r on c.id=r.courses_ID", $select,
         implode(" and ", $where), $orderby, $groupby, $limit);
  return EfrontCourse :: convertDatabaseResultToCourseObjects($result);
    }
    public function countGroupCoursesIncludingUnassigned($constraints = array()) {
     !empty($constraints) OR $constraints = array('archive' => false, 'active' => true);
     list($where, $limit, $orderby) = EfrontCourse :: convertCourseConstraintsToSqlParameters($constraints);
     $result = eF_countTableData("courses c left outer join (select courses_ID from courses_to_groups where groups_ID=".$this -> group['id'].") r on c.id=r.courses_ID", "c.id",
         implode(" and ", $where));
  return $result[0]['count'];
    }
     /**

     * Add courses to group

     *

     * This function is used to add courses to the current group

     * <br>Example:

     * <code>

     * $group = new EfrontGroup(2);

     * $group -> addCourse(3, 'professor'); // will add course with id 3 and role 'professor' to the group's courses

     * </code>

     *

     * @param $courses_ID and $user_type

     * @return boolean True if everything is ok

     * @since 3.5.2

     * @access public

     */
    public function addCourse($courses_ID, $user_type = "student") {
        // Check if the course exists in the group's list
        $courses = $this -> getCourses();
        if (in_array($courses_ID, array_keys($courses))) {
            // If the course is already assigned check if you need
            // to update the user type for this course
            if ($courses[$courses_ID]['user_type'] != $user_type) {
                $ok = eF_updateTableData("courses_to_groups", array("user_type" => $user_type), "courses_ID = " . $courses_ID);
                $this -> courses[$courses_ID]['user_type'] = $user_type;
                return $ok;
            }
        } else {
            $fields = array('courses_ID' => $courses_ID,
                'user_type' => $user_type,
                'groups_ID' => $this -> group['id']);
            if ($ok = eF_insertTableData("courses_to_groups", $fields)) {
                $newCourse = new EfrontCourse($courses_ID);
                $this -> courses[$courses_ID] = array('courses_ID' => $courses_ID,'courses_name'=> $newCourse -> course['name'], 'user_type' => $user_type);
            }
            return $ok;
        }
        // if control flow reaches here then the course was already assigned and with the same user_type
        return false;
    }
    /**

     * Remove courses from group

     *

     * This function is used to remove courses from the current group

     * <br>Example:

     * <code>

     * $group = new EfrontGroup(2);

     * $group -> removeCourses(array(21, 32));	// remove courses with ids 21 and 32

     * </code>

     *

     * @param mixed $users An array of course ids or EfrontCourse objects, or a single id or EfrontCourse object

     * @return boolean True if everything is ok

     * @since 3.5.2

     * @access public

     */
    public function removeCourses($courses) {
        if (!is_array($courses)) {
            if ($courses instanceof EfrontCourse) {
                $courses = $courses -> course['id'];
            }
            $courses = array($courses);
        }
        foreach ($courses as $course) {
            if ($course instanceof EfrontCourse) {
                $course = $course -> course['id'];
            }
            if (eF_checkParameter($course, 'id')) {
                eF_deleteTableData("courses_to_groups", "courses_ID ='".$course."' and groups_ID=".$this -> group['id']);
            }
        }
        return true;
    }
    public function setData($fields, $persist = false) {
        if (sizeof($fields['name']) > 0)
            $this -> group['name'] = $fields['name'];
        if (sizeof($fields['description']) > 0)
            $this -> group['description'] = $fields['description'];
        if (sizeof($fields['active']) > 0)
            $this -> group['active'] = $fields['active'];
        if ($persist) {
            $this -> persist();
        }
    }
    /**

     * Persist group values

     *

     * This function is used to persist any changes made to the current

     * group.

     * <br/>Example:

     * <code>

     * $group = new EfrontGroup(3);										//Instantiate group with id 3

     * $group -> group['name'] = 'new name';							//Change a group's value

     * $group -> persist();												//Store changes values to the database

     * </code>

     *

     * @return boolean True if everything is ok

     * @since 3.5.0

     * @access public

     */
    public function persist() {
        // Remove the current default group
        if ($this -> group['is_default']) {
            eF_updateTableData("groups", array("is_default" => 0), "1=1");
        }
        $ok = eF_updateTableData("groups", $this -> group, "id=".$this -> group['id']);
        return $ok;
    }
   /**

     * Adds a user to the default group

     *

     * This function adds a user to the default group, assigning to him the lessons

     * of that group.

     *

     * <br/>Example:

     * <code>

     * $userObject = EfrontUserFactory::factory('joe'); 	// create user object joe

     * EfrontGroup :: addToDefaultGroup($userObject);

     * </code>

     *

     * @param $user InstanceOf EfrontUser

     * @return true if everything ok

     * @since 3.5.2

     * @access public

     */
   private static $default_group = false;
   public static function addToDefaultGroup($user) {
    if (!($user instanceof EfrontUser)) {
     $login = $user['login'];
    } else {
     $login = $user -> user['login'];
    }
    // Get the default eFront group
    if (!$default_group) {
     $default_group = eF_getTableData("groups", "*", "is_default = 1 AND active = 1");
     if (sizeof($default_group)) {
      $default_group = $default_group[0];
     } else {
      $default_group = true;
      return;
     }
    }
    // pr($default_group);
    try {
     $group = new EfrontGroup($default_group);
     $group -> addUsers($login);
/*

   		$group -> updateUsers($login);



   		// Get updated version of user

   		try {

   			$updatedUser = EfrontUserFactory::factory($login);

   		} catch (Exception $e) {

   			throw $e;

   		}



   		// Assign default group type

   		$groupLessons = $group -> getLessons();

   		$lessonIds = array_keys($groupLessons);

   		if(!empty($lessonIds)) {

   			if ($updatedUser -> user['user_types_ID'] != 0) {

   				$user_type = $updatedUser -> user['user_types_ID'];

   			} else {

   				$user_type = $updatedUser -> user['user_type'];

   			}



   			$user_types = array();

   			foreach($lessonIds as $lesson) {

   				$user_types[] = $user_type;

   			}

   			$user -> addLessons($lessonIds, $user_types, 1);

   		}

   		$groupCourses = $group -> getCourses();

   		$courseIds = array_keys($groupCourses);

   		if(!empty($courseIds)) {

   			$user_types = array();

   			foreach($courseIds as $course) {

   				$user_types[] = $user_type;

   			}

   			$user -> addCourses($courseIds, $user_types, 1);

   		}

*/
    } catch (Exception $e) {
     // otherwise no default group has been defined
    }
    return true;
   }
   /**

     * Returns the existing groups

     *

     * This function returns the existing groups

     * group.

     * <br/>Example:

     * <code>

     * $groups -> EfrontGroup :: getGroups();

     * </code>

     *

     * @param boolean Flat to indicate whether to return group objects or not

     * @param boolean Flag to indicate whether to return disabled groups

     * @return array An array of groups. Each element is the group array

     * @since 3.5.0

     * @access public

     */
    public static function getGroups($returnObjects = false, $returnDisabled = false){
        $groups = array();
        if ($returnDisabled){
            $data = ef_getTableData("groups", "id, name");
        }
        else{
            $data = ef_getTableData("groups", "id, name", "active = 1");
        }
        if ($returnObjects){
            foreach ($data as $group_info){
                $group = new EfrontGroup($group_info['id']);
                $groups[$group_info['id']] = $group;
            }
        }
        else{
            foreach ($data as $group_info){
                $groups[$group_info['id']] = $group_info;
            }
        }
        return $groups;
    }
   /**

     * Returns the lessons that are associated with the group's users (NOT necessarily with the group)

     *

     * <br/>Example:

     * <code>

     * $group = new EfrontGroup(2);

     * $group->getLessonGroupUsers();

     * </code>

     *

     * @param boolean Flat to indicate whether to return lesson objects or not

     * @param boolean Flag to indicate whether to return disabled lessons

     * @return array An array of lessons. Each element is the lesson array

     * @since 3.6.0

     * @access public

     */
    public function getLessonGroupUsers($returnObjects = false, $returnDisabled = false){
        $lessons = array();
        if ($returnDisabled){
            $data = eF_getTableData("lessons JOIN users_to_lessons ON lessons.id = users_to_lessons.lessons_ID JOIN users_to_groups ON users_to_groups.users_LOGIN = users_to_lessons.users_LOGIN", "lessons.*, count(users_to_lessons.users_LOGIN) as group_users_count", "users_to_lessons.archive=0 and groups_ID = ". $this -> group['id'], "", "lessons_ID");
        } else{
            $data = eF_getTableData("lessons JOIN users_to_lessons ON lessons.id = users_to_lessons.lessons_ID JOIN users_to_groups ON users_to_groups.users_LOGIN = users_to_lessons.users_LOGIN", "lessons.*, count(users_to_lessons.users_LOGIN) as group_users_count", "users_to_lessons.archive=0 and lessons.active = 1 AND groups_ID = ". $this -> group['id'], "", "lessons_ID");
        }
        if ($returnObjects){
            foreach ($data as $lesson_info){
                $lesson = new EfrontLesson($lesson_info['id']);
                $lessons[$lesson_info['id']] = $lesson;
            }
        }
        else{
            foreach ($data as $lesson_info){
                $lessons[] = $lesson_info;
            }
        }
        return $lessons;
    }
}
?>
