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.
258 * It will add an entry for a pending group/project (status 'P')
260 * @param object The User object.
261 * @param string The full name of the user.
262 * @param string The Unix name of the user.
263 * @param string The new group description.
264 * @param string The purpose of the group.
265 * @param boolean Whether to send an email or not
266 * @param int The id of the project this new project is based on
267 * @return boolean success or not
269 function create(&$user, $group_name, $unix_name, $description, $purpose, $unix_box = 'shell1',
270 $scm_box = 'cvs1', $is_public = 1, $send_mail = true, $built_from_template = 0) {
271 // $user is ignored - anyone can create pending group
274 if ($this->getID()!=0) {
275 $this->setError(_('Group::create: Group object already exists'));
277 } else if (!$this->validateGroupName($group_name)) {
279 } else if (!account_groupnamevalid($unix_name)) {
280 $this->setError(_('Invalid Unix name'));
282 } else if (!$SYS->sysUseUnixName($unix_name)) {
283 $this->setError(_('Unix name already taken'));
285 } else if (db_numrows(db_query_params('SELECT group_id FROM groups WHERE unix_group_name=$1',
286 array($unix_name))) > 0) {
287 $this->setError(_('Unix name already taken'));
289 } else if (strlen($purpose)<10) {
290 $this->setError(_('Please describe your Registration Purpose in a more comprehensive manner'));
292 } else if (strlen($purpose)>1500) {
293 $this->setError(_('The Registration Purpose text is too long. Please make it smaller than 1500 bytes.'));
295 } else if (strlen($description)<10) {
296 $this->setError(_('Describe in a more comprehensive manner your project.'));
298 } else if (strlen($description)>255) {
299 $this->setError(_('Your project description is too long. Please make it smaller than 256 bytes.'));
304 $res = db_query_params('
320 VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)',
321 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 type_id=$1, unix_box=$2, http_domain=$3
431 if (!$res || db_affected_rows($res) < 1) {
432 $this->setError(_('ERROR: DB: Could not change group properties: %s'),db_error());
437 // Log the audit trail
438 if ($type_id != $this->data_array['type_id']) {
439 $this->addHistory('type_id', $this->data_array['type_id']);
441 if ($unix_box != $this->data_array['unix_box']) {
442 $this->addHistory('unix_box', $this->data_array['unix_box']);
444 if ($http_domain != $this->data_array['http_domain']) {
445 $this->addHistory('http_domain', $this->data_array['http_domain']);
448 if (!$this->fetchData($this->getID())) {
457 * update - Update number of common properties.
459 * Unlike updateAdmin(), this function accessible to project admin.
461 * @param object User requesting operation (for access control).
462 * @param boolean Whether group is publicly accessible (0/1).
463 * @param string Project's license (string ident).
464 * @param int Group type (1-project, 2-foundry).
465 * @param string Machine on which group's home directory located.
466 * @param string Domain which serves group's WWW.
467 * @return int status.
470 function update(&$user, $group_name, $homepage, $short_description, $use_mail, $use_survey, $use_forum,
471 $use_pm, $use_pm_depend_box, $use_scm, $use_news, $use_docman,
472 $new_doc_address, $send_all_docs, $logo_image_id,
473 $use_ftp, $use_tracker, $use_frs, $use_stats, $tags, $is_public) {
475 $perm =& $this->getPermission();
477 if (!$perm || !is_object($perm)) {
478 $this->setError(_('Could not get permission.'));
482 if (!$perm->isAdmin()) {
483 $this->setError(_('Permission denied.'));
487 // Validate some values
488 if ($this->getPublicName() != $group_name) {
489 if (!$this->validateGroupName($group_name)) {
494 if ($new_doc_address) {
495 $invalid_mails = validate_emails($new_doc_address);
496 if (count($invalid_mails) > 0) {
497 $this->setError(sprintf(ngettext('New Doc Address Appeared Invalid: %s', 'New Doc Addresses Appeared Invalid: %s', count($invalid_mails)),implode(',',$invalid_mails)));
502 // in the database, these all default to '1',
503 // so we have to explicity set 0
516 if (!$use_pm_depend_box) {
517 $use_pm_depend_box = 0;
540 if (!$send_all_docs) {
544 $homepage = ltrim($homepage);
546 $homepage = util_make_url('/projects/' . $this->getUnixName() . '/');
549 if (strlen(htmlspecialchars($short_description))>255) {
550 $this->setError(_('Error updating project information: Maximum length for Project Description is 255 chars.'));
556 //XXX not yet actived logo_image_id='$logo_image_id',
557 $res = db_query_params('UPDATE groups
560 short_description=$3,
565 use_pm_depend_box=$8,
575 array(htmlspecialchars($group_name),
577 htmlspecialchars($short_description),
594 $this->setError(sprintf(_('Error updating project information: %s'), db_error()));
599 if (!$this->setUseDocman($use_docman)) {
600 $this->setError(sprintf(_('Error updating project information: use_docman %s'), db_error()));
605 if ($this->setTags($tags) === false) {
610 $hook_params = array();
611 $hook_params['group'] = $this;
612 $hook_params['group_id'] = $this->getID();
613 $hook_params['group_homepage'] = $homepage;
614 $hook_params['group_name'] = htmlspecialchars($group_name);
615 $hook_params['group_description'] = htmlspecialchars($short_description);
616 $hook_params['group_ispublic'] = $is_public;
617 if (!plugin_hook("group_update", $hook_params)) {
618 if (!$this->isError()) {
619 $this->setError(_('Error updating project information in plugin_hook group_update'));
625 // Log the audit trail
626 $this->addHistory('Changed Public Info', '');
628 if (!$this->fetchData($this->getID())) {
637 * getID - Simply return the group_id for this object.
639 * @return int group_id.
642 return $this->data_array['group_id'];
646 * getType() - Foundry, project, etc.
648 * @return int The type flag from the database.
651 return $this->data_array['type_id'];
656 * getStatus - the status code.
658 * Statuses char include I,H,A,D,P.
659 * TODO : document what these mean :
666 function getStatus() {
667 return $this->data_array['status'];
671 * setStatus - set the status code.
673 * Statuses include I,H,A,D,P.
674 * TODO : document what these mean :
681 * @param object User requesting operation (for access control).
682 * @param string Status value.
683 * @return boolean success.
686 function setStatus(&$user, $status) {
689 if (!forge_check_global_perm('approve_projects')) {
690 $this->setPermissionDeniedError();
694 // Projects in 'A' status can only go to 'H' or 'D'
695 // Projects in 'D' status can only go to 'A'
696 // Projects in 'P' status can only go to 'A' OR 'D'
697 // Projects in 'I' status can only go to 'P'
698 // Projects in 'H' status can only go to 'A' OR 'D'
699 $allowed_status_changes = array(
700 'AH'=>1,'AD'=>1,'DA'=>1,'PA'=>1,'PD'=>1,
701 'IP'=>1,'HA'=>1,'HD'=>1
704 // Check that status transition is valid
705 if ($this->getStatus() != $status
706 && !$allowed_status_changes[$this->getStatus().$status]) {
707 $this->setError(_('Invalid Status Change'));
713 $res = db_query_params('UPDATE groups
715 WHERE group_id=$2', array($status, $this->getID()));
717 if (!$res || db_affected_rows($res) < 1) {
718 $this->setError(sprintf(_('ERROR: DB: Could not change group status: %s'),db_error()));
724 // Activate system group, if not yet
725 if (!$SYS->sysCheckGroup($this->getID())) {
726 if (!$SYS->sysCreateGroup($this->getID())) {
727 $this->setError($SYS->getErrorMessage());
732 if (!$this->activateUsers()) {
737 /* Otherwise, the group is not active, and make sure that
738 System group is not active either */
739 } else if ($SYS->sysCheckGroup($this->getID())) {
740 if (!$SYS->sysRemoveGroup($this->getID())) {
741 $this->setError($SYS->getErrorMessage());
747 $hook_params = array();
748 $hook_params['group'] = $this;
749 $hook_params['group_id'] = $this->getID();
750 $hook_params['status'] = $status;
751 plugin_hook("group_setstatus", $hook_params);
755 // Log the audit trail
756 if ($status != $this->getStatus()) {
757 $this->addHistory('Status', $this->getStatus());
760 $this->data_array['status'] = $status;
765 * isProject - Simple boolean test to see if it's a project or not.
767 * @return boolean is_project.
769 function isProject() {
770 if ($this->getType()==1) {
778 * isPublic - Wrapper around RBAC to check if a project is anonymously readable
780 * @return boolean is_public.
782 function isPublic() {
783 $ra = RoleAnonymous::getInstance() ;
784 return $ra->hasPermission('project_read', $this->getID());
788 * isActive - Database field status of 'A' returns true.
790 * @return boolean is_active.
792 function isActive() {
793 if ($this->getStatus()=='A') {
801 * isTemplate - Simply returns the is_template flag from the database.
803 * @return boolean is_template.
805 function isTemplate() {
806 return $this->data_array['is_template'];
810 * setAsTemplate - Set the template status of a project
812 * @param boolean is_template.
814 function setAsTemplate($booleanparam) {
816 $booleanparam = $booleanparam ? 1 : 0;
817 $res = db_query_params('UPDATE groups SET is_template=$1 WHERE group_id=$2',
818 array($booleanparam, $this->getID()));
820 $this->data_array['is_template']=$booleanparam;
830 * getTemplateProject - Return the project template this project is built from
832 * @return object The template project
834 function getTemplateProject() {
835 return group_get_object($this->data_array['built_from_template']);
839 * getUnixName - the unix_name
841 * @return string unix_name.
843 function getUnixName() {
844 return strtolower($this->data_array['unix_group_name']);
848 * getPublicName - the full-length public name.
850 * @return string The group_name.
852 function getPublicName() {
853 return $this->data_array['group_name'];
857 * getRegisterPurpose - the text description of the purpose of this project.
859 * @return string The description.
861 function getRegisterPurpose() {
862 return $this->data_array['register_purpose'];
866 * getDescription - the text description of this project.
868 * @return string The description.
870 function getDescription() {
871 return $this->data_array['short_description'];
875 * getStartDate - the unix time this project was registered.
877 * @return int (unix time) of registration.
879 function getStartDate() {
880 return $this->data_array['register_time'];
884 * getLogoImageID - the id of the logo in the database for this project.
886 * @return int The ID of logo image in db_images table (or 100 if none).
888 function getLogoImageID() {
889 return $this->data_array['logo_image_id'];
893 * getUnixBox - the hostname of the unix box where this project is located.
895 * @return string The name of the unix machine for the group.
897 function getUnixBox() {
898 return $this->data_array['unix_box'];
902 * getSCMBox - the hostname of the scm box where this project is located.
904 * @return string The name of the unix machine for the group.
906 function getSCMBox() {
907 return $this->data_array['scm_box'];
910 * setSCMBox - the hostname of the scm box where this project is located.
912 * @param string The name of the new SCM_BOX
914 function setSCMBox($scm_box) {
916 if ($scm_box == $this->data_array['scm_box']) {
921 $res = db_query_params('UPDATE groups SET scm_box=$1 WHERE group_id=$2', array($scm_box, $this->getID ()));
923 $this->addHistory('scm_box', $this->data_array['scm_box']);
924 $this->data_array['scm_box'] = $scm_box;
929 $this->setError(_("Couldn't insert SCM_BOX to database"));
933 $this->setError(_("SCM Box can't be empty"));
939 * getDomain - the hostname.domain where their web page is located.
941 * @return string The name of the group [web] domain.
943 function getDomain() {
944 return $this->data_array['http_domain'];
948 * getRegistrationPurpose - the text description of the purpose of this project.
950 * @return string The application for project hosting.
952 function getRegistrationPurpose() {
953 return $this->data_array['register_purpose'];
958 * getAdmins() - Get array of Admin user objects.
960 * @return array Array of User objects.
962 function &getAdmins() {
963 $roles = RBACEngine::getInstance()->getRolesByAllowedAction ('project_admin', $this->getID());
967 foreach ($roles as $role) {
968 if (! ($role instanceof RoleExplicit)) {
971 if ($role->getHomeProject() == NULL
972 || $role->getHomeProject()->getID() != $this->getID()) {
976 foreach ($role->getUsers() as $u) {
977 $user_ids[] = $u->getID();
980 return user_get_objects(array_unique($user_ids));
984 Common Group preferences for tools
988 * enableAnonSCM - whether or not this group has opted to enable Anonymous SCM.
990 * @return boolean enable_scm.
992 function enableAnonSCM() {
994 $r = RoleAnonymous::getInstance();
995 return $r->hasPermission('scm', $this->getID(), 'read');
997 if ($this->isPublic() && $this->usesSCM()) {
998 return $this->data_array['enable_anonscm'];
1005 function SetUsesAnonSCM($booleanparam) {
1007 $booleanparam = $booleanparam ? 1 : 0;
1009 $r = RoleAnonymous::getInstance();
1010 $r->setSetting('scm', $this->getID(), $booleanparam);
1013 $res = db_query_params('UPDATE groups SET enable_anonscm=$1 WHERE group_id=$2',
1014 array($booleanparam, $this->getID()));
1016 $this->data_array['enable_anonscm'] = $booleanparam;
1026 * enablePserver - whether or not this group has opted to enable Pserver.
1028 * @return boolean enable_pserver.
1030 function enablePserver() {
1031 if ($this->usesSCM()) {
1032 return $this->data_array['enable_pserver'];
1038 function SetUsesPserver($booleanparam) {
1040 $booleanparam = $booleanparam ? 1 : 0;
1041 $res = db_query_params('UPDATE groups SET enable_pserver=$1 WHERE group_id=$2',
1042 array($booleanparam, $this->getID()));
1044 $this->data_array['enable_pserver'] = $booleanparam;
1053 * usesSCM - whether or not this group has opted to use SCM.
1055 * @return boolean uses_scm.
1057 function usesSCM() {
1058 if (forge_get_config('use_scm')) {
1059 return $this->data_array['use_scm'];
1066 * setUseSCM - Set the SCM usage
1068 * @param boolean enabled/disabled
1070 function setUseSCM($booleanparam) {
1072 $booleanparam = $booleanparam ? 1 : 0 ;
1073 $res = db_query_params('UPDATE groups SET use_scm=$1 WHERE group_id=$2',
1074 array($booleanparam, $this->getID()));
1076 $this->data_array['use_scm']=$booleanparam;
1086 * usesMail - whether or not this group has opted to use mailing lists.
1088 * @return boolean uses_mail.
1090 function usesMail() {
1091 if (forge_get_config('use_mail')) {
1092 return $this->data_array['use_mail'];
1099 * setUseMail - Set the mailing-list usage
1101 * @param boolean enabled/disabled
1103 function setUseMail($booleanparam) {
1105 $booleanparam = $booleanparam ? 1 : 0 ;
1106 $res = db_query_params('UPDATE groups SET use_mail=$1 WHERE group_id=$2',
1107 array($booleanparam, $this->getID()));
1109 $this->data_array['use_mail']=$booleanparam;
1119 * usesNews - whether or not this group has opted to use news.
1121 * @return boolean uses_news.
1123 function usesNews() {
1124 if (forge_get_config('use_news')) {
1125 return $this->data_array['use_news'];
1132 * usesForum - whether or not this group has opted to use discussion forums.
1134 * @return boolean uses_forum.
1136 function usesForum() {
1137 if (forge_get_config('use_forum')) {
1138 return $this->data_array['use_forum'];
1145 * setUseForum - Set the forum usage
1147 * @param boolean enabled/disabled
1149 function setUseForum($booleanparam) {
1151 $booleanparam = $booleanparam ? 1 : 0;
1152 $res = db_query_params('UPDATE groups SET use_forum=$1 WHERE group_id=$2',
1153 array($booleanparam, $this->getID()));
1155 $this->data_array['use_forum']=$booleanparam;
1165 * usesStats - whether or not this group has opted to use stats.
1167 * @return boolean uses_stats.
1169 function usesStats() {
1170 return $this->data_array['use_stats'];
1174 * usesFRS - whether or not this group has opted to use file release system.
1176 * @return boolean uses_frs.
1178 function usesFRS() {
1179 if (forge_get_config('use_frs')) {
1180 return $this->data_array['use_frs'];
1187 * setUseFRS - Set the FRS usage
1189 * @param boolean enabled/disabled
1191 function setUseFRS($booleanparam) {
1193 $booleanparam = $booleanparam ? 1 : 0;
1194 $res = db_query_params('UPDATE groups SET use_frs=$1 WHERE group_id=$2',
1195 array ($booleanparam, $this->getID()));
1197 $this->data_array['use_frs']=$booleanparam;
1207 * usesTracker - whether or not this group has opted to use tracker.
1209 * @return boolean uses_tracker.
1211 function usesTracker() {
1212 if (forge_get_config('use_tracker')) {
1213 return $this->data_array['use_tracker'];
1220 * setUseTracker - Set the tracker usage
1222 * @param boolean enabled/disabled
1224 function setUseTracker ($booleanparam) {
1226 $booleanparam = $booleanparam ? 1 : 0 ;
1227 $res = db_query_params ('UPDATE groups SET use_tracker=$1 WHERE group_id=$2',
1228 array ($booleanparam, $this->getID()));
1230 $this->data_array['use_tracker']=$booleanparam;
1240 * useCreateOnline - whether or not this group has opted to use create online documents option.
1242 * @return boolean use_docman_create_online.
1244 function useCreateOnline() {
1245 if (forge_get_config('use_docman')) {
1246 return $this->data_array['use_docman_create_online'];
1253 * usesDocman - whether or not this group has opted to use docman.
1255 * @return boolean use_docman.
1257 function usesDocman() {
1258 if (forge_get_config('use_docman')) {
1259 return $this->data_array['use_docman'];
1266 * setUseDocman - Set the docman usage
1268 * @param boolean enabled/disabled
1270 function setUseDocman($booleanparam) {
1272 $booleanparam = $booleanparam ? 1 : 0;
1273 $res = db_query_params('UPDATE groups SET use_docman = $1 WHERE group_id = $2',
1274 array($booleanparam, $this->getID()));
1276 // check if / doc_group exists, if not create it
1277 $trashdir = db_query_params('select groupname from doc_groups where groupname = $1 and group_id = $2',
1278 array('.trash', $this->getID()));
1279 if ($trashdir && db_numrows($trashdir) == 0) {
1280 $resinsert = db_query_params('insert into doc_groups (groupname, group_id, stateid) values ($1, $2, $3)',
1281 array('.trash', $this->getID(), '2'));
1287 $this->data_array['use_docman'] = $booleanparam;
1297 * useDocmanSearch - whether or not this group has opted to use docman search engine.
1299 * @return boolean use_docman_search.
1301 function useDocmanSearch() {
1302 if (forge_get_config('use_docman')) {
1303 return $this->data_array['use_docman_search'];
1310 * useWebdav - whether or not this group has opted to use webdav interface.
1312 * @return boolean use_docman_search.
1314 function useWebdav() {
1315 if (forge_get_config('use_webdav')) {
1316 return $this->data_array['use_webdav'];
1323 * usesFTP - whether or not this group has opted to use FTP.
1325 * @return boolean uses_ftp.
1327 function usesFTP() {
1328 if (forge_get_config('use_ftp')) {
1329 return $this->data_array['use_ftp'];
1336 * usesSurvey - whether or not this group has opted to use surveys.
1338 * @return boolean uses_survey.
1340 function usesSurvey() {
1341 if (forge_get_config('use_survey')) {
1342 return $this->data_array['use_survey'];
1349 * usesPM - whether or not this group has opted to Project Manager.
1351 * @return boolean uses_projman.
1354 if (forge_get_config('use_pm')) {
1355 return $this->data_array['use_pm'];
1362 * setUsePM - Set the PM usage
1364 * @param boolean enabled/disabled
1366 function setUsePM($booleanparam) {
1368 $booleanparam = $booleanparam ? 1 : 0;
1369 $res = db_query_params('UPDATE groups SET use_pm=$1 WHERE group_id=$2',
1370 array($booleanparam, $this->getID()));
1372 $this->data_array['use_pm']=$booleanparam;
1382 * getPlugins - get a list of all available group plugins
1384 * @return array array containing plugin_id => plugin_name
1386 function getPlugins() {
1387 if (!isset($this->plugins_data)) {
1388 $this->plugins_data = array();
1389 $res = db_query_params('SELECT group_plugin.plugin_id, plugins.plugin_name
1390 FROM group_plugin, plugins
1391 WHERE group_plugin.group_id=$1
1392 AND group_plugin.plugin_id=plugins.plugin_id', array($this->getID()));
1393 $rows = db_numrows($res);
1395 for ($i=0; $i<$rows; $i++) {
1396 $plugin_id = db_result($res, $i, 'plugin_id');
1397 $this->plugins_data[$plugin_id] = db_result($res, $i, 'plugin_name');
1400 return $this->plugins_data;
1404 * usesPlugin - returns true if the group uses a particular plugin
1406 * @param string name of the plugin
1407 * @return boolean whether plugin is being used or not
1409 function usesPlugin($pluginname) {
1410 $plugins_data = $this->getPlugins();
1411 foreach ($plugins_data as $p_id => $p_name) {
1412 if ($p_name == $pluginname) {
1420 * added for Codendi compatibility
1421 * usesServices - returns true if the group uses a particular plugin or feature
1423 * @param string name of the plugin
1424 * @return boolean whether plugin is being used or not
1426 function usesService($feature) {
1427 $plugins_data = $this->getPlugins();
1428 $pm = plugin_manager_get_object();
1429 foreach ($plugins_data as $p_id => $p_name) {
1430 if ($p_name == $feature) {
1433 if ($pm->getPluginByName($p_name)->provide($feature)) {
1441 * setPluginUse - enables/disables plugins for the group
1443 * @param string name of the plugin
1444 * @param boolean the new state
1445 * @return string database result
1447 function setPluginUse($pluginname, $val=true) {
1448 if ($val == $this->usesPlugin($pluginname)) {
1449 // State is already good, returning
1452 $res = db_query_params('SELECT plugin_id FROM plugins WHERE plugin_name=$1',
1453 array($pluginname));
1454 $rows = db_numrows($res);
1456 // Error: no plugin by that name
1459 $plugin_id = db_result($res,0,'plugin_id');
1461 unset($this->plugins_data);
1463 $res = db_query_params('INSERT INTO group_plugin (group_id, plugin_id) VALUES ($1, $2)',
1464 array($this->getID(),
1468 $res = db_query_params('DELETE FROM group_plugin WHERE group_id=$1 AND plugin_id=$2',
1469 array($this->getID(),
1476 * getDocEmailAddress - get email address(es) to send doc notifications to.
1478 * @return string email address.
1480 function getDocEmailAddress() {
1481 return $this->data_array['new_doc_address'];
1485 * DocEmailAll - whether or not this group has opted to use receive notices on all doc updates.
1487 * @return boolean email_on_all_doc_updates.
1489 function docEmailAll() {
1490 return $this->data_array['send_all_docs'];
1495 * getHomePage - The URL for this project's home page.
1497 * @return string homepage URL.
1499 function getHomePage() {
1500 return $this->data_array['homepage'];
1504 * getTags - Tags of this project.
1506 * @return string List of tags. Comma separated
1508 function getTags() {
1509 $sql = 'SELECT name FROM project_tags WHERE group_id = $1';
1510 $res = db_query_params($sql, array($this->getID()));
1511 return join(', ', util_result_column_to_array($res));
1515 * setTags - Set tags of this project.
1517 * @return string database result.
1519 function setTags($tags) {
1521 $sql = 'DELETE FROM project_tags WHERE group_id=$1';
1522 $res = db_query_params($sql, array($this->getID()));
1524 $this->setError('Deleting old tags: '.db_error());
1528 $inserted = array();
1529 $tags_array = preg_split('/[;,]/', $tags);
1530 foreach ($tags_array as $tag) {
1531 $tag = preg_replace('/[\t\r\n]/', ' ', $tag);
1532 // Allowed caracteres: [A-Z][a-z][0-9] -_&'#+.
1533 if (preg_match('/[^[:alnum:]| |\-|_|\&|\'|#|\+|\.]/', $tag)) {
1534 $this->setError(_('Bad tag name, you only can use the following characters: [A-Z][a-z][0-9]-_&\'#+. and space'));
1539 if ($tag == '' || array_search($tag, $inserted) !== false) continue;
1540 $sql = 'INSERT INTO project_tags (group_id,name) VALUES ($1, $2)';
1541 $res = db_query_params($sql, array($this->getID(), $tag));
1543 $this->setError(_('Setting tags: ').db_error());
1554 * getPermission - Return a Permission for this Group
1556 * @return object The Permission.
1558 function &getPermission() {
1559 return permission_get_object($this);
1563 function delete($sure, $really_sure, $really_really_sure) {
1564 if (!$sure || !$really_sure || !$really_really_sure) {
1565 $this->setMissingParamsError(_('Please tick all checkboxes.'));
1568 if ($this->getID() == forge_get_config('news_group') ||
1569 $this->getID() == 1 ||
1570 $this->getID() == forge_get_config('stats_group') ||
1571 $this->getID() == forge_get_config('peer_rating_group')) {
1572 $this->setError(_('Cannot Delete System Group'));
1575 $perm =& $this->getPermission();
1576 if (!$perm || !is_object($perm)) {
1577 $this->setPermissionDeniedError();
1579 } elseif ($perm->isError()) {
1580 $this->setPermissionDeniedError();
1582 } elseif (!$perm->isSuperUser()) {
1583 $this->setPermissionDeniedError();
1589 // Remove all the members
1591 $members =& $this->getMembers();
1592 foreach ($members as $i) {
1593 if(!$this->removeUser($i->getID())) {
1594 $this->setError(_('Could not properly remove member:').' '.$i->getID());
1598 // Failsafe until user_group table is gone
1599 $res = db_query_params('DELETE FROM user_group WHERE group_id=$1',
1600 array($this->getID()));
1602 // unlink roles from this project
1603 $ra = RoleAnonymous::getInstance();
1604 $rl = RoleLoggedIn::getInstance();
1605 $ra->unlinkProject($this);
1606 $rl->unlinkProject($this);
1607 // @todo : unlink all the other roles created in the project...
1612 $atf = new ArtifactTypeFactory($this);
1613 $at_arr =& $atf->getArtifactTypes();
1614 foreach ($at_arr as $i) {
1615 if (!is_object($i)) {
1618 if (!$i->delete(1,1)) {
1619 $this->setError(_('Could not properly delete the tracker:').' '.$i->getErrorMessage());
1626 $ff = new ForumFactory($this);
1627 $f_arr =& $ff->getForums();
1628 foreach ($f_arr as $i) {
1629 if (!is_object($i)) {
1632 if(!$i->delete(1,1)) {
1633 $this->setError(_('Could not properly delete the forum:').' '.$i->getErrorMessage());
1638 // Delete Subprojects
1640 $pgf = new ProjectGroupFactory($this);
1641 $pg_arr =& $pgf->getProjectGroups();
1642 foreach ($pg_arr as $i) {
1643 if (!is_object($i)) {
1646 if (!$i->delete(1,1)) {
1647 $this->setError(_('Could not properly delete the ProjectGroup:').' '.$i->getErrorMessage());
1652 // Delete FRS Packages
1654 $res = db_query_params('SELECT * FROM frs_package WHERE group_id=$1',
1655 array($this->getID()));
1656 while ($arr = db_fetch_array($res)) {
1657 $frsp=new FRSPackage($this, $arr['package_id'], $arr);
1658 if (!$frsp->delete(1, 1)) {
1659 $this->setError(_('Could not properly delete the FRSPackage:').' '.$frsp->getErrorMessage());
1666 $news_group=group_get_object(forge_get_config('news_group'));
1667 $res = db_query_params('SELECT forum_id FROM news_bytes WHERE group_id=$1',
1668 array($this->getID()));
1670 $this->setError(_('Error Deleting News: ').db_error());
1675 for ($i=0; $i<db_numrows($res); $i++) {
1676 $Forum = new Forum($news_group,db_result($res,$i,'forum_id'));
1677 if (!$Forum->delete(1,1)) {
1678 $this->setError(_("Could Not Delete News Forum: %d"),$Forum->getID());
1682 $res = db_query_params('DELETE FROM news_bytes WHERE group_id=$1',
1683 array($this->getID()));
1685 $this->setError(_('Error Deleting News: ').db_error());
1693 $res = db_query_params('DELETE FROM doc_data WHERE group_id=$1',
1694 array($this->getID()));
1696 $this->setError(_('Error Deleting Documents: ').db_error());
1701 $res = db_query_params('DELETE FROM doc_groups WHERE group_id=$1',
1702 array($this->getID()));
1704 $this->setError(_('Error Deleting Documents: ').db_error());
1712 $res=db_query_params('DELETE FROM project_tags WHERE group_id=$1', array($this->getID()));
1714 $this->setError(_('Error Deleting Tags: ').db_error());
1720 // Delete group history
1722 $res = db_query_params('DELETE FROM group_history WHERE group_id=$1',
1723 array($this->getID()));
1725 $this->setError(_('Error Deleting Project History: ').db_error());
1731 // Delete group plugins
1733 $res = db_query_params('DELETE FROM group_plugin WHERE group_id=$1',
1734 array($this->getID()));
1736 $this->setError(_('Error Deleting Project Plugins: ').db_error());
1742 // Delete group cvs stats
1744 $res = db_query_params ('DELETE FROM stats_cvs_group WHERE group_id=$1',
1745 array ($this->getID())) ;
1747 $this->setError(_('Error Deleting SCM Statistics: ').db_error());
1755 $sf = new SurveyFactory($this);
1756 $s_arr =& $sf->getSurveys();
1757 foreach ($s_arr as $i) {
1758 if (!is_object($i)) {
1761 if (!$i->delete()) {
1762 $this->setError(_('Could not properly delete the survey'));
1767 // Delete SurveyQuestions
1769 $sqf = new SurveyQuestionFactory($this);
1770 $sq_arr =& $sqf->getSurveyQuestions();
1771 foreach ($sq_arr as $i) {
1772 if (!is_object($i)) {
1775 if (!$i->delete()) {
1776 $this->setError(_('Could not properly delete the survey questions'));
1781 // Delete Mailing List Factory
1783 $mlf = new MailingListFactory($this);
1784 $ml_arr =& $mlf->getMailingLists();
1785 foreach ($ml_arr as $i) {
1786 if (!is_object($i)) {
1789 if (!$i->delete(1,1)) {
1790 $this->setError(_('Could not properly delete the mailing list'));
1797 $res = db_query_params('DELETE FROM trove_group_link WHERE group_id=$1',
1798 array($this->getID()));
1800 $this->setError(_('Error Deleting Trove: ').db_error());
1805 $res = db_query_params('DELETE FROM trove_agg WHERE group_id=$1',
1806 array($this->getID()));
1808 $this->setError(_('Error Deleting Trove: ').db_error());
1816 $res = db_query_params('DELETE FROM project_sums_agg WHERE group_id=$1',
1817 array($this->getID()));
1819 $this->setError(_('Error Deleting Counters: ').db_error());
1824 $res = db_query_params('INSERT INTO deleted_groups (unix_group_name, delete_date, isdeleted) VALUES ($1, $2, $3)',
1825 array($this->getUnixName(),
1829 $this->setError(_('Error Deleting Project:').' '.db_error());
1834 $res = db_query_params('DELETE FROM groups WHERE group_id=$1',
1835 array($this->getID()));
1837 $this->setError(_('Error Deleting Project:').' '.db_error());
1844 $hook_params = array();
1845 $hook_params['group'] = $this;
1846 $hook_params['group_id'] = $this->getID();
1847 plugin_hook("group_delete", $hook_params);
1849 if (forge_get_config('upload_dir') != '' && $this->getUnixName()) {
1850 exec('/bin/rm -rf '.forge_get_config('upload_dir').'/'.$this->getUnixName().'/');
1852 if (forge_get_config('ftp_upload_dir') != '' && $this->getUnixName()) {
1853 exec('/bin/rm -rf '.forge_get_config('ftp_upload_dir').'/'.$this->getUnixName().'/');
1858 $res = db_query_params('DELETE FROM rep_group_act_monthly WHERE group_id=$1',
1859 array ($this->getID()));
1860 //echo 'rep_group_act_monthly'.db_error();
1861 $res = db_query_params('DELETE FROM rep_group_act_weekly WHERE group_id=$1',
1862 array ($this->getID()));
1863 //echo 'rep_group_act_weekly'.db_error();
1864 $res = db_query_params('DELETE FROM rep_group_act_daily WHERE group_id=$1',
1865 array ($this->getID()));
1866 //echo 'rep_group_act_daily'.db_error();
1867 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());
1942 if (!$SYS->sysGroupCheckUser($this->getID(),$user_id)) {
1943 $this->setError($SYS->getErrorMessage());
1947 } else { // NOT USE_PFO_RBAC
1950 // if not already a member, add them
1952 $res_member = db_query_params('SELECT user_id
1954 WHERE user_id=$1 AND group_id=$2',
1955 array($user_id, $this->getID()));
1957 if (db_numrows($res_member) < 1) {
1959 // Create this user's row in the user_group table
1961 $res = db_query_params('INSERT INTO user_group
1962 (user_id,group_id,admin_flags,forum_flags,project_flags,
1963 doc_flags,cvs_flags,member_role,release_flags,artifact_flags)
1964 VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)',
1976 //verify the insert worked
1977 if (!$res || db_affected_rows($res) < 1) {
1978 $this->setError(sprintf(_('ERROR: Could Not Add User To Group: %s'),db_error()));
1983 // check and create if group doesn't exists
1985 //echo "<h2>Group::addUser SYS->sysCheckCreateGroup(".$this->getID().")</h2>";
1986 if (!$SYS->sysCheckCreateGroup($this->getID())){
1987 $this->setError($SYS->getErrorMessage());
1992 // check and create if user doesn't exists
1994 //echo "<h2>Group::addUser SYS->sysCheckCreateUser($user_id)</h2>";
1995 if (!$SYS->sysCheckCreateUser($user_id)) {
1996 $this->setError($SYS->getErrorMessage());
2003 //echo "<h2>Group::addUser role->setUser($user_id)</h2>";
2004 if (!$role->setUser($user_id)) {
2005 $this->setError('addUser::role::setUser'.$role->getErrorMessage());
2011 // user was already a member
2012 // make sure they are set up
2014 $user= user_get_object($user_id,$res_newuser);
2015 $user->fetchData($user->getID());
2016 $role = new Role($this,$role_id);
2017 if (!$role || !is_object($role)) {
2018 $this->setError(_('Error Getting Role Object'));
2021 } elseif ($role->isError()) {
2022 $this->setError('addUser::roleget::'.$role->getErrorMessage());
2026 //echo "<h2>Already Member Group::addUser role->setUser($user_id)</h2>";
2027 if (!$role->setUser($user_id)) {
2028 $this->setError('addUser::role::setUser'.$role->getErrorMessage());
2033 // set up their system info
2035 //echo "<h2>Already Member Group::addUser SYS->sysCheckCreateUser($user_id)</h2>";
2036 if (!$SYS->sysCheckCreateUser($user_id)) {
2037 $this->setError($SYS->getErrorMessage());
2045 // user doesn't exist
2047 $this->setError(_('ERROR: User does not exist'));
2052 $hook_params['group'] = $this;
2053 $hook_params['group_id'] = $this->getID();
2054 $hook_params['user'] = &user_get_object($user_id);
2055 $hook_params['user_id'] = $user_id;
2056 plugin_hook ("group_adduser", $hook_params);
2061 $this->addHistory('Added User',$user_identifier);
2067 * removeUser - controls removing a user from a group.
2069 * Users can remove themselves.
2071 * @param int The ID of the user to remove.
2072 * @return boolean success.
2074 function removeUser($user_id) {
2077 if ($user_id != user_getid()
2078 || !forge_check_perm('project_admin', $this->getID())) {
2079 $this->setPermissionDeniedError();
2086 $user = user_get_object($user_id);
2087 $roles = RBACEngine::getInstance()->getAvailableRolesForUser($user);
2089 foreach ($roles as $role) {
2090 if ($role->getHomeProject() && $role->getHomeProject()->getID() == $this->getID()) {
2091 $found_role = $role;
2095 if ($found_role == NULL) {
2096 $this->setError(sprintf(_('ERROR: User not removed: %s')));
2100 $found_role->removeUser($user);
2101 if (!$SYS->sysGroupCheckUser($this->getID(), $user_id)) {
2102 $this->setError($SYS->getErrorMessage());
2108 $res = db_query_params('DELETE FROM user_group WHERE group_id=$1 AND user_id=$2',
2109 array($this->getID(),
2111 if (!$res || db_affected_rows($res) < 1) {
2112 $this->setError(_('ERROR: User not removed:').' '.db_error());
2119 // reassign open artifacts to id=100
2121 $res = db_query_params('UPDATE artifact SET assigned_to=100
2122 WHERE group_artifact_id
2123 IN (SELECT group_artifact_id
2124 FROM artifact_group_list
2125 WHERE group_id=$1 AND status_id=1 AND assigned_to=$2)',
2126 array($this->getID(),
2129 $this->setError(_('ERROR: DB: artifact:').' '.db_error());
2135 // reassign open tasks to id=100
2136 // first have to purge any assignments that would cause
2137 // conflict with existing assignment to 100
2139 $res = db_query_params('DELETE FROM project_assigned_to
2140 WHERE project_task_id IN (SELECT pt.project_task_id
2141 FROM project_task pt, project_group_list pgl, project_assigned_to pat
2142 WHERE pt.group_project_id = pgl.group_project_id
2143 AND pat.project_task_id=pt.project_task_id
2144 AND pt.status_id=1 AND pgl.group_id=$1
2145 AND pat.assigned_to_id=$2)
2146 AND assigned_to_id=100',
2147 array($this->getID(),
2150 $this->setError(sprintf(_('ERROR: DB: project_assigned_to %d: %s'), 1, db_error()));
2154 $res = db_query_params('UPDATE project_assigned_to SET assigned_to_id=100
2155 WHERE project_task_id IN (SELECT pt.project_task_id
2156 FROM project_task pt, project_group_list pgl
2157 WHERE pt.group_project_id = pgl.group_project_id
2158 AND pt.status_id=1 AND pgl.group_id=$1)
2159 AND assigned_to_id=$2',
2160 array($this->getID(),
2163 $this->setError(sprintf(_('ERROR: DB: project_assigned_to %d: %s'), 2, db_error()));
2169 // Remove user from system
2171 if (!$SYS->sysGroupRemoveUser($this->getID(), $user_id)) {
2172 $this->setError($SYS->getErrorMessage());
2177 $hook_params['group'] = $this;
2178 $hook_params['group_id'] = $this->getID();
2179 $hook_params['user'] = user_get_object($user_id);
2180 $hook_params['user_id'] = $user_id;
2181 plugin_hook ("group_removeuser", $hook_params);
2184 $this->addHistory('Removed User',$user_id);
2191 * updateUser - controls updating a user's role in this group.
2193 * @param int The ID of the user.
2194 * @param int The role_id to set this user to.
2195 * @return boolean success.
2197 function updateUser($user_id,$role_id) {
2200 if (!forge_check_perm ('project_admin', $this->getID())) {
2201 $this->setPermissionDeniedError();
2206 $newrole = RBACEngine::getInstance()->getRoleById ($role_id) ;
2207 if (!$newrole || !is_object($newrole)) {
2208 $this->setError(_('Could Not Get Role'));
2210 } elseif ($newrole->isError()) {
2211 $this->setError(sprintf(_('Role: %s'),$role->getErrorMessage()));
2213 } elseif ($newrole->getHomeProject() == NULL
2214 || $newrole->getHomeProject()->getID() != $this->getID()) {
2215 $this->setError(_('Wrong destination role'));
2218 $user = user_get_object ($user_id) ;
2219 $roles = RBACEngine::getInstance()->getAvailableRolesForUser ($user) ;
2220 $found_role = NULL ;
2221 foreach ($roles as $role) {
2222 if ($role->getHomeProject() && $role->getHomeProject()->getID() == $this->getID()) {
2223 $found_role = $role ;
2227 if ($found_role == NULL) {
2228 $this->setError(sprintf(_('ERROR: User not removed: %s')));
2232 $found_role->removeUser ($user) ;
2233 $newrole->addUser ($user) ;
2235 $role = new Role($this,$role_id);
2236 if (!$role || !is_object($role)) {
2237 $this->setError(_('Could Not Get Role'));
2239 } elseif ($role->isError()) {
2240 $this->setError(sprintf(_('Role: %s'),$role->getErrorMessage()));
2243 //echo "<h3>Group::updateUser role->setUser($user_id)</h3>";
2244 if (!$role->setUser($user_id)) {
2245 $this->setError(sprintf(_('Role: %s'),$role->getErrorMessage()));
2250 $this->addHistory('Updated User',$user_id);
2255 * addHistory - Makes an audit trail entry for this project.
2257 * @param string The name of the field.
2258 * @param string The Old Value for this $field_name.
2259 * @return database result handle.
2262 function addHistory($field_name, $old_value) {
2263 return db_query_params ('INSERT INTO group_history(group_id,field_name,old_value,mod_by,adddate)
2264 VALUES ($1,$2,$3,$4,$5)',
2265 array ($this->getID(),
2273 * activateUsers - Make sure that group members have unix accounts.
2275 * Setup unix accounts for group members. Can be called even
2276 * if members are already active.
2280 function activateUsers() {
2282 Activate member(s) of the project
2286 $members = $this->getUsers (true) ;
2288 foreach ($members as $member) {
2290 foreach (RBACEngine::getInstance()->getAvailableRolesForUser ($member) as $role) {
2291 if ($role->getHomeProject() && $role->getHomeProject()->getID() == $this->getID()) {
2294 if (!$this->addUser($member->getUnixName(),$role->getID())) {
2301 $res_member = db_query_params('SELECT user_id,role_id FROM user_group WHERE group_id=$1',
2302 array ($this->getID()));
2303 while ($row_member = db_fetch_array($res_member)) {
2304 $u = user_get_object($row_member['user_id']);
2305 if (!$this->addUser($u->getUnixName(),$row_member['role_id'])) {
2315 * getMembers - returns array of User objects for this project
2317 * @return array of User objects for this group.
2319 function getMembers() {
2320 return $this->getUsers (true) ;
2324 * replaceTemplateStrings - fill-in some blanks with project name
2326 * @param string Template string
2327 * @return string String after replacements
2329 function replaceTemplateStrings($string) {
2330 $string = str_replace ('UNIXNAME', $this->getUnixName(), $string) ;
2331 $string = str_replace ('PUBLICNAME', $this->getPublicName(), $string) ;
2332 $string = str_replace ('DESCRIPTION', $this->getDescription(), $string) ;
2337 * approve - Approve pending project.
2339 * @param object The User object who is doing the updating.
2342 function approve(&$user) {
2344 require_once $gfcommon.'widget/WidgetLayoutManager.class.php';
2346 if ($this->getStatus()=='A') {
2347 $this->setError(_("Group already active"));
2353 // Step 1: Activate group and create LDAP entries
2354 if (!$this->setStatus($user, 'A')) {
2359 // Switch to system language for item creation
2360 setup_gettext_from_sys_lang();
2362 // Create default roles
2364 $idadmin_group = NULL;
2365 foreach (get_group_join_requests ($this) as $gjr) {
2366 $idadmin_group = $gjr->getUserID();
2369 if ($idadmin_group == NULL) {
2370 $idadmin_group = $user->getID();
2373 $admin_group = db_query_params('SELECT user_id FROM user_group WHERE group_id=$1 AND admin_flags=$2',
2374 array($this->getID(),
2376 if (db_numrows($admin_group) > 0) {
2377 $idadmin_group = db_result($admin_group,0,'user_id');
2379 $idadmin_group = $user->getID();
2380 db_query_params('INSERT INTO user_group (user_id, group_id, admin_flags) VALUES ($1, $2, $3)',
2381 array($idadmin_group,
2387 $template = $this->getTemplateProject();
2388 $id_mappings = array();
2389 $seen_local_roles = false;
2391 // Copy roles from template project
2392 foreach($template->getRoles() as $oldrole) {
2393 if ($oldrole->getHomeProject() != NULL) {
2394 $role = new Role($this);
2396 // Need to use a different role name so that the permissions aren't set from the hardcoded defaults
2397 $role->create('TEMPORARY ROLE NAME', $data, true);
2398 $role->setName($oldrole->getName());
2399 $seen_local_roles = true;
2402 $role->linkProject($this);
2404 $id_mappings['role'][$oldrole->getID()] = $role->getID();
2405 // Reuse the project_admin permission
2406 $role->setSetting ('project_admin', $this->getID(), $oldrole->getSetting ('project_admin', $template->getID())) ;
2410 if (!$seen_local_roles) {
2411 $role = new Role($this);
2412 $adminperms = array ('project_admin' => array ($this->getID() => 1)) ;
2413 $role_id = $role->create ('Admin', $adminperms, true) ;
2417 $roles = $this->getRoles() ;
2418 foreach ($roles as $r) {
2419 if ($r->getSetting ('project_admin', $this->getID())) {
2420 $r->addUser(user_get_object ($idadmin_group));
2425 // Temporarily switch to the submitter's identity
2426 $saved_session = session_get_user();
2427 session_set_internal($idadmin_group);
2430 if (forge_get_config('use_tracker')) {
2431 $this->setUseTracker ($template->usesTracker());
2432 if ($template->usesTracker()) {
2433 $oldatf = new ArtifactTypeFactory($template);
2434 foreach ($oldatf->getArtifactTypes() as $o) {
2435 $t = new ArtifactType ($this) ;
2436 $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()) ;
2437 $id_mappings['tracker'][$o->getID()] = $t->getID();
2438 $t->cloneFieldsFrom ($o->getID());
2443 if (forge_get_config('use_pm')) {
2444 $this->setUsePM ($template->usesPM());
2445 if ($template->usesPM()) {
2446 $oldpgf = new ProjectGroupFactory($template);
2447 foreach ($oldpgf->getProjectGroups() as $o) {
2448 $pg = new ProjectGroup($this);
2449 $pg->create($this->replaceTemplateStrings($o->getName()),$this->replaceTemplateStrings($o->getDescription()),$o->isPublic(),$o->getSendAllPostsTo());
2450 $id_mappings['pm'][$o->getID()] = $pg->getID();
2455 if (forge_get_config('use_forum')) {
2456 $this->setUseForum($template->usesForum()) ;
2457 if ($template->usesForum()) {
2458 $oldff = new ForumFactory($template) ;
2459 foreach ($oldff->getForums() as $o) {
2460 $f = new Forum($this);
2461 $f->create($this->replaceTemplateStrings($o->getName()),$this->replaceTemplateStrings($o->getDescription()),$o->isPublic(),$o->getSendAllPostsTo(),1,$o->allowAnonymous(),$o->getModerationLevel());
2462 $id_mappings['forum'][$o->getID()] = $f->getID();
2467 if (forge_get_config('use_docman')) {
2468 $this->setUseDocman($template->usesDocman());
2469 if ($template->usesDocman()) {
2470 $olddgf = new DocumentGroupFactory($template);
2471 // First pass: create all docgroups
2472 $id_mappings['docman_docgroup'][0] = 0;
2473 foreach ($olddgf->getDocumentGroups() as $o) {
2474 $ndgf = new DocumentGroup($this);
2475 // .trash is a reserved directory
2476 if ($o->getName() != '.trash' && $o->getParentID() == 0) {
2477 $ndgf->create($this->replaceTemplateStrings($o->getName()));
2478 $id_mappings['docman_docgroup'][$o->getID()] = $ndgf->getID();
2481 // Second pass: restore hierarchy links
2482 foreach ($olddgf->getDocumentGroups() as $o) {
2483 $ndgf = new DocumentGroup($this);
2484 if ($o->getName() != '.trash' && $o->getParentID() == 0) {
2485 $ndgf->fetchData($id_mappings['docman_docgroup'][$o->getID()]);
2486 $ndgf->update($ndgf->getName(), $id_mappings['docman_docgroup'][$o->getParentID()]);
2492 if (forge_get_config('use_frs')) {
2493 $this->setUseFRS ($template->usesFRS());
2494 if ($template->usesFRS()) {
2495 foreach (get_frs_packages($template) as $o) {
2496 $newp = new FRSPackage($this);
2497 $nname = $this->replaceTemplateStrings($o->getName());
2498 $newp->create ($nname, $o->isPublic());
2503 if (forge_get_config('use_mail')) {
2504 $this->setUseMail($template->usesMail()) ;
2505 if ($template->usesMail()) {
2506 $oldmlf = new MailingListFactory($template);
2507 foreach ($oldmlf->getMailingLists() as $o) {
2508 $ml = new MailingList($this);
2509 $nname = preg_replace ('/^'.$template->getUnixName().'-/','',$o->getName()) ;
2511 $ndescription = $this->replaceTemplateStrings($o->getDescription()) ;
2512 $ml->create($nname, $ndescription, $o->isPublic());
2517 $this->setUseSCM ($template->usesSCM()) ;
2519 foreach ($template->getPlugins() as $plugin_id => $plugin_name) {
2520 $this->setPluginUse ($plugin_name) ;
2523 foreach ($template->getRoles() as $oldrole) {
2524 $newrole = RBACEngine::getInstance()->getRoleById ($id_mappings['role'][$oldrole->getID()]) ;
2525 if ($oldrole->getHomeProject() != NULL
2526 && $oldrole->getHomeProject()->getID() == $template->getID()) {
2527 $newrole->setPublic ($oldrole->isPublic()) ;
2529 $oldsettings = $oldrole->getSettingsForProject ($template) ;
2531 $sections = array ('project_read', 'project_admin', 'frs', 'scm', 'docman', 'tracker_admin', 'new_tracker', 'forum_admin', 'new_forum', 'pm_admin', 'new_pm') ;
2532 foreach ($sections as $section) {
2533 $newrole->setSetting ($section, $this->getID(), $oldsettings[$section][$template->getID()]) ;
2536 $sections = array ('tracker', 'pm', 'forum') ;
2537 foreach ($sections as $section) {
2538 if (isset ($oldsettings[$section])) {
2539 foreach ($oldsettings[$section] as $k => $v) {
2540 // Only copy perms for tools that have been copied
2541 if (isset ($id_mappings[$section][$k])) {
2542 $newrole->setSetting ($section,
2543 $id_mappings[$section][$k],
2551 $lm = new WidgetLayoutManager();
2552 $lm->createDefaultLayoutForProject ($this->getID(), $template->getID()) ;
2554 $params = array () ;
2555 $params['template'] = $template ;
2556 $params['project'] = $this ;
2557 $params['id_mappings'] = $id_mappings ;
2558 plugin_hook_by_reference ('clone_project_from_template', $params) ;
2560 // Disable everything
2561 $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, use_ftp=0, use_tracker=0, use_frs=0, use_stats=0 WHERE group_id=$1',
2563 array ($this->getID())) ;
2566 $this->normalizeAllRoles();
2567 $this->activateUsers();
2569 // Switch back to user preference
2570 session_set_internal($saved_session->getID());
2571 setup_gettext_from_context();
2575 $this->sendApprovalEmail();
2576 $this->addHistory('Approved', 'x');
2579 // Plugin can make approve operation there
2581 $params[0] = $idadmin_group;
2582 $params[1] = $this->getID();
2583 plugin_hook('group_approved', $params);
2591 * sendApprovalEmail - Send new project email.
2593 * @return boolean success.
2596 function sendApprovalEmail() {
2597 $admins = RBACEngine::getInstance()->getUsersByAllowedAction ('project_admin', $this->getID()) ;
2599 if (count($admins) < 1) {
2600 $this->setError(_("Group does not have any administrators."));
2604 // send one email per admin
2605 foreach ($admins as $admin) {
2606 setup_gettext_for_user ($admin) ;
2608 $message=sprintf(_('Your project registration for %4$s has been approved.
2610 Project Full Name: %1$s
2611 Project Unix Name: %2$s
2613 Your DNS will take up to a day to become active on our site.
2614 Your web site is accessible through your shell account. Please read
2615 site documentation (see link below) about intended usage, available
2616 services, and directory layout of the account.
2619 own project page in %4$s while logged in, you will find
2620 additional menu functions to your left labeled \'Project Admin\'.
2622 We highly suggest that you now visit %4$s and create a public
2623 description for your project. This can be done by visiting your project
2624 page while logged in, and selecting \'Project Admin\' from the menus
2625 on the left (or by visiting %3$s
2628 Your project will also not appear in the Trove Software Map (primary
2629 list of projects hosted on %4$s which offers great flexibility in
2630 browsing and search) until you categorize it in the project administration
2631 screens. So that people can find your project, you should do this now.
2632 Visit your project while logged in, and select \'Project Admin\' from the
2635 Enjoy the system, and please tell others about %4$s. Let us know
2636 if there is anything we can do to help you.
2639 htmlspecialchars_decode($this->getPublicName()),
2640 $this->getUnixName(),
2641 util_make_url ('/project/admin/?group_id='.$this->getID()),
2642 forge_get_config ('forge_name'));
2644 util_send_message($admin->getEmail(), sprintf(_('%1$s Project Approved'), forge_get_config ('forge_name')), $message);
2646 setup_gettext_from_context();
2654 * sendRejectionEmail - Send project rejection email.
2656 * This function sends out a rejection message to a user who
2657 * registered a project.
2659 * @param int The id of the response to use.
2660 * @param string The rejection message.
2661 * @return boolean completion status.
2664 function sendRejectionEmail($response_id, $message="zxcv") {
2665 $submitters = array () ;
2667 foreach (get_group_join_requests ($this) as $gjr) {
2668 $submitters[] = user_get_object($gjr->getUserID());
2671 $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",
2673 while ($arr = db_fetch_array($res)) {
2674 $submitter[] = user_get_object($arr['user_id']);
2678 if (count ($submitters) < 1) {
2679 $this->setError(_("Group does not have any administrators."));
2683 foreach ($submitters as $admin) {
2684 setup_gettext_for_user($admin);
2686 $response=sprintf(_('Your project registration for %3$s has been denied.
2688 Project Full Name: %1$s
2689 Project Unix Name: %2$s
2691 Reasons for negative decision:
2693 '), $this->getPublicName(), $this->getUnixName(), forge_get_config('forge_name'));
2695 // Check to see if they want to send a custom rejection response
2696 if ($response_id == 0) {
2697 $response .= $message;
2699 $response .= db_result(
2700 db_query_params('SELECT response_text FROM canned_responses WHERE response_id=$1', array ($response_id)),
2705 util_send_message($admin->getEmail(), sprintf(_('%1$s Project Denied'), forge_get_config ('forge_name')), $response);
2706 setup_gettext_from_context();
2713 * sendNewProjectNotificationEmail - Send new project notification email.
2715 * This function sends out a notification email to the
2716 * SourceForge admin user when a new project is
2719 * @return boolean success.
2722 function sendNewProjectNotificationEmail() {
2723 // Get the user who wants to register the project
2724 $submitters = array();
2726 foreach (get_group_join_requests ($this) as $gjr) {
2727 $submitters[] = user_get_object($gjr->getUserID());
2730 $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",
2732 while ($arr = db_fetch_array ($res)) {
2733 $submitter[] = user_get_object($arr['user_id']);
2736 if (count ($submitters) < 1) {
2737 $this->setError(_("Could not find user who has submitted the project."));
2741 $admins = RBACEngine::getInstance()->getUsersByAllowedAction ('approve_projects', -1) ;
2743 if (count($admins) < 1) {
2744 $this->setError(_("There is no administrator to send the mail to."));
2748 foreach ($admins as $admin) {
2749 $admin_email = $admin->getEmail () ;
2750 setup_gettext_for_user ($admin) ;
2752 foreach ($submitters as $u) {
2753 $submitter_names[] = $u->getRealName() ;
2756 $message = sprintf(_('New %1$s Project Submitted
2758 Project Full Name: %2$s
2759 Submitted Description: %3$s
2761 forge_get_config ('forge_name'),
2762 htmlspecialchars_decode($this->getPublicName()),
2763 htmlspecialchars_decode($this->getRegistrationPurpose()));
2765 foreach ($submitters as $submitter) {
2766 $message .= sprintf(_('Submitter: %1$s (%2$s)
2768 $submitter->getRealName(),
2769 $submitter->getUnixName());
2772 $message .= sprintf (_('
2773 Please visit the following URL to approve or reject this project:
2775 util_make_url ('/admin/approve-pending.php')) ;
2776 util_send_message($admin_email, sprintf(_('New %1$s Project Submitted'), forge_get_config ('forge_name')), $message);
2777 setup_gettext_from_context();
2781 $email = $submitter->getEmail() ;
2782 setup_gettext_for_user ($submitter) ;
2784 $message=sprintf(_('New %1$s Project Submitted
2786 Project Full Name: %2$s
2787 Submitted Description: %3$s
2789 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'));
2791 util_send_message($email, sprintf(_('New %1$s Project Submitted'), forge_get_config ('forge_name')), $message);
2792 setup_gettext_from_context();
2801 * validateGroupName - Validate the group name
2803 * @param string Group name.
2805 * @return boolean an error false and set an error is the group name is invalide otherwise return true
2807 function validateGroupName($group_name) {
2808 if (strlen($group_name)<3) {
2809 $this->setError(_('Group name is too short'));
2811 } else if (strlen(htmlspecialchars($group_name))>50) {
2812 $this->setError(_('Group name is too long'));
2814 } else if ($group=group_get_object_by_publicname($group_name)) {
2815 $this->setError(_('Group name already taken'));
2823 * getRoles - Get the roles of the group.
2825 * @return array Role ids of this group.
2827 function getRolesId() {
2828 $role_ids = array();
2831 $res = db_query_params('SELECT role_id FROM pfo_role WHERE home_group_id=$1',
2832 array($this->getID()));
2833 while ($arr = db_fetch_array($res)) {
2834 $role_ids[] = $arr['role_id'];
2836 $res = db_query_params('SELECT role_id FROM role_project_refs WHERE group_id=$1',
2837 array($this->getID()));
2838 while ($arr = db_fetch_array($res)) {
2839 $role_ids[] = $arr['role_id'];
2842 $res = db_query_params('SELECT role_id FROM role WHERE group_id=$1',
2843 array($this->getID()));
2844 while ($arr = db_fetch_array($res)) {
2845 $role_ids[] = $arr['role_id'];
2849 return array_unique($role_ids);
2853 * getRoles - Get the roles of the group.
2855 * @return array Roles of this group.
2857 function getRoles() {
2860 $roles = $this->getRolesId();
2862 $engine = RBACEngine::getInstance();
2863 foreach ($roles as $role_id) {
2864 $result[] = $engine->getRoleById ($role_id);
2867 foreach ($roles as $role_id) {
2868 $result[] = new Role ($this, $role_id);
2875 function normalizeAllRoles() {
2876 $roles = $this->getRoles();
2878 foreach ($roles as $r) {
2879 $r->normalizeData();
2884 * getUnixStatus - Status of activation of unix account.
2886 * @return char (N)one, (A)ctive, (S)uspended or (D)eleted
2888 function getUnixStatus() {
2889 return $this->data_array['unix_status'];
2893 * setUnixStatus - Sets status of activation of unix account.
2895 * @param string The unix status.
2901 * @return boolean success.
2903 function setUnixStatus($status) {
2906 $res = db_query_params ('UPDATE groups SET unix_status=$1 WHERE group_id=$2',
2911 $this->setError(sprintf(_('ERROR - Could Not Update Group Unix Status: %s'),db_error()));
2915 if ($status == 'A') {
2916 if (!$SYS->sysCheckCreateGroup($this->getID())) {
2917 $this->setError($SYS->getErrorMessage());
2922 if ($SYS->sysCheckGroup($this->getID())) {
2923 if (!$SYS->sysRemoveGroup($this->getID())) {
2924 $this->setError($SYS->getErrorMessage());
2931 $this->data_array['unix_status']=$status;
2938 * getUsers - Get the users of a group
2940 * @return array of user's objects.
2942 function getUsers($onlylocal = true) {
2943 if (!isset($this->membersArr)) {
2944 $this->membersArr = array () ;
2948 foreach ($this->getRoles() as $role) {
2950 && ($role->getHomeProject() == NULL || $role->getHomeProject()->getID() != $this->getID())) {
2953 foreach ($role->getUsers() as $user) {
2954 $ids[] = $user->getID() ;
2957 $ids = array_unique ($ids) ;
2958 foreach ($ids as $id) {
2959 $u = user_get_object ($id) ;
2960 if ($u->isActive()) {
2961 $this->membersArr[] = $u ;
2966 $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',
2967 array ($this->getID(),
2969 if (!$users_group_res) {
2970 $this->setError(_('Error: Enable to get users from group'). ' ' . $this->getID() . ' ' .db_error());
2974 for ($i=0; $i<db_numrows($users_group_res); $i++) {
2975 $this->membersArr[$i] = new GFUser(db_result($users_group_res,$i,'user_id'),false);
2980 return $this->membersArr;
2983 function setDocmanCreateOnlineStatus($status) {
2985 /* if we activate search engine, we probably want to reindex */
2986 $res = db_query_params('UPDATE groups SET use_docman_create_online=$1 WHERE group_id=$2',
2987 array($status, $this->getID()));
2990 $this->setError(sprintf(_('ERROR - Could Not Update Group DocmanCreateOnline Status: %s'),db_error()));
2994 $this->data_array['use_docman_create_online']=$status;
3000 function setDocmanWebdav($status) {
3002 /* if we activate search engine, we probably want to reindex */
3003 $res = db_query_params('UPDATE groups SET use_webdav=$1 WHERE group_id=$2',
3008 $this->setError(sprintf(_('ERROR - Could Not Update Group UseWebdab Status: %s'),db_error()));
3012 $this->data_array['use_webdav']=$status;
3018 function setDocmanSearchStatus($status) {
3020 /* if we activate search engine, we probably want to reindex */
3021 $res = db_query_params('UPDATE groups SET use_docman_search=$1, force_docman_reindex=$1 WHERE group_id=$2',
3026 $this->setError(sprintf(_('ERROR - Could Not Update Group UseDocmanSearch Status: %s'),db_error()));
3030 $this->data_array['use_docman_search']=$status;
3036 function setDocmanForceReindexSearch($status) {
3038 /* if we activate search engine, we probably want to reindex */
3039 $res = db_query_params('UPDATE groups SET force_docman_reindex=$1 WHERE group_id=$2',
3044 $this->setError(sprintf(_('ERROR - Could Not Update Group force_docman_reindex %s'),db_error()));
3048 $this->data_array['force_docman_reindex']=$status;
3054 function setStorageAPI($type) {
3058 function getStorageAPI() {
3064 * group_getname() - get the group name
3066 * @param int The group ID
3070 function group_getname ($group_id = 0) {
3071 $grp = group_get_object($group_id);
3073 return $grp->getPublicName();
3080 * group_getunixname() - get the unixname for a group
3082 * @param int The group ID
3086 function group_getunixname ($group_id) {
3087 $grp = group_get_object($group_id);
3089 return $grp->getUnixName();
3096 * group_get_result() - Get the group object result ID.
3098 * @param int The group ID
3102 function &group_get_result($group_id=0) {
3103 $grp = group_get_object($group_id);
3105 return $grp->getData();
3111 function getAllProjectTags($onlyvisible = true) {
3112 $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',
3115 if (!$res || db_numrows($res) == 0) {
3121 while ($arr = db_fetch_array($res)) {
3123 $group_id = $arr[1];
3124 if (!isset($result[$tag])) {
3125 $result[$tag] = array();
3128 if (!$onlyvisible || forge_check_perm('project_read', $group_id)) {
3129 $p = group_get_object($group_id);
3130 $result[$tag][] = array('unix_group_name' => $p->getUnixName(),
3131 'group_id' => $group_id);
3139 * Utility class to compare project based in various criteria (names, unixnames, id, ...)
3142 class ProjectComparator {
3143 var $criterion = 'name' ;
3145 function Compare ($a, $b) {
3146 switch ($this->criterion) {
3149 $namecmp = strcoll ($a->getPublicName(), $b->getPublicName()) ;
3150 if ($namecmp != 0) {
3153 /* If several projects share a same public name */
3154 return strcoll ($a->getUnixName(), $b->getUnixName()) ;
3157 return strcmp ($a->getUnixName(), $b->getUnixName()) ;
3160 $aid = $a->getID() ;
3161 $bid = $b->getID() ;
3165 return ($a < $b) ? -1 : 1;
3171 function sortProjectList (&$list, $criterion='name') {
3172 $cmp = new ProjectComparator () ;
3173 $cmp->criterion = $criterion ;
3175 return usort ($list, array ($cmp, 'Compare')) ;
3180 // c-file-style: "bsd"