5 * Copyright 1999-2001, VA Linux Systems, Inc.
6 * Copyright 2009-2010, Roland Mas
7 * Copyright 2010-2011, Franck Villaume - Capgemini
8 * Copyright (C) 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.'));
301 srand((double)microtime()*1000000);
302 $random_num = rand(0,1000000);
306 $res = db_query_params('
323 VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)',
324 array(htmlspecialchars ($group_name),
327 htmlspecialchars($description),
328 $unix_name.".".forge_get_config('web_host'),
329 $unix_name.".".forge_get_config('web_host'),
333 htmlspecialchars($purpose),
337 $built_from_template));
338 if (!$res || db_affected_rows($res) < 1) {
339 $this->setError(sprintf(_('ERROR: Could not create group: %s'),db_error()));
344 $id = db_insertid($res, 'groups', 'group_id');
346 $this->setError(sprintf(_('ERROR: Could not get group id: %s'),db_error()));
351 if (!$this->fetchData($id)) {
357 $gjr = new GroupJoinRequest($this);
358 $gjr->create($user->getID(),
359 'Fake GroupJoinRequest to store the creator of a project',
363 // Now, make the user an admin
365 $res=db_query_params('INSERT INTO user_group (user_id, group_id, admin_flags,
366 cvs_flags, artifact_flags, forum_flags, role_id)
367 VALUES ($1, $2, $3, $4, $5, $6, $7)',
368 array($user->getID(),
375 if (!$res || db_affected_rows($res) < 1) {
376 $this->setError(sprintf(_('ERROR: Could not add admin to newly created group: %s'),db_error()));
382 $hook_params = array();
383 $hook_params['group'] = $this;
384 $hook_params['group_id'] = $this->getID();
385 $hook_params['group_name'] = $group_name;
386 $hook_params['unix_group_name'] = $unix_name;
387 plugin_hook("group_create", $hook_params);
391 $this->sendNewProjectNotificationEmail();
399 * updateAdmin - Update core properties of group object.
401 * This function require site admin privilege.
403 * @param object User requesting operation (for access control).
404 * @param boolean Whether group is publicly accessible (0/1).
405 * @param int Group type (1-project, 2-foundry).
406 * @param string Machine on which group's home directory located.
407 * @param string Domain which serves group's WWW.
411 function updateAdmin(&$user, $is_public, $type_id, $unix_box, $http_domain) {
412 $perm =& $this->getPermission();
414 if (!$perm || !is_object($perm)) {
415 $this->setError(_('Could not get permission.'));
419 if (!$perm->isSuperUser()) {
420 $this->setError(_('Permission denied.'));
426 $res = db_query_params('
428 SET is_public=$1, type_id=$2,
429 unix_box=$3, http_domain=$4
437 if (!$res || db_affected_rows($res) < 1) {
438 $this->setError(_('ERROR: DB: Could not change group properties: %s'),db_error());
443 // Log the audit trail
444 if ($is_public != $this->isPublic()) {
445 $this->addHistory('is_public', $this->isPublic());
447 if ($type_id != $this->data_array['type_id']) {
448 $this->addHistory('type_id', $this->data_array['type_id']);
450 if ($unix_box != $this->data_array['unix_box']) {
451 $this->addHistory('unix_box', $this->data_array['unix_box']);
453 if ($http_domain != $this->data_array['http_domain']) {
454 $this->addHistory('http_domain', $this->data_array['http_domain']);
457 if (!$this->fetchData($this->getID())) {
466 * update - Update number of common properties.
468 * Unlike updateAdmin(), this function accessible to project admin.
470 * @param object User requesting operation (for access control).
471 * @param boolean Whether group is publicly accessible (0/1).
472 * @param string Project's license (string ident).
473 * @param int Group type (1-project, 2-foundry).
474 * @param string Machine on which group's home directory located.
475 * @param string Domain which serves group's WWW.
476 * @return int status.
479 function update(&$user, $group_name, $homepage, $short_description, $use_mail, $use_survey, $use_forum,
480 $use_pm, $use_pm_depend_box, $use_scm, $use_news, $use_docman,
481 $new_doc_address, $send_all_docs, $logo_image_id,
482 $use_ftp, $use_tracker, $use_frs, $use_stats, $tags, $is_public) {
484 $perm =& $this->getPermission();
486 if (!$perm || !is_object($perm)) {
487 $this->setError(_('Could not get permission.'));
491 if (!$perm->isAdmin()) {
492 $this->setError(_('Permission denied.'));
496 // Validate some values
497 if ($this->getPublicName() != $group_name) {
498 if (!$this->validateGroupName($group_name)) {
503 if ($new_doc_address) {
504 $invalid_mails = validate_emails($new_doc_address);
505 if (count($invalid_mails) > 0) {
506 $this->setError(sprintf(ngettext('New Doc Address Appeared Invalid: %s', 'New Doc Addresses Appeared Invalid: %s', count($invalid_mails)),implode(',',$invalid_mails)));
511 // in the database, these all default to '1',
512 // so we have to explicity set 0
525 if (!$use_pm_depend_box) {
526 $use_pm_depend_box = 0;
549 if (!$send_all_docs) {
553 $homepage = ltrim($homepage);
555 $homepage = forge_get_config('web_host').'/projects/'.$this->getUnixName().'/';
558 if (strlen(htmlspecialchars($short_description))>255) {
559 $this->setError(_('Error updating project information: Maximum length for Project Description is 255 chars.'));
565 //XXX not yet actived logo_image_id='$logo_image_id',
566 $res = db_query_params('UPDATE groups
569 short_description=$3,
574 use_pm_depend_box=$8,
586 array(htmlspecialchars($group_name),
588 htmlspecialchars($short_description),
607 $this->setError(sprintf(_('Error updating project information: %s'), db_error()));
612 if ($this->setTags($tags) === false) {
617 $hook_params = array();
618 $hook_params['group'] = $this;
619 $hook_params['group_id'] = $this->getID();
620 $hook_params['group_homepage'] = $homepage;
621 $hook_params['group_name'] = htmlspecialchars($group_name);
622 $hook_params['group_description'] = htmlspecialchars($short_description);
623 $hook_params['group_ispublic'] = $is_public;
624 if (!plugin_hook("group_update", $hook_params)) {
625 if (!$this->isError()) {
626 $this->setError(_('Error updating project information in plugin_hook group_update'));
632 // Log the audit trail
633 $this->addHistory('Changed Public Info', '');
635 if (!$this->fetchData($this->getID())) {
644 * getID - Simply return the group_id for this object.
646 * @return int group_id.
649 return $this->data_array['group_id'];
653 * getType() - Foundry, project, etc.
655 * @return int The type flag from the database.
658 return $this->data_array['type_id'];
663 * getStatus - the status code.
665 * Statuses char include I,H,A,D.
667 function getStatus() {
668 return $this->data_array['status'];
672 * setStatus - set the status code.
674 * Statuses include I,H,A,D.
676 * @param object User requesting operation (for access control).
677 * @param string Status value.
678 * @return boolean success.
681 function setStatus(&$user, $status) {
684 if (!forge_check_global_perm('approve_projects')) {
685 $this->setPermissionDeniedError();
689 // Projects in 'A' status can only go to 'H' or 'D'
690 // Projects in 'D' status can only go to 'A'
691 // Projects in 'P' status can only go to 'A' OR 'D'
692 // Projects in 'I' status can only go to 'P'
693 // Projects in 'H' status can only go to 'A' OR 'D'
694 $allowed_status_changes = array(
695 'AH'=>1,'AD'=>1,'DA'=>1,'PA'=>1,'PD'=>1,
696 'IP'=>1,'HA'=>1,'HD'=>1
699 // Check that status transition is valid
700 if ($this->getStatus() != $status
701 && !$allowed_status_changes[$this->getStatus().$status]) {
702 $this->setError(_('Invalid Status Change'));
708 $res = db_query_params('UPDATE groups
710 WHERE group_id=$2', array($status, $this->getID()));
712 if (!$res || db_affected_rows($res) < 1) {
713 $this->setError(sprintf(_('ERROR: DB: Could not change group status: %s'),db_error()));
719 // Activate system group, if not yet
720 if (!$SYS->sysCheckGroup($this->getID())) {
721 if (!$SYS->sysCreateGroup($this->getID())) {
722 $this->setError($SYS->getErrorMessage());
727 if (!$this->activateUsers()) {
732 /* Otherwise, the group is not active, and make sure that
733 System group is not active either */
734 } else if ($SYS->sysCheckGroup($this->getID())) {
735 if (!$SYS->sysRemoveGroup($this->getID())) {
736 $this->setError($SYS->getErrorMessage());
742 $hook_params = array();
743 $hook_params['group'] = $this;
744 $hook_params['group_id'] = $this->getID();
745 $hook_params['status'] = $status;
746 plugin_hook("group_setstatus", $hook_params);
750 // Log the audit trail
751 if ($status != $this->getStatus()) {
752 $this->addHistory('Status', $this->getStatus());
755 $this->data_array['status'] = $status;
760 * isProject - Simple boolean test to see if it's a project or not.
762 * @return boolean is_project.
764 function isProject() {
765 if ($this->getType()==1) {
773 * isPublic - Simply returns the is_public flag from the database.
775 * @return boolean is_public.
777 function isPublic() {
778 return $this->data_array['is_public'];
782 * isActive - Database field status of 'A' returns true.
784 * @return boolean is_active.
786 function isActive() {
787 if ($this->getStatus()=='A') {
795 * isTemplate - Simply returns the is_template flag from the database.
797 * @return boolean is_template.
799 function isTemplate() {
800 return $this->data_array['is_template'];
804 * setAsTemplate - Set the template status of a project
806 * @param boolean is_template.
808 function setAsTemplate ($booleanparam) {
810 $booleanparam = $booleanparam ? 1 : 0 ;
811 $res = db_query_params ('UPDATE groups SET is_template=$1 WHERE group_id=$2',
812 array ($booleanparam, $this->getID()));
814 $this->data_array['is_template']=$booleanparam;
824 * getTemplateProject - Return the project template this project is built from
826 * @return object The template project
828 function getTemplateProject() {
829 return group_get_object($this->data_array['built_from_template']);
833 * getUnixName - the unix_name
835 * @return string unix_name.
837 function getUnixName() {
838 return strtolower($this->data_array['unix_group_name']);
842 * getPublicName - the full-length public name.
844 * @return string The group_name.
846 function getPublicName() {
847 return $this->data_array['group_name'];
851 * getRegisterPurpose - the text description of the purpose of this project.
853 * @return string The description.
855 function getRegisterPurpose() {
856 return $this->data_array['register_purpose'];
860 * getDescription - the text description of this project.
862 * @return string The description.
864 function getDescription() {
865 return $this->data_array['short_description'];
869 * getStartDate - the unix time this project was registered.
871 * @return int (unix time) of registration.
873 function getStartDate() {
874 return $this->data_array['register_time'];
878 * getLogoImageID - the id of the logo in the database for this project.
880 * @return int The ID of logo image in db_images table (or 100 if none).
882 function getLogoImageID() {
883 return $this->data_array['logo_image_id'];
887 * getUnixBox - the hostname of the unix box where this project is located.
889 * @return string The name of the unix machine for the group.
891 function getUnixBox() {
892 return $this->data_array['unix_box'];
896 * getSCMBox - the hostname of the scm box where this project is located.
898 * @return string The name of the unix machine for the group.
900 function getSCMBox() {
901 return $this->data_array['scm_box'];
904 * setSCMBox - the hostname of the scm box where this project is located.
906 * @param string The name of the new SCM_BOX
908 function setSCMBox($scm_box) {
910 if ($scm_box == $this->data_array['scm_box']) {
915 $res = db_query_params('UPDATE groups SET scm_box=$1 WHERE group_id=$2', array($scm_box, $this->getID ()));
917 $this->addHistory('scm_box', $this->data_array['scm_box']);
918 $this->data_array['scm_box'] = $scm_box;
923 $this->setError(_("Couldn't insert SCM_BOX to database"));
927 $this->setError(_("SCM Box can't be empty"));
933 * getDomain - the hostname.domain where their web page is located.
935 * @return string The name of the group [web] domain.
937 function getDomain() {
938 return $this->data_array['http_domain'];
942 * getRegistrationPurpose - the text description of the purpose of this project.
944 * @return string The application for project hosting.
946 function getRegistrationPurpose() {
947 return $this->data_array['register_purpose'];
952 * getAdmins() - Get array of Admin user objects.
954 * @return array Array of User objects.
956 function &getAdmins() {
957 $roles = RBACEngine::getInstance()->getRolesByAllowedAction ('project_admin', $this->getID());
961 foreach ($roles as $role) {
962 if (! ($role instanceof RoleExplicit)) {
965 if ($role->getHomeProject() == NULL
966 || $role->getHomeProject()->getID() != $this->getID()) {
970 foreach ($role->getUsers() as $u) {
971 $user_ids[] = $u->getID();
974 return user_get_objects(array_unique($user_ids));
978 Common Group preferences for tools
982 * enableAnonSCM - whether or not this group has opted to enable Anonymous SCM.
984 * @return boolean enable_scm.
986 function enableAnonSCM() {
988 $r = RoleAnonymous::getInstance();
989 return $r->hasPermission('scm', $this->getID(), 'read');
991 if ($this->isPublic() && $this->usesSCM()) {
992 return $this->data_array['enable_anonscm'];
999 function SetUsesAnonSCM($booleanparam) {
1001 $booleanparam = $booleanparam ? 1 : 0;
1003 $r = RoleAnonymous::getInstance();
1004 $r->setSetting('scm', $this->getID(), $booleanparam);
1007 $res = db_query_params('UPDATE groups SET enable_anonscm=$1 WHERE group_id=$2',
1008 array($booleanparam, $this->getID()));
1010 $this->data_array['enable_anonscm'] = $booleanparam;
1019 function setUsesSCM($booleanparam) {
1021 $booleanparam = $booleanparam ? 1 : 0;
1022 $res = db_query_params('UPDATE groups SET use_scm=$1 WHERE group_id=$2',
1023 array($booleanparam, $this->getID()));
1025 $this->data_array['use_scm'] = $booleanparam;
1034 * enablePserver - whether or not this group has opted to enable Pserver.
1036 * @return boolean enable_pserver.
1038 function enablePserver() {
1039 if ($this->usesSCM()) {
1040 return $this->data_array['enable_pserver'];
1046 function SetUsesPserver($booleanparam) {
1048 $booleanparam = $booleanparam ? 1 : 0;
1049 $res = db_query_params('UPDATE groups SET enable_pserver=$1 WHERE group_id=$2',
1050 array($booleanparam, $this->getID()));
1052 $this->data_array['enable_pserver'] = $booleanparam;
1061 * usesSCM - whether or not this group has opted to use SCM.
1063 * @return boolean uses_scm.
1065 function usesSCM() {
1066 if (forge_get_config('use_scm')) {
1067 return $this->data_array['use_scm'];
1074 * setUseSCM - Set the SCM usage
1076 * @param boolean enabled/disabled
1078 function setUseSCM ($booleanparam) {
1080 $booleanparam = $booleanparam ? 1 : 0 ;
1081 $res = db_query_params ('UPDATE groups SET use_scm=$1 WHERE group_id=$2',
1082 array ($booleanparam, $this->getID()));
1084 $this->data_array['use_scm']=$booleanparam;
1094 * usesMail - whether or not this group has opted to use mailing lists.
1096 * @return boolean uses_mail.
1098 function usesMail() {
1099 if (forge_get_config('use_mail')) {
1100 return $this->data_array['use_mail'];
1107 * setUseMail - Set the mailing-list usage
1109 * @param boolean enabled/disabled
1111 function setUseMail ($booleanparam) {
1113 $booleanparam = $booleanparam ? 1 : 0 ;
1114 $res = db_query_params ('UPDATE groups SET use_mail=$1 WHERE group_id=$2',
1115 array ($booleanparam, $this->getID()));
1117 $this->data_array['use_mail']=$booleanparam;
1127 * usesNews - whether or not this group has opted to use news.
1129 * @return boolean uses_news.
1131 function usesNews() {
1132 if (forge_get_config('use_news')) {
1133 return $this->data_array['use_news'];
1140 * usesForum - whether or not this group has opted to use discussion forums.
1142 * @return boolean uses_forum.
1144 function usesForum() {
1145 if (forge_get_config('use_forum')) {
1146 return $this->data_array['use_forum'];
1153 * setUseForum - Set the forum usage
1155 * @param boolean enabled/disabled
1157 function setUseForum ($booleanparam) {
1159 $booleanparam = $booleanparam ? 1 : 0 ;
1160 $res = db_query_params ('UPDATE groups SET use_forum=$1 WHERE group_id=$2',
1161 array ($booleanparam, $this->getID()));
1163 $this->data_array['use_forum']=$booleanparam;
1173 * usesStats - whether or not this group has opted to use stats.
1175 * @return boolean uses_stats.
1177 function usesStats() {
1178 return $this->data_array['use_stats'];
1182 * usesFRS - whether or not this group has opted to use file release system.
1184 * @return boolean uses_frs.
1186 function usesFRS() {
1187 if (forge_get_config('use_frs')) {
1188 return $this->data_array['use_frs'];
1195 * setUseFRS - Set the FRS usage
1197 * @param boolean enabled/disabled
1199 function setUseFRS ($booleanparam) {
1201 $booleanparam = $booleanparam ? 1 : 0 ;
1202 $res = db_query_params ('UPDATE groups SET use_frs=$1 WHERE group_id=$2',
1203 array ($booleanparam, $this->getID()));
1205 $this->data_array['use_frs']=$booleanparam;
1215 * usesTracker - whether or not this group has opted to use tracker.
1217 * @return boolean uses_tracker.
1219 function usesTracker() {
1220 if (forge_get_config('use_tracker')) {
1221 return $this->data_array['use_tracker'];
1228 * setUseTracker - Set the tracker usage
1230 * @param boolean enabled/disabled
1232 function setUseTracker ($booleanparam) {
1234 $booleanparam = $booleanparam ? 1 : 0 ;
1235 $res = db_query_params ('UPDATE groups SET use_tracker=$1 WHERE group_id=$2',
1236 array ($booleanparam, $this->getID()));
1238 $this->data_array['use_tracker']=$booleanparam;
1248 * useCreateOnline - whether or not this group has opted to use create online documents option.
1250 * @return boolean use_docman_create_online.
1252 function useCreateOnline() {
1253 if (forge_get_config('use_docman')) {
1254 return $this->data_array['use_docman_create_online'];
1261 * usesDocman - whether or not this group has opted to use docman.
1263 * @return boolean use_docman.
1265 function usesDocman() {
1266 if (forge_get_config('use_docman')) {
1267 return $this->data_array['use_docman'];
1274 * setUseDocman - Set the docman usage
1276 * @param boolean enabled/disabled
1278 function setUseDocman ($booleanparam) {
1280 $booleanparam = $booleanparam ? 1 : 0 ;
1281 $res = db_query_params ('UPDATE groups SET use_docman=$1 WHERE group_id=$2',
1282 array ($booleanparam, $this->getID()));
1284 $this->data_array['use_docman']=$booleanparam;
1294 * useDocmanSearch - whether or not this group has opted to use docman search engine.
1296 * @return boolean use_docman_search.
1298 function useDocmanSearch() {
1299 if (forge_get_config('use_docman')) {
1300 return $this->data_array['use_docman_search'];
1307 * useWebdav - whether or not this group has opted to use webdav interface.
1309 * @return boolean use_docman_search.
1311 function useWebdav() {
1312 if (forge_get_config('use_webdav')) {
1313 return $this->data_array['use_webdav'];
1320 * usesFTP - whether or not this group has opted to use FTP.
1322 * @return boolean uses_ftp.
1324 function usesFTP() {
1325 if (forge_get_config('use_ftp')) {
1326 return $this->data_array['use_ftp'];
1333 * usesSurvey - whether or not this group has opted to use surveys.
1335 * @return boolean uses_survey.
1337 function usesSurvey() {
1338 if (forge_get_config('use_survey')) {
1339 return $this->data_array['use_survey'];
1346 * usesPM - whether or not this group has opted to Project Manager.
1348 * @return boolean uses_projman.
1351 if (forge_get_config('use_pm')) {
1352 return $this->data_array['use_pm'];
1359 * setUsePM - Set the PM usage
1361 * @param boolean enabled/disabled
1363 function setUsePM ($booleanparam) {
1365 $booleanparam = $booleanparam ? 1 : 0 ;
1366 $res = db_query_params ('UPDATE groups SET use_pm=$1 WHERE group_id=$2',
1367 array ($booleanparam, $this->getID()));
1369 $this->data_array['use_pm']=$booleanparam;
1379 * getPlugins - get a list of all available group plugins
1381 * @return array array containing plugin_id => plugin_name
1383 function getPlugins() {
1384 if (!isset($this->plugins_data)) {
1385 $this->plugins_data = array();
1386 $res = db_query_params('SELECT group_plugin.plugin_id, plugins.plugin_name
1387 FROM group_plugin, plugins
1388 WHERE group_plugin.group_id=$1
1389 AND group_plugin.plugin_id=plugins.plugin_id', array($this->getID()));
1390 $rows = db_numrows($res);
1392 for ($i=0; $i<$rows; $i++) {
1393 $plugin_id = db_result($res, $i, 'plugin_id');
1394 $this->plugins_data[$plugin_id] = db_result($res, $i, 'plugin_name');
1397 return $this->plugins_data;
1401 * usesPlugin - returns true if the group uses a particular plugin
1403 * @param string name of the plugin
1404 * @return boolean whether plugin is being used or not
1406 function usesPlugin($pluginname) {
1407 $plugins_data = $this->getPlugins();
1408 foreach ($plugins_data as $p_id => $p_name) {
1409 if ($p_name == $pluginname) {
1417 * added for Codendi compatibility
1418 * usesServices - returns true if the group uses a particular plugin or feature
1420 * @param string name of the plugin
1421 * @return boolean whether plugin is being used or not
1423 function usesService($feature) {
1424 $plugins_data = $this->getPlugins();
1425 $pm = plugin_manager_get_object();
1426 foreach ($plugins_data as $p_id => $p_name) {
1427 if ($p_name == $feature) {
1430 if ($pm->getPluginByName($p_name)->provide($feature)) {
1438 * setPluginUse - enables/disables plugins for the group
1440 * @param string name of the plugin
1441 * @param boolean the new state
1442 * @return string database result
1444 function setPluginUse($pluginname, $val=true) {
1445 if ($val == $this->usesPlugin($pluginname)) {
1446 // State is already good, returning
1449 $res = db_query_params('SELECT plugin_id FROM plugins WHERE plugin_name=$1',
1450 array($pluginname));
1451 $rows = db_numrows($res);
1453 // Error: no plugin by that name
1456 $plugin_id = db_result($res,0,'plugin_id');
1458 unset($this->plugins_data);
1460 $res = db_query_params('INSERT INTO group_plugin (group_id, plugin_id) VALUES ($1, $2)',
1461 array($this->getID(),
1465 $res = db_query_params('DELETE FROM group_plugin WHERE group_id=$1 AND plugin_id=$2',
1466 array($this->getID(),
1473 * getDocEmailAddress - get email address(es) to send doc notifications to.
1475 * @return string email address.
1477 function getDocEmailAddress() {
1478 return $this->data_array['new_doc_address'];
1482 * DocEmailAll - whether or not this group has opted to use receive notices on all doc updates.
1484 * @return boolean email_on_all_doc_updates.
1486 function docEmailAll() {
1487 return $this->data_array['send_all_docs'];
1492 * getHomePage - The URL for this project's home page.
1494 * @return string homepage URL.
1496 function getHomePage() {
1497 return $this->data_array['homepage'];
1501 * getTags - Tags of this project.
1503 * @return string List of tags. Commat separated
1505 function getTags() {
1506 $sql = 'SELECT name FROM project_tags WHERE group_id = $1';
1507 $res = db_query_params($sql, array($this->getID()));
1508 return join(', ', util_result_column_to_array($res));
1512 * setTags - Set tags of this project.
1514 * @return string database result.
1516 function setTags($tags) {
1518 $sql = 'DELETE FROM project_tags WHERE group_id=$1';
1519 $res = db_query_params($sql, array($this->getID()));
1521 $this->setError('Deleting old tags: '.db_error());
1525 $inserted = array();
1526 $tags_array = preg_split('/[;,]/', $tags);
1527 foreach ($tags_array as $tag) {
1528 $tag = preg_replace('/[\t\r\n]/', ' ', $tag);
1529 // Allowed caracteres: [A-Z][a-z][0-9] -_&'#+.
1530 if (preg_match('/[^[:alnum:]| |\-|_|\&|\'|#|\+|\.]/', $tag)) {
1531 $this->setError(_('Bad tag name, you only can use the following characters: [A-Z][a-z][0-9]-_&\'#+. and space'));
1536 if ($tag == '' || array_search($tag, $inserted) !== false) continue;
1537 $sql = 'INSERT INTO project_tags (group_id,name) VALUES ($1, $2)';
1538 $res = db_query_params($sql, array($this->getID(), $tag));
1540 $this->setError(_('Setting tags: ').db_error());
1551 * getPermission - Return a Permission for this Group
1553 * @return object The Permission.
1555 function &getPermission() {
1556 return permission_get_object($this);
1560 function delete($sure, $really_sure, $really_really_sure) {
1561 if (!$sure || !$really_sure || !$really_really_sure) {
1562 $this->setMissingParamsError(_('Please tick all checkboxes.'));
1565 if ($this->getID() == forge_get_config('news_group') ||
1566 $this->getID() == 1 ||
1567 $this->getID() == forge_get_config('stats_group') ||
1568 $this->getID() == forge_get_config('peer_rating_group')) {
1569 $this->setError(_('Cannot Delete System Group'));
1572 $perm =& $this->getPermission();
1573 if (!$perm || !is_object($perm)) {
1574 $this->setPermissionDeniedError();
1576 } elseif ($perm->isError()) {
1577 $this->setPermissionDeniedError();
1579 } elseif (!$perm->isSuperUser()) {
1580 $this->setPermissionDeniedError();
1586 // Remove all the members
1588 $members =& $this->getMembers();
1589 foreach ($members as $i) {
1590 if(!$this->removeUser($i->getID())) {
1591 $this->setError(_('Could not properly remove member:').' '.$i->getID());
1595 // Failsafe until user_group table is gone
1596 $res = db_query_params('DELETE FROM user_group WHERE group_id=$1',
1597 array($this->getID()));
1599 // unlink roles to this project
1600 if ($this->isPublic()) {
1601 $ra = RoleAnonymous::getInstance();
1602 $rl = RoleLoggedIn::getInstance();
1603 $ra->unlinkProject($this);
1604 $rl->unlinkProject($this);
1606 // @todo : unlink all the other roles created in the project...
1611 $atf = new ArtifactTypeFactory($this);
1612 $at_arr =& $atf->getArtifactTypes();
1613 foreach ($at_arr as $i) {
1614 if (!is_object($i)) {
1617 if (!$i->delete(1,1)) {
1618 $this->setError(_('Could not properly delete the tracker:').' '.$i->getErrorMessage());
1625 $ff = new ForumFactory($this);
1626 $f_arr =& $ff->getForums();
1627 foreach ($f_arr as $i) {
1628 if (!is_object($i)) {
1631 if(!$i->delete(1,1)) {
1632 $this->setError(_('Could not properly delete the forum:').' '.$i->getErrorMessage());
1637 // Delete Subprojects
1639 $pgf = new ProjectGroupFactory($this);
1640 $pg_arr =& $pgf->getProjectGroups();
1641 foreach ($pg_arr as $i) {
1642 if (!is_object($i)) {
1645 if (!$i->delete(1,1)) {
1646 $this->setError(_('Could not properly delete the ProjectGroup:').' '.$i->getErrorMessage());
1651 // Delete FRS Packages
1653 $res = db_query_params('SELECT * FROM frs_package WHERE group_id=$1',
1654 array($this->getID()));
1655 while ($arr = db_fetch_array($res)) {
1656 $frsp=new FRSPackage($this, $arr['package_id'], $arr);
1657 if (!$frsp->delete(1, 1)) {
1658 $this->setError(_('Could not properly delete the FRSPackage:').' '.$frsp->getErrorMessage());
1665 $news_group=group_get_object(forge_get_config('news_group'));
1666 $res = db_query_params('SELECT forum_id FROM news_bytes WHERE group_id=$1',
1667 array($this->getID()));
1669 $this->setError(_('Error Deleting News: ').db_error());
1674 for ($i=0; $i<db_numrows($res); $i++) {
1675 $Forum = new Forum($news_group,db_result($res,$i,'forum_id'));
1676 if (!$Forum->delete(1,1)) {
1677 $this->setError(_("Could Not Delete News Forum: %d"),$Forum->getID());
1681 $res = db_query_params('DELETE FROM news_bytes WHERE group_id=$1',
1682 array($this->getID()));
1684 $this->setError(_('Error Deleting News: ').db_error());
1692 $res = db_query_params('DELETE FROM doc_data WHERE group_id=$1',
1693 array($this->getID()));
1695 $this->setError(_('Error Deleting Documents: ').db_error());
1700 $res = db_query_params('DELETE FROM doc_groups WHERE group_id=$1',
1701 array($this->getID()));
1703 $this->setError(_('Error Deleting Documents: ').db_error());
1711 $res=db_query_params('DELETE FROM project_tags WHERE group_id=$1', array($this->getID()));
1713 $this->setError(_('Error Deleting Tags: ').db_error());
1719 // Delete group history
1721 $res = db_query_params('DELETE FROM group_history WHERE group_id=$1',
1722 array($this->getID()));
1724 $this->setError(_('Error Deleting Project History: ').db_error());
1730 // Delete group plugins
1732 $res = db_query_params('DELETE FROM group_plugin WHERE group_id=$1',
1733 array($this->getID()));
1735 $this->setError(_('Error Deleting Project Plugins: ').db_error());
1741 // Delete group cvs stats
1743 $res = db_query_params ('DELETE FROM stats_cvs_group WHERE group_id=$1',
1744 array ($this->getID())) ;
1746 $this->setError(_('Error Deleting SCM Statistics: ').db_error());
1754 $sf = new SurveyFactory($this);
1755 $s_arr =& $sf->getSurveys();
1756 foreach ($s_arr as $i) {
1757 if (!is_object($i)) {
1760 if (!$i->delete()) {
1761 $this->setError(_('Could not properly delete the survey'));
1766 // Delete SurveyQuestions
1768 $sqf = new SurveyQuestionFactory($this);
1769 $sq_arr =& $sqf->getSurveyQuestions();
1770 foreach ($sq_arr as $i) {
1771 if (!is_object($i)) {
1774 if (!$i->delete()) {
1775 $this->setError(_('Could not properly delete the survey questions'));
1780 // Delete Mailing List Factory
1782 $mlf = new MailingListFactory($this);
1783 $ml_arr =& $mlf->getMailingLists();
1784 foreach ($ml_arr as $i) {
1785 if (!is_object($i)) {
1788 if (!$i->delete(1,1)) {
1789 $this->setError(_('Could not properly delete the mailing list'));
1796 $res = db_query_params('DELETE FROM trove_group_link WHERE group_id=$1',
1797 array($this->getID()));
1799 $this->setError(_('Error Deleting Trove: ').db_error());
1804 $res = db_query_params('DELETE FROM trove_agg WHERE group_id=$1',
1805 array($this->getID()));
1807 $this->setError(_('Error Deleting Trove: ').db_error());
1815 $res = db_query_params('DELETE FROM project_sums_agg WHERE group_id=$1',
1816 array($this->getID()));
1818 $this->setError(_('Error Deleting Counters: ').db_error());
1823 $res = db_query_params('INSERT INTO deleted_groups (unix_group_name, delete_date, isdeleted) VALUES ($1, $2, $3)',
1824 array($this->getUnixName(),
1828 $this->setError(_('Error Deleting Project:').' '.db_error());
1833 $res = db_query_params('DELETE FROM groups WHERE group_id=$1',
1834 array($this->getID()));
1836 $this->setError(_('Error Deleting Project:').' '.db_error());
1843 $hook_params = array();
1844 $hook_params['group'] = $this;
1845 $hook_params['group_id'] = $this->getID();
1846 plugin_hook("group_delete", $hook_params);
1848 if (forge_get_config('upload_dir') != '' && $this->getUnixName()) {
1849 exec('/bin/rm -rf '.forge_get_config('upload_dir').'/'.$this->getUnixName().'/');
1851 if (forge_get_config('ftp_upload_dir') != '' && $this->getUnixName()) {
1852 exec('/bin/rm -rf '.forge_get_config('ftp_upload_dir').'/'.$this->getUnixName().'/');
1857 $res = db_query_params('DELETE FROM rep_group_act_monthly WHERE group_id=$1',
1858 array ($this->getID()));
1859 //echo 'rep_group_act_monthly'.db_error();
1860 $res = db_query_params('DELETE FROM rep_group_act_weekly WHERE group_id=$1',
1861 array ($this->getID()));
1862 //echo 'rep_group_act_weekly'.db_error();
1863 $res = db_query_params('DELETE FROM rep_group_act_daily WHERE group_id=$1',
1864 array ($this->getID()));
1865 //echo 'rep_group_act_daily'.db_error();
1866 unset($this->data_array);
1872 Basic functions to add/remove users to/from a group
1873 and update their permissions
1877 * addUser - controls adding a user to a group.
1879 * @param string Unix name of the user to add OR integer user_id.
1880 * @param int The role_id this user should have.
1881 * @return boolean success.
1884 function addUser($user_identifier,$role_id) {
1887 Admins can add users to groups
1890 if (!forge_check_perm ('project_admin', $this->getID())) {
1891 $this->setPermissionDeniedError();
1897 get user id for this user's unix_name
1899 if (is_int ($user_identifier)) { // user_id or user_name
1900 $res_newuser = db_query_params ('SELECT * FROM users WHERE user_id=$1', array ($user_identifier)) ;
1902 $res_newuser = db_query_params ('SELECT * FROM users WHERE user_name=$1', array ($user_identifier)) ;
1904 if (db_numrows($res_newuser) > 0) {
1906 // make sure user is active
1908 if (db_result($res_newuser,0,'status') != 'A') {
1909 $this->setError(_('User is not active. Only active users can be added.'));
1915 // user was found - set new user_id var
1917 $user_id = db_result($res_newuser,0,'user_id');
1919 $role = new Role($this,$role_id);
1920 if (!$role || !is_object($role)) {
1921 $this->setError(_('Error Getting Role Object'));
1924 } elseif ($role->isError()) {
1925 $this->setError('addUser::roleget::'.$role->getErrorMessage());
1931 $role->addUser(user_get_object ($user_id)) ;
1932 if (!$SYS->sysCheckCreateGroup($this->getID())){
1933 $this->setError($SYS->getErrorMessage());
1937 if (!$SYS->sysCheckCreateUser($user_id)) {
1938 $this->setError($SYS->getErrorMessage());
1945 // if not already a member, add them
1947 $res_member = db_query_params('SELECT user_id
1949 WHERE user_id=$1 AND group_id=$2',
1950 array($user_id, $this->getID()));
1952 if (db_numrows($res_member) < 1) {
1954 // Create this user's row in the user_group table
1956 $res = db_query_params('INSERT INTO user_group
1957 (user_id,group_id,admin_flags,forum_flags,project_flags,
1958 doc_flags,cvs_flags,member_role,release_flags,artifact_flags)
1959 VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)',
1971 //verify the insert worked
1972 if (!$res || db_affected_rows($res) < 1) {
1973 $this->setError(sprintf(_('ERROR: Could Not Add User To Group: %s'),db_error()));
1978 // check and create if group doesn't exists
1980 //echo "<h2>Group::addUser SYS->sysCheckCreateGroup(".$this->getID().")</h2>";
1981 if (!$SYS->sysCheckCreateGroup($this->getID())){
1982 $this->setError($SYS->getErrorMessage());
1987 // check and create if user doesn't exists
1989 //echo "<h2>Group::addUser SYS->sysCheckCreateUser($user_id)</h2>";
1990 if (!$SYS->sysCheckCreateUser($user_id)) {
1991 $this->setError($SYS->getErrorMessage());
1998 //echo "<h2>Group::addUser role->setUser($user_id)</h2>";
1999 if (!$role->setUser($user_id)) {
2000 $this->setError('addUser::role::setUser'.$role->getErrorMessage());
2006 // user was already a member
2007 // make sure they are set up
2009 $user= user_get_object($user_id,$res_newuser);
2010 $user->fetchData($user->getID());
2011 $role = new Role($this,$role_id);
2012 if (!$role || !is_object($role)) {
2013 $this->setError(_('Error Getting Role Object'));
2016 } elseif ($role->isError()) {
2017 $this->setError('addUser::roleget::'.$role->getErrorMessage());
2021 //echo "<h2>Already Member Group::addUser role->setUser($user_id)</h2>";
2022 if (!$role->setUser($user_id)) {
2023 $this->setError('addUser::role::setUser'.$role->getErrorMessage());
2028 // set up their system info
2030 //echo "<h2>Already Member Group::addUser SYS->sysCheckCreateUser($user_id)</h2>";
2031 if (!$SYS->sysCheckCreateUser($user_id)) {
2032 $this->setError($SYS->getErrorMessage());
2040 // user doesn't exist
2042 $this->setError(_('ERROR: User does not exist'));
2047 $hook_params['group'] = $this;
2048 $hook_params['group_id'] = $this->getID();
2049 $hook_params['user'] = &user_get_object($user_id);
2050 $hook_params['user_id'] = $user_id;
2051 plugin_hook ("group_adduser", $hook_params);
2056 $this->addHistory('Added User',$user_identifier);
2062 * removeUser - controls removing a user from a group.
2064 * Users can remove themselves.
2066 * @param int The ID of the user to remove.
2067 * @return boolean success.
2069 function removeUser($user_id) {
2072 if ($user_id != user_getid()
2073 || !forge_check_perm('project_admin', $this->getID())) {
2074 $this->setPermissionDeniedError();
2081 $user = user_get_object($user_id);
2082 $roles = RBACEngine::getInstance()->getAvailableRolesForUser($user);
2084 foreach ($roles as $role) {
2085 if ($role->getHomeProject() && $role->getHomeProject()->getID() == $this->getID()) {
2086 $found_role = $role;
2090 if ($found_role == NULL) {
2091 $this->setError(sprintf(_('ERROR: User not removed: %s')));
2095 $found_role->removeUser($user);
2096 if (!$SYS->sysGroupCheckUser($this->getID(), $user_id)) {
2097 $this->setError($SYS->getErrorMessage());
2103 $res = db_query_params('DELETE FROM user_group WHERE group_id=$1 AND user_id=$2',
2104 array($this->getID(),
2106 if (!$res || db_affected_rows($res) < 1) {
2107 $this->setError(_('ERROR: User not removed:').' '.db_error());
2114 // reassign open artifacts to id=100
2116 $res = db_query_params('UPDATE artifact SET assigned_to=100
2117 WHERE group_artifact_id
2118 IN (SELECT group_artifact_id
2119 FROM artifact_group_list
2120 WHERE group_id=$1 AND status_id=1 AND assigned_to=$2)',
2121 array($this->getID(),
2124 $this->setError(_('ERROR: DB: artifact:').' '.db_error());
2130 // reassign open tasks to id=100
2131 // first have to purge any assignments that would cause
2132 // conflict with existing assignment to 100
2134 $res = db_query_params('DELETE FROM project_assigned_to
2135 WHERE project_task_id IN (SELECT pt.project_task_id
2136 FROM project_task pt, project_group_list pgl, project_assigned_to pat
2137 WHERE pt.group_project_id = pgl.group_project_id
2138 AND pat.project_task_id=pt.project_task_id
2139 AND pt.status_id=1 AND pgl.group_id=$1
2140 AND pat.assigned_to_id=$2)
2141 AND assigned_to_id=100',
2142 array($this->getID(),
2145 $this->setError(sprintf(_('ERROR: DB: project_assigned_to %d: %s'), 1, db_error()));
2149 $res = db_query_params('UPDATE project_assigned_to SET assigned_to_id=100
2150 WHERE project_task_id IN (SELECT pt.project_task_id
2151 FROM project_task pt, project_group_list pgl
2152 WHERE pt.group_project_id = pgl.group_project_id
2153 AND pt.status_id=1 AND pgl.group_id=$1)
2154 AND assigned_to_id=$2',
2155 array($this->getID(),
2158 $this->setError(sprintf(_('ERROR: DB: project_assigned_to %d: %s'), 2, db_error()));
2164 // Remove user from system
2166 if (!$SYS->sysGroupRemoveUser($this->getID(), $user_id)) {
2167 $this->setError($SYS->getErrorMessage());
2172 $hook_params['group'] = $this;
2173 $hook_params['group_id'] = $this->getID();
2174 $hook_params['user'] = user_get_object($user_id);
2175 $hook_params['user_id'] = $user_id;
2176 plugin_hook ("group_removeuser", $hook_params);
2179 $this->addHistory('Removed User',$user_id);
2186 * updateUser - controls updating a user's role in this group.
2188 * @param int The ID of the user.
2189 * @param int The role_id to set this user to.
2190 * @return boolean success.
2192 function updateUser($user_id,$role_id) {
2195 if (!forge_check_perm ('project_admin', $this->getID())) {
2196 $this->setPermissionDeniedError();
2201 $newrole = RBACEngine::getInstance()->getRoleById ($role_id) ;
2202 if (!$newrole || !is_object($newrole)) {
2203 $this->setError(_('Could Not Get Role'));
2205 } elseif ($newrole->isError()) {
2206 $this->setError(sprintf(_('Role: %s'),$role->getErrorMessage()));
2208 } elseif ($newrole->getHomeProject() == NULL
2209 || $newrole->getHomeProject()->getID() != $this->getID()) {
2210 $this->setError(_('Wrong destination role'));
2213 $user = user_get_object ($user_id) ;
2214 $roles = RBACEngine::getInstance()->getAvailableRolesForUser ($user) ;
2215 $found_role = NULL ;
2216 foreach ($roles as $role) {
2217 if ($role->getHomeProject() && $role->getHomeProject()->getID() == $this->getID()) {
2218 $found_role = $role ;
2222 if ($found_role == NULL) {
2223 $this->setError(sprintf(_('ERROR: User not removed: %s')));
2227 $found_role->removeUser ($user) ;
2228 $newrole->addUser ($user) ;
2230 $role = new Role($this,$role_id);
2231 if (!$role || !is_object($role)) {
2232 $this->setError(_('Could Not Get Role'));
2234 } elseif ($role->isError()) {
2235 $this->setError(sprintf(_('Role: %s'),$role->getErrorMessage()));
2238 //echo "<h3>Group::updateUser role->setUser($user_id)</h3>";
2239 if (!$role->setUser($user_id)) {
2240 $this->setError(sprintf(_('Role: %s'),$role->getErrorMessage()));
2245 $this->addHistory('Updated User',$user_id);
2250 * addHistory - Makes an audit trail entry for this project.
2252 * @param string The name of the field.
2253 * @param string The Old Value for this $field_name.
2254 * @return database result handle.
2257 function addHistory($field_name, $old_value) {
2258 return db_query_params ('INSERT INTO group_history(group_id,field_name,old_value,mod_by,adddate)
2259 VALUES ($1,$2,$3,$4,$5)',
2260 array ($this->getID(),
2268 * activateUsers - Make sure that group members have unix accounts.
2270 * Setup unix accounts for group members. Can be called even
2271 * if members are already active.
2275 function activateUsers() {
2277 Activate member(s) of the project
2281 $members = $this->getUsers (true) ;
2283 foreach ($members as $member) {
2285 foreach (RBACEngine::getInstance()->getAvailableRolesForUser ($member) as $role) {
2286 if ($role->getHomeProject() && $role->getHomeProject()->getID() == $this->getID()) {
2289 if (!$this->addUser($member->getUnixName(),$role->getID())) {
2296 $res_member = db_query_params('SELECT user_id,role_id FROM user_group WHERE group_id=$1',
2297 array ($this->getID()));
2298 while ($row_member = db_fetch_array($res_member)) {
2299 $u = user_get_object($row_member['user_id']);
2300 if (!$this->addUser($u->getUnixName(),$row_member['role_id'])) {
2310 * getMembers - returns array of User objects for this project
2312 * @return array of User objects for this group.
2314 function getMembers() {
2315 return $this->getUsers (true) ;
2319 * replaceTemplateStrings - fill-in some blanks with project name
2321 * @param string Template string
2322 * @return string String after replacements
2324 function replaceTemplateStrings($string) {
2325 $string = str_replace ('UNIXNAME', $this->getUnixName(), $string) ;
2326 $string = str_replace ('PUBLICNAME', $this->getPublicName(), $string) ;
2327 $string = str_replace ('DESCRIPTION', $this->getDescription(), $string) ;
2332 * approve - Approve pending project.
2334 * @param object The User object who is doing the updating.
2337 function approve(&$user) {
2339 require_once $gfcommon.'widget/WidgetLayoutManager.class.php';
2341 if ($this->getStatus()=='A') {
2342 $this->setError(_("Group already active"));
2348 // Step 1: Activate group and create LDAP entries
2349 if (!$this->setStatus($user, 'A')) {
2354 // Switch to system language for item creation
2355 setup_gettext_from_sys_lang ();
2357 // Create default roles
2359 $idadmin_group = NULL ;
2360 foreach (get_group_join_requests ($this) as $gjr) {
2361 $idadmin_group = $gjr->getUserID() ;
2364 if ($idadmin_group == NULL) {
2365 $idadmin_group = $user->getID();
2368 $admin_group = db_query_params ('SELECT user_id FROM user_group WHERE group_id=$1 AND admin_flags=$2',
2369 array ($this->getID(),
2371 if (db_numrows($admin_group) > 0) {
2372 $idadmin_group = db_result($admin_group,0,'user_id');
2374 $idadmin_group = $user->getID();
2375 db_query_params ('INSERT INTO user_group (user_id, group_id, admin_flags) VALUES ($1, $2, $3)',
2376 array ($idadmin_group,
2382 $template = $this->getTemplateProject() ;
2383 $id_mappings = array ();
2384 $seen_local_roles = false ;
2386 // Copy roles from template project
2387 foreach ($template->getRoles() as $oldrole) {
2388 if ($oldrole->getHomeProject() != NULL) {
2389 $role = new Role ($this) ;
2391 // Need to use a different role name so that the permissions aren't set from the hardcoded defaults
2392 $role->create ('TEMPORARY ROLE NAME', $data, true) ;
2393 $role->setName ($oldrole->getName()) ;
2394 $seen_local_roles = true ;
2397 $role->linkProject ($this) ;
2399 $id_mappings['role'][$oldrole->getID()] = $role->getID() ;
2400 // Reuse the project_admin permission
2401 $role->setSetting ('project_admin', $this->getID(), $oldrole->getSetting ('project_admin', $template->getID())) ;
2405 if (!$seen_local_roles) {
2406 $role = new Role($this);
2407 $adminperms = array ('project_admin' => array ($this->getID() => 1)) ;
2408 $role_id = $role->create ('Admin', $adminperms, true) ;
2412 $roles = $this->getRoles() ;
2413 foreach ($roles as $r) {
2414 if ($r->getSetting ('project_admin', $this->getID())) {
2415 $r->addUser (user_get_object ($idadmin_group)) ;
2420 // Temporarily switch to the submitter's identity
2421 $saved_session = session_get_user () ;
2422 session_set_internal ($idadmin_group) ;
2425 if (forge_get_config ('use_tracker')) {
2426 $this->setUseTracker ($template->usesTracker()) ;
2427 if ($template->usesTracker()) {
2428 $oldatf = new ArtifactTypeFactory ($template) ;
2429 foreach ($oldatf->getArtifactTypes() as $o) {
2430 $t = new ArtifactType ($this) ;
2431 $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()) ;
2432 $id_mappings['tracker'][$o->getID()] = $t->getID() ;
2433 $t->cloneFieldsFrom ($o->getID()) ;
2438 if (forge_get_config ('use_pm')) {
2439 $this->setUsePM ($template->usesPM()) ;
2440 if ($template->usesPM()) {
2441 $oldpgf = new ProjectGroupFactory ($template) ;
2442 foreach ($oldpgf->getProjectGroups() as $o) {
2443 $pg = new ProjectGroup ($this) ;
2444 $pg->create ($this->replaceTemplateStrings($o->getName()),$this->replaceTemplateStrings($o->getDescription()),$o->isPublic(),$o->getSendAllPostsTo()) ;
2445 $id_mappings['pm'][$o->getID()] = $pg->getID() ;
2450 if (forge_get_config ('use_forum')) {
2451 $this->setUseForum ($template->usesForum()) ;
2452 if ($template->usesForum()) {
2453 $oldff = new ForumFactory ($template) ;
2454 foreach ($oldff->getForums() as $o) {
2455 $f = new Forum ($this) ;
2456 $f->create ($this->replaceTemplateStrings($o->getName()),$this->replaceTemplateStrings($o->getDescription()),$o->isPublic(),$o->getSendAllPostsTo(),1,$o->allowAnonymous(),$o->getModerationLevel()) ;
2457 $id_mappings['forum'][$o->getID()] = $f->getID() ;
2462 if (forge_get_config ('use_docman')) {
2463 $this->setUseDocman ($template->usesDocman()) ;
2464 if ($template->usesDocman()) {
2465 $olddgf = new DocumentGroupFactory ($template) ;
2466 // First pass: create all docgroups
2467 $id_mappings['docman_docgroup'][0] = 0 ;
2468 foreach ($olddgf->getDocumentGroups() as $o) {
2469 $ndgf = new DocumentGroup ($this) ;
2470 $ndgf->create($this->replaceTemplateStrings($o->getName())) ;
2471 $id_mappings['docman_docgroup'][$o->getID()] = $ndgf->getID() ;
2473 // Second pass: restore hierarchy links
2474 foreach ($olddgf->getDocumentGroups() as $o) {
2475 $ndgf = new DocumentGroup ($this) ;
2476 $ndgf->fetchData ($id_mappings['docman_docgroup'][$o->getID()]) ;
2477 $ndgf->update ($ndgf->getName(),$id_mappings['docman_docgroup'][$o->getParentID()]) ;
2482 if (forge_get_config ('use_frs')) {
2483 $this->setUseFRS ($template->usesFRS()) ;
2484 if ($template->usesFRS()) {
2485 foreach (get_frs_packages ($template) as $o) {
2486 $newp = new FRSPackage ($this) ;
2487 $nname = $this->replaceTemplateStrings($o->getName()) ;
2488 $newp->create ($nname, $o->isPublic()) ;
2493 if (forge_get_config ('use_mail')) {
2494 $this->setUseMail ($template->usesMail()) ;
2495 if ($template->usesMail()) {
2496 $oldmlf = new MailingListFactory ($template) ;
2497 foreach ($oldmlf->getMailingLists() as $o) {
2498 $ml = new MailingList ($this) ;
2499 $nname = preg_replace ('/^'.$template->getUnixName().'-/','',$o->getName()) ;
2501 $ndescription = $this->replaceTemplateStrings($o->getDescription()) ;
2502 $ml->create ($nname, $ndescription, $o->isPublic()) ;
2507 $this->setUseSCM ($template->usesSCM()) ;
2509 foreach ($template->getPlugins() as $plugin_id => $plugin_name) {
2510 $this->setPluginUse ($plugin_name) ;
2513 foreach ($template->getRoles() as $oldrole) {
2514 $newrole = RBACEngine::getInstance()->getRoleById ($id_mappings['role'][$oldrole->getID()]) ;
2515 if ($oldrole->getHomeProject() != NULL
2516 && $oldrole->getHomeProject()->getID() == $template->getID()) {
2517 $newrole->setPublic ($oldrole->isPublic()) ;
2519 $oldsettings = $oldrole->getSettingsForProject ($template) ;
2521 $sections = array ('project_read', 'project_admin', 'frs', 'scm', 'docman', 'tracker_admin', 'new_tracker', 'forum_admin', 'new_forum', 'pm_admin', 'new_pm') ;
2522 foreach ($sections as $section) {
2523 $newrole->setSetting ($section, $this->getID(), $oldsettings[$section][$template->getID()]) ;
2526 $sections = array ('tracker', 'pm', 'forum') ;
2527 foreach ($sections as $section) {
2528 if (isset ($oldsettings[$section])) {
2529 foreach ($oldsettings[$section] as $k => $v) {
2530 // Only copy perms for tools that have been copied
2531 if (isset ($id_mappings[$section][$k])) {
2532 $newrole->setSetting ($section,
2533 $id_mappings[$section][$k],
2541 $lm = new WidgetLayoutManager();
2542 $lm->createDefaultLayoutForProject ($this->getID(), $template->getID()) ;
2544 $params = array () ;
2545 $params['template'] = $template ;
2546 $params['project'] = $this ;
2547 $params['id_mappings'] = $id_mappings ;
2548 plugin_hook_by_reference ('clone_project_from_template', $params) ;
2550 // Disable everything
2551 $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',
2553 array ($this->getID())) ;
2556 $this->normalizeAllRoles();
2558 // Switch back to user preference
2559 session_set_internal($saved_session->getID());
2560 setup_gettext_from_context();
2564 $this->sendApprovalEmail();
2565 $this->addHistory('Approved', 'x');
2568 // Plugin can make approve operation there
2570 $params[0] = $idadmin_group;
2571 $params[1] = $this->getID();
2572 plugin_hook('group_approved', $params);
2580 * sendApprovalEmail - Send new project email.
2582 * @return boolean success.
2585 function sendApprovalEmail() {
2586 $admins = RBACEngine::getInstance()->getUsersByAllowedAction ('project_admin', $this->getID()) ;
2588 if (count($admins) < 1) {
2589 $this->setError(_("Group does not have any administrators."));
2593 // send one email per admin
2594 foreach ($admins as $admin) {
2595 setup_gettext_for_user ($admin) ;
2597 $message=sprintf(_('Your project registration for %4$s has been approved.
2599 Project Full Name: %1$s
2600 Project Unix Name: %2$s
2602 Your DNS will take up to a day to become active on our site.
2603 Your web site is accessible through your shell account. Please read
2604 site documentation (see link below) about intended usage, available
2605 services, and directory layout of the account.
2608 own project page in %4$s while logged in, you will find
2609 additional menu functions to your left labeled \'Project Admin\'.
2611 We highly suggest that you now visit %4$s and create a public
2612 description for your project. This can be done by visiting your project
2613 page while logged in, and selecting \'Project Admin\' from the menus
2614 on the left (or by visiting %3$s
2617 Your project will also not appear in the Trove Software Map (primary
2618 list of projects hosted on %4$s which offers great flexibility in
2619 browsing and search) until you categorize it in the project administration
2620 screens. So that people can find your project, you should do this now.
2621 Visit your project while logged in, and select \'Project Admin\' from the
2624 Enjoy the system, and please tell others about %4$s. Let us know
2625 if there is anything we can do to help you.
2628 htmlspecialchars_decode($this->getPublicName()),
2629 $this->getUnixName(),
2630 util_make_url ('/project/admin/?group_id='.$this->getID()),
2631 forge_get_config ('forge_name'));
2633 util_send_message($admin->getEmail(), sprintf(_('%1$s Project Approved'), forge_get_config ('forge_name')), $message);
2635 setup_gettext_from_context();
2643 * sendRejectionEmail - Send project rejection email.
2645 * This function sends out a rejection message to a user who
2646 * registered a project.
2648 * @param int The id of the response to use.
2649 * @param string The rejection message.
2650 * @return boolean completion status.
2653 function sendRejectionEmail($response_id, $message="zxcv") {
2654 $submitters = array () ;
2656 foreach (get_group_join_requests ($this) as $gjr) {
2657 $submitters[] = user_get_object($gjr->getUserID());
2660 $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",
2662 while ($arr = db_fetch_array($res)) {
2663 $submitter[] = user_get_object($arr['user_id']);
2667 if (count ($submitters) < 1) {
2668 $this->setError(_("Group does not have any administrators."));
2672 foreach ($submitters as $admin) {
2673 setup_gettext_for_user($admin);
2675 $response=sprintf(_('Your project registration for %3$s has been denied.
2677 Project Full Name: %1$s
2678 Project Unix Name: %2$s
2680 Reasons for negative decision:
2682 '), $this->getPublicName(), $this->getUnixName(), forge_get_config('forge_name'));
2684 // Check to see if they want to send a custom rejection response
2685 if ($response_id == 0) {
2686 $response .= $message;
2688 $response .= db_result(
2689 db_query_params('SELECT response_text FROM canned_responses WHERE response_id=$1', array ($response_id)),
2694 util_send_message($admin->getEmail(), sprintf(_('%1$s Project Denied'), forge_get_config ('forge_name')), $response);
2695 setup_gettext_from_context();
2702 * sendNewProjectNotificationEmail - Send new project notification email.
2704 * This function sends out a notification email to the
2705 * SourceForge admin user when a new project is
2708 * @return boolean success.
2711 function sendNewProjectNotificationEmail() {
2712 // Get the user who wants to register the project
2713 $submitters = array();
2715 foreach (get_group_join_requests ($this) as $gjr) {
2716 $submitters[] = user_get_object($gjr->getUserID());
2719 $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",
2721 while ($arr = db_fetch_array ($res)) {
2722 $submitter[] = user_get_object($arr['user_id']);
2725 if (count ($submitters) < 1) {
2726 $this->setError(_("Could not find user who has submitted the project."));
2730 $admins = RBACEngine::getInstance()->getUsersByAllowedAction ('approve_projects', -1) ;
2732 if (count($admins) < 1) {
2733 $this->setError(_("There is no administrator to send the mail to."));
2737 foreach ($admins as $admin) {
2738 $admin_email = $admin->getEmail () ;
2739 setup_gettext_for_user ($admin) ;
2741 foreach ($submitters as $u) {
2742 $submitter_names[] = $u->getRealName() ;
2745 $message = sprintf(_('New %1$s Project Submitted
2747 Project Full Name: %2$s
2748 Submitted Description: %3$s
2750 forge_get_config ('forge_name'),
2751 htmlspecialchars_decode($this->getPublicName()),
2752 htmlspecialchars_decode($this->getRegistrationPurpose()));
2754 foreach ($submitters as $submitter) {
2755 $message .= sprintf(_('Submitter: %1$s (%2$s)
2757 $submitter->getRealName(),
2758 $submitter->getUnixName());
2761 $message .= sprintf (_('
2762 Please visit the following URL to approve or reject this project:
2764 util_make_url ('/admin/approve-pending.php')) ;
2765 util_send_message($admin_email, sprintf(_('New %1$s Project Submitted'), forge_get_config ('forge_name')), $message);
2766 setup_gettext_from_context();
2770 $email = $submitter->getEmail() ;
2771 setup_gettext_for_user ($submitter) ;
2773 $message=sprintf(_('New %1$s Project Submitted
2775 Project Full Name: %2$s
2776 Submitted Description: %3$s
2778 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'));
2780 util_send_message($email, sprintf(_('New %1$s Project Submitted'), forge_get_config ('forge_name')), $message);
2781 setup_gettext_from_context();
2790 * validateGroupName - Validate the group name
2792 * @param string Group name.
2794 * @return boolean an error false and set an error is the group name is invalide otherwise return true
2796 function validateGroupName($group_name) {
2797 if (strlen($group_name)<3) {
2798 $this->setError(_('Group name is too short'));
2800 } else if (strlen(htmlspecialchars($group_name))>50) {
2801 $this->setError(_('Group name is too long'));
2803 } else if ($group=group_get_object_by_publicname($group_name)) {
2804 $this->setError(_('Group name already taken'));
2812 * getRoles - Get the roles of the group.
2814 * @return array Role ids of this group.
2816 function getRolesId() {
2817 $role_ids = array();
2820 $res = db_query_params('SELECT role_id FROM pfo_role WHERE home_group_id=$1',
2821 array($this->getID()));
2822 while ($arr = db_fetch_array($res)) {
2823 $role_ids[] = $arr['role_id'];
2825 $res = db_query_params('SELECT role_id FROM role_project_refs WHERE group_id=$1',
2826 array($this->getID()));
2827 while ($arr = db_fetch_array($res)) {
2828 $role_ids[] = $arr['role_id'];
2831 $res = db_query_params('SELECT role_id FROM role WHERE group_id=$1',
2832 array($this->getID()));
2833 while ($arr = db_fetch_array($res)) {
2834 $role_ids[] = $arr['role_id'];
2838 return array_unique($role_ids);
2842 * getRoles - Get the roles of the group.
2844 * @return array Roles of this group.
2846 function getRoles() {
2849 $roles = $this->getRolesId();
2851 $engine = RBACEngine::getInstance();
2852 foreach ($roles as $role_id) {
2853 $result[] = $engine->getRoleById ($role_id);
2856 foreach ($roles as $role_id) {
2857 $result[] = new Role ($this, $role_id);
2864 function normalizeAllRoles() {
2865 $roles = $this->getRoles();
2867 foreach ($roles as $r) {
2868 $r->normalizeData();
2873 * getUnixStatus - Status of activation of unix account.
2875 * @return char (N)one, (A)ctive, (S)uspended or (D)eleted
2877 function getUnixStatus() {
2878 return $this->data_array['unix_status'];
2882 * setUnixStatus - Sets status of activation of unix account.
2884 * @param string The unix status.
2890 * @return boolean success.
2892 function setUnixStatus($status) {
2895 $res = db_query_params ('UPDATE groups SET unix_status=$1 WHERE group_id=$2',
2900 $this->setError(sprintf(_('ERROR - Could Not Update Group Unix Status: %s'),db_error()));
2904 if ($status == 'A') {
2905 if (!$SYS->sysCheckCreateGroup($this->getID())) {
2906 $this->setError($SYS->getErrorMessage());
2911 if ($SYS->sysCheckGroup($this->getID())) {
2912 if (!$SYS->sysRemoveGroup($this->getID())) {
2913 $this->setError($SYS->getErrorMessage());
2920 $this->data_array['unix_status']=$status;
2927 * getUsers - Get the users of a group
2929 * @return array of user's objects.
2931 function getUsers($onlylocal = true) {
2932 if (!isset($this->membersArr)) {
2933 $this->membersArr = array () ;
2937 foreach ($this->getRoles() as $role) {
2939 && ($role->getHomeProject() == NULL || $role->getHomeProject()->getID() != $this->getID())) {
2942 foreach ($role->getUsers() as $user) {
2943 $ids[] = $user->getID() ;
2946 $ids = array_unique ($ids) ;
2947 foreach ($ids as $id) {
2948 $u = user_get_object ($id) ;
2949 if ($u->isActive()) {
2950 $this->membersArr[] = $u ;
2955 $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',
2956 array ($this->getID(),
2958 if (!$users_group_res) {
2959 $this->setError(_('Error: Enable to get users from group'). ' ' . $this->getID() . ' ' .db_error());
2963 for ($i=0; $i<db_numrows($users_group_res); $i++) {
2964 $this->membersArr[$i] = new GFUser(db_result($users_group_res,$i,'user_id'),false);
2969 return $this->membersArr;
2972 function setDocmanCreateOnlineStatus($status) {
2974 /* if we activate search engine, we probably want to reindex */
2975 $res = db_query_params('UPDATE groups SET use_docman_create_online=$1 WHERE group_id=$2',
2976 array($status, $this->getID()));
2979 $this->setError(sprintf(_('ERROR - Could Not Update Group DocmanCreateOnline Status: %s'),db_error()));
2983 $this->data_array['use_docman_create_online']=$status;
2989 function setDocmanWebdav($status) {
2991 /* if we activate search engine, we probably want to reindex */
2992 $res = db_query_params('UPDATE groups SET use_webdav=$1 WHERE group_id=$2',
2997 $this->setError(sprintf(_('ERROR - Could Not Update Group UseWebdab Status: %s'),db_error()));
3001 $this->data_array['use_webdav']=$status;
3007 function setDocmanSearchStatus($status) {
3009 /* if we activate search engine, we probably want to reindex */
3010 $res = db_query_params('UPDATE groups SET use_docman_search=$1, force_docman_reindex=$1 WHERE group_id=$2',
3015 $this->setError(sprintf(_('ERROR - Could Not Update Group UseDocmanSearch Status: %s'),db_error()));
3019 $this->data_array['use_docman_search']=$status;
3025 function setDocmanForceReindexSearch($status) {
3027 /* if we activate search engine, we probably want to reindex */
3028 $res = db_query_params('UPDATE groups SET force_docman_reindex=$1 WHERE group_id=$2',
3033 $this->setError(sprintf(_('ERROR - Could Not Update Group force_docman_reindex %s'),db_error()));
3037 $this->data_array['force_docman_reindex']=$status;
3043 function setStorageAPI($type) {
3047 function getStorageAPI() {
3053 * group_getname() - get the group name
3055 * @param int The group ID
3059 function group_getname ($group_id = 0) {
3060 $grp = group_get_object($group_id);
3062 return $grp->getPublicName();
3069 * group_getunixname() - get the unixname for a group
3071 * @param int The group ID
3075 function group_getunixname ($group_id) {
3076 $grp = group_get_object($group_id);
3078 return $grp->getUnixName();
3085 * group_get_result() - Get the group object result ID.
3087 * @param int The group ID
3091 function &group_get_result($group_id=0) {
3092 $grp = group_get_object($group_id);
3094 return $grp->getData();
3100 function getAllProjectTags($onlyvisible = true) {
3101 $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',
3104 if (!$res || db_numrows($res) == 0) {
3110 while ($arr = db_fetch_array($res)) {
3112 $group_id = $arr[1];
3113 if (!isset($result[$tag])) {
3114 $result[$tag] = array();
3117 if (!$onlyvisible || forge_check_perm('project_read', $group_id)) {
3118 $p = group_get_object($group_id);
3119 $result[$tag][] = array('unix_group_name' => $p->getUnixName(),
3120 'group_id' => $group_id);
3127 class ProjectComparator {
3128 var $criterion = 'name' ;
3130 function Compare ($a, $b) {
3131 switch ($this->criterion) {
3134 $namecmp = strcoll ($a->getPublicName(), $b->getPublicName()) ;
3135 if ($namecmp != 0) {
3138 /* If several projects share a same public name */
3139 return strcoll ($a->getUnixName(), $b->getUnixName()) ;
3142 return strcmp ($a->getUnixName(), $b->getUnixName()) ;
3145 $aid = $a->getID() ;
3146 $bid = $b->getID() ;
3150 return ($a < $b) ? -1 : 1;
3156 function sortProjectList (&$list, $criterion='name') {
3157 $cmp = new ProjectComparator () ;
3158 $cmp->criterion = $criterion ;
3160 return usort ($list, array ($cmp, 'Compare')) ;
3165 // c-file-style: "bsd"