5 * Copyright 1999-2001, VA Linux Systems, Inc.
6 * Copyright 2009-2013, Roland Mas
7 * Copyright 2010-2011, Franck Villaume - Capgemini
8 * Copyright 2010-2012, Alain Peyrat - Alcatel-Lucent
9 * Copyright 2012-2016, Franck Villaume - TrivialDev
10 * Copyright 2013, French Ministry of National Education
11 * http://fusionforge.org
13 * This file is part of FusionForge. FusionForge is free software;
14 * you can redistribute it and/or modify it under the terms of the
15 * GNU General Public License as published by the Free Software
16 * Foundation; either version 2 of the Licence, or (at your option)
19 * FusionForge is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License along
25 * with FusionForge; if not, write to the Free Software Foundation, Inc.,
26 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29 require_once $gfcommon.'tracker/ArtifactTypes.class.php';
30 require_once $gfcommon.'tracker/ArtifactTypeFactory.class.php';
31 require_once $gfcommon.'tracker/RoadmapFactory.class.php';
32 require_once $gfcommon.'forum/Forum.class.php';
33 require_once $gfcommon.'forum/ForumFactory.class.php';
34 require_once $gfcommon.'pm/ProjectGroup.class.php';
35 require_once $gfcommon.'pm/ProjectGroupFactory.class.php';
36 require_once $gfcommon.'include/Role.class.php';
37 require_once $gfcommon.'frs/FRSPackage.class.php';
38 require_once $gfcommon.'docman/DocumentGroup.class.php';
39 require_once $gfcommon.'docman/DocumentGroupFactory.class.php';
40 require_once $gfcommon.'mail/MailingList.class.php';
41 require_once $gfcommon.'mail/MailingListFactory.class.php';
42 require_once $gfcommon.'survey/SurveyFactory.class.php';
43 require_once $gfcommon.'survey/SurveyQuestionFactory.class.php';
44 require_once $gfcommon.'include/gettext.php';
45 require_once $gfcommon.'include/GroupJoinRequest.class.php';
50 * group_get_object() - Get the group object.
52 * group_get_object() is useful so you can pool group objects/save database queries
53 * You should always use this instead of instantiating the object directly.
55 * You can now optionally pass in a db result handle. If you do, it re-uses that query
56 * to instantiate the objects.
58 * IMPORTANT! That db result must contain all fields
59 * from groups table or you will have problems
61 * @param int $group_id Required
62 * @param int|bool $res Result set handle ("SELECT * FROM groups WHERE group_id=xx")
63 * @return Group|bool A group object or false on failure
65 function &group_get_object($group_id, $res = false) {
66 //create a common set of group objects
67 //saves a little wear on the database
69 //automatically checks group_type and
70 //returns appropriate object
73 if (!isset($GROUP_OBJ["_".$group_id."_"])) {
75 //the db result handle was passed in
77 $res = db_query_params('SELECT * FROM groups WHERE group_id=$1', array($group_id));
79 if (!$res || db_numrows($res) < 1) {
80 $GROUP_OBJ["_".$group_id."_"]=false;
83 check group type and set up object
85 if (db_result($res,0,'type_id') == 1) {
87 $GROUP_OBJ["_".$group_id."_"] = new Group($group_id, $res);
90 $GROUP_OBJ["_".$group_id."_"] = false;
94 return $GROUP_OBJ["_".$group_id."_"];
97 function &group_get_objects($id_arr) {
100 // Note: if we don't do this, the result may be corrupted
104 foreach ($id_arr as $id) {
106 // See if this ID already has been fetched in the cache
108 if (!isset($GROUP_OBJ["_".$id."_"])) {
112 if (count($fetch) > 0) {
113 $res=db_query_params('SELECT * FROM groups WHERE group_id = ANY ($1)',
114 array(db_int_array_to_any_clause($fetch)));
115 while ($arr = db_fetch_array($res)) {
116 $GROUP_OBJ["_".$arr['group_id']."_"] = new Group($arr['group_id'],$arr);
119 foreach ($id_arr as $id) {
120 $return[] =& $GROUP_OBJ["_".$id."_"];
125 function &group_get_active_projects() {
126 $res = db_query_params('SELECT group_id FROM groups WHERE status=$1',
128 return group_get_objects(util_result_column_to_array($res,0));
131 function &group_get_all_projects() {
132 $res = db_query_params ('SELECT group_id FROM groups',
134 return group_get_objects(util_result_column_to_array($res,0));
137 function &group_get_template_projects() {
138 $res = db_query_params('SELECT group_id FROM groups WHERE is_template=1 AND status != $1',
140 return group_get_objects(util_result_column_to_array($res,0));
143 function &group_get_object_by_name($groupname) {
144 $res = db_query_params('SELECT * FROM groups WHERE unix_group_name=$1', array($groupname));
145 return group_get_object(db_result($res, 0, 'group_id'), $res);
148 function &group_get_objects_by_name($groupname_arr) {
149 $res = db_query_params('SELECT group_id FROM groups WHERE unix_group_name = ANY ($1)',
150 array(db_string_array_to_any_clause($groupname_arr)));
151 $arr =& util_result_column_to_array($res,0);
152 return group_get_objects($arr);
155 function group_get_object_by_publicname($groupname) {
156 $res = db_query_params('SELECT * FROM groups WHERE lower(group_name) LIKE $1',
157 array(htmlspecialchars(html_entity_decode(strtolower($groupname)))));
158 return group_get_object(db_result($res, 0, 'group_id'), $res);
162 * get_public_active_projects_asc() - Get a list of rows for public active projects (initially in trove/full_list)
164 * @param int $max_query_limit Optional Maximum number of rows to limit query length
165 * @param int $offset start to retrieve rows from offset value
166 * @return array List of public active projects
168 function group_get_public_active_projects_asc($max_query_limit = -1, $offset = 0) {
170 if (session_loggedin()) {
172 $userRoles = $LUSER->getRoles();
173 if (count($userRoles)) {
174 foreach ($userRoles as $r) {
175 $role_id .= ', '.$r->getID();
180 $res_grp = db_query_params ('
181 SELECT group_id, group_name, unix_group_name, short_description, register_time
183 WHERE status = $1 AND type_id=1 AND is_template=0 AND register_time > 0
184 AND group_id in (select ref_id FROM pfo_role_setting WHERE section_name = $2 and perm_val = 1 and role_id IN ('.$role_id.'))
185 ORDER BY group_name ASC
187 array('A', 'project_read'),
188 $max_query_limit, $offset);
190 while ($row_grp = db_fetch_array($res_grp)) {
191 $projects[] = $row_grp;
197 * group_get_readable_projects_using_tag_asc() - Get a list of group_id for active projects (initially in trove/tag_cloud)
199 * @param string $selected_tag Tag to search
200 * @param int $max_query_limit Optional Maximum number of rows to limit query length
201 * @param int $offset start to retrieve rows from offset value
202 * @return array List of public active projects
204 function group_get_readable_projects_using_tag_asc($selected_tag, $max_query_limit = -1, $offset = 0) {
206 if (session_loggedin()) {
208 $userRoles = $LUSER->getRoles();
209 if (count($userRoles)) {
210 foreach ($userRoles as $r) {
211 $role_id .= ', '.$r->getID();
216 $res_grp = db_query_params ('SELECT groups.group_id, group_name, unix_group_name, short_description, register_time
217 FROM project_tags, groups
218 WHERE LOWER(name) = $1
219 AND project_tags.group_id = groups.group_id
220 AND groups.status = $2 AND groups.type_id=1 AND groups.is_template=0 AND groups.register_time > 0
221 AND groups.group_id in (select ref_id FROM pfo_role_setting WHERE section_name = $3 and perm_val = 1 and role_id IN ('.$role_id.'))
222 ORDER BY groups.group_name ASC',
223 array(strtolower($selected_tag), 'A', 'project_read'),
224 $max_query_limit, $offset);
226 while ($row_grp = db_fetch_array($res_grp)) {
227 $projects[] = $row_grp;
232 class Group extends FFError {
234 * Associative array of data from db.
236 * @var array $data_array.
241 * array of User objects.
243 * @var array $membersArr.
248 * Whether the use is an admin/super user of this project.
250 * @var bool $is_admin.
255 * Artifact types result handle.
257 * @var int $types_res.
262 * Associative array of data for plugins.
264 * @var array $plugins_data.
270 * Associative array of data for the group menu.
272 * @var array $menu_data.
277 * Group - Group object constructor - use group_get_object() to instantiate.
279 * @param int|bool $id Required - Id of the group you want to instantiate.
280 * @param int|bool $res Database result from select query OR associative array of all columns.
282 function __construct($id = false, $res = false) {
283 parent::__construct();
285 //setting up an empty object
286 //probably going to call create()
290 if (!$this->fetchData($id)) {
295 // Assoc array was passed in
297 if (is_array($res)) {
298 $this->data_array =& $res;
300 if (db_numrows($res) < 1) {
301 //function in class we extended
302 $this->setError(_('Group Not Found'));
303 $this->data_array=array();
306 //set up an associative array for use by other functions
307 $this->data_array = db_fetch_array_by_row($res, 0);
315 * fetchData - May need to refresh database fields if an update occurred.
317 * @param int $group_id The group_id.
318 * @return bool success or not
320 function fetchData($group_id) {
321 $res = db_query_params ('SELECT * FROM groups WHERE group_id=$1',
323 if (!$res || db_numrows($res) < 1) {
324 $this->setError(sprintf('fetchData(): %s', db_error()));
327 $this->data_array = db_fetch_array($res);
332 * create - Create new group.
334 * This method should be called on empty Group object.
335 * It will add an entry for a pending group/project (status 'P')
337 * @param object $user The User object.
338 * @param string $group_name The full name of the user.
339 * @param string $unix_name The Unix name of the user.
340 * @param string $description The new group description.
341 * @param string $purpose The purpose of the group.
342 * @param string $unix_box
343 * @param string $scm_box
344 * @param bool $is_public
345 * @param bool $send_mail Whether to send an email or not
346 * @param int $built_from_template The id of the project this new project is based on
347 * @return bool success or not
349 function create(&$user, $group_name, $unix_name, $description, $purpose, $unix_box = 'shell1',
350 $scm_box = 'cvs1', $is_public = true, $send_mail = true, $built_from_template = 0) {
351 // $user is ignored - anyone can create pending group
354 if ($this->getID()!=0) {
355 $this->setError(_('Group object already exists.'));
357 } elseif (!$this->validateGroupName($group_name)) {
358 $this->setError(_('Invalid project name'));
360 } elseif (!account_groupnamevalid($unix_name)) {
361 $this->setError(_('Invalid Unix Name.'));
363 } elseif (!$SYS->sysUseUnixName($unix_name)) {
364 $this->setError(_('Unix name already taken.'));
366 } elseif (db_numrows(db_query_params('SELECT group_id FROM groups WHERE unix_group_name=$1',
367 array($unix_name))) > 0) {
368 $this->setError(_('Unix name already taken.'));
370 } elseif (strlen($purpose)<10) {
371 $this->setError(_('Please describe your Registration Project Purpose and Summarization in a more comprehensive manner.'));
373 } elseif (strlen($purpose)>1500) {
374 $this->setError(_('The Registration Project Purpose and Summarization text is too long. Please make it smaller than 1500 characters.'));
376 } elseif (strlen($description)<10) {
377 $this->setError(_('Describe in a more comprehensive manner your project.'));
381 // Check if sys_use_project_vhost for homepage
382 if (forge_get_config('use_project_vhost')) {
383 $homepage = $unix_name.".".forge_get_config('web_host');
385 $homepage = forge_get_config('web_host')."/www/".$unix_name."/";
390 $res = db_query_params('
405 VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)',
406 array(htmlspecialchars($group_name),
408 htmlspecialchars($description),
414 htmlspecialchars($purpose),
416 md5(util_randbytes()),
417 $built_from_template));
418 if (!$res || db_affected_rows($res) < 1) {
419 $this->setError(sprintf(_('Error: Cannot create group: %s'),db_error()));
424 $id = db_insertid($res, 'groups', 'group_id');
426 $this->setError(sprintf(_('Error: Cannot get group id: %s'),db_error()));
431 if (!$this->fetchData($id)) {
436 $gjr = new GroupJoinRequest($this);
437 $gjr->create($user->getID(),
438 'Fake GroupJoinRequest to store the creator of a project',
441 $hook_params = array();
442 $hook_params['group'] = $this;
443 $hook_params['group_id'] = $this->getID();
444 $hook_params['group_name'] = $group_name;
445 $hook_params['unix_group_name'] = $unix_name;
446 plugin_hook("group_create", $hook_params);
450 $this->sendNewProjectNotificationEmail();
458 * updateAdmin - Update core properties of group object.
460 * This function require site admin privilege.
462 * @param object $user User requesting operation (for access control).
463 * @param int $type_id Group type (1-project, 2-foundry).
464 * @param string $unix_box Machine on which group's home directory located.
465 * @param string $http_domain Domain which serves group's WWW.
466 * @return bool status.
469 function updateAdmin(&$user, $type_id, $unix_box, $http_domain) {
470 $perm =& $this->getPermission();
472 if (!$perm || !is_object($perm)) {
473 $this->setError(_('Could not get permission.'));
477 if (!$perm->isSuperUser()) {
478 $this->setError(_('Permission denied.'));
484 $res = db_query_params('
486 SET type_id=$1, unix_box=$2, http_domain=$3
493 if (!$res || db_affected_rows($res) < 1) {
494 $this->setError(_('Error: Cannot change group properties: %s'),db_error());
499 // Log the audit trail
500 if ($type_id != $this->data_array['type_id']) {
501 $this->addHistory('type_id', $this->data_array['type_id']);
503 if ($unix_box != $this->data_array['unix_box']) {
504 $this->addHistory('unix_box', $this->data_array['unix_box']);
506 if ($http_domain != $this->data_array['http_domain']) {
507 $this->addHistory('http_domain', $this->data_array['http_domain']);
510 if (!$this->fetchData($this->getID())) {
519 * update - Update number of common properties.
521 * Unlike updateAdmin(), this function accessible to project admin.
523 * @param object $user User requesting operation (for access control).
524 * @param string $group_name
525 * @param string $homepage
526 * @param string $short_description
527 * @param bool $use_mail
528 * @param bool $use_survey
529 * @param bool $use_forum
530 * @param bool $use_pm
531 * @param bool $use_pm_depend_box
532 * @param bool $use_scm
533 * @param bool $use_news
534 * @param bool $use_docman
535 * @param string $new_doc_address
536 * @param bool $send_all_docs
537 * @param int $logo_image_id XXXX UNUSED XXXX -> see getLogoImageID function
538 * @param bool $use_ftp
539 * @param bool $use_tracker
540 * @param bool $use_frs
541 * @param bool $use_stats
542 * @param string $tags
543 * @param bool $use_activity
544 * @param bool $is_public group is publicly accessible
545 * @return int status.
548 function update(&$user, $group_name, $homepage, $short_description, $use_mail, $use_survey, $use_forum,
549 $use_pm, $use_pm_depend_box, $use_scm, $use_news, $use_docman,
550 $new_doc_address, $send_all_docs, $logo_image_id,
551 $use_ftp, $use_tracker, $use_frs, $use_stats, $tags, $use_activity, $is_public) {
553 $perm =& $this->getPermission();
555 if (!$perm || !is_object($perm)) {
556 $this->setError(_('Could not get permission.'));
560 if (!$perm->isAdmin()) {
561 $this->setError(_('Permission denied.'));
565 // Validate some values
566 if ($this->getPublicName() != htmlspecialchars($group_name)) {
567 if (!$this->validateGroupName($group_name)) {
572 if ($new_doc_address) {
573 $invalid_mails = validate_emails($new_doc_address);
574 if (count($invalid_mails) > 0) {
575 $this->setError(sprintf(ngettext('New Doc Address Appeared Invalid: %s', 'New Doc Addresses Appeared Invalid: %s', count($invalid_mails)),implode(',',$invalid_mails)));
580 // in the database, these all default to '1',
581 // so we have to explicitly set 0
594 if (!$use_pm_depend_box) {
595 $use_pm_depend_box = 0;
618 if (!$use_activity) {
621 if (!$send_all_docs) {
625 $homepage = ltrim($homepage);
627 $homepage = util_make_url('/projects/' . $this->getUnixName() . '/');
632 $res = db_query_params('UPDATE groups
635 short_description=$3,
640 use_pm_depend_box=$8,
651 array(htmlspecialchars($group_name),
653 htmlspecialchars($short_description),
670 if (!$res || db_affected_rows($res) < 1) {
671 $this->setError(sprintf(_('Error updating project information: %s'), db_error()));
676 if (!$this->setUseDocman($use_docman)) {
677 $this->setError(sprintf(_('Error updating project information: use_docman %s'), db_error()));
682 if ($this->setTags($tags) === false) {
687 // Log the audit trail
688 $this->addHistory('Changed Public Info', '');
690 if (!$this->fetchData($this->getID())) {
695 $hook_params = array();
696 $hook_params['group'] = $this;
697 $hook_params['group_id'] = $this->getID();
698 $hook_params['group_homepage'] = $homepage;
699 $hook_params['group_name'] = htmlspecialchars($group_name);
700 $hook_params['group_description'] = htmlspecialchars($short_description);
701 $hook_params['group_ispublic'] = $is_public;
702 if (!plugin_hook("group_update", $hook_params)) {
703 if (!$this->isError()) {
704 $this->setError(_('Error updating project information in plugin_hook group_update'));
715 * getID - Simply return the group_id for this object.
717 * @return int group_id.
720 return $this->data_array['group_id'];
724 * getType() - Foundry, project, etc.
726 * @return int The type flag from the database.
729 return $this->data_array['type_id'];
734 * getStatus - the status code.
736 * Statuses char include I,H,A,D,P.
743 function getStatus() {
744 return $this->data_array['status'];
748 * setStatus - set the status code.
750 * Statuses include I,H,A,D,P.
757 * @param object $user User requesting operation (for access control).
758 * @param string $status Status value.
759 * @return bool success.
762 function setStatus(&$user, $status) {
765 if (!forge_check_global_perm_for_user($user, 'approve_projects')) {
766 $this->setPermissionDeniedError();
770 // Projects in 'A' status can only go to 'H' or 'D'
771 // Projects in 'D' status can only go to 'A'
772 // Projects in 'P' status can only go to 'A' OR 'D'
773 // Projects in 'I' status can only go to 'P'
774 // Projects in 'H' status can only go to 'A' OR 'D'
775 $allowed_status_changes = array(
776 'AH'=>1,'AD'=>1,'DA'=>1,'PA'=>1,'PD'=>1,
777 'IP'=>1,'HA'=>1,'HD'=>1
780 // Check that status transition is valid
781 if ($this->getStatus() != $status
782 && !array_key_exists($this->getStatus(). $status, $allowed_status_changes)) {
783 $this->setError(_('Invalid Status Change From: ').$this->getStatus(). _(' To: '.$status));
789 $res = db_query_params('UPDATE groups
791 WHERE group_id=$2', array($status, $this->getID()));
793 if (!$res || db_affected_rows($res) < 1) {
794 $this->setError(sprintf(_('Error: Cannot change group status: %s'),db_error()));
800 // Activate system group, if not yet
801 if (!$SYS->sysCheckGroup($this->getID())) {
802 if (!$SYS->sysCreateGroup($this->getID())) {
803 $this->setError($SYS->getErrorMessage());
808 if (!$this->activateUsers()) {
813 /* Otherwise, the group is not active, and make sure that
814 System group is not active either */
815 } elseif ($SYS->sysCheckGroup($this->getID())) {
816 if (!$SYS->sysRemoveGroup($this->getID())) {
817 $this->setError($SYS->getErrorMessage());
823 $hook_params = array();
824 $hook_params['group'] = $this;
825 $hook_params['group_id'] = $this->getID();
826 $hook_params['status'] = $status;
827 plugin_hook("group_setstatus", $hook_params);
831 // Log the audit trail
832 if ($status != $this->getStatus()) {
833 $this->addHistory(_('Status'), $this->getStatus());
836 $this->data_array['status'] = $status;
841 * isProject - Simple boolean test to see if it's a project or not.
843 * @return bool is_project.
845 function isProject() {
846 if ($this->getType()==1) {
854 * isPublic - Wrapper around RBAC to check if a project is anonymously readable
856 * @return boo is_public.
858 function isPublic() {
859 $ra = RoleAnonymous::getInstance();
860 return $ra->hasPermission('project_read', $this->getID());
864 * isActive - Database field status of 'A' returns true.
866 * @return bool is_active.
868 function isActive() {
869 if ($this->getStatus()=='A') {
877 * isTemplate - Simply returns the is_template flag from the database.
879 * @return bool is_template.
881 function isTemplate() {
882 return $this->data_array['is_template'];
886 * setAsTemplate - Set the template status of a project
888 * @param bool $booleanparam is_template.
891 function setAsTemplate($booleanparam) {
893 $booleanparam = $booleanparam ? 1 : 0;
894 $res = db_query_params('UPDATE groups SET is_template=$1 WHERE group_id=$2',
895 array($booleanparam, $this->getID()));
897 $this->data_array['is_template']=$booleanparam;
907 * getTemplateProject - Return the project template this project is built from
909 * @return object The template project
911 function getTemplateProject() {
912 return group_get_object($this->data_array['built_from_template']);
916 * getUnixName - the unix_name
918 * @return string unix_name.
920 function getUnixName() {
921 return strtolower($this->data_array['unix_group_name']);
925 * getPublicName - the full-length public name.
927 * @return string The group_name.
929 function getPublicName() {
930 return $this->data_array['group_name'];
934 * getRegisterPurpose - the text description of the purpose of this project.
936 * @return string The description.
938 function getRegisterPurpose() {
939 return $this->data_array['register_purpose'];
943 * getDescription - the text description of this project.
945 * @return string The description.
947 function getDescription() {
948 return $this->data_array['short_description'];
952 * getStartDate - the unix time this project was registered.
954 * @return int (unix time) of registration.
956 function getStartDate() {
957 return $this->data_array['register_time'];
961 * getLogoImageID - the id of the logo in the database for this project.
963 * @return int The ID of logo image in db_images table (or 100 if none).
965 function getLogoImageID() {
966 if (!isset($this->data_array['logo_image_id'])) {
967 $res = db_query_params('select id from db_images where group_id = $1 and is_logo = $2',
968 array($this->getID(), 1));
969 if ($res && db_numrows($res)) {
970 $this->data_array['logo_image_id'] = db_result($res, 0, 'id');
972 $this->data_array['logo_image_id'] = null;
975 return $this->data_array['logo_image_id'];
979 * getUnixBox - the hostname of the unix box where this project is located.
981 * @return string The name of the unix machine for the group.
983 function getUnixBox() {
984 return $this->data_array['unix_box'];
988 * getSCMBox - the hostname of the scm box where this project is located.
990 * @return string The name of the unix machine for the group.
992 function getSCMBox() {
993 return $this->data_array['scm_box'];
996 * setSCMBox - the hostname of the scm box where this project is located.
998 * @param string $scm_box The name of the new SCM_BOX
1001 function setSCMBox($scm_box) {
1003 if ($scm_box == $this->data_array['scm_box']) {
1008 $res = db_query_params('UPDATE groups SET scm_box=$1 WHERE group_id=$2', array($scm_box, $this->getID()));
1010 $this->addHistory('scm_box', $this->data_array['scm_box']);
1011 $this->data_array['scm_box'] = $scm_box;
1016 $this->setError(_("Could not insert SCM_BOX to database"));
1020 $this->setError(_("SCM Box cannot be empty"));
1026 * getDomain - the hostname.domain where their web page is located.
1028 * @return string The name of the group [web] domain.
1030 function getDomain() {
1031 return $this->data_array['http_domain'];
1035 * getRegistrationPurpose - the text description of the purpose of this project.
1037 * @return string The application for project hosting.
1039 function getRegistrationPurpose() {
1040 return $this->data_array['register_purpose'];
1044 * getAdmins - Get array of Admin user objects.
1046 * @return array Array of User objects.
1048 function &getAdmins() {
1049 $roles = RBACEngine::getInstance()->getRolesByAllowedAction ('project_admin', $this->getID());
1051 $user_ids = array();
1053 foreach ($roles as $role) {
1054 if (! ($role instanceof RoleExplicit)) {
1057 if ($role->getHomeProject() == NULL
1058 || $role->getHomeProject()->getID() != $this->getID()) {
1062 foreach ($role->getUsers() as $u) {
1063 $user_ids[] = $u->getID();
1066 $active_ids = array();
1067 $ids = array_unique ($user_ids);
1068 foreach ($ids as $id) {
1069 $u = user_get_object ($id);
1070 if ($u->isActive()) {
1078 Common Group preferences for tools
1082 * enableAnonSCM - whether or not this group has opted to enable Anonymous SCM.
1084 * @return boolean enable_scm.
1086 function enableAnonSCM() {
1087 $r = RoleAnonymous::getInstance();
1088 return $r->hasPermission('scm', $this->getID(), 'read');
1091 function SetUsesAnonSCM($booleanparam) {
1093 $booleanparam = $booleanparam ? 1 : 0;
1094 $r = RoleAnonymous::getInstance();
1095 $r->setSetting('scm', $this->getID(), $booleanparam);
1100 * enablePserver - whether or not this group has opted to enable Pserver.
1102 * @return bool enable_pserver.
1104 function enablePserver() {
1105 if ($this->usesSCM()) {
1106 return $this->data_array['enable_pserver'];
1112 function SetUsesPserver($booleanparam) {
1114 $booleanparam = $booleanparam ? 1 : 0;
1115 $res = db_query_params('UPDATE groups SET enable_pserver=$1 WHERE group_id=$2',
1116 array($booleanparam, $this->getID()));
1118 $this->data_array['enable_pserver'] = $booleanparam;
1128 * usesSCM - whether or not this group has opted to use SCM.
1130 * @return bool uses_scm.
1132 function usesSCM() {
1133 if (forge_get_config('use_scm')) {
1134 return $this->data_array['use_scm'];
1141 * setUseSCM - Set the SCM usage
1143 * @param bool $booleanparam enabled/disabled
1146 function setUseSCM($booleanparam) {
1148 $booleanparam = $booleanparam ? 1 : 0;
1149 $res = db_query_params('UPDATE groups SET use_scm=$1 WHERE group_id=$2',
1150 array($booleanparam, $this->getID()));
1152 $this->data_array['use_scm']=$booleanparam;
1162 * usesMail - whether or not this group has opted to use mailing lists.
1164 * @return bool uses_mail.
1166 function usesMail() {
1167 if (forge_get_config('use_mail')) {
1168 return $this->data_array['use_mail'];
1173 $hook_params = array();
1174 $hook_params['group'] = $this;
1175 $hook_params['group_id'] = $this->getID();
1176 $hook_params['group_homepage'] = $this->getHomePage();
1177 $hook_params['group_name'] = $this->getPublicName();
1178 $hook_params['group_description'] = $this->getDescription();
1179 plugin_hook ("group_update", $hook_params);
1183 * setUseMail - Set the mailing-list usage
1185 * @param bool $booleanparam enabled/disabled
1188 function setUseMail($booleanparam) {
1190 $booleanparam = $booleanparam ? 1 : 0;
1191 $res = db_query_params('UPDATE groups SET use_mail=$1 WHERE group_id=$2',
1192 array($booleanparam, $this->getID()));
1194 $this->data_array['use_mail']=$booleanparam;
1204 * usesNews - whether or not this group has opted to use news.
1206 * @return bool uses_news.
1208 function usesNews() {
1209 if (forge_get_config('use_news')) {
1210 return $this->data_array['use_news'];
1216 function setUseNews($booleanparam) {
1218 $booleanparam = $booleanparam ? 1 : 0;
1219 $res = db_query_params('UPDATE groups SET use_news=$1 WHERE group_id=$2',
1220 array($booleanparam, $this->getID()));
1222 $this->data_array['use_news']=$booleanparam;
1232 * usesActivity - whether or not this group has opted to display Project Activities.
1234 * @return bool uses_activities.
1236 function usesActivity() {
1237 if (forge_get_config('use_activity')) {
1238 return $this->data_array['use_activity'];
1244 function setUseActivity($booleanparam) {
1246 $booleanparam = $booleanparam ? 1 : 0;
1247 $res = db_query_params('UPDATE groups SET use_activity=$1 WHERE group_id=$2',
1248 array($booleanparam, $this->getID()));
1250 $this->data_array['use_activity']=$booleanparam;
1260 * usesForum - whether or not this group has opted to use discussion forums.
1262 * @return bool uses_forum.
1264 function usesForum() {
1265 if (forge_get_config('use_forum')) {
1266 return $this->data_array['use_forum'];
1273 * setUseForum - Set the forum usage
1275 * @param bool $booleanparam enabled/disabled
1278 function setUseForum($booleanparam) {
1280 $booleanparam = $booleanparam ? 1 : 0;
1281 $res = db_query_params('UPDATE groups SET use_forum=$1 WHERE group_id=$2',
1282 array($booleanparam, $this->getID()));
1284 $this->data_array['use_forum']=$booleanparam;
1294 * usesStats - whether or not this group has opted to use stats.
1296 * @return bool uses_stats.
1298 function usesStats() {
1299 return $this->data_array['use_stats'];
1303 * usesFRS - whether or not this group has opted to use file release system.
1305 * @return bool uses_frs.
1307 function usesFRS() {
1308 if (forge_get_config('use_frs')) {
1309 return $this->data_array['use_frs'];
1316 * setUseFRS - Set the FRS usage
1318 * @param bool $booleanparam enabled/disabled
1321 function setUseFRS($booleanparam) {
1323 $booleanparam = $booleanparam ? 1 : 0;
1324 $res = db_query_params('UPDATE groups SET use_frs=$1 WHERE group_id=$2',
1325 array($booleanparam, $this->getID()));
1327 $this->data_array['use_frs']=$booleanparam;
1337 * usesTracker - whether or not this group has opted to use tracker.
1339 * @return bool uses_tracker.
1341 function usesTracker() {
1342 if (forge_get_config('use_tracker')) {
1343 return $this->data_array['use_tracker'];
1350 * setUseTracker - Set the tracker usage
1352 * @param bool $booleanparam enabled/disabled
1355 function setUseTracker($booleanparam) {
1357 $booleanparam = $booleanparam ? 1 : 0;
1358 $res = db_query_params ('UPDATE groups SET use_tracker=$1 WHERE group_id=$2',
1359 array($booleanparam, $this->getID()));
1361 $this->data_array['use_tracker']=$booleanparam;
1371 * useCreateOnline - whether or not this group has opted to use create online documents option.
1373 * @return bool use_docman_create_online.
1375 function useCreateOnline() {
1376 if (forge_get_config('use_docman')) {
1377 return $this->data_array['use_docman_create_online'];
1384 * usesDocman - whether or not this group has opted to use docman.
1386 * @return bool use_docman.
1388 function usesDocman() {
1389 if (forge_get_config('use_docman')) {
1390 return $this->data_array['use_docman'];
1397 * setUseDocman - Set the docman usage
1399 * @param bool $booleanparam enabled/disabled
1402 function setUseDocman($booleanparam) {
1404 $booleanparam = $booleanparam ? 1 : 0;
1405 $res = db_query_params('UPDATE groups SET use_docman = $1 WHERE group_id = $2',
1406 array($booleanparam, $this->getID()));
1408 // check if / doc_group exists, if not create it
1409 $trashdir = db_query_params('select groupname from doc_groups where groupname = $1 and group_id = $2',
1410 array('.trash', $this->getID()));
1411 if ($trashdir && db_numrows($trashdir) == 0) {
1412 $resinsert = db_query_params('insert into doc_groups (groupname, group_id, stateid) values ($1, $2, $3)',
1413 array('.trash', $this->getID(), '2'));
1419 $this->data_array['use_docman'] = $booleanparam;
1429 * useDocmanSearch - whether or not this group has opted to use docman search engine.
1431 * @return bool use_docman_search.
1433 function useDocmanSearch() {
1434 if (forge_get_config('use_docman')) {
1435 return $this->data_array['use_docman_search'];
1442 * useWebdav - whether or not this group has opted to use webdav interface.
1444 * @return bool use_docman_search.
1446 function useWebdav() {
1447 if (forge_get_config('use_webdav')) {
1448 return $this->data_array['use_webdav'];
1455 * usesFTP - whether or not this group has opted to use FTP.
1457 * @return bool uses_ftp.
1459 function usesFTP() {
1460 if (forge_get_config('use_ftp')) {
1461 return $this->data_array['use_ftp'];
1468 * usesSurvey - whether or not this group has opted to use surveys.
1470 * @return bool uses_survey.
1472 function usesSurvey() {
1473 if (forge_get_config('use_survey')) {
1474 return $this->data_array['use_survey'];
1481 * usesPM - whether or not this group has opted to Project Manager.
1483 * @return bool uses_projman.
1486 if (forge_get_config('use_pm')) {
1487 return $this->data_array['use_pm'];
1494 * setUsePM - Set the PM usage
1496 * @param bool $booleanparam enabled/disabled
1499 function setUsePM($booleanparam) {
1501 $booleanparam = $booleanparam ? 1 : 0;
1502 $res = db_query_params('UPDATE groups SET use_pm=$1 WHERE group_id=$2',
1503 array($booleanparam, $this->getID()));
1505 $this->data_array['use_pm']=$booleanparam;
1515 * getPlugins - get a list of all available group plugins
1517 * @return array array containing plugin_id => plugin_name
1519 function getPlugins() {
1520 if (!isset($this->plugins_data)) {
1521 $this->plugins_data = array();
1522 $res = db_query_params('SELECT group_plugin.plugin_id, plugins.plugin_name
1523 FROM group_plugin, plugins
1524 WHERE group_plugin.group_id=$1
1525 AND group_plugin.plugin_id=plugins.plugin_id', array($this->getID()));
1526 $rows = db_numrows($res);
1528 for ($i=0; $i<$rows; $i++) {
1529 $plugin_id = db_result($res, $i, 'plugin_id');
1530 $this->plugins_data[$plugin_id] = db_result($res, $i, 'plugin_name');
1533 return $this->plugins_data;
1537 * usesPlugin - returns true if the group uses a particular plugin
1539 * @param string $pluginname name of the plugin
1540 * @return bool whether plugin is being used or not
1542 function usesPlugin($pluginname) {
1543 $plugins_data = $this->getPlugins();
1544 foreach ($plugins_data as $p_id => $p_name) {
1545 if ($p_name == $pluginname) {
1553 * added for Codendi compatibility
1554 * usesServices - returns true if the group uses a particular plugin or feature
1556 * @param string $feature name of the plugin
1557 * @return bool whether plugin is being used or not
1559 function usesService($feature) {
1560 $plugins_data = $this->getPlugins();
1561 $pm = plugin_manager_get_object();
1562 foreach ($plugins_data as $p_id => $p_name) {
1563 if ($p_name == $feature) {
1566 if ($pm->getPluginByName($p_name)->provide($feature)) {
1574 * setPluginUse - enables/disables plugins for the group
1576 * @param string $pluginname name of the plugin
1577 * @param bool $val the new state
1578 * @return string database result
1580 function setPluginUse($pluginname, $val=true) {
1581 if ($val == $this->usesPlugin($pluginname)) {
1582 // State is already good, returning
1585 $res = db_query_params('SELECT plugin_id FROM plugins WHERE plugin_name=$1',
1586 array($pluginname));
1587 $rows = db_numrows($res);
1589 // Error: no plugin by that name
1592 $plugin_id = db_result($res,0,'plugin_id');
1594 unset($this->plugins_data);
1596 $res = db_query_params('INSERT INTO group_plugin (group_id, plugin_id) VALUES ($1, $2)',
1597 array($this->getID(),
1600 $res = db_query_params('DELETE FROM group_plugin WHERE group_id=$1 AND plugin_id=$2',
1601 array($this->getID(),
1604 $this->normalizeAllRoles();
1605 $hook_params = array();
1606 $hook_params['group_id'] = $this->getID();
1607 $hook_params['val'] = $val;
1608 plugin_hook("group_plugin_use", $hook_params);
1613 * getDocEmailAddress - get email address(es) to send doc notifications to.
1615 * @return string email address.
1617 function getDocEmailAddress() {
1618 return $this->data_array['new_doc_address'];
1622 * docEmailAll - whether or not this group has opted to use receive notices on all doc updates.
1624 * @return bool email_on_all_doc_updates.
1626 function docEmailAll() {
1627 return $this->data_array['send_all_docs'];
1631 * getFRSEmailAddress - get email address(es) to send FRS notifications to.
1633 * @return string email address.
1635 function getFRSEmailAddress() {
1636 return $this->data_array['new_frs_address'];
1640 * frsEmailAll - whether or not this group has opted to use receive notices on all frs updates.
1642 * @return bool email_on_all_frs_updates.
1644 function frsEmailAll() {
1645 return $this->data_array['send_all_frs'];
1649 * getHomePage - The URL for this project's home page.
1651 * @return string homepage URL.
1653 function getHomePage() {
1654 if (!preg_match("/^[a-zA-Z][a-zA-Z0-9+.-]*:/",
1655 $this->data_array['homepage'])) {
1656 $this->data_array['homepage'] = 'http://' .
1657 $this->data_array['homepage'];
1659 return $this->data_array['homepage'];
1663 * setHomepage - the hostname of the website url where this project is located.
1665 * @param string $homepage The name of the new HOMEPAGE
1668 function setHomepage($homepage) {
1670 if ($homepage == $this->data_array['homepage']) {
1675 $res = db_query_params('UPDATE groups SET homepage=$1 WHERE group_id=$2', array($homepage, $this->getID()));
1677 $this->addHistory('homepage', $this->data_array['homepage']);
1678 $this->data_array['homepage'] = $homepage;
1683 $this->setError(_("Could not insert homepage to database"));
1687 $this->setError(_("Homepage cannot be empty"));
1693 * getTags - Tags of this project.
1695 * @return string List of tags. Comma separated
1697 function getTags() {
1698 $sql = 'SELECT name FROM project_tags WHERE group_id = $1';
1699 $res = db_query_params($sql, array($this->getID()));
1700 return join(', ', util_result_column_to_array($res));
1704 * setTags - Set tags of this project.
1706 * @param string $tags
1707 * @return string database result.
1709 function setTags($tags) {
1711 $sql = 'DELETE FROM project_tags WHERE group_id=$1';
1712 $res = db_query_params($sql, array($this->getID()));
1714 $this->setError('Deleting old tags: '.db_error());
1718 $inserted = array();
1719 $tags_array = preg_split('/[;,]/', $tags);
1720 foreach ($tags_array as $tag) {
1721 $tag = preg_replace('/[\t\r\n]/', ' ', $tag);
1722 // Allowed caracteres: [A-Z][a-z][0-9] -_&'#+.
1723 if (preg_match('/[^[:alnum:]| |\-|_|\&|\'|#|\+|\.]/', $tag)) {
1724 $this->setError(_('Bad tag name, you only can use the following characters: [A-Z][a-z][0-9]-_&\'#+. and space'));
1729 if ($tag == '' || array_search($tag, $inserted) !== false) continue;
1730 $sql = 'INSERT INTO project_tags (group_id,name) VALUES ($1, $2)';
1731 $res = db_query_params($sql, array($this->getID(), $tag));
1733 $this->setError(_('Setting tags:') . ' ' .
1745 * getPermission - Return a Permission for this Group
1747 * @return object The Permission.
1749 function &getPermission() {
1750 return permission_get_object($this);
1753 function delete($sure, $really_sure, $really_really_sure) {
1754 if (!$sure || !$really_sure || !$really_really_sure) {
1755 $this->setMissingParamsError(_('Please tick all checkboxes.'));
1758 if ($this->getID() == forge_get_config('news_group') ||
1759 $this->getID() == 1 ||
1760 $this->getID() == forge_get_config('stats_group') ||
1761 $this->getID() == forge_get_config('peer_rating_group')) {
1762 $this->setError(_('Cannot Delete System Group'));
1765 $perm = $this->getPermission();
1766 if (!$perm || !is_object($perm)) {
1767 $this->setPermissionDeniedError();
1769 } elseif ($perm->isError()) {
1770 $this->setPermissionDeniedError();
1772 } elseif (!$perm->isSuperUser()) {
1773 $this->setPermissionDeniedError();
1779 // Remove all the members
1781 $members = $this->getMembers(false);
1782 foreach ($members as $i) {
1783 if(!$this->removeUser($i->getID())) {
1784 $this->setError(_('Could not properly remove member:').' '.$i->getID());
1789 // unlink roles from this project
1790 foreach ($this->getRoles() as $r) {
1791 if ($r->getHomeProject() == NULL
1792 || $r->getHomeProject()->getID() != $this->getID()) {
1793 $r->unlinkProject($this);
1800 $atf = new ArtifactTypeFactory($this, true);
1801 $at_arr = $atf->getArtifactTypes();
1802 foreach ($at_arr as $i) {
1803 if (!is_object($i)) {
1806 if (!$i->delete(1,1)) {
1807 $this->setError(_('Could not properly delete the tracker:').' '.$i->getErrorMessage());
1814 $rmf = new RoadmapFactory($this);
1815 $rm_arr = $rmf->getRoadmaps();
1816 foreach ($rm_arr as $i) {
1817 if (!is_object($i)) {
1820 if (!$i->delete()) {
1821 $this->setError(_('Could not properly delete the roadmap:') . ' ' . $i->getErrorMessage());
1829 $ff = new ForumFactory($this, true);
1830 $f_arr = $ff->getForums();
1831 foreach ($f_arr as $i) {
1832 if (!is_object($i)) {
1835 if(!$i->delete(1,1)) {
1836 $this->setError(_('Could not properly delete the forum:').' '.$i->getErrorMessage());
1842 // Delete Subprojects
1844 $pgf = new ProjectGroupFactory($this, true);
1845 $pg_arr = $pgf->getProjectGroups();
1846 foreach ($pg_arr as $i) {
1847 if (!is_object($i)) {
1850 if (!$i->delete(1,1)) {
1851 $this->setError(_('Could not properly delete the ProjectGroup:').' '.$i->getErrorMessage());
1857 // Delete FRS Packages
1859 $res = db_query_params('SELECT * FROM frs_package WHERE group_id=$1',
1860 array($this->getID()));
1862 $this->setError(_('Error FRS Packages: ').db_error());
1867 while ($arr = db_fetch_array($res)) {
1868 $frsp=new FRSPackage($this, $arr['package_id'], $arr);
1869 if (!$frsp->delete(1, 1)) {
1870 $this->setError(_('Could not properly delete the FRSPackage:').' '.$frsp->getErrorMessage());
1877 $news_group=group_get_object(forge_get_config('news_group'));
1878 $res = db_query_params('SELECT forum_id FROM news_bytes WHERE group_id=$1',
1879 array($this->getID()));
1881 $this->setError(_('Error Deleting News: ').db_error());
1886 for ($i=0; $i<db_numrows($res); $i++) {
1887 $Forum = new Forum($news_group,db_result($res,$i,'forum_id'));
1888 if (!$Forum->delete(1,1)) {
1889 $this->setError(_("Could Not Delete News Forum: %d"),$Forum->getID());
1894 // Delete news forums in group itself
1895 for ($i = 0; $i < db_numrows($res); $i++) {
1896 $Forum = new Forum($this, db_result($res, $i, 'forum_id'));
1897 if (!$Forum->delete(1, 1)) {
1898 $this->setError(_("Could Not Delete News Forum: %d"), $Forum->getID());
1903 $res = db_query_params('DELETE FROM news_bytes WHERE group_id=$1',
1904 array($this->getID()));
1906 $this->setError(_('Error Deleting News: ').db_error());
1914 $res = db_query_params('DELETE FROM doc_data WHERE group_id=$1',
1915 array($this->getID()));
1917 $this->setError(_('Error Deleting Documents: ').db_error());
1922 $res = db_query_params('DELETE FROM doc_groups WHERE group_id=$1',
1923 array($this->getID()));
1925 $this->setError(_('Error Deleting Documents: ').db_error());
1933 $res=db_query_params('DELETE FROM project_tags WHERE group_id=$1', array($this->getID()));
1935 $this->setError(_('Error Deleting Tags: ').db_error());
1941 // Delete group history
1943 $res = db_query_params('DELETE FROM group_history WHERE group_id=$1',
1944 array($this->getID()));
1946 $this->setError(_('Error Deleting Project History: ').db_error());
1952 // Delete group plugins
1954 $res = db_query_params('DELETE FROM group_plugin WHERE group_id=$1',
1955 array($this->getID()));
1957 $this->setError(_('Error Deleting Project Plugins: ').db_error());
1963 // Delete group cvs stats
1965 $res = db_query_params ('DELETE FROM stats_cvs_group WHERE group_id=$1',
1966 array($this->getID()));
1968 $this->setError(_('Error Deleting SCM Statistics: ').db_error());
1976 $sf = new SurveyFactory($this, true);
1977 $s_arr =& $sf->getSurveys();
1978 foreach ($s_arr as $i) {
1979 if (!is_object($i)) {
1982 if (!$i->delete()) {
1983 $this->setError(_('Could not properly delete the survey'));
1988 // Delete SurveyQuestions
1990 $sqf = new SurveyQuestionFactory($this);
1991 $sq_arr = $sqf->getSurveyQuestions();
1992 if (is_array($sq_arr)) {
1993 foreach ($sq_arr as $i) {
1994 if (!is_object($i)) {
1997 if (!$i->delete()) {
1998 $this->setError(_('Could not properly delete the survey questions'));
2006 // Delete Mailing List Factory
2008 $mlf = new MailingListFactory($this, true);
2009 $ml_arr = $mlf->getMailingLists();
2010 foreach ($ml_arr as $i) {
2011 if (!is_object($i)) {
2014 if (!$i->delete(1,1)) {
2015 $this->setError(_('Could not properly delete the mailing list'));
2023 $res = db_query_params('DELETE FROM trove_group_link WHERE group_id=$1',
2024 array($this->getID()));
2026 $this->setError(_('Error Deleting Trove: ').db_error());
2031 $res = db_query_params('DELETE FROM trove_agg WHERE group_id=$1',
2032 array($this->getID()));
2034 $this->setError(_('Error Deleting Trove: ').db_error());
2042 $res = db_query_params('DELETE FROM project_sums_agg WHERE group_id=$1',
2043 array($this->getID()));
2045 $this->setError(_('Error Deleting Counters: ').db_error());
2050 $res = db_query_params('INSERT INTO deleted_groups (unix_group_name, delete_date, isdeleted) VALUES ($1, $2, $3)',
2051 array($this->getUnixName(),
2055 $this->setError(_('Error Deleting Project:').' '.db_error());
2060 // Remove users & delete roles from this project
2061 $members = $this->getMembers();
2062 foreach ($members as $userObject) {
2063 $this->removeUser($userObject->getID());
2065 $localRolesId = $this->getRolesId(false);
2066 foreach ($localRolesId as $localRoleId) {
2067 $roleObject = new Role($this, $localRoleId);
2068 $roleObject->delete();
2070 // Delete entry in groups.
2071 $res = db_query_params('DELETE FROM groups WHERE group_id=$1',
2072 array($this->getID()));
2074 $this->setError(_('Error Deleting Project:').' '.db_error());
2081 $hook_params = array();
2082 $hook_params['group'] = $this;
2083 $hook_params['group_id'] = $this->getID();
2084 plugin_hook("group_delete", $hook_params);
2086 if (forge_get_config('upload_dir') != '' && $this->getUnixName()) {
2087 exec('/bin/rm -rf '.forge_get_config('upload_dir').'/'.$this->getUnixName().'/');
2089 if (forge_get_config('ftp_upload_dir') != '' && $this->getUnixName()) {
2090 exec('/bin/rm -rf '.forge_get_config('ftp_upload_dir').'/'.$this->getUnixName().'/');
2095 db_query_params('DELETE FROM rep_group_act_monthly WHERE group_id=$1',
2096 array($this->getID()));
2097 //echo 'rep_group_act_monthly'.db_error();
2098 db_query_params('DELETE FROM rep_group_act_weekly WHERE group_id=$1',
2099 array($this->getID()));
2100 //echo 'rep_group_act_weekly'.db_error();
2101 db_query_params('DELETE FROM rep_group_act_daily WHERE group_id=$1',
2102 array($this->getID()));
2103 //echo 'rep_group_act_daily'.db_error();
2104 unset($this->data_array);
2109 Basic functions to add/remove users to/from a group
2110 and update their permissions
2114 * addUser - controls adding a user to a group.
2116 * @param string $user_identifier Unix name of the user to add OR integer user_id.
2117 * @param int $role_id The role_id this user should have.
2118 * @return bool success.
2121 function addUser($user_identifier, $role_id) {
2124 Admins can add users to groups
2127 if (!forge_check_perm ('project_admin', $this->getID())) {
2128 $this->setPermissionDeniedError();
2134 get user id for this user's unix_name
2136 if (is_int ($user_identifier)) { // user_id or user_name
2137 $res_newuser = db_query_params ('SELECT * FROM users WHERE user_id=$1', array($user_identifier));
2139 $res_newuser = db_query_params ('SELECT * FROM users WHERE user_name=$1', array($user_identifier));
2141 if (db_numrows($res_newuser) > 0) {
2143 // make sure user is active
2145 if (db_result($res_newuser,0,'status') != 'A') {
2146 $this->setError(_('User is not active. Only active users can be added.'));
2152 // user was found - set new user_id var
2154 $user_id = db_result($res_newuser,0,'user_id');
2156 $role = new Role($this, $role_id);
2157 if (!$role || !is_object($role)) {
2158 $this->setError(_('Error Getting Role Object'));
2161 } elseif ($role->isError()) {
2162 $this->setError('addUser::roleget::'.$role->getErrorMessage());
2167 $role->addUser(user_get_object($user_id));
2168 if (!$SYS->sysCheckCreateGroup($this->getID())){
2169 $this->setError($SYS->getErrorMessage());
2173 if (!$SYS->sysCheckCreateUser($user_id)) {
2174 $this->setError($SYS->getErrorMessage());
2178 if (!$SYS->sysGroupCheckUser($this->getID(),$user_id)) {
2179 $this->setError($SYS->getErrorMessage());
2185 // user doesn't exist
2187 $this->setError(_('That user does not exist.'));
2192 $hook_params['group'] = $this;
2193 $hook_params['group_id'] = $this->getID();
2194 $hook_params['user'] = user_get_object($user_id);
2195 $hook_params['user_id'] = $user_id;
2196 plugin_hook ("group_adduser", $hook_params);
2201 $this->addHistory(_('Added User'),$user_identifier);
2207 $add_u = user_get_object($user_id);
2209 foreach ($this->membersArr as $u) {
2210 if ($u->getID() == $add_u->getID()) {
2216 $this->membersArr[] = $add_u;
2222 * removeUser - controls removing a user from a group.
2224 * Users can remove themselves.
2226 * @param int $user_id The ID of the user to remove.
2227 * @return bool success.
2229 function removeUser($user_id) {
2232 if ($user_id != user_getid()
2233 && !forge_check_perm('project_admin', $this->getID())) {
2234 $this->setPermissionDeniedError();
2240 $user = user_get_object($user_id);
2241 $roles = RBACEngine::getInstance()->getAvailableRolesForUser($user);
2242 $found_roles = array();
2243 foreach ($roles as $role) {
2244 if ($role->getHomeProject() && $role->getHomeProject()->getID() == $this->getID()) {
2245 $found_roles[] = $role;
2248 if (count($found_roles) == 0) {
2249 $this->setError(sprintf(_('Error: User not removed: %s')));
2253 foreach ($found_roles as $found_role) {
2254 $found_role->removeUser($user);
2255 if (!$SYS->sysGroupCheckUser($this->getID(), $user_id)) {
2256 $this->setError($SYS->getErrorMessage());
2263 // reassign open artifacts to id=100
2265 $res = db_query_params('UPDATE artifact SET assigned_to=100
2266 WHERE group_artifact_id
2267 IN (SELECT group_artifact_id
2268 FROM artifact_group_list
2269 WHERE group_id=$1 AND status_id=1 AND assigned_to=$2)',
2270 array($this->getID(),
2273 $this->setError(_('Error: artifact:').' '.db_error());
2279 // reassign open tasks to id=100
2280 // first have to purge any assignments that would cause
2281 // conflict with existing assignment to 100
2283 $res = db_query_params('DELETE FROM project_assigned_to
2284 WHERE project_task_id IN (SELECT pt.project_task_id
2285 FROM project_task pt, project_group_list pgl, project_assigned_to pat
2286 WHERE pt.group_project_id = pgl.group_project_id
2287 AND pat.project_task_id=pt.project_task_id
2288 AND pt.status_id=1 AND pgl.group_id=$1
2289 AND pat.assigned_to_id=$2)
2290 AND assigned_to_id=100',
2291 array($this->getID(),
2294 $this->setError(sprintf(_('Error: project_assigned_to %d: %s'), 1, db_error()));
2298 $res = db_query_params('UPDATE project_assigned_to SET assigned_to_id=100
2299 WHERE project_task_id IN (SELECT pt.project_task_id
2300 FROM project_task pt, project_group_list pgl
2301 WHERE pt.group_project_id = pgl.group_project_id
2302 AND pt.status_id=1 AND pgl.group_id=$1)
2303 AND assigned_to_id=$2',
2304 array($this->getID(),
2307 $this->setError(sprintf(_('Error: project_assigned_to %d: %s'), 2, db_error()));
2313 // Remove user from system
2315 if (!$SYS->sysGroupRemoveUser($this->getID(), $user_id)) {
2316 $this->setError($SYS->getErrorMessage());
2321 $hook_params['group'] = $this;
2322 $hook_params['group_id'] = $this->getID();
2323 $hook_params['user'] = user_get_object($user_id);
2324 $hook_params['user_id'] = $user_id;
2325 plugin_hook ("group_removeuser", $hook_params);
2328 $this->addHistory(_('Removed User'), $user_id);
2335 $del_u = user_get_object($user_id);
2336 foreach ($this->membersArr as $k => $u) {
2337 if ($u->getID() == $del_u->getID()) {
2338 unset($this->membersArr[$k]);
2347 * updateUser - controls updating a user's role in this group.
2349 * @param int $user_id The ID of the user.
2350 * @param int $role_id The role_id to set this user to.
2351 * @return bool success.
2353 function updateUser($user_id, $role_id) {
2355 if (!forge_check_perm ('project_admin', $this->getID())) {
2356 $this->setPermissionDeniedError();
2360 $newrole = RBACEngine::getInstance()->getRoleById ($role_id);
2361 if (!$newrole || !is_object($newrole)) {
2362 $this->setError(_('Could Not Get Role'));
2364 } elseif ($newrole->isError()) {
2365 $this->setError(sprintf(_('Role: %s'),$role->getErrorMessage()));
2367 } elseif ($newrole->getHomeProject() == NULL
2368 || $newrole->getHomeProject()->getID() != $this->getID()) {
2369 $this->setError(_('Wrong destination role'));
2372 $user = user_get_object ($user_id);
2373 $roles = RBACEngine::getInstance()->getAvailableRolesForUser ($user);
2375 foreach ($roles as $role) {
2376 if ($role->getHomeProject() && $role->getHomeProject()->getID() == $this->getID()) {
2377 $found_role = $role;
2381 if ($found_role == NULL) {
2382 $this->setError(sprintf(_('Error: User not removed: %s')));
2386 $found_role->removeUser ($user);
2387 $newrole->addUser ($user);
2389 $this->addHistory(_('Updated User'),$user_id);
2394 * addHistory - Makes an audit trail entry for this project.
2396 * @param string $field_name The name of the field.
2397 * @param string $old_value The Old Value for this $field_name.
2398 * @return resource database result handle.
2401 function addHistory($field_name, $old_value) {
2402 if ($old_value == NULL) {
2406 return db_query_params ('INSERT INTO group_history(group_id,field_name,old_value,mod_by,adddate)
2407 VALUES ($1,$2,$3,$4,$5)',
2408 array($this->getID(),
2416 * activateUsers - Make sure that group members have unix accounts.
2418 * Setup unix accounts for group members. Can be called even
2419 * if members are already active.
2423 function activateUsers() {
2425 Activate member(s) of the project
2430 $members = $this->getUsers (true);
2432 foreach ($members as $member) {
2433 $user_id = $member->getID();
2435 if (!$SYS->sysCheckCreateGroup($this->getID())){
2436 $this->setError($SYS->getErrorMessage());
2440 if (!$SYS->sysCheckCreateUser($user_id)) {
2441 $this->setError($SYS->getErrorMessage());
2445 if (!$SYS->sysGroupCheckUser($this->getID(),$user_id)) {
2446 $this->setError($SYS->getErrorMessage());
2456 * getMembers - returns array of User objects for this project
2458 * @param boolean $onlyactive Only users with state active, or all users of group
2459 * @return array of User objects for this group.
2461 function getMembers($onlyactive = true) {
2462 return $this->getUsers (true, $onlyactive);
2466 * replaceTemplateStrings - fill-in some blanks with project name
2468 * @param string $string Template string
2469 * @return string String after replacements
2471 function replaceTemplateStrings($string) {
2472 $string = str_replace ('UNIXNAME', $this->getUnixName(), $string);
2473 $string = str_replace ('PUBLICNAME', $this->getPublicName(), $string);
2474 $string = str_replace ('DESCRIPTION', $this->getDescription(), $string);
2479 * approve - Approve pending project.
2481 * @param object $user The User object who is doing the updating.
2485 function approve(&$user) {
2486 global $gfcommon,$gfwww;
2487 require_once $gfcommon.'widget/WidgetLayoutManager.class.php';
2489 if ($this->getStatus()=='A') {
2490 $this->setError(_("Group already active"));
2496 // Step 1: Activate group and create LDAP entries
2497 if (!$this->setStatus($user, 'A')) {
2504 // Switch to system language for item creation
2505 setup_gettext_from_sys_lang();
2507 // Create default roles
2508 $idadmin_group = NULL;
2509 foreach (get_group_join_requests ($this) as $gjr) {
2510 $idadmin_group = $gjr->getUserID();
2513 if ($idadmin_group == NULL) {
2514 $idadmin_group = $user->getID();
2517 $template = $this->getTemplateProject();
2518 $id_mappings = array();
2519 $seen_admin_role = false;
2521 // Copy roles from template project
2522 foreach($template->getRoles() as $oldrole) {
2523 if ($oldrole->getHomeProject() != NULL) {
2524 $role = new Role($this);
2526 // Need to use a different role name so that the permissions aren't set from the hardcoded defaults
2527 $role->create('TEMPORARY ROLE NAME', $data, true);
2528 $role->setName($oldrole->getName());
2529 if ($oldrole->getSetting ('project_admin', $template->getID())) {
2530 $seen_admin_role = true;
2534 $role->linkProject($this);
2536 $id_mappings['role'][$oldrole->getID()] = $role->getID();
2537 // Reuse the project_admin permission
2538 $role->setSetting ('project_admin', $this->getID(), $oldrole->getSetting ('project_admin', $template->getID()));
2542 if (!$seen_admin_role) {
2543 $role = new Role($this);
2544 $adminperms = array('project_admin' => array ($this->getID() => 1));
2545 $role_id = $role->create ('Admin', $adminperms, true);
2548 $roles = $this->getRoles();
2549 foreach ($roles as $r) {
2550 if ($r->getHomeProject() == NULL) {
2553 if ($r->getSetting ('project_admin', $this->getID())) {
2554 $r->addUser(user_get_object ($idadmin_group));
2558 // Temporarily switch to the submitter's identity
2559 $saved_session = session_get_user();
2560 session_set_internal($idadmin_group);
2563 if (forge_get_config('use_tracker')) {
2564 $this->setUseTracker ($template->usesTracker());
2565 if ($template->usesTracker()) {
2566 $oldatf = new ArtifactTypeFactory($template);
2567 foreach ($oldatf->getArtifactTypes() as $o) {
2568 $t = new ArtifactType ($this);
2569 $t->create ($this->replaceTemplateStrings($o->getName()),$this->replaceTemplateStrings($o->getDescription()),$o->emailAll(),$o->getEmailAddress(),$o->getDuePeriod()/86400,0,$o->getSubmitInstructions(),$o->getBrowseInstructions());
2570 $id_mappings['tracker'][$o->getID()] = $t->getID();
2571 $t->cloneFieldsFrom ($o->getID());
2576 if (forge_get_config('use_pm')) {
2577 $this->setUsePM ($template->usesPM());
2578 if ($template->usesPM()) {
2579 $oldpgf = new ProjectGroupFactory($template);
2580 foreach ($oldpgf->getProjectGroups() as $o) {
2581 $pg = new ProjectGroup($this);
2582 $pg->create($this->replaceTemplateStrings($o->getName()),$this->replaceTemplateStrings($o->getDescription()),$o->getSendAllPostsTo());
2583 $id_mappings['pm'][$o->getID()] = $pg->getID();
2588 if (forge_get_config('use_forum')) {
2589 $this->setUseForum($template->usesForum());
2590 if ($template->usesForum()) {
2591 $oldff = new ForumFactory($template);
2592 foreach ($oldff->getForums() as $o) {
2593 $f = new Forum($this);
2594 $f->create($this->replaceTemplateStrings($o->getName()),$this->replaceTemplateStrings($o->getDescription()),$o->getSendAllPostsTo(),1);
2595 $id_mappings['forum'][$o->getID()] = $f->getID();
2600 if (forge_get_config('use_docman')) {
2601 $this->setUseDocman($template->usesDocman());
2602 if ($template->usesDocman()) {
2603 $olddgf = new DocumentGroupFactory($template);
2604 // First pass: create all docgroups
2605 $id_mappings['docman_docgroup'][0] = 0;
2606 foreach ($olddgf->getDocumentGroups(array(1, 5)) as $o) {
2607 $ndgf = new DocumentGroup($this);
2608 // .trash is a reserved directory
2609 if ($o->getName() != '.trash' && $o->getParentID() == 0) {
2610 $ndgf->create($this->replaceTemplateStrings($o->getName()));
2611 $id_mappings['docman_docgroup'][$o->getID()] = $ndgf->getID();
2614 // Second pass: restore hierarchy links & stateid
2615 foreach ($olddgf->getDocumentGroups(array(1, 5)) as $o) {
2616 $ndgf = new DocumentGroup($this);
2617 if ($o->getName() != '.trash' && $o->getParentID() == 0) {
2618 $ndgf->fetchData($id_mappings['docman_docgroup'][$o->getID()]);
2619 $ndgf->update($ndgf->getName(), $id_mappings['docman_docgroup'][$o->getParentID()], $id_mappings['docman_docgroup'][$o->getState()]);
2625 if (forge_get_config('use_frs')) {
2626 $this->setUseFRS ($template->usesFRS());
2627 if ($template->usesFRS()) {
2628 foreach (get_frs_packages($template) as $o) {
2629 $newp = new FRSPackage($this);
2630 $nname = $this->replaceTemplateStrings($o->getName());
2631 $newp->create ($nname, $o->isPublic());
2632 $id_mappings['frs'][$o->getID()] = $newp->getID();
2637 if (forge_get_config('use_mail')) {
2638 $this->setUseMail($template->usesMail());
2639 if ($template->usesMail()) {
2640 $oldmlf = new MailingListFactory($template);
2641 foreach ($oldmlf->getMailingLists() as $o) {
2642 $ml = new MailingList($this);
2643 $nname = preg_replace ('/^'.$template->getUnixName().'-/','',$o->getName());
2645 $ndescription = $this->replaceTemplateStrings($o->getDescription());
2646 $ml->create($nname, $ndescription, $o->isPublic());
2652 /* use SCM plugin from template group */
2653 $this->setUseSCM($template->usesSCM());
2655 foreach ($template->getPlugins() as
2656 $plugin_id => $plugin_name) {
2657 $this->setPluginUse($plugin_name);
2660 /* use SCM choice from registration page */
2661 foreach ($template->getPlugins() as $plugin_id => $plugin_name) {
2662 if (substr($plugin_name, 3) == 'scm' &&
2663 $plugin_name != 'scmhook') {
2664 /* skip copying scm plugins */
2667 /* enable other plugins though */
2668 $this->setPluginUse($plugin_name);
2672 foreach ($template->getRoles() as $oldrole) {
2673 $newrole = RBACEngine::getInstance()->getRoleById ($id_mappings['role'][$oldrole->getID()]);
2674 if ($oldrole->getHomeProject() != NULL
2675 && $oldrole->getHomeProject()->getID() == $template->getID()) {
2676 $newrole->setPublic ($oldrole->isPublic());
2678 $oldsettings = $oldrole->getSettingsForProject ($template);
2680 $sections = array('project_read', 'project_admin', 'scm', 'docman', 'tracker_admin', 'new_tracker', 'forum_admin', 'new_forum', 'pm_admin', 'new_pm', 'frs_admin', 'new_frs');
2681 foreach ($sections as $section) {
2682 $newrole->setSetting ($section, $this->getID(), $oldsettings[$section][$template->getID()]);
2685 $sections = array('tracker', 'pm', 'forum', 'frs');
2686 foreach ($sections as $section) {
2687 if (isset ($oldsettings[$section])) {
2688 foreach ($oldsettings[$section] as $k => $v) {
2689 // Only copy perms for tools that have been copied
2690 if (isset ($id_mappings[$section][$k])) {
2691 $newrole->setSetting ($section,
2692 $id_mappings[$section][$k],
2700 $lm = new WidgetLayoutManager();
2701 $lm->createDefaultLayoutForProject ($this->getID(), $template->getID());
2704 $params['template'] = $template;
2705 $params['project'] = $this;
2706 $params['id_mappings'] = $id_mappings;
2707 plugin_hook_by_reference ('clone_project_from_template', $params);
2709 // Disable everything - except use_scm (manually set in the registration page)
2710 db_query_params ('UPDATE groups SET use_mail=0, use_survey=0, use_forum=0, use_pm=0, use_pm_depend_box=0, use_news=0, use_docman=0, use_ftp=0, use_tracker=0, use_frs=0, use_stats=0 WHERE group_id=$1',
2711 array($this->getID()));
2714 $this->normalizeAllRoles();
2715 // empty members cache because the group creator is not yet in cache.
2716 unset($this->membersArr);
2717 $this->activateUsers();
2719 // Delete fake join request
2720 foreach (get_group_join_requests ($this) as $gjr) {
2724 // Switch back to user preference
2725 session_set_internal($saved_session->getID());
2726 setup_gettext_from_context();
2728 $this->sendApprovalEmail();
2729 $this->addHistory(_('Approved'), 'x');
2732 // Plugin can make approve operation there
2735 $params['group'] = $this;
2736 $params['group_id'] = $this->getID();
2737 plugin_hook('group_approved', $params);
2743 * sendApprovalEmail - Send new project email.
2745 * @return bool success.
2748 function sendApprovalEmail() {
2749 $admins = RBACEngine::getInstance()->getUsersByAllowedAction ('project_admin', $this->getID());
2751 if (count($admins) < 1) {
2752 $this->setError(_("Group does not have any administrators."));
2756 // send one email per admin
2757 foreach ($admins as $admin) {
2758 setup_gettext_for_user ($admin);
2760 $message = sprintf(_('Your project registration for %4$s has been approved.
2762 Project Full Name: %1$s
2763 Project Unix Name: %2$s
2765 Your DNS will take up to a day to become active on our site.
2766 Your web site is accessible through your shell account. Please read
2767 site documentation (see link below) about intended usage, available
2768 services, and directory layout of the account.
2771 own project page in %4$s while logged in, you will find
2772 additional menu functions to your left labeled \'Project Admin\'.
2774 We highly suggest that you now visit %4$s and create a public
2775 description for your project. This can be done by visiting your project
2776 page while logged in, and selecting \'Project Admin\' from the menus
2777 on the left (or by visiting %3$s
2780 Your project will also not appear in the Trove Software Map (primary
2781 list of projects hosted on %4$s which offers great flexibility in
2782 browsing and search) until you categorize it in the project administration
2783 screens. So that people can find your project, you should do this now.
2784 Visit your project while logged in, and select \'Project Admin\' from the
2787 Enjoy the system, and please tell others about %4$s. Let us know
2788 if there is anything we can do to help you.
2791 htmlspecialchars_decode($this->getPublicName()),
2792 $this->getUnixName(),
2793 util_make_url ('/project/admin/?group_id='.$this->getID()),
2794 forge_get_config ('forge_name'));
2796 util_send_message($admin->getEmail(), sprintf(_('%s Project Approved'), forge_get_config ('forge_name')), $message);
2798 setup_gettext_from_context();
2805 * sendRejectionEmail - Send project rejection email.
2807 * This function sends out a rejection message to a user who
2808 * registered a project.
2810 * @param int $response_id The id of the response to use.
2811 * @param string $message The rejection message.
2812 * @return bool completion status.
2815 function sendRejectionEmail($response_id, $message="zxcv") {
2816 $submitters = array();
2817 foreach (get_group_join_requests ($this) as $gjr) {
2818 $submitters[] = user_get_object($gjr->getUserID());
2821 if (count ($submitters) < 1) {
2822 $this->setError(_("Group does not have any administrators."));
2826 foreach ($submitters as $admin) {
2827 setup_gettext_for_user($admin);
2829 $response = sprintf(_('Your project registration for %s has been denied.'), forge_get_config('forge_name')) . "\n\n"
2830 . _('Project Full Name')._(': '). $this->getPublicName() . "\n"
2831 . _('Project Unix Name')._(': '). $this->getUnixName() . "\n\n"
2832 . _('Reasons for negative decision')._(': ') . "\n\n";
2834 // Check to see if they want to send a custom rejection response
2835 if ($response_id == 0) {
2836 $response .= $message;
2838 $response .= db_result(
2839 db_query_params('SELECT response_text FROM canned_responses WHERE response_id=$1', array($response_id)),
2844 util_send_message($admin->getEmail(), sprintf(_('%s Project Denied'), forge_get_config ('forge_name')), $response);
2845 setup_gettext_from_context();
2852 * sendNewProjectNotificationEmail - Send new project notification email.
2854 * This function sends out a notification email to the
2855 * SourceForge admin user when a new project is
2858 * @return bool success.
2861 function sendNewProjectNotificationEmail() {
2862 // Get the user who wants to register the project
2863 $submitters = array();
2864 foreach (get_group_join_requests ($this) as $gjr) {
2865 $submitters[] = user_get_object($gjr->getUserID());
2867 if (count ($submitters) < 1) {
2868 $this->setError(_("Could not find user who has submitted the project."));
2872 $admins = RBACEngine::getInstance()->getUsersByAllowedAction ('approve_projects', -1);
2874 if (count($admins) < 1) {
2875 $this->setError(_("There is no administrator to send the mail to."));
2879 foreach ($admins as $admin) {
2880 $admin_email = $admin->getEmail();
2881 setup_gettext_for_user ($admin);
2883 $message = sprintf(_('New %s Project Submitted'), forge_get_config ('forge_name')) . "\n\n"
2884 . _('Project Full Name')._(': ').htmlspecialchars_decode($this->getPublicName()) . "\n"
2885 . _('Submitted Description')._(': ').htmlspecialchars_decode($this->getRegistrationPurpose()) . "\n";
2887 foreach ($submitters as $submitter) {
2888 $message .= _('Submitter')._(': ').$submitter->getRealName().' ('.$submitter->getUnixName().')' . "\n\n";
2892 . _('Please visit the following URL to approve or reject this project')._(': '). "\n"
2893 . util_make_url('/admin/approve-pending.php');
2894 util_send_message($admin_email, sprintf(_('New %s Project Submitted'), forge_get_config('forge_name')), $message);
2895 setup_gettext_from_context();
2898 $email = $submitter->getEmail();
2899 setup_gettext_for_user ($submitter);
2901 $message = sprintf(_('New %s Project Submitted'), forge_get_config ('forge_name')) . "\n\n"
2902 . _('Project Full Name')._(': ') . $this->getPublicName() . "\n"
2903 . _('Submitted Description')._(': ') . util_unconvert_htmlspecialchars($this->getRegistrationPurpose()) . "\n\n"
2904 . sprintf(_('The %s admin team will now examine your project submission. You will be notified of their decision.'),
2905 forge_get_config ('web_host'));
2907 util_send_message($email, sprintf(_('New %s Project Submitted'), forge_get_config ('forge_name')), $message);
2908 setup_gettext_from_context();
2914 * validateGroupName - Validate the group name
2916 * @param string Group name.
2918 * @return boolean an error false and set an error is the group name is invalid otherwise return true
2920 function validateGroupName($group_name) {
2921 if (strlen($group_name)<3) {
2922 $this->setError(_('Group name is too short'));
2924 } elseif (strlen(htmlspecialchars($group_name))>40) {
2925 $this->setError(_('Group name is too long'));
2927 } elseif (group_get_object_by_publicname($group_name)) {
2928 $this->setError(_('Group name already taken'));
2935 * getRolesId - Get Ids of the roles of the group.
2937 * @param bool all role ids or local role ids only. Default is all role ids
2938 * @return array Role ids of this group.
2940 function getRolesId($global = true) {
2941 $role_ids = array();
2943 $res = db_query_params('SELECT role_id FROM pfo_role WHERE home_group_id=$1',
2944 array($this->getID()));
2945 while ($arr = db_fetch_array($res)) {
2946 $role_ids[] = $arr['role_id'];
2949 $res = db_query_params('SELECT role_id FROM role_project_refs WHERE group_id=$1',
2950 array($this->getID()));
2951 while ($arr = db_fetch_array($res)) {
2952 $role_ids[] = $arr['role_id'];
2956 return array_unique($role_ids);
2960 * getRoles - Get the roles of the group.
2962 * @return array Roles of this group.
2964 function getRoles() {
2967 $roles = $this->getRolesId();
2968 $engine = RBACEngine::getInstance();
2969 foreach ($roles as $role_id) {
2970 $result[] = $engine->getRoleById ($role_id);
2976 function normalizeAllRoles() {
2977 $roles = $this->getRoles();
2979 foreach ($roles as $r) {
2980 $r->normalizeData();
2985 * getUnixStatus - Status of activation of unix account.
2987 * @return string Values: (N)one, (A)ctive, (S)uspended or (D)eleted
2989 function getUnixStatus() {
2990 return $this->data_array['unix_status'];
2994 * setUnixStatus - Sets status of activation of unix account.
2996 * @param string $status The unix status.
3002 * @return bool success.
3004 function setUnixStatus($status) {
3007 $res = db_query_params ('UPDATE groups SET unix_status=$1 WHERE group_id=$2',
3012 $this->setError(sprintf(_('Error: Cannot Update Group Unix Status: %s'),db_error()));
3016 if ($status == 'A') {
3017 if (!$SYS->sysCheckCreateGroup($this->getID())) {
3018 $this->setError($SYS->getErrorMessage());
3023 if ($SYS->sysCheckGroup($this->getID())) {
3024 if (!$SYS->sysRemoveGroup($this->getID())) {
3025 $this->setError($SYS->getErrorMessage());
3032 $this->data_array['unix_status']=$status;
3039 * getUsers - Get the users of a group
3041 * @param bool $onlylocal
3042 * @param boolean $onlyactive Only users with state active, or all users of group
3043 * @return array user's objects.
3045 function getUsers($onlylocal = true, $onlyactive = true) {
3046 if (!isset($this->membersArr)) {
3047 $this->membersArr = array();
3050 foreach ($this->getRoles() as $role) {
3052 && ($role->getHomeProject() == NULL || $role->getHomeProject()->getID() != $this->getID())) {
3055 foreach ($role->getUsers() as $user) {
3056 $ids[] = $user->getID();
3059 $ids = array_unique ($ids);
3060 foreach ($ids as $id) {
3061 $u = user_get_object ($id);
3062 if (!$onlyactive || $u->isActive()) {
3063 $this->membersArr[] = $u;
3067 return $this->membersArr;
3070 function setDocmanCreateOnlineStatus($status) {
3072 /* if we activate search engine, we probably want to reindex */
3073 $res = db_query_params('UPDATE groups SET use_docman_create_online=$1 WHERE group_id=$2',
3074 array($status, $this->getID()));
3077 $this->setError(sprintf(_('Error: Cannot Update Group DocmanCreateOnline Status: %s'),db_error()));
3081 $this->data_array['use_docman_create_online']=$status;
3087 function setDocmanWebdav($status) {
3089 /* if we activate search engine, we probably want to reindex */
3090 $res = db_query_params('UPDATE groups SET use_webdav=$1 WHERE group_id=$2',
3095 $this->setError(sprintf(_('Error: Cannot Update Group UseWebdab Status: %s'),db_error()));
3099 $this->data_array['use_webdav']=$status;
3105 function setDocmanSearchStatus($status) {
3107 /* if we activate search engine, we probably want to reindex */
3108 $res = db_query_params('UPDATE groups SET use_docman_search=$1, force_docman_reindex=$1 WHERE group_id=$2',
3113 $this->setError(sprintf(_('Error: Cannot Update Group UseDocmanSearch Status: %s'),db_error()));
3117 $this->data_array['use_docman_search']=$status;
3123 function setDocmanForceReindexSearch($status) {
3125 /* if we activate search engine, we probably want to reindex */
3126 $res = db_query_params('UPDATE groups SET force_docman_reindex=$1 WHERE group_id=$2',
3131 $this->setError(sprintf(_('Error: Cannot Update Group force_docman_reindex %s'),db_error()));
3135 $this->data_array['force_docman_reindex']=$status;
3143 * group_getname() - get the group name
3145 * @param int $group_id The group ID
3150 function group_getname ($group_id = 0) {
3151 $grp = group_get_object($group_id);
3153 return $grp->getPublicName();
3160 * group_getunixname() - get the unixname for a group
3162 * @param int $group_id The group ID
3167 function group_getunixname ($group_id) {
3168 $grp = group_get_object($group_id);
3170 return $grp->getUnixName();
3177 * group_get_result() - Get the group object result ID.
3179 * @param int $group_id The group ID
3184 function &group_get_result($group_id=0) {
3185 $grp = group_get_object($group_id);
3187 return $grp->getData();
3193 function getAllProjectTags($onlyvisible = true) {
3194 $res = db_query_params('SELECT project_tags.name, groups.group_id FROM groups, project_tags WHERE groups.group_id = project_tags.group_id AND groups.status = $1 ORDER BY project_tags.name, groups.group_id',
3197 if (!$res || db_numrows($res) == 0) {
3203 while ($arr = db_fetch_array($res)) {
3205 $group_id = $arr[1];
3206 if (!isset($result[$tag])) {
3207 $result[$tag] = array();
3210 if (!$onlyvisible || forge_check_perm('project_read', $group_id)) {
3211 $p = group_get_object($group_id);
3212 $result[$tag][] = array('unix_group_name' => $p->getUnixName(),
3213 'group_id' => $group_id);
3221 * Utility class to compare project based in various criteria (names, unixnames, id, ...)
3224 class ProjectComparator {
3225 var $criterion = 'name';
3227 function Compare ($a, $b) {
3228 switch ($this->criterion) {
3231 $namecmp = strcoll ($a->getPublicName(), $b->getPublicName());
3232 if ($namecmp != 0) {
3235 /* If several projects share a same public name */
3236 return strcoll ($a->getUnixName(), $b->getUnixName());
3239 return strcmp ($a->getUnixName(), $b->getUnixName());
3247 return ($a < $b) ? -1 : 1;
3253 function sortProjectList (&$list, $criterion='name') {
3254 $cmp = new ProjectComparator();
3255 $cmp->criterion = $criterion;
3257 return usort ($list, array($cmp, 'Compare'));
3262 // c-file-style: "bsd"