5 * Copyright 1999-2001, VA Linux Systems, Inc.
6 * Copyright 2009-2010, Roland Mas
7 * Copyright 2010-2011, Franck Villaume - Capgemini
8 * Copyright 2010-2011, Alain Peyrat - Alcatel-Lucent
9 * http://fusionforge.org
11 * This file is part of FusionForge.
13 * FusionForge is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published
15 * by the Free Software Foundation; either version 2 of the License,
16 * or (at your option) any later version.
18 * FusionForge is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with FusionForge; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
29 require_once $gfcommon.'tracker/ArtifactTypes.class.php';
30 require_once $gfcommon.'tracker/ArtifactTypeFactory.class.php';
31 require_once $gfcommon.'forum/Forum.class.php';
32 require_once $gfcommon.'forum/ForumFactory.class.php';
33 require_once $gfcommon.'pm/ProjectGroup.class.php';
34 require_once $gfcommon.'pm/ProjectGroupFactory.class.php';
35 require_once $gfcommon.'include/Role.class.php';
36 require_once $gfcommon.'frs/FRSPackage.class.php';
37 require_once $gfcommon.'docman/DocumentGroup.class.php';
38 require_once $gfcommon.'docman/DocumentGroupFactory.class.php';
39 require_once $gfcommon.'mail/MailingList.class.php';
40 require_once $gfcommon.'mail/MailingListFactory.class.php';
41 require_once $gfcommon.'survey/SurveyFactory.class.php';
42 require_once $gfcommon.'survey/SurveyQuestionFactory.class.php';
43 require_once $gfcommon.'include/gettext.php';
44 require_once $gfcommon.'include/GroupJoinRequest.class.php';
49 * group_get_object() - Get the group object.
51 * group_get_object() is useful so you can pool group objects/save database queries
52 * You should always use this instead of instantiating the object directly.
54 * You can now optionally pass in a db result handle. If you do, it re-uses that query
55 * to instantiate the objects.
57 * IMPORTANT! That db result must contain all fields
58 * from groups table or you will have problems
61 * @param int Result set handle ("SELECT * FROM groups WHERE group_id=xx")
62 * @return object a group object or false on failure
64 function &group_get_object($group_id, $res = false) {
65 //create a common set of group objects
66 //saves a little wear on the database
68 //automatically checks group_type and
69 //returns appropriate object
72 if (!isset($GROUP_OBJ["_".$group_id."_"])) {
74 //the db result handle was passed in
76 $res = db_query_params('SELECT * FROM groups WHERE group_id=$1', array($group_id)) ;
78 if (!$res || db_numrows($res) < 1) {
79 $GROUP_OBJ["_".$group_id."_"]=false;
82 check group type and set up object
84 if (db_result($res,0,'type_id') == 1) {
86 $GROUP_OBJ["_".$group_id."_"] = new Group($group_id, $res);
89 $GROUP_OBJ["_".$group_id."_"] = false;
93 return $GROUP_OBJ["_".$group_id."_"];
96 function &group_get_objects($id_arr) {
99 // Note: if we don't do this, the result may be corrupted
103 foreach ($id_arr as $id) {
105 // See if this ID already has been fetched in the cache
107 if (!isset($GROUP_OBJ["_".$id."_"])) {
111 if (count($fetch) > 0) {
112 $res=db_query_params('SELECT * FROM groups WHERE group_id = ANY ($1)',
113 array(db_int_array_to_any_clause($fetch)));
114 while ($arr = db_fetch_array($res)) {
115 $GROUP_OBJ["_".$arr['group_id']."_"] = new Group($arr['group_id'],$arr);
118 foreach ($id_arr as $id) {
119 $return[] =& $GROUP_OBJ["_".$id."_"];
124 function &group_get_active_projects() {
125 $res = db_query_params('SELECT group_id FROM groups WHERE status=$1',
127 return group_get_objects(util_result_column_to_array($res,0));
130 function &group_get_template_projects() {
131 $res=db_query_params ('SELECT group_id FROM groups WHERE is_template=1 AND status != $1',
133 return group_get_objects (util_result_column_to_array($res,0)) ;
136 function &group_get_object_by_name($groupname) {
137 $res = db_query_params('SELECT * FROM groups WHERE unix_group_name=$1', array($groupname));
138 return group_get_object(db_result($res, 0, 'group_id'), $res);
141 function &group_get_objects_by_name($groupname_arr) {
142 $res = db_query_params('SELECT group_id FROM groups WHERE unix_group_name = ANY ($1)',
143 array(db_string_array_to_any_clause($groupname_arr)));
144 $arr =& util_result_column_to_array($res,0);
145 return group_get_objects($arr);
148 function &group_get_object_by_publicname($groupname) {
149 $res = db_query_params('SELECT * FROM groups WHERE lower(group_name) LIKE $1',
150 array(htmlspecialchars(strtolower($groupname))));
151 return group_get_object(db_result($res, 0, 'group_id'), $res);
154 class Group extends Error {
156 * Associative array of data from db.
158 * @var array $data_array.
163 * array of User objects.
165 * @var array $membersArr.
170 * Whether the use is an admin/super user of this project.
172 * @var bool $is_admin.
177 * Artifact types result handle.
179 * @var int $types_res.
184 * Associative array of data for plugins.
186 * @var array $plugins_data.
192 * Associative array of data for the group menu.
194 * @var array $menu_data.
199 * Group - Group object constructor - use group_get_object() to instantiate.
201 * @param int Required - group_id of the group you want to instantiate.
202 * @param int Database result from select query OR associative array of all columns.
203 * @return boolean success or not
205 function Group($id = false, $res = false) {
208 //setting up an empty object
209 //probably going to call create()
213 if (!$this->fetchData($id)) {
218 // Assoc array was passed in
220 if (is_array($res)) {
221 $this->data_array =& $res;
223 if (db_numrows($res) < 1) {
224 //function in class we extended
225 $this->setError(_('Group Not Found'));
226 $this->data_array=array();
229 //set up an associative array for use by other functions
230 $this->data_array = db_fetch_array_by_row($res, 0);
238 * fetchData - May need to refresh database fields if an update occurred.
240 * @param int The group_id.
241 * @return boolean success or not
243 function fetchData($group_id) {
244 $res = db_query_params ('SELECT * FROM groups WHERE group_id=$1',
246 if (!$res || db_numrows($res) < 1) {
247 $this->setError(sprintf(_('fetchData():: %s'),db_error()));
250 $this->data_array = db_fetch_array($res);
255 * create - Create new group.
257 * This method should be called on empty Group object.
259 * @param object The User object.
260 * @param string The full name of the user.
261 * @param string The Unix name of the user.
262 * @param string The new group description.
263 * @param string The purpose of the group.
264 * @param boolean Whether to send an email or not
265 * @param int The id of the project this new project is based on
266 * @return boolean success or not
268 function create(&$user, $group_name, $unix_name, $description, $purpose, $unix_box='shell1', $scm_box='cvs1', $is_public=1, $send_mail=true, $built_from_template=0) {
269 // $user is ignored - anyone can create pending group
272 if ($this->getID()!=0) {
273 $this->setError(_('Group::create: Group object already exists'));
275 } else if (!$this->validateGroupName($group_name)) {
277 } else if (!account_groupnamevalid($unix_name)) {
278 $this->setError(_('Invalid Unix name'));
280 } else if (!$SYS->sysUseUnixName($unix_name)) {
281 $this->setError(_('Unix name already taken'));
283 } else if (db_numrows(db_query_params('SELECT group_id FROM groups WHERE unix_group_name=$1',
284 array($unix_name))) > 0) {
285 $this->setError(_('Unix name already taken'));
287 } else if (strlen($purpose)<10) {
288 $this->setError(_('Please describe your Registration Purpose in a more comprehensive manner'));
290 } else if (strlen($purpose)>1500) {
291 $this->setError(_('The Registration Purpose text is too long. Please make it smaller than 1500 bytes.'));
293 } else if (strlen($description)<10) {
294 $this->setError(_('Describe in a more comprehensive manner your project.'));
296 } else if (strlen($description)>255) {
297 $this->setError(_('Your project description is too long. Please make it smaller than 256 bytes.'));
302 $res = db_query_params('
319 VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)',
320 array (htmlspecialchars ($group_name),
323 htmlspecialchars($description),
324 $unix_name.".".forge_get_config('web_host'),
325 $unix_name.".".forge_get_config('web_host'),
329 htmlspecialchars($purpose),
332 md5(util_randbytes()),
333 $built_from_template));
334 if (!$res || db_affected_rows($res) < 1) {
335 $this->setError(sprintf(_('ERROR: Could not create group: %s'),db_error()));
340 $id = db_insertid($res, 'groups', 'group_id');
342 $this->setError(sprintf(_('ERROR: Could not get group id: %s'),db_error()));
347 if (!$this->fetchData($id)) {
353 $gjr = new GroupJoinRequest($this);
354 $gjr->create($user->getID(),
355 'Fake GroupJoinRequest to store the creator of a project',
359 // Now, make the user an admin
361 $res=db_query_params('INSERT INTO user_group (user_id, group_id, admin_flags,
362 cvs_flags, artifact_flags, forum_flags, role_id)
363 VALUES ($1, $2, $3, $4, $5, $6, $7)',
364 array($user->getID(),
371 if (!$res || db_affected_rows($res) < 1) {
372 $this->setError(sprintf(_('ERROR: Could not add admin to newly created group: %s'),db_error()));
378 $hook_params = array();
379 $hook_params['group'] = $this;
380 $hook_params['group_id'] = $this->getID();
381 $hook_params['group_name'] = $group_name;
382 $hook_params['unix_group_name'] = $unix_name;
383 plugin_hook("group_create", $hook_params);
387 $this->sendNewProjectNotificationEmail();
395 * updateAdmin - Update core properties of group object.
397 * This function require site admin privilege.
399 * @param object User requesting operation (for access control).
400 * @param boolean Whether group is publicly accessible (0/1).
401 * @param int Group type (1-project, 2-foundry).
402 * @param string Machine on which group's home directory located.
403 * @param string Domain which serves group's WWW.
407 function updateAdmin(&$user, $is_public, $type_id, $unix_box, $http_domain) {
408 $perm =& $this->getPermission();
410 if (!$perm || !is_object($perm)) {
411 $this->setError(_('Could not get permission.'));
415 if (!$perm->isSuperUser()) {
416 $this->setError(_('Permission denied.'));
422 $res = db_query_params('
424 SET is_public=$1, type_id=$2,
425 unix_box=$3, http_domain=$4
433 if (!$res || db_affected_rows($res) < 1) {
434 $this->setError(_('ERROR: DB: Could not change group properties: %s'),db_error());
439 // Log the audit trail
440 if ($is_public != $this->isPublic()) {
441 $this->addHistory('is_public', $this->isPublic());
443 if ($type_id != $this->data_array['type_id']) {
444 $this->addHistory('type_id', $this->data_array['type_id']);
446 if ($unix_box != $this->data_array['unix_box']) {
447 $this->addHistory('unix_box', $this->data_array['unix_box']);
449 if ($http_domain != $this->data_array['http_domain']) {
450 $this->addHistory('http_domain', $this->data_array['http_domain']);
453 if (!$this->fetchData($this->getID())) {
462 * update - Update number of common properties.
464 * Unlike updateAdmin(), this function accessible to project admin.
466 * @param object User requesting operation (for access control).
467 * @param boolean Whether group is publicly accessible (0/1).
468 * @param string Project's license (string ident).
469 * @param int Group type (1-project, 2-foundry).
470 * @param string Machine on which group's home directory located.
471 * @param string Domain which serves group's WWW.
472 * @return int status.
475 function update(&$user, $group_name, $homepage, $short_description, $use_mail, $use_survey, $use_forum,
476 $use_pm, $use_pm_depend_box, $use_scm, $use_news, $use_docman,
477 $new_doc_address, $send_all_docs, $logo_image_id,
478 $use_ftp, $use_tracker, $use_frs, $use_stats, $tags, $is_public) {
480 $perm =& $this->getPermission();
482 if (!$perm || !is_object($perm)) {
483 $this->setError(_('Could not get permission.'));
487 if (!$perm->isAdmin()) {
488 $this->setError(_('Permission denied.'));
492 // Validate some values
493 if ($this->getPublicName() != $group_name) {
494 if (!$this->validateGroupName($group_name)) {
499 if ($new_doc_address) {
500 $invalid_mails = validate_emails($new_doc_address);
501 if (count($invalid_mails) > 0) {
502 $this->setError(sprintf(ngettext('New Doc Address Appeared Invalid: %s', 'New Doc Addresses Appeared Invalid: %s', count($invalid_mails)),implode(',',$invalid_mails)));
507 // in the database, these all default to '1',
508 // so we have to explicity set 0
521 if (!$use_pm_depend_box) {
522 $use_pm_depend_box = 0;
545 if (!$send_all_docs) {
549 $homepage = ltrim($homepage);
551 $homepage = forge_get_config('web_host').'/projects/'.$this->getUnixName().'/';
554 if (strlen(htmlspecialchars($short_description))>255) {
555 $this->setError(_('Error updating project information: Maximum length for Project Description is 255 chars.'));
561 //XXX not yet actived logo_image_id='$logo_image_id',
562 $res = db_query_params('UPDATE groups
565 short_description=$3,
570 use_pm_depend_box=$8,
582 array(htmlspecialchars($group_name),
584 htmlspecialchars($short_description),
603 $this->setError(sprintf(_('Error updating project information: %s'), db_error()));
608 if ($this->setTags($tags) === false) {
613 $hook_params = array();
614 $hook_params['group'] = $this;
615 $hook_params['group_id'] = $this->getID();
616 $hook_params['group_homepage'] = $homepage;
617 $hook_params['group_name'] = htmlspecialchars($group_name);
618 $hook_params['group_description'] = htmlspecialchars($short_description);
619 $hook_params['group_ispublic'] = $is_public;
620 if (!plugin_hook("group_update", $hook_params)) {
621 if (!$this->isError()) {
622 $this->setError(_('Error updating project information in plugin_hook group_update'));
628 // Log the audit trail
629 $this->addHistory('Changed Public Info', '');
631 if (!$this->fetchData($this->getID())) {
640 * getID - Simply return the group_id for this object.
642 * @return int group_id.
645 return $this->data_array['group_id'];
649 * getType() - Foundry, project, etc.
651 * @return int The type flag from the database.
654 return $this->data_array['type_id'];
659 * getStatus - the status code.
661 * Statuses char include I,H,A,D.
663 function getStatus() {
664 return $this->data_array['status'];
668 * setStatus - set the status code.
670 * Statuses include I,H,A,D.
672 * @param object User requesting operation (for access control).
673 * @param string Status value.
674 * @return boolean success.
677 function setStatus(&$user, $status) {
680 if (!forge_check_global_perm('approve_projects')) {
681 $this->setPermissionDeniedError();
685 // Projects in 'A' status can only go to 'H' or 'D'
686 // Projects in 'D' status can only go to 'A'
687 // Projects in 'P' status can only go to 'A' OR 'D'
688 // Projects in 'I' status can only go to 'P'
689 // Projects in 'H' status can only go to 'A' OR 'D'
690 $allowed_status_changes = array(
691 'AH'=>1,'AD'=>1,'DA'=>1,'PA'=>1,'PD'=>1,
692 'IP'=>1,'HA'=>1,'HD'=>1
695 // Check that status transition is valid
696 if ($this->getStatus() != $status
697 && !$allowed_status_changes[$this->getStatus().$status]) {
698 $this->setError(_('Invalid Status Change'));
704 $res = db_query_params('UPDATE groups
706 WHERE group_id=$2', array($status, $this->getID()));
708 if (!$res || db_affected_rows($res) < 1) {
709 $this->setError(sprintf(_('ERROR: DB: Could not change group status: %s'),db_error()));
715 // Activate system group, if not yet
716 if (!$SYS->sysCheckGroup($this->getID())) {
717 if (!$SYS->sysCreateGroup($this->getID())) {
718 $this->setError($SYS->getErrorMessage());
723 if (!$this->activateUsers()) {
728 /* Otherwise, the group is not active, and make sure that
729 System group is not active either */
730 } else if ($SYS->sysCheckGroup($this->getID())) {
731 if (!$SYS->sysRemoveGroup($this->getID())) {
732 $this->setError($SYS->getErrorMessage());
738 $hook_params = array();
739 $hook_params['group'] = $this;
740 $hook_params['group_id'] = $this->getID();
741 $hook_params['status'] = $status;
742 plugin_hook("group_setstatus", $hook_params);
746 // Log the audit trail
747 if ($status != $this->getStatus()) {
748 $this->addHistory('Status', $this->getStatus());
751 $this->data_array['status'] = $status;
756 * isProject - Simple boolean test to see if it's a project or not.
758 * @return boolean is_project.
760 function isProject() {
761 if ($this->getType()==1) {
769 * isPublic - Simply returns the is_public flag from the database.
771 * @return boolean is_public.
773 function isPublic() {
774 return $this->data_array['is_public'];
778 * isActive - Database field status of 'A' returns true.
780 * @return boolean is_active.
782 function isActive() {
783 if ($this->getStatus()=='A') {
791 * isTemplate - Simply returns the is_template flag from the database.
793 * @return boolean is_template.
795 function isTemplate() {
796 return $this->data_array['is_template'];
800 * setAsTemplate - Set the template status of a project
802 * @param boolean is_template.
804 function setAsTemplate ($booleanparam) {
806 $booleanparam = $booleanparam ? 1 : 0 ;
807 $res = db_query_params ('UPDATE groups SET is_template=$1 WHERE group_id=$2',
808 array ($booleanparam, $this->getID()));
810 $this->data_array['is_template']=$booleanparam;
820 * getTemplateProject - Return the project template this project is built from
822 * @return object The template project
824 function getTemplateProject() {
825 return group_get_object($this->data_array['built_from_template']);
829 * getUnixName - the unix_name
831 * @return string unix_name.
833 function getUnixName() {
834 return strtolower($this->data_array['unix_group_name']);
838 * getPublicName - the full-length public name.
840 * @return string The group_name.
842 function getPublicName() {
843 return $this->data_array['group_name'];
847 * getRegisterPurpose - the text description of the purpose of this project.
849 * @return string The description.
851 function getRegisterPurpose() {
852 return $this->data_array['register_purpose'];
856 * getDescription - the text description of this project.
858 * @return string The description.
860 function getDescription() {
861 return $this->data_array['short_description'];
865 * getStartDate - the unix time this project was registered.
867 * @return int (unix time) of registration.
869 function getStartDate() {
870 return $this->data_array['register_time'];
874 * getLogoImageID - the id of the logo in the database for this project.
876 * @return int The ID of logo image in db_images table (or 100 if none).
878 function getLogoImageID() {
879 return $this->data_array['logo_image_id'];
883 * getUnixBox - the hostname of the unix box where this project is located.
885 * @return string The name of the unix machine for the group.
887 function getUnixBox() {
888 return $this->data_array['unix_box'];
892 * getSCMBox - the hostname of the scm box where this project is located.
894 * @return string The name of the unix machine for the group.
896 function getSCMBox() {
897 return $this->data_array['scm_box'];
900 * setSCMBox - the hostname of the scm box where this project is located.
902 * @param string The name of the new SCM_BOX
904 function setSCMBox($scm_box) {
906 if ($scm_box == $this->data_array['scm_box']) {
911 $res = db_query_params('UPDATE groups SET scm_box=$1 WHERE group_id=$2', array($scm_box, $this->getID ()));
913 $this->addHistory('scm_box', $this->data_array['scm_box']);
914 $this->data_array['scm_box'] = $scm_box;
919 $this->setError(_("Couldn't insert SCM_BOX to database"));
923 $this->setError(_("SCM Box can't be empty"));
929 * getDomain - the hostname.domain where their web page is located.
931 * @return string The name of the group [web] domain.
933 function getDomain() {
934 return $this->data_array['http_domain'];
938 * getRegistrationPurpose - the text description of the purpose of this project.
940 * @return string The application for project hosting.
942 function getRegistrationPurpose() {
943 return $this->data_array['register_purpose'];
948 * getAdmins() - Get array of Admin user objects.
950 * @return array Array of User objects.
952 function &getAdmins() {
953 $roles = RBACEngine::getInstance()->getRolesByAllowedAction ('project_admin', $this->getID());
957 foreach ($roles as $role) {
958 if (! ($role instanceof RoleExplicit)) {
961 if ($role->getHomeProject() == NULL
962 || $role->getHomeProject()->getID() != $this->getID()) {
966 foreach ($role->getUsers() as $u) {
967 $user_ids[] = $u->getID();
970 return user_get_objects(array_unique($user_ids));
974 Common Group preferences for tools
978 * enableAnonSCM - whether or not this group has opted to enable Anonymous SCM.
980 * @return boolean enable_scm.
982 function enableAnonSCM() {
984 $r = RoleAnonymous::getInstance();
985 return $r->hasPermission('scm', $this->getID(), 'read');
987 if ($this->isPublic() && $this->usesSCM()) {
988 return $this->data_array['enable_anonscm'];
995 function SetUsesAnonSCM($booleanparam) {
997 $booleanparam = $booleanparam ? 1 : 0;
999 $r = RoleAnonymous::getInstance();
1000 $r->setSetting('scm', $this->getID(), $booleanparam);
1003 $res = db_query_params('UPDATE groups SET enable_anonscm=$1 WHERE group_id=$2',
1004 array($booleanparam, $this->getID()));
1006 $this->data_array['enable_anonscm'] = $booleanparam;
1016 * enablePserver - whether or not this group has opted to enable Pserver.
1018 * @return boolean enable_pserver.
1020 function enablePserver() {
1021 if ($this->usesSCM()) {
1022 return $this->data_array['enable_pserver'];
1028 function SetUsesPserver($booleanparam) {
1030 $booleanparam = $booleanparam ? 1 : 0;
1031 $res = db_query_params('UPDATE groups SET enable_pserver=$1 WHERE group_id=$2',
1032 array($booleanparam, $this->getID()));
1034 $this->data_array['enable_pserver'] = $booleanparam;
1043 * usesSCM - whether or not this group has opted to use SCM.
1045 * @return boolean uses_scm.
1047 function usesSCM() {
1048 if (forge_get_config('use_scm')) {
1049 return $this->data_array['use_scm'];
1056 * setUseSCM - Set the SCM usage
1058 * @param boolean enabled/disabled
1060 function setUseSCM ($booleanparam) {
1062 $booleanparam = $booleanparam ? 1 : 0 ;
1063 $res = db_query_params ('UPDATE groups SET use_scm=$1 WHERE group_id=$2',
1064 array ($booleanparam, $this->getID()));
1066 $this->data_array['use_scm']=$booleanparam;
1076 * usesMail - whether or not this group has opted to use mailing lists.
1078 * @return boolean uses_mail.
1080 function usesMail() {
1081 if (forge_get_config('use_mail')) {
1082 return $this->data_array['use_mail'];
1089 * setUseMail - Set the mailing-list usage
1091 * @param boolean enabled/disabled
1093 function setUseMail ($booleanparam) {
1095 $booleanparam = $booleanparam ? 1 : 0 ;
1096 $res = db_query_params ('UPDATE groups SET use_mail=$1 WHERE group_id=$2',
1097 array ($booleanparam, $this->getID()));
1099 $this->data_array['use_mail']=$booleanparam;
1109 * usesNews - whether or not this group has opted to use news.
1111 * @return boolean uses_news.
1113 function usesNews() {
1114 if (forge_get_config('use_news')) {
1115 return $this->data_array['use_news'];
1122 * usesForum - whether or not this group has opted to use discussion forums.
1124 * @return boolean uses_forum.
1126 function usesForum() {
1127 if (forge_get_config('use_forum')) {
1128 return $this->data_array['use_forum'];
1135 * setUseForum - Set the forum usage
1137 * @param boolean enabled/disabled
1139 function setUseForum ($booleanparam) {
1141 $booleanparam = $booleanparam ? 1 : 0 ;
1142 $res = db_query_params ('UPDATE groups SET use_forum=$1 WHERE group_id=$2',
1143 array ($booleanparam, $this->getID()));
1145 $this->data_array['use_forum']=$booleanparam;
1155 * usesStats - whether or not this group has opted to use stats.
1157 * @return boolean uses_stats.
1159 function usesStats() {
1160 return $this->data_array['use_stats'];
1164 * usesFRS - whether or not this group has opted to use file release system.
1166 * @return boolean uses_frs.
1168 function usesFRS() {
1169 if (forge_get_config('use_frs')) {
1170 return $this->data_array['use_frs'];
1177 * setUseFRS - Set the FRS usage
1179 * @param boolean enabled/disabled
1181 function setUseFRS ($booleanparam) {
1183 $booleanparam = $booleanparam ? 1 : 0 ;
1184 $res = db_query_params ('UPDATE groups SET use_frs=$1 WHERE group_id=$2',
1185 array ($booleanparam, $this->getID()));
1187 $this->data_array['use_frs']=$booleanparam;
1197 * usesTracker - whether or not this group has opted to use tracker.
1199 * @return boolean uses_tracker.
1201 function usesTracker() {
1202 if (forge_get_config('use_tracker')) {
1203 return $this->data_array['use_tracker'];
1210 * setUseTracker - Set the tracker usage
1212 * @param boolean enabled/disabled
1214 function setUseTracker ($booleanparam) {
1216 $booleanparam = $booleanparam ? 1 : 0 ;
1217 $res = db_query_params ('UPDATE groups SET use_tracker=$1 WHERE group_id=$2',
1218 array ($booleanparam, $this->getID()));
1220 $this->data_array['use_tracker']=$booleanparam;
1230 * useCreateOnline - whether or not this group has opted to use create online documents option.
1232 * @return boolean use_docman_create_online.
1234 function useCreateOnline() {
1235 if (forge_get_config('use_docman')) {
1236 return $this->data_array['use_docman_create_online'];
1243 * usesDocman - whether or not this group has opted to use docman.
1245 * @return boolean use_docman.
1247 function usesDocman() {
1248 if (forge_get_config('use_docman')) {
1249 return $this->data_array['use_docman'];
1256 * setUseDocman - Set the docman usage
1258 * @param boolean enabled/disabled
1260 function setUseDocman ($booleanparam) {
1262 $booleanparam = $booleanparam ? 1 : 0 ;
1263 $res = db_query_params ('UPDATE groups SET use_docman=$1 WHERE group_id=$2',
1264 array ($booleanparam, $this->getID()));
1266 $this->data_array['use_docman']=$booleanparam;
1276 * useDocmanSearch - whether or not this group has opted to use docman search engine.
1278 * @return boolean use_docman_search.
1280 function useDocmanSearch() {
1281 if (forge_get_config('use_docman')) {
1282 return $this->data_array['use_docman_search'];
1289 * useWebdav - whether or not this group has opted to use webdav interface.
1291 * @return boolean use_docman_search.
1293 function useWebdav() {
1294 if (forge_get_config('use_webdav')) {
1295 return $this->data_array['use_webdav'];
1302 * usesFTP - whether or not this group has opted to use FTP.
1304 * @return boolean uses_ftp.
1306 function usesFTP() {
1307 if (forge_get_config('use_ftp')) {
1308 return $this->data_array['use_ftp'];
1315 * usesSurvey - whether or not this group has opted to use surveys.
1317 * @return boolean uses_survey.
1319 function usesSurvey() {
1320 if (forge_get_config('use_survey')) {
1321 return $this->data_array['use_survey'];
1328 * usesPM - whether or not this group has opted to Project Manager.
1330 * @return boolean uses_projman.
1333 if (forge_get_config('use_pm')) {
1334 return $this->data_array['use_pm'];
1341 * setUsePM - Set the PM usage
1343 * @param boolean enabled/disabled
1345 function setUsePM ($booleanparam) {
1347 $booleanparam = $booleanparam ? 1 : 0 ;
1348 $res = db_query_params ('UPDATE groups SET use_pm=$1 WHERE group_id=$2',
1349 array ($booleanparam, $this->getID()));
1351 $this->data_array['use_pm']=$booleanparam;
1361 * getPlugins - get a list of all available group plugins
1363 * @return array array containing plugin_id => plugin_name
1365 function getPlugins() {
1366 if (!isset($this->plugins_data)) {
1367 $this->plugins_data = array();
1368 $res = db_query_params('SELECT group_plugin.plugin_id, plugins.plugin_name
1369 FROM group_plugin, plugins
1370 WHERE group_plugin.group_id=$1
1371 AND group_plugin.plugin_id=plugins.plugin_id', array($this->getID()));
1372 $rows = db_numrows($res);
1374 for ($i=0; $i<$rows; $i++) {
1375 $plugin_id = db_result($res, $i, 'plugin_id');
1376 $this->plugins_data[$plugin_id] = db_result($res, $i, 'plugin_name');
1379 return $this->plugins_data;
1383 * usesPlugin - returns true if the group uses a particular plugin
1385 * @param string name of the plugin
1386 * @return boolean whether plugin is being used or not
1388 function usesPlugin($pluginname) {
1389 $plugins_data = $this->getPlugins();
1390 foreach ($plugins_data as $p_id => $p_name) {
1391 if ($p_name == $pluginname) {
1399 * added for Codendi compatibility
1400 * usesServices - returns true if the group uses a particular plugin or feature
1402 * @param string name of the plugin
1403 * @return boolean whether plugin is being used or not
1405 function usesService($feature) {
1406 $plugins_data = $this->getPlugins();
1407 $pm = plugin_manager_get_object();
1408 foreach ($plugins_data as $p_id => $p_name) {
1409 if ($p_name == $feature) {
1412 if ($pm->getPluginByName($p_name)->provide($feature)) {
1420 * setPluginUse - enables/disables plugins for the group
1422 * @param string name of the plugin
1423 * @param boolean the new state
1424 * @return string database result
1426 function setPluginUse($pluginname, $val=true) {
1427 if ($val == $this->usesPlugin($pluginname)) {
1428 // State is already good, returning
1431 $res = db_query_params('SELECT plugin_id FROM plugins WHERE plugin_name=$1',
1432 array($pluginname));
1433 $rows = db_numrows($res);
1435 // Error: no plugin by that name
1438 $plugin_id = db_result($res,0,'plugin_id');
1440 unset($this->plugins_data);
1442 $res = db_query_params('INSERT INTO group_plugin (group_id, plugin_id) VALUES ($1, $2)',
1443 array($this->getID(),
1447 $res = db_query_params('DELETE FROM group_plugin WHERE group_id=$1 AND plugin_id=$2',
1448 array($this->getID(),
1455 * getDocEmailAddress - get email address(es) to send doc notifications to.
1457 * @return string email address.
1459 function getDocEmailAddress() {
1460 return $this->data_array['new_doc_address'];
1464 * DocEmailAll - whether or not this group has opted to use receive notices on all doc updates.
1466 * @return boolean email_on_all_doc_updates.
1468 function docEmailAll() {
1469 return $this->data_array['send_all_docs'];
1474 * getHomePage - The URL for this project's home page.
1476 * @return string homepage URL.
1478 function getHomePage() {
1479 return $this->data_array['homepage'];
1483 * getTags - Tags of this project.
1485 * @return string List of tags. Comma separated
1487 function getTags() {
1488 $sql = 'SELECT name FROM project_tags WHERE group_id = $1';
1489 $res = db_query_params($sql, array($this->getID()));
1490 return join(', ', util_result_column_to_array($res));
1494 * setTags - Set tags of this project.
1496 * @return string database result.
1498 function setTags($tags) {
1500 $sql = 'DELETE FROM project_tags WHERE group_id=$1';
1501 $res = db_query_params($sql, array($this->getID()));
1503 $this->setError('Deleting old tags: '.db_error());
1507 $inserted = array();
1508 $tags_array = preg_split('/[;,]/', $tags);
1509 foreach ($tags_array as $tag) {
1510 $tag = preg_replace('/[\t\r\n]/', ' ', $tag);
1511 // Allowed caracteres: [A-Z][a-z][0-9] -_&'#+.
1512 if (preg_match('/[^[:alnum:]| |\-|_|\&|\'|#|\+|\.]/', $tag)) {
1513 $this->setError(_('Bad tag name, you only can use the following characters: [A-Z][a-z][0-9]-_&\'#+. and space'));
1518 if ($tag == '' || array_search($tag, $inserted) !== false) continue;
1519 $sql = 'INSERT INTO project_tags (group_id,name) VALUES ($1, $2)';
1520 $res = db_query_params($sql, array($this->getID(), $tag));
1522 $this->setError(_('Setting tags: ').db_error());
1533 * getPermission - Return a Permission for this Group
1535 * @return object The Permission.
1537 function &getPermission() {
1538 return permission_get_object($this);
1542 function delete($sure, $really_sure, $really_really_sure) {
1543 if (!$sure || !$really_sure || !$really_really_sure) {
1544 $this->setMissingParamsError(_('Please tick all checkboxes.'));
1547 if ($this->getID() == forge_get_config('news_group') ||
1548 $this->getID() == 1 ||
1549 $this->getID() == forge_get_config('stats_group') ||
1550 $this->getID() == forge_get_config('peer_rating_group')) {
1551 $this->setError(_('Cannot Delete System Group'));
1554 $perm =& $this->getPermission();
1555 if (!$perm || !is_object($perm)) {
1556 $this->setPermissionDeniedError();
1558 } elseif ($perm->isError()) {
1559 $this->setPermissionDeniedError();
1561 } elseif (!$perm->isSuperUser()) {
1562 $this->setPermissionDeniedError();
1568 // Remove all the members
1570 $members =& $this->getMembers();
1571 foreach ($members as $i) {
1572 if(!$this->removeUser($i->getID())) {
1573 $this->setError(_('Could not properly remove member:').' '.$i->getID());
1577 // Failsafe until user_group table is gone
1578 $res = db_query_params('DELETE FROM user_group WHERE group_id=$1',
1579 array($this->getID()));
1581 // unlink roles to this project
1582 if ($this->isPublic()) {
1583 $ra = RoleAnonymous::getInstance();
1584 $rl = RoleLoggedIn::getInstance();
1585 $ra->unlinkProject($this);
1586 $rl->unlinkProject($this);
1588 // @todo : unlink all the other roles created in the project...
1593 $atf = new ArtifactTypeFactory($this);
1594 $at_arr =& $atf->getArtifactTypes();
1595 foreach ($at_arr as $i) {
1596 if (!is_object($i)) {
1599 if (!$i->delete(1,1)) {
1600 $this->setError(_('Could not properly delete the tracker:').' '.$i->getErrorMessage());
1607 $ff = new ForumFactory($this);
1608 $f_arr =& $ff->getForums();
1609 foreach ($f_arr as $i) {
1610 if (!is_object($i)) {
1613 if(!$i->delete(1,1)) {
1614 $this->setError(_('Could not properly delete the forum:').' '.$i->getErrorMessage());
1619 // Delete Subprojects
1621 $pgf = new ProjectGroupFactory($this);
1622 $pg_arr =& $pgf->getProjectGroups();
1623 foreach ($pg_arr as $i) {
1624 if (!is_object($i)) {
1627 if (!$i->delete(1,1)) {
1628 $this->setError(_('Could not properly delete the ProjectGroup:').' '.$i->getErrorMessage());
1633 // Delete FRS Packages
1635 $res = db_query_params('SELECT * FROM frs_package WHERE group_id=$1',
1636 array($this->getID()));
1637 while ($arr = db_fetch_array($res)) {
1638 $frsp=new FRSPackage($this, $arr['package_id'], $arr);
1639 if (!$frsp->delete(1, 1)) {
1640 $this->setError(_('Could not properly delete the FRSPackage:').' '.$frsp->getErrorMessage());
1647 $news_group=group_get_object(forge_get_config('news_group'));
1648 $res = db_query_params('SELECT forum_id FROM news_bytes WHERE group_id=$1',
1649 array($this->getID()));
1651 $this->setError(_('Error Deleting News: ').db_error());
1656 for ($i=0; $i<db_numrows($res); $i++) {
1657 $Forum = new Forum($news_group,db_result($res,$i,'forum_id'));
1658 if (!$Forum->delete(1,1)) {
1659 $this->setError(_("Could Not Delete News Forum: %d"),$Forum->getID());
1663 $res = db_query_params('DELETE FROM news_bytes WHERE group_id=$1',
1664 array($this->getID()));
1666 $this->setError(_('Error Deleting News: ').db_error());
1674 $res = db_query_params('DELETE FROM doc_data WHERE group_id=$1',
1675 array($this->getID()));
1677 $this->setError(_('Error Deleting Documents: ').db_error());
1682 $res = db_query_params('DELETE FROM doc_groups WHERE group_id=$1',
1683 array($this->getID()));
1685 $this->setError(_('Error Deleting Documents: ').db_error());
1693 $res=db_query_params('DELETE FROM project_tags WHERE group_id=$1', array($this->getID()));
1695 $this->setError(_('Error Deleting Tags: ').db_error());
1701 // Delete group history
1703 $res = db_query_params('DELETE FROM group_history WHERE group_id=$1',
1704 array($this->getID()));
1706 $this->setError(_('Error Deleting Project History: ').db_error());
1712 // Delete group plugins
1714 $res = db_query_params('DELETE FROM group_plugin WHERE group_id=$1',
1715 array($this->getID()));
1717 $this->setError(_('Error Deleting Project Plugins: ').db_error());
1723 // Delete group cvs stats
1725 $res = db_query_params ('DELETE FROM stats_cvs_group WHERE group_id=$1',
1726 array ($this->getID())) ;
1728 $this->setError(_('Error Deleting SCM Statistics: ').db_error());
1736 $sf = new SurveyFactory($this);
1737 $s_arr =& $sf->getSurveys();
1738 foreach ($s_arr as $i) {
1739 if (!is_object($i)) {
1742 if (!$i->delete()) {
1743 $this->setError(_('Could not properly delete the survey'));
1748 // Delete SurveyQuestions
1750 $sqf = new SurveyQuestionFactory($this);
1751 $sq_arr =& $sqf->getSurveyQuestions();
1752 foreach ($sq_arr as $i) {
1753 if (!is_object($i)) {
1756 if (!$i->delete()) {
1757 $this->setError(_('Could not properly delete the survey questions'));
1762 // Delete Mailing List Factory
1764 $mlf = new MailingListFactory($this);
1765 $ml_arr =& $mlf->getMailingLists();
1766 foreach ($ml_arr as $i) {
1767 if (!is_object($i)) {
1770 if (!$i->delete(1,1)) {
1771 $this->setError(_('Could not properly delete the mailing list'));
1778 $res = db_query_params('DELETE FROM trove_group_link WHERE group_id=$1',
1779 array($this->getID()));
1781 $this->setError(_('Error Deleting Trove: ').db_error());
1786 $res = db_query_params('DELETE FROM trove_agg WHERE group_id=$1',
1787 array($this->getID()));
1789 $this->setError(_('Error Deleting Trove: ').db_error());
1797 $res = db_query_params('DELETE FROM project_sums_agg WHERE group_id=$1',
1798 array($this->getID()));
1800 $this->setError(_('Error Deleting Counters: ').db_error());
1805 $res = db_query_params('INSERT INTO deleted_groups (unix_group_name, delete_date, isdeleted) VALUES ($1, $2, $3)',
1806 array($this->getUnixName(),
1810 $this->setError(_('Error Deleting Project:').' '.db_error());
1815 $res = db_query_params('DELETE FROM groups WHERE group_id=$1',
1816 array($this->getID()));
1818 $this->setError(_('Error Deleting Project:').' '.db_error());
1825 $hook_params = array();
1826 $hook_params['group'] = $this;
1827 $hook_params['group_id'] = $this->getID();
1828 plugin_hook("group_delete", $hook_params);
1830 if (forge_get_config('upload_dir') != '' && $this->getUnixName()) {
1831 exec('/bin/rm -rf '.forge_get_config('upload_dir').'/'.$this->getUnixName().'/');
1833 if (forge_get_config('ftp_upload_dir') != '' && $this->getUnixName()) {
1834 exec('/bin/rm -rf '.forge_get_config('ftp_upload_dir').'/'.$this->getUnixName().'/');
1839 $res = db_query_params('DELETE FROM rep_group_act_monthly WHERE group_id=$1',
1840 array ($this->getID()));
1841 //echo 'rep_group_act_monthly'.db_error();
1842 $res = db_query_params('DELETE FROM rep_group_act_weekly WHERE group_id=$1',
1843 array ($this->getID()));
1844 //echo 'rep_group_act_weekly'.db_error();
1845 $res = db_query_params('DELETE FROM rep_group_act_daily WHERE group_id=$1',
1846 array ($this->getID()));
1847 //echo 'rep_group_act_daily'.db_error();
1848 unset($this->data_array);
1854 Basic functions to add/remove users to/from a group
1855 and update their permissions
1859 * addUser - controls adding a user to a group.
1861 * @param string Unix name of the user to add OR integer user_id.
1862 * @param int The role_id this user should have.
1863 * @return boolean success.
1866 function addUser($user_identifier,$role_id) {
1869 Admins can add users to groups
1872 if (!forge_check_perm ('project_admin', $this->getID())) {
1873 $this->setPermissionDeniedError();
1879 get user id for this user's unix_name
1881 if (is_int ($user_identifier)) { // user_id or user_name
1882 $res_newuser = db_query_params ('SELECT * FROM users WHERE user_id=$1', array ($user_identifier)) ;
1884 $res_newuser = db_query_params ('SELECT * FROM users WHERE user_name=$1', array ($user_identifier)) ;
1886 if (db_numrows($res_newuser) > 0) {
1888 // make sure user is active
1890 if (db_result($res_newuser,0,'status') != 'A') {
1891 $this->setError(_('User is not active. Only active users can be added.'));
1897 // user was found - set new user_id var
1899 $user_id = db_result($res_newuser,0,'user_id');
1901 $role = new Role($this,$role_id);
1902 if (!$role || !is_object($role)) {
1903 $this->setError(_('Error Getting Role Object'));
1906 } elseif ($role->isError()) {
1907 $this->setError('addUser::roleget::'.$role->getErrorMessage());
1913 $role->addUser(user_get_object ($user_id)) ;
1914 if (!$SYS->sysCheckCreateGroup($this->getID())){
1915 $this->setError($SYS->getErrorMessage());
1919 if (!$SYS->sysCheckCreateUser($user_id)) {
1920 $this->setError($SYS->getErrorMessage());
1927 // if not already a member, add them
1929 $res_member = db_query_params('SELECT user_id
1931 WHERE user_id=$1 AND group_id=$2',
1932 array($user_id, $this->getID()));
1934 if (db_numrows($res_member) < 1) {
1936 // Create this user's row in the user_group table
1938 $res = db_query_params('INSERT INTO user_group
1939 (user_id,group_id,admin_flags,forum_flags,project_flags,
1940 doc_flags,cvs_flags,member_role,release_flags,artifact_flags)
1941 VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)',
1953 //verify the insert worked
1954 if (!$res || db_affected_rows($res) < 1) {
1955 $this->setError(sprintf(_('ERROR: Could Not Add User To Group: %s'),db_error()));
1960 // check and create if group doesn't exists
1962 //echo "<h2>Group::addUser SYS->sysCheckCreateGroup(".$this->getID().")</h2>";
1963 if (!$SYS->sysCheckCreateGroup($this->getID())){
1964 $this->setError($SYS->getErrorMessage());
1969 // check and create if user doesn't exists
1971 //echo "<h2>Group::addUser SYS->sysCheckCreateUser($user_id)</h2>";
1972 if (!$SYS->sysCheckCreateUser($user_id)) {
1973 $this->setError($SYS->getErrorMessage());
1980 //echo "<h2>Group::addUser role->setUser($user_id)</h2>";
1981 if (!$role->setUser($user_id)) {
1982 $this->setError('addUser::role::setUser'.$role->getErrorMessage());
1988 // user was already a member
1989 // make sure they are set up
1991 $user= user_get_object($user_id,$res_newuser);
1992 $user->fetchData($user->getID());
1993 $role = new Role($this,$role_id);
1994 if (!$role || !is_object($role)) {
1995 $this->setError(_('Error Getting Role Object'));
1998 } elseif ($role->isError()) {
1999 $this->setError('addUser::roleget::'.$role->getErrorMessage());
2003 //echo "<h2>Already Member Group::addUser role->setUser($user_id)</h2>";
2004 if (!$role->setUser($user_id)) {
2005 $this->setError('addUser::role::setUser'.$role->getErrorMessage());
2010 // set up their system info
2012 //echo "<h2>Already Member Group::addUser SYS->sysCheckCreateUser($user_id)</h2>";
2013 if (!$SYS->sysCheckCreateUser($user_id)) {
2014 $this->setError($SYS->getErrorMessage());
2022 // user doesn't exist
2024 $this->setError(_('ERROR: User does not exist'));
2029 $hook_params['group'] = $this;
2030 $hook_params['group_id'] = $this->getID();
2031 $hook_params['user'] = &user_get_object($user_id);
2032 $hook_params['user_id'] = $user_id;
2033 plugin_hook ("group_adduser", $hook_params);
2038 $this->addHistory('Added User',$user_identifier);
2044 * removeUser - controls removing a user from a group.
2046 * Users can remove themselves.
2048 * @param int The ID of the user to remove.
2049 * @return boolean success.
2051 function removeUser($user_id) {
2054 if ($user_id != user_getid()
2055 || !forge_check_perm('project_admin', $this->getID())) {
2056 $this->setPermissionDeniedError();
2063 $user = user_get_object($user_id);
2064 $roles = RBACEngine::getInstance()->getAvailableRolesForUser($user);
2066 foreach ($roles as $role) {
2067 if ($role->getHomeProject() && $role->getHomeProject()->getID() == $this->getID()) {
2068 $found_role = $role;
2072 if ($found_role == NULL) {
2073 $this->setError(sprintf(_('ERROR: User not removed: %s')));
2077 $found_role->removeUser($user);
2078 if (!$SYS->sysGroupCheckUser($this->getID(), $user_id)) {
2079 $this->setError($SYS->getErrorMessage());
2085 $res = db_query_params('DELETE FROM user_group WHERE group_id=$1 AND user_id=$2',
2086 array($this->getID(),
2088 if (!$res || db_affected_rows($res) < 1) {
2089 $this->setError(_('ERROR: User not removed:').' '.db_error());
2096 // reassign open artifacts to id=100
2098 $res = db_query_params('UPDATE artifact SET assigned_to=100
2099 WHERE group_artifact_id
2100 IN (SELECT group_artifact_id
2101 FROM artifact_group_list
2102 WHERE group_id=$1 AND status_id=1 AND assigned_to=$2)',
2103 array($this->getID(),
2106 $this->setError(_('ERROR: DB: artifact:').' '.db_error());
2112 // reassign open tasks to id=100
2113 // first have to purge any assignments that would cause
2114 // conflict with existing assignment to 100
2116 $res = db_query_params('DELETE FROM project_assigned_to
2117 WHERE project_task_id IN (SELECT pt.project_task_id
2118 FROM project_task pt, project_group_list pgl, project_assigned_to pat
2119 WHERE pt.group_project_id = pgl.group_project_id
2120 AND pat.project_task_id=pt.project_task_id
2121 AND pt.status_id=1 AND pgl.group_id=$1
2122 AND pat.assigned_to_id=$2)
2123 AND assigned_to_id=100',
2124 array($this->getID(),
2127 $this->setError(sprintf(_('ERROR: DB: project_assigned_to %d: %s'), 1, db_error()));
2131 $res = db_query_params('UPDATE project_assigned_to SET assigned_to_id=100
2132 WHERE project_task_id IN (SELECT pt.project_task_id
2133 FROM project_task pt, project_group_list pgl
2134 WHERE pt.group_project_id = pgl.group_project_id
2135 AND pt.status_id=1 AND pgl.group_id=$1)
2136 AND assigned_to_id=$2',
2137 array($this->getID(),
2140 $this->setError(sprintf(_('ERROR: DB: project_assigned_to %d: %s'), 2, db_error()));
2146 // Remove user from system
2148 if (!$SYS->sysGroupRemoveUser($this->getID(), $user_id)) {
2149 $this->setError($SYS->getErrorMessage());
2154 $hook_params['group'] = $this;
2155 $hook_params['group_id'] = $this->getID();
2156 $hook_params['user'] = user_get_object($user_id);
2157 $hook_params['user_id'] = $user_id;
2158 plugin_hook ("group_removeuser", $hook_params);
2161 $this->addHistory('Removed User',$user_id);
2168 * updateUser - controls updating a user's role in this group.
2170 * @param int The ID of the user.
2171 * @param int The role_id to set this user to.
2172 * @return boolean success.
2174 function updateUser($user_id,$role_id) {
2177 if (!forge_check_perm ('project_admin', $this->getID())) {
2178 $this->setPermissionDeniedError();
2183 $newrole = RBACEngine::getInstance()->getRoleById ($role_id) ;
2184 if (!$newrole || !is_object($newrole)) {
2185 $this->setError(_('Could Not Get Role'));
2187 } elseif ($newrole->isError()) {
2188 $this->setError(sprintf(_('Role: %s'),$role->getErrorMessage()));
2190 } elseif ($newrole->getHomeProject() == NULL
2191 || $newrole->getHomeProject()->getID() != $this->getID()) {
2192 $this->setError(_('Wrong destination role'));
2195 $user = user_get_object ($user_id) ;
2196 $roles = RBACEngine::getInstance()->getAvailableRolesForUser ($user) ;
2197 $found_role = NULL ;
2198 foreach ($roles as $role) {
2199 if ($role->getHomeProject() && $role->getHomeProject()->getID() == $this->getID()) {
2200 $found_role = $role ;
2204 if ($found_role == NULL) {
2205 $this->setError(sprintf(_('ERROR: User not removed: %s')));
2209 $found_role->removeUser ($user) ;
2210 $newrole->addUser ($user) ;
2212 $role = new Role($this,$role_id);
2213 if (!$role || !is_object($role)) {
2214 $this->setError(_('Could Not Get Role'));
2216 } elseif ($role->isError()) {
2217 $this->setError(sprintf(_('Role: %s'),$role->getErrorMessage()));
2220 //echo "<h3>Group::updateUser role->setUser($user_id)</h3>";
2221 if (!$role->setUser($user_id)) {
2222 $this->setError(sprintf(_('Role: %s'),$role->getErrorMessage()));
2227 $this->addHistory('Updated User',$user_id);
2232 * addHistory - Makes an audit trail entry for this project.
2234 * @param string The name of the field.
2235 * @param string The Old Value for this $field_name.
2236 * @return database result handle.
2239 function addHistory($field_name, $old_value) {
2240 return db_query_params ('INSERT INTO group_history(group_id,field_name,old_value,mod_by,adddate)
2241 VALUES ($1,$2,$3,$4,$5)',
2242 array ($this->getID(),
2250 * activateUsers - Make sure that group members have unix accounts.
2252 * Setup unix accounts for group members. Can be called even
2253 * if members are already active.
2257 function activateUsers() {
2259 Activate member(s) of the project
2263 $members = $this->getUsers (true) ;
2265 foreach ($members as $member) {
2267 foreach (RBACEngine::getInstance()->getAvailableRolesForUser ($member) as $role) {
2268 if ($role->getHomeProject() && $role->getHomeProject()->getID() == $this->getID()) {
2271 if (!$this->addUser($member->getUnixName(),$role->getID())) {
2278 $res_member = db_query_params('SELECT user_id,role_id FROM user_group WHERE group_id=$1',
2279 array ($this->getID()));
2280 while ($row_member = db_fetch_array($res_member)) {
2281 $u = user_get_object($row_member['user_id']);
2282 if (!$this->addUser($u->getUnixName(),$row_member['role_id'])) {
2292 * getMembers - returns array of User objects for this project
2294 * @return array of User objects for this group.
2296 function getMembers() {
2297 return $this->getUsers (true) ;
2301 * replaceTemplateStrings - fill-in some blanks with project name
2303 * @param string Template string
2304 * @return string String after replacements
2306 function replaceTemplateStrings($string) {
2307 $string = str_replace ('UNIXNAME', $this->getUnixName(), $string) ;
2308 $string = str_replace ('PUBLICNAME', $this->getPublicName(), $string) ;
2309 $string = str_replace ('DESCRIPTION', $this->getDescription(), $string) ;
2314 * approve - Approve pending project.
2316 * @param object The User object who is doing the updating.
2319 function approve(&$user) {
2321 require_once $gfcommon.'widget/WidgetLayoutManager.class.php';
2323 if ($this->getStatus()=='A') {
2324 $this->setError(_("Group already active"));
2330 // Step 1: Activate group and create LDAP entries
2331 if (!$this->setStatus($user, 'A')) {
2336 // Switch to system language for item creation
2337 setup_gettext_from_sys_lang ();
2339 // Create default roles
2341 $idadmin_group = NULL ;
2342 foreach (get_group_join_requests ($this) as $gjr) {
2343 $idadmin_group = $gjr->getUserID() ;
2346 if ($idadmin_group == NULL) {
2347 $idadmin_group = $user->getID();
2350 $admin_group = db_query_params ('SELECT user_id FROM user_group WHERE group_id=$1 AND admin_flags=$2',
2351 array ($this->getID(),
2353 if (db_numrows($admin_group) > 0) {
2354 $idadmin_group = db_result($admin_group,0,'user_id');
2356 $idadmin_group = $user->getID();
2357 db_query_params ('INSERT INTO user_group (user_id, group_id, admin_flags) VALUES ($1, $2, $3)',
2358 array ($idadmin_group,
2364 $template = $this->getTemplateProject() ;
2365 $id_mappings = array ();
2366 $seen_local_roles = false ;
2368 // Copy roles from template project
2369 foreach ($template->getRoles() as $oldrole) {
2370 if ($oldrole->getHomeProject() != NULL) {
2371 $role = new Role ($this) ;
2373 // Need to use a different role name so that the permissions aren't set from the hardcoded defaults
2374 $role->create ('TEMPORARY ROLE NAME', $data, true) ;
2375 $role->setName ($oldrole->getName()) ;
2376 $seen_local_roles = true ;
2379 $role->linkProject ($this) ;
2381 $id_mappings['role'][$oldrole->getID()] = $role->getID() ;
2382 // Reuse the project_admin permission
2383 $role->setSetting ('project_admin', $this->getID(), $oldrole->getSetting ('project_admin', $template->getID())) ;
2387 if (!$seen_local_roles) {
2388 $role = new Role($this);
2389 $adminperms = array ('project_admin' => array ($this->getID() => 1)) ;
2390 $role_id = $role->create ('Admin', $adminperms, true) ;
2394 $roles = $this->getRoles() ;
2395 foreach ($roles as $r) {
2396 if ($r->getSetting ('project_admin', $this->getID())) {
2397 $r->addUser (user_get_object ($idadmin_group)) ;
2402 // Temporarily switch to the submitter's identity
2403 $saved_session = session_get_user () ;
2404 session_set_internal ($idadmin_group) ;
2407 if (forge_get_config ('use_tracker')) {
2408 $this->setUseTracker ($template->usesTracker()) ;
2409 if ($template->usesTracker()) {
2410 $oldatf = new ArtifactTypeFactory ($template) ;
2411 foreach ($oldatf->getArtifactTypes() as $o) {
2412 $t = new ArtifactType ($this) ;
2413 $t->create ($this->replaceTemplateStrings($o->getName()),$this->replaceTemplateStrings($o->getDescription()),$o->isPublic(),$o->allowsAnon(),$o->emailAll(),$o->getEmailAddress(),$o->getDuePeriod()/86400,0,$o->getSubmitInstructions(),$o->getBrowseInstructions()) ;
2414 $id_mappings['tracker'][$o->getID()] = $t->getID() ;
2415 $t->cloneFieldsFrom ($o->getID()) ;
2420 if (forge_get_config ('use_pm')) {
2421 $this->setUsePM ($template->usesPM()) ;
2422 if ($template->usesPM()) {
2423 $oldpgf = new ProjectGroupFactory ($template) ;
2424 foreach ($oldpgf->getProjectGroups() as $o) {
2425 $pg = new ProjectGroup ($this) ;
2426 $pg->create ($this->replaceTemplateStrings($o->getName()),$this->replaceTemplateStrings($o->getDescription()),$o->isPublic(),$o->getSendAllPostsTo()) ;
2427 $id_mappings['pm'][$o->getID()] = $pg->getID() ;
2432 if (forge_get_config ('use_forum')) {
2433 $this->setUseForum ($template->usesForum()) ;
2434 if ($template->usesForum()) {
2435 $oldff = new ForumFactory ($template) ;
2436 foreach ($oldff->getForums() as $o) {
2437 $f = new Forum ($this) ;
2438 $f->create ($this->replaceTemplateStrings($o->getName()),$this->replaceTemplateStrings($o->getDescription()),$o->isPublic(),$o->getSendAllPostsTo(),1,$o->allowAnonymous(),$o->getModerationLevel()) ;
2439 $id_mappings['forum'][$o->getID()] = $f->getID() ;
2444 if (forge_get_config ('use_docman')) {
2445 $this->setUseDocman ($template->usesDocman()) ;
2446 if ($template->usesDocman()) {
2447 $olddgf = new DocumentGroupFactory ($template) ;
2448 // First pass: create all docgroups
2449 $id_mappings['docman_docgroup'][0] = 0 ;
2450 foreach ($olddgf->getDocumentGroups() as $o) {
2451 $ndgf = new DocumentGroup ($this) ;
2452 $ndgf->create($this->replaceTemplateStrings($o->getName())) ;
2453 $id_mappings['docman_docgroup'][$o->getID()] = $ndgf->getID() ;
2455 // Second pass: restore hierarchy links
2456 foreach ($olddgf->getDocumentGroups() as $o) {
2457 $ndgf = new DocumentGroup ($this) ;
2458 $ndgf->fetchData ($id_mappings['docman_docgroup'][$o->getID()]) ;
2459 $ndgf->update ($ndgf->getName(),$id_mappings['docman_docgroup'][$o->getParentID()]) ;
2464 if (forge_get_config ('use_frs')) {
2465 $this->setUseFRS ($template->usesFRS()) ;
2466 if ($template->usesFRS()) {
2467 foreach (get_frs_packages ($template) as $o) {
2468 $newp = new FRSPackage ($this) ;
2469 $nname = $this->replaceTemplateStrings($o->getName()) ;
2470 $newp->create ($nname, $o->isPublic()) ;
2475 if (forge_get_config ('use_mail')) {
2476 $this->setUseMail ($template->usesMail()) ;
2477 if ($template->usesMail()) {
2478 $oldmlf = new MailingListFactory ($template) ;
2479 foreach ($oldmlf->getMailingLists() as $o) {
2480 $ml = new MailingList ($this) ;
2481 $nname = preg_replace ('/^'.$template->getUnixName().'-/','',$o->getName()) ;
2483 $ndescription = $this->replaceTemplateStrings($o->getDescription()) ;
2484 $ml->create ($nname, $ndescription, $o->isPublic()) ;
2489 $this->setUseSCM ($template->usesSCM()) ;
2491 foreach ($template->getPlugins() as $plugin_id => $plugin_name) {
2492 $this->setPluginUse ($plugin_name) ;
2495 foreach ($template->getRoles() as $oldrole) {
2496 $newrole = RBACEngine::getInstance()->getRoleById ($id_mappings['role'][$oldrole->getID()]) ;
2497 if ($oldrole->getHomeProject() != NULL
2498 && $oldrole->getHomeProject()->getID() == $template->getID()) {
2499 $newrole->setPublic ($oldrole->isPublic()) ;
2501 $oldsettings = $oldrole->getSettingsForProject ($template) ;
2503 $sections = array ('project_read', 'project_admin', 'frs', 'scm', 'docman', 'tracker_admin', 'new_tracker', 'forum_admin', 'new_forum', 'pm_admin', 'new_pm') ;
2504 foreach ($sections as $section) {
2505 $newrole->setSetting ($section, $this->getID(), $oldsettings[$section][$template->getID()]) ;
2508 $sections = array ('tracker', 'pm', 'forum') ;
2509 foreach ($sections as $section) {
2510 if (isset ($oldsettings[$section])) {
2511 foreach ($oldsettings[$section] as $k => $v) {
2512 // Only copy perms for tools that have been copied
2513 if (isset ($id_mappings[$section][$k])) {
2514 $newrole->setSetting ($section,
2515 $id_mappings[$section][$k],
2523 $lm = new WidgetLayoutManager();
2524 $lm->createDefaultLayoutForProject ($this->getID(), $template->getID()) ;
2526 $params = array () ;
2527 $params['template'] = $template ;
2528 $params['project'] = $this ;
2529 $params['id_mappings'] = $id_mappings ;
2530 plugin_hook_by_reference ('clone_project_from_template', $params) ;
2532 // Disable everything
2533 $res = db_query_params ('UPDATE groups SET use_mail=0, use_survey=0, use_forum=0, use_pm=0, use_pm_depend_box=0, use_scm=0, use_news=0, use_docman=0, is_public=0, use_ftp=0, use_tracker=0, use_frs=0, use_stats=0 WHERE group_id=$1',
2535 array ($this->getID())) ;
2538 $this->normalizeAllRoles();
2540 // Switch back to user preference
2541 session_set_internal($saved_session->getID());
2542 setup_gettext_from_context();
2546 $this->sendApprovalEmail();
2547 $this->addHistory('Approved', 'x');
2550 // Plugin can make approve operation there
2552 $params[0] = $idadmin_group;
2553 $params[1] = $this->getID();
2554 plugin_hook('group_approved', $params);
2562 * sendApprovalEmail - Send new project email.
2564 * @return boolean success.
2567 function sendApprovalEmail() {
2568 $admins = RBACEngine::getInstance()->getUsersByAllowedAction ('project_admin', $this->getID()) ;
2570 if (count($admins) < 1) {
2571 $this->setError(_("Group does not have any administrators."));
2575 // send one email per admin
2576 foreach ($admins as $admin) {
2577 setup_gettext_for_user ($admin) ;
2579 $message=sprintf(_('Your project registration for %4$s has been approved.
2581 Project Full Name: %1$s
2582 Project Unix Name: %2$s
2584 Your DNS will take up to a day to become active on our site.
2585 Your web site is accessible through your shell account. Please read
2586 site documentation (see link below) about intended usage, available
2587 services, and directory layout of the account.
2590 own project page in %4$s while logged in, you will find
2591 additional menu functions to your left labeled \'Project Admin\'.
2593 We highly suggest that you now visit %4$s and create a public
2594 description for your project. This can be done by visiting your project
2595 page while logged in, and selecting \'Project Admin\' from the menus
2596 on the left (or by visiting %3$s
2599 Your project will also not appear in the Trove Software Map (primary
2600 list of projects hosted on %4$s which offers great flexibility in
2601 browsing and search) until you categorize it in the project administration
2602 screens. So that people can find your project, you should do this now.
2603 Visit your project while logged in, and select \'Project Admin\' from the
2606 Enjoy the system, and please tell others about %4$s. Let us know
2607 if there is anything we can do to help you.
2610 htmlspecialchars_decode($this->getPublicName()),
2611 $this->getUnixName(),
2612 util_make_url ('/project/admin/?group_id='.$this->getID()),
2613 forge_get_config ('forge_name'));
2615 util_send_message($admin->getEmail(), sprintf(_('%1$s Project Approved'), forge_get_config ('forge_name')), $message);
2617 setup_gettext_from_context();
2625 * sendRejectionEmail - Send project rejection email.
2627 * This function sends out a rejection message to a user who
2628 * registered a project.
2630 * @param int The id of the response to use.
2631 * @param string The rejection message.
2632 * @return boolean completion status.
2635 function sendRejectionEmail($response_id, $message="zxcv") {
2636 $submitters = array () ;
2638 foreach (get_group_join_requests ($this) as $gjr) {
2639 $submitters[] = user_get_object($gjr->getUserID());
2642 $res = db_query_params("SELECT u.user_id FROM users u, user_group ug WHERE ug.group_id=$1 AND u.user_id=ug.user_id",
2644 while ($arr = db_fetch_array($res)) {
2645 $submitter[] = user_get_object($arr['user_id']);
2649 if (count ($submitters) < 1) {
2650 $this->setError(_("Group does not have any administrators."));
2654 foreach ($submitters as $admin) {
2655 setup_gettext_for_user($admin);
2657 $response=sprintf(_('Your project registration for %3$s has been denied.
2659 Project Full Name: %1$s
2660 Project Unix Name: %2$s
2662 Reasons for negative decision:
2664 '), $this->getPublicName(), $this->getUnixName(), forge_get_config('forge_name'));
2666 // Check to see if they want to send a custom rejection response
2667 if ($response_id == 0) {
2668 $response .= $message;
2670 $response .= db_result(
2671 db_query_params('SELECT response_text FROM canned_responses WHERE response_id=$1', array ($response_id)),
2676 util_send_message($admin->getEmail(), sprintf(_('%1$s Project Denied'), forge_get_config ('forge_name')), $response);
2677 setup_gettext_from_context();
2684 * sendNewProjectNotificationEmail - Send new project notification email.
2686 * This function sends out a notification email to the
2687 * SourceForge admin user when a new project is
2690 * @return boolean success.
2693 function sendNewProjectNotificationEmail() {
2694 // Get the user who wants to register the project
2695 $submitters = array();
2697 foreach (get_group_join_requests ($this) as $gjr) {
2698 $submitters[] = user_get_object($gjr->getUserID());
2701 $res = db_query_params("SELECT u.user_id FROM users u, user_group ug WHERE ug.group_id=$1 AND u.user_id=ug.user_id",
2703 while ($arr = db_fetch_array ($res)) {
2704 $submitter[] = user_get_object($arr['user_id']);
2707 if (count ($submitters) < 1) {
2708 $this->setError(_("Could not find user who has submitted the project."));
2712 $admins = RBACEngine::getInstance()->getUsersByAllowedAction ('approve_projects', -1) ;
2714 if (count($admins) < 1) {
2715 $this->setError(_("There is no administrator to send the mail to."));
2719 foreach ($admins as $admin) {
2720 $admin_email = $admin->getEmail () ;
2721 setup_gettext_for_user ($admin) ;
2723 foreach ($submitters as $u) {
2724 $submitter_names[] = $u->getRealName() ;
2727 $message = sprintf(_('New %1$s Project Submitted
2729 Project Full Name: %2$s
2730 Submitted Description: %3$s
2732 forge_get_config ('forge_name'),
2733 htmlspecialchars_decode($this->getPublicName()),
2734 htmlspecialchars_decode($this->getRegistrationPurpose()));
2736 foreach ($submitters as $submitter) {
2737 $message .= sprintf(_('Submitter: %1$s (%2$s)
2739 $submitter->getRealName(),
2740 $submitter->getUnixName());
2743 $message .= sprintf (_('
2744 Please visit the following URL to approve or reject this project:
2746 util_make_url ('/admin/approve-pending.php')) ;
2747 util_send_message($admin_email, sprintf(_('New %1$s Project Submitted'), forge_get_config ('forge_name')), $message);
2748 setup_gettext_from_context();
2752 $email = $submitter->getEmail() ;
2753 setup_gettext_for_user ($submitter) ;
2755 $message=sprintf(_('New %1$s Project Submitted
2757 Project Full Name: %2$s
2758 Submitted Description: %3$s
2760 The %1$s admin team will now examine your project submission. You will be notified of their decision.'), forge_get_config ('forge_name'), $this->getPublicName(), util_unconvert_htmlspecialchars($this->getRegistrationPurpose()), forge_get_config('web_host'));
2762 util_send_message($email, sprintf(_('New %1$s Project Submitted'), forge_get_config ('forge_name')), $message);
2763 setup_gettext_from_context();
2772 * validateGroupName - Validate the group name
2774 * @param string Group name.
2776 * @return boolean an error false and set an error is the group name is invalide otherwise return true
2778 function validateGroupName($group_name) {
2779 if (strlen($group_name)<3) {
2780 $this->setError(_('Group name is too short'));
2782 } else if (strlen(htmlspecialchars($group_name))>50) {
2783 $this->setError(_('Group name is too long'));
2785 } else if ($group=group_get_object_by_publicname($group_name)) {
2786 $this->setError(_('Group name already taken'));
2794 * getRoles - Get the roles of the group.
2796 * @return array Role ids of this group.
2798 function getRolesId() {
2799 $role_ids = array();
2802 $res = db_query_params('SELECT role_id FROM pfo_role WHERE home_group_id=$1',
2803 array($this->getID()));
2804 while ($arr = db_fetch_array($res)) {
2805 $role_ids[] = $arr['role_id'];
2807 $res = db_query_params('SELECT role_id FROM role_project_refs WHERE group_id=$1',
2808 array($this->getID()));
2809 while ($arr = db_fetch_array($res)) {
2810 $role_ids[] = $arr['role_id'];
2813 $res = db_query_params('SELECT role_id FROM role WHERE group_id=$1',
2814 array($this->getID()));
2815 while ($arr = db_fetch_array($res)) {
2816 $role_ids[] = $arr['role_id'];
2820 return array_unique($role_ids);
2824 * getRoles - Get the roles of the group.
2826 * @return array Roles of this group.
2828 function getRoles() {
2831 $roles = $this->getRolesId();
2833 $engine = RBACEngine::getInstance();
2834 foreach ($roles as $role_id) {
2835 $result[] = $engine->getRoleById ($role_id);
2838 foreach ($roles as $role_id) {
2839 $result[] = new Role ($this, $role_id);
2846 function normalizeAllRoles() {
2847 $roles = $this->getRoles();
2849 foreach ($roles as $r) {
2850 $r->normalizeData();
2855 * getUnixStatus - Status of activation of unix account.
2857 * @return char (N)one, (A)ctive, (S)uspended or (D)eleted
2859 function getUnixStatus() {
2860 return $this->data_array['unix_status'];
2864 * setUnixStatus - Sets status of activation of unix account.
2866 * @param string The unix status.
2872 * @return boolean success.
2874 function setUnixStatus($status) {
2877 $res = db_query_params ('UPDATE groups SET unix_status=$1 WHERE group_id=$2',
2882 $this->setError(sprintf(_('ERROR - Could Not Update Group Unix Status: %s'),db_error()));
2886 if ($status == 'A') {
2887 if (!$SYS->sysCheckCreateGroup($this->getID())) {
2888 $this->setError($SYS->getErrorMessage());
2893 if ($SYS->sysCheckGroup($this->getID())) {
2894 if (!$SYS->sysRemoveGroup($this->getID())) {
2895 $this->setError($SYS->getErrorMessage());
2902 $this->data_array['unix_status']=$status;
2909 * getUsers - Get the users of a group
2911 * @return array of user's objects.
2913 function getUsers($onlylocal = true) {
2914 if (!isset($this->membersArr)) {
2915 $this->membersArr = array () ;
2919 foreach ($this->getRoles() as $role) {
2921 && ($role->getHomeProject() == NULL || $role->getHomeProject()->getID() != $this->getID())) {
2924 foreach ($role->getUsers() as $user) {
2925 $ids[] = $user->getID() ;
2928 $ids = array_unique ($ids) ;
2929 foreach ($ids as $id) {
2930 $u = user_get_object ($id) ;
2931 if ($u->isActive()) {
2932 $this->membersArr[] = $u ;
2937 $users_group_res = db_query_params ('SELECT u.user_id FROM users u, user_group ug WHERE ug.group_id=$1 AND ug.user_id=u.user_id AND u.status=$2',
2938 array ($this->getID(),
2940 if (!$users_group_res) {
2941 $this->setError(_('Error: Enable to get users from group'). ' ' . $this->getID() . ' ' .db_error());
2945 for ($i=0; $i<db_numrows($users_group_res); $i++) {
2946 $this->membersArr[$i] = new GFUser(db_result($users_group_res,$i,'user_id'),false);
2951 return $this->membersArr;
2954 function setDocmanCreateOnlineStatus($status) {
2956 /* if we activate search engine, we probably want to reindex */
2957 $res = db_query_params('UPDATE groups SET use_docman_create_online=$1 WHERE group_id=$2',
2958 array($status, $this->getID()));
2961 $this->setError(sprintf(_('ERROR - Could Not Update Group DocmanCreateOnline Status: %s'),db_error()));
2965 $this->data_array['use_docman_create_online']=$status;
2971 function setDocmanWebdav($status) {
2973 /* if we activate search engine, we probably want to reindex */
2974 $res = db_query_params('UPDATE groups SET use_webdav=$1 WHERE group_id=$2',
2979 $this->setError(sprintf(_('ERROR - Could Not Update Group UseWebdab Status: %s'),db_error()));
2983 $this->data_array['use_webdav']=$status;
2989 function setDocmanSearchStatus($status) {
2991 /* if we activate search engine, we probably want to reindex */
2992 $res = db_query_params('UPDATE groups SET use_docman_search=$1, force_docman_reindex=$1 WHERE group_id=$2',
2997 $this->setError(sprintf(_('ERROR - Could Not Update Group UseDocmanSearch Status: %s'),db_error()));
3001 $this->data_array['use_docman_search']=$status;
3007 function setDocmanForceReindexSearch($status) {
3009 /* if we activate search engine, we probably want to reindex */
3010 $res = db_query_params('UPDATE groups SET force_docman_reindex=$1 WHERE group_id=$2',
3015 $this->setError(sprintf(_('ERROR - Could Not Update Group force_docman_reindex %s'),db_error()));
3019 $this->data_array['force_docman_reindex']=$status;
3025 function setStorageAPI($type) {
3029 function getStorageAPI() {
3035 * group_getname() - get the group name
3037 * @param int The group ID
3041 function group_getname ($group_id = 0) {
3042 $grp = group_get_object($group_id);
3044 return $grp->getPublicName();
3051 * group_getunixname() - get the unixname for a group
3053 * @param int The group ID
3057 function group_getunixname ($group_id) {
3058 $grp = group_get_object($group_id);
3060 return $grp->getUnixName();
3067 * group_get_result() - Get the group object result ID.
3069 * @param int The group ID
3073 function &group_get_result($group_id=0) {
3074 $grp = group_get_object($group_id);
3076 return $grp->getData();
3082 function getAllProjectTags($onlyvisible = true) {
3083 $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',
3086 if (!$res || db_numrows($res) == 0) {
3092 while ($arr = db_fetch_array($res)) {
3094 $group_id = $arr[1];
3095 if (!isset($result[$tag])) {
3096 $result[$tag] = array();
3099 if (!$onlyvisible || forge_check_perm('project_read', $group_id)) {
3100 $p = group_get_object($group_id);
3101 $result[$tag][] = array('unix_group_name' => $p->getUnixName(),
3102 'group_id' => $group_id);
3109 class ProjectComparator {
3110 var $criterion = 'name' ;
3112 function Compare ($a, $b) {
3113 switch ($this->criterion) {
3116 $namecmp = strcoll ($a->getPublicName(), $b->getPublicName()) ;
3117 if ($namecmp != 0) {
3120 /* If several projects share a same public name */
3121 return strcoll ($a->getUnixName(), $b->getUnixName()) ;
3124 return strcmp ($a->getUnixName(), $b->getUnixName()) ;
3127 $aid = $a->getID() ;
3128 $bid = $b->getID() ;
3132 return ($a < $b) ? -1 : 1;
3138 function sortProjectList (&$list, $criterion='name') {
3139 $cmp = new ProjectComparator () ;
3140 $cmp->criterion = $criterion ;
3142 return usort ($list, array ($cmp, 'Compare')) ;
3147 // c-file-style: "bsd"