[ Index ] |
PHP Cross Reference of Eventum |
[Summary view] [Print] [Text view]
1 <?php 2 /* vim: set expandtab tabstop=4 shiftwidth=4 encoding=utf-8: */ 3 // +----------------------------------------------------------------------+ 4 // | Eventum - Issue Tracking System | 5 // +----------------------------------------------------------------------+ 6 // | Copyright (c) 2003, 2004, 2005, 2006, 2007 MySQL AB | 7 // | | 8 // | This program is free software; you can redistribute it and/or modify | 9 // | it under the terms of the GNU General Public License as published by | 10 // | the Free Software Foundation; either version 2 of the License, or | 11 // | (at your option) any later version. | 12 // | | 13 // | This program is distributed in the hope that it will be useful, | 14 // | but WITHOUT ANY WARRANTY; without even the implied warranty of | 15 // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 16 // | GNU General Public License for more details. | 17 // | | 18 // | You should have received a copy of the GNU General Public License | 19 // | along with this program; if not, write to: | 20 // | | 21 // | Free Software Foundation, Inc. | 22 // | 59 Temple Place - Suite 330 | 23 // | Boston, MA 02111-1307, USA. | 24 // +----------------------------------------------------------------------+ 25 // | Authors: João Prado Maia <jpm@mysql.com> | 26 // +----------------------------------------------------------------------+ 27 // 28 // @(#) $Id: class.project.php 3246 2007-02-09 09:10:12Z glen $ 29 // 30 31 require_once (APP_INC_PATH . "class.error_handler.php"); 32 require_once (APP_INC_PATH . "class.misc.php"); 33 require_once (APP_INC_PATH . "class.group.php"); 34 require_once (APP_INC_PATH . "class.validation.php"); 35 require_once (APP_INC_PATH . "class.date.php"); 36 require_once (APP_INC_PATH . "class.category.php"); 37 require_once (APP_INC_PATH . "class.release.php"); 38 require_once (APP_INC_PATH . "class.filter.php"); 39 require_once (APP_INC_PATH . "class.support.php"); 40 require_once (APP_INC_PATH . "class.issue.php"); 41 require_once (APP_INC_PATH . "class.status.php"); 42 require_once (APP_INC_PATH . "class.display_column.php"); 43 44 /** 45 * Class to handle the business logic related to the administration 46 * of projects in the system. 47 * 48 * @version 1.0 49 * @author João Prado Maia <jpm@mysql.com> 50 */ 51 52 class Project 53 { 54 /** 55 * Method used to get the outgoing email sender address associated with 56 * a given project. 57 * 58 * @access public 59 * @param integer $prj_id The project ID 60 * @return array The outgoing sender information 61 */ 62 function getOutgoingSenderAddress($prj_id) 63 { 64 $stmt = "SELECT 65 prj_outgoing_sender_name, 66 prj_outgoing_sender_email 67 FROM 68 " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "project 69 WHERE 70 prj_id=" . Misc::escapeInteger($prj_id); 71 $res = $GLOBALS["db_api"]->dbh->getRow($stmt, DB_FETCHMODE_ASSOC); 72 if (PEAR::isError($res)) { 73 Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__); 74 return array( 75 'name' => '', 76 'email' => '' 77 ); 78 } else { 79 if (!empty($res)) { 80 return array( 81 'name' => $res['prj_outgoing_sender_name'], 82 'email' => $res['prj_outgoing_sender_email'] 83 ); 84 } else { 85 return array( 86 'name' => '', 87 'email' => '' 88 ); 89 } 90 } 91 } 92 93 94 /** 95 * Method used to get the initial status that should be set to a new issue 96 * created and associated with a given project. 97 * 98 * @access public 99 * @param integer $prj_id The project ID 100 * @return integer The status ID 101 */ 102 function getInitialStatus($prj_id) 103 { 104 $stmt = "SELECT 105 prj_initial_sta_id 106 FROM 107 " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "project 108 WHERE 109 prj_id=" . Misc::escapeInteger($prj_id); 110 $res = $GLOBALS["db_api"]->dbh->getOne($stmt); 111 if (PEAR::isError($res)) { 112 Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__); 113 return ""; 114 } else { 115 return $res; 116 } 117 } 118 119 120 /** 121 * Method used to get the options related to the anonymous posting 122 * of new issues. 123 * 124 * @access public 125 * @param integer $prj_id The project ID 126 * @return array The anonymous posting options 127 */ 128 function getAnonymousPostOptions($prj_id) 129 { 130 $stmt = "SELECT 131 prj_anonymous_post_options 132 FROM 133 " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "project 134 WHERE 135 prj_id=" . Misc::escapeInteger($prj_id); 136 $res = $GLOBALS["db_api"]->dbh->getOne($stmt); 137 if (PEAR::isError($res)) { 138 Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__); 139 return ""; 140 } else { 141 if (!is_string($res)) { 142 $res = (string) $res; 143 } 144 return @unserialize($res); 145 } 146 } 147 148 149 /** 150 * Method used to update the anonymous posting related options. 151 * 152 * @access public 153 * @param integer $prj_id The project ID 154 * @return integer 1 if the update worked, -1 otherwise 155 */ 156 function updateAnonymousPost($prj_id) 157 { 158 $stmt = "UPDATE 159 " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "project 160 SET 161 prj_anonymous_post='" . Misc::escapeString($_POST["anonymous_post"]) . "', 162 prj_anonymous_post_options='" . Misc::escapeString(@serialize($_POST["options"])) . "' 163 WHERE 164 prj_id=" . Misc::escapeInteger($prj_id); 165 $res = $GLOBALS["db_api"]->dbh->query($stmt); 166 if (PEAR::isError($res)) { 167 Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__); 168 return -1; 169 } else { 170 return 1; 171 } 172 } 173 174 175 /** 176 * Method used to get the list of projects that allow anonymous 177 * posting of new issues. 178 * 179 * @access public 180 * @return array The list of projects 181 */ 182 function getAnonymousList() 183 { 184 $stmt = "SELECT 185 prj_id, 186 prj_title 187 FROM 188 " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "project 189 WHERE 190 prj_anonymous_post='enabled' 191 ORDER BY 192 prj_title"; 193 $res = $GLOBALS["db_api"]->dbh->getAssoc($stmt); 194 if (PEAR::isError($res)) { 195 Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__); 196 return ""; 197 } else { 198 return $res; 199 } 200 } 201 202 203 /** 204 * Method used to check whether a project exists or not. 205 * 206 * @access public 207 * @param integer $prj_id The project ID 208 * @return boolean 209 */ 210 function exists($prj_id) 211 { 212 $stmt = "SELECT 213 COUNT(*) AS total 214 FROM 215 " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "project 216 WHERE 217 prj_id=" . Misc::escapeInteger($prj_id); 218 $res = $GLOBALS["db_api"]->dbh->getOne($stmt); 219 if (PEAR::isError($res)) { 220 Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__); 221 return false; 222 } else { 223 if ($res > 0) { 224 return true; 225 } else { 226 return false; 227 } 228 } 229 } 230 231 232 /** 233 * Method used to get the project ID of the given project title. 234 * 235 * @access public 236 * @param string $prj_title The project title 237 * @return integer The project ID 238 */ 239 function getID($prj_title) 240 { 241 $stmt = "SELECT 242 prj_id 243 FROM 244 " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "project 245 WHERE 246 prj_title='" . Misc::escapeString($prj_title) . "'"; 247 $res = $GLOBALS["db_api"]->dbh->getOne($stmt); 248 if (PEAR::isError($res)) { 249 Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__); 250 return ""; 251 } else { 252 return $res; 253 } 254 } 255 256 257 /** 258 * Method used to get the title of a given project ID. 259 * 260 * @access public 261 * @param integer $prj_id The project ID 262 * @return string The project title 263 */ 264 function getName($prj_id) 265 { 266 static $returns; 267 268 if (!empty($returns[$prj_id])) { 269 return $returns[$prj_id]; 270 } 271 272 $stmt = "SELECT 273 prj_title 274 FROM 275 " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "project 276 WHERE 277 prj_id=" . Misc::escapeInteger($prj_id); 278 $res = $GLOBALS["db_api"]->dbh->getOne($stmt); 279 if (PEAR::isError($res)) { 280 Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__); 281 return ""; 282 } else { 283 $returns[$prj_id] = $res; 284 return $res; 285 } 286 } 287 288 289 /** 290 * Method used to get if reporters should be segregated for a project ID 291 * 292 * @access public 293 * @param integer $prj_id The project ID 294 * @return boolean If reporters should be segregated 295 */ 296 function getSegregateReporters($prj_id) 297 { 298 static $returns; 299 300 if (!empty($returns[$prj_id])) { 301 return $returns[$prj_id]; 302 } 303 304 $stmt = "SELECT 305 prj_segregate_reporter 306 FROM 307 " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "project 308 WHERE 309 prj_id=" . Misc::escapeInteger($prj_id); 310 $res = $GLOBALS["db_api"]->dbh->getOne($stmt); 311 if (PEAR::isError($res)) { 312 Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__); 313 return true; 314 } else { 315 if ($res == 1) { 316 $res = true; 317 } else { 318 $res = false; 319 } 320 $returns[$prj_id] = $res; 321 return $res; 322 } 323 } 324 325 326 /** 327 * Method used to get the details for a given project ID. 328 * 329 * @access public 330 * @param integer $prj_id The project ID 331 * @return array The project details 332 */ 333 function getDetails($prj_id) 334 { 335 $stmt = "SELECT 336 * 337 FROM 338 " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "project 339 WHERE 340 prj_id=" . Misc::escapeInteger($prj_id); 341 $res = $GLOBALS["db_api"]->dbh->getRow($stmt, DB_FETCHMODE_ASSOC); 342 if (PEAR::isError($res)) { 343 Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__); 344 return ""; 345 } else { 346 $res["prj_assigned_users"] = Project::getUserColList($res["prj_id"]); 347 $res['assigned_statuses'] = array_keys(Status::getAssocStatusList($res['prj_id'])); 348 return $res; 349 } 350 } 351 352 353 /** 354 * Method used to remove a given set of projects from the system. 355 * 356 * @access public 357 * @return boolean 358 */ 359 function remove() 360 { 361 $items = @implode(", ", Misc::escapeInteger($_POST["items"])); 362 $stmt = "DELETE FROM 363 " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "project 364 WHERE 365 prj_id IN ($items)"; 366 $res = $GLOBALS["db_api"]->dbh->query($stmt); 367 if (PEAR::isError($res)) { 368 Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__); 369 return false; 370 } else { 371 Project::removeUserByProjects($_POST["items"]); 372 Category::removeByProjects($_POST["items"]); 373 Release::removeByProjects($_POST["items"]); 374 Filter::removeByProjects($_POST["items"]); 375 Email_Account::removeAccountByProjects($_POST["items"]); 376 Issue::removeByProjects($_POST["items"]); 377 Custom_Field::removeByProjects($_POST["items"]); 378 $statuses = array_keys(Status::getAssocStatusList($_POST["items"])); 379 foreach ($_POST["items"] as $prj_id) { 380 Status::removeProjectAssociations($statuses, $prj_id); 381 } 382 Group::disassociateProjects($_POST["items"]); 383 return true; 384 } 385 } 386 387 388 /** 389 * Method used to remove all project/user associations for a given 390 * set of projects. 391 * 392 * @access public 393 * @param array $ids The project IDs 394 * @param array $users_to_not_remove Users that should not be removed 395 * @return boolean 396 */ 397 function removeUserByProjects($ids, $users_to_not_remove = false) 398 { 399 $items = @implode(", ", Misc::escapeInteger($ids)); 400 $stmt = "DELETE FROM 401 " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "project_user 402 WHERE 403 pru_prj_id IN ($items)"; 404 if ($users_to_not_remove != false) { 405 $stmt .= " AND\n pru_usr_id NOT IN(" . join(', ', Misc::escapeInteger($users_to_not_remove)) . ")"; 406 } 407 $res = $GLOBALS["db_api"]->dbh->query($stmt); 408 if (PEAR::isError($res)) { 409 Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__); 410 return false; 411 } else { 412 return true; 413 } 414 } 415 416 417 /** 418 * Method used to update the details of the project information. 419 * 420 * @access public 421 * @return integer 1 if the update worked, -1 otherwise 422 */ 423 function update() 424 { 425 if (Validation::isWhitespace($_POST["title"])) { 426 return -2; 427 } 428 $stmt = "UPDATE 429 " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "project 430 SET 431 prj_title='" . Misc::escapeString($_POST["title"]) . "', 432 prj_status='" . Misc::escapeString($_POST["status"]) . "', 433 prj_lead_usr_id=" . Misc::escapeInteger($_POST["lead_usr_id"]) . ", 434 prj_initial_sta_id=" . Misc::escapeInteger($_POST["initial_status"]) . ", 435 prj_outgoing_sender_name='" . Misc::escapeString($_POST["outgoing_sender_name"]) . "', 436 prj_outgoing_sender_email='" . Misc::escapeString($_POST["outgoing_sender_email"]) . "', 437 prj_remote_invocation='" . Misc::escapeString($_POST["remote_invocation"]) . "', 438 prj_segregate_reporter='" . Misc::escapeString($_POST["segregate_reporter"]) . "', 439 prj_customer_backend='" . Misc::escapeString($_POST["customer_backend"]) . "', 440 prj_workflow_backend='" . Misc::escapeString($_POST["workflow_backend"]) . "' 441 WHERE 442 prj_id=" . Misc::escapeInteger($_POST["id"]); 443 $res = $GLOBALS["db_api"]->dbh->query($stmt); 444 if (PEAR::isError($res)) { 445 Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__); 446 return -1; 447 } else { 448 Project::removeUserByProjects(array($_POST["id"]), $_POST["users"]); 449 for ($i = 0; $i < count($_POST["users"]); $i++) { 450 if ($_POST["users"][$i] == $_POST["lead_usr_id"]) { 451 Project::associateUser($_POST["id"], $_POST["users"][$i], User::getRoleID("Manager")); 452 } elseif (User::getRoleByUser($_POST["users"][$i], $_POST["id"]) == '') { 453 // users who are now being associated with this project should be set to 'Standard User' 454 Project::associateUser($_POST["id"], $_POST["users"][$i], User::getRoleID("Standard User")); 455 } 456 } 457 $statuses = array_keys(Status::getAssocStatusList($_POST["id"])); 458 if (count($statuses) > 0) { 459 Status::removeProjectAssociations($statuses, $_POST["id"]); 460 } 461 foreach ($_POST['statuses'] as $sta_id) { 462 Status::addProjectAssociation($sta_id, $_POST["id"]); 463 } 464 return 1; 465 } 466 } 467 468 469 /** 470 * Method used to associate an user to a project. If the user association already exists 471 * no change will be made. 472 * 473 * @access public 474 * @param integer $prj_id The project ID 475 * @param integer $usr_id The user ID 476 * @param integer $role The role of the user 477 * @return boolean 478 */ 479 function associateUser($prj_id, $usr_id, $role) 480 { 481 $prj_id = Misc::escapeInteger($prj_id); 482 $usr_id = Misc::escapeInteger($usr_id); 483 // see if association already exists 484 $sql = "SELECT 485 pru_id 486 FROM 487 " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "project_user 488 WHERE 489 pru_prj_id = $prj_id AND 490 pru_usr_id = $usr_id"; 491 $res = $GLOBALS["db_api"]->dbh->getOne($sql); 492 if (PEAR::isError($res)) { 493 Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__); 494 return false; 495 } else { 496 if (empty($res)) { 497 $stmt = "INSERT INTO 498 " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "project_user 499 ( 500 pru_usr_id, 501 pru_prj_id, 502 pru_role 503 ) VALUES ( 504 $usr_id, 505 $prj_id, 506 " . Misc::escapeInteger($role) . " 507 )"; 508 $res = $GLOBALS["db_api"]->dbh->query($stmt); 509 if (PEAR::isError($res)) { 510 Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__); 511 return false; 512 } else { 513 return true; 514 } 515 } 516 return true; 517 } 518 } 519 520 521 /** 522 * Method used to add a new project to the system. 523 * 524 * @access public 525 * @return integer 1 if the update worked, -1 or -2 otherwise 526 */ 527 function insert() 528 { 529 if (Validation::isWhitespace($_POST["title"])) { 530 return -2; 531 } 532 $stmt = "INSERT INTO 533 " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "project 534 ( 535 prj_created_date, 536 prj_title, 537 prj_status, 538 prj_lead_usr_id, 539 prj_initial_sta_id, 540 prj_outgoing_sender_name, 541 prj_outgoing_sender_email, 542 prj_remote_invocation, 543 prj_customer_backend, 544 prj_workflow_backend 545 ) VALUES ( 546 '" . Date_API::getCurrentDateGMT() . "', 547 '" . Misc::escapeString($_POST["title"]) . "', 548 '" . Misc::escapeString($_POST["status"]) . "', 549 " . Misc::escapeInteger($_POST["lead_usr_id"]) . ", 550 " . Misc::escapeInteger($_POST["initial_status"]) . ", 551 '" . Misc::escapeString($_POST["outgoing_sender_name"]) . "', 552 '" . Misc::escapeString($_POST["outgoing_sender_email"]) . "', 553 '" . Misc::escapeString($_POST["remote_invocation"]) . "', 554 '" . Misc::escapeString($_POST["customer_backend"]) . "', 555 '" . Misc::escapeString($_POST["workflow_backend"]) . "' 556 )"; 557 $res = $GLOBALS["db_api"]->dbh->query($stmt); 558 if (PEAR::isError($res)) { 559 Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__); 560 return -1; 561 } else { 562 $new_prj_id = $GLOBALS["db_api"]->get_last_insert_id(); 563 for ($i = 0; $i < count($_POST["users"]); $i++) { 564 if ($_POST["users"][$i] == $_POST["lead_usr_id"]) { 565 $role_id = User::getRoleID("Manager"); 566 } else { 567 $role_id = User::getRoleID("Standard User"); 568 } 569 Project::associateUser($new_prj_id, $_POST["users"][$i], $role_id); 570 } 571 foreach ($_POST['statuses'] as $sta_id) { 572 Status::addProjectAssociation($sta_id, $new_prj_id); 573 } 574 Display_Column::setupNewProject($new_prj_id); 575 576 return 1; 577 } 578 } 579 580 581 /** 582 * Method used to get the list of projects available in the 583 * system. 584 * 585 * @access public 586 * @return array The list of projects 587 */ 588 function getList() 589 { 590 $stmt = "SELECT 591 prj_id, 592 prj_title, 593 prj_status, 594 usr_full_name 595 FROM 596 " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "project, 597 " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "user 598 WHERE 599 prj_lead_usr_id=usr_id 600 ORDER BY 601 prj_title"; 602 $res = $GLOBALS["db_api"]->dbh->getAll($stmt, DB_FETCHMODE_ASSOC); 603 if (PEAR::isError($res)) { 604 Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__); 605 return ""; 606 } else { 607 return $res; 608 } 609 } 610 611 612 /** 613 * Method used to get an associative array of project ID and title 614 * of all projects available in the system to a given user ID. 615 * 616 * @access public 617 * @param integer $usr_id The user ID 618 * @param boolean $force_refresh If the cache should not be used. 619 * @param boolean $include_role if the user role should be included. 620 * @return array The list of projects 621 */ 622 function getAssocList($usr_id, $force_refresh = false, $include_role = false) 623 { 624 static $returns; 625 626 if ((!empty($returns[$usr_id][$include_role])) && ($force_refresh != true)) { 627 return $returns[$usr_id][$include_role]; 628 } 629 630 $stmt = "SELECT 631 prj_id, 632 prj_title"; 633 if ($include_role) { 634 $stmt .= ",\npru_role"; 635 } 636 $stmt .= " 637 FROM 638 " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "project, 639 " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "project_user 640 WHERE 641 prj_id=pru_prj_id AND 642 pru_usr_id=" . Misc::escapeInteger($usr_id) . " 643 ORDER BY 644 prj_title"; 645 if ($include_role) { 646 $res = $GLOBALS["db_api"]->dbh->getAssoc($stmt, true, array(), DB_FETCHMODE_ASSOC); 647 } else { 648 $res = $GLOBALS["db_api"]->dbh->getAssoc($stmt); 649 } 650 if (PEAR::isError($res)) { 651 Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__); 652 return ""; 653 } else { 654 if ($include_role) { 655 foreach ($res as $prj_id => $data) { 656 $res[$prj_id]['role'] = User::getRole($data['pru_role']); 657 } 658 } 659 $returns[$usr_id][$include_role] = $res; 660 return $res; 661 } 662 } 663 664 665 /** 666 * Method used to get the list of users associated with a given project. 667 * 668 * @access public 669 * @param integer $prj_id The project ID 670 * @param string $status The desired user status 671 * @param integer $role The role ID of the user 672 * @return array The list of users 673 */ 674 function getUserAssocList($prj_id, $status = NULL, $role = NULL) 675 { 676 $stmt = "SELECT 677 usr_id, 678 usr_full_name 679 FROM 680 " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "user, 681 " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "project_user 682 WHERE 683 pru_prj_id=" . Misc::escapeInteger($prj_id) . " AND 684 pru_usr_id=usr_id AND 685 usr_id != " . APP_SYSTEM_USER_ID; 686 if ($status != NULL) { 687 $stmt .= " AND usr_status='active' "; 688 } 689 if ($role != NULL) { 690 $stmt .= " AND pru_role > " . Misc::escapeInteger($role); 691 } 692 $stmt .= " 693 ORDER BY 694 usr_full_name ASC"; 695 $res = $GLOBALS["db_api"]->dbh->getAssoc($stmt); 696 if (PEAR::isError($res)) { 697 Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__); 698 return ""; 699 } else { 700 return $res; 701 } 702 } 703 704 705 /** 706 * Method used to get a list of user IDs associated with a given 707 * project. 708 * 709 * @access public 710 * @param integer $prj_id The project ID 711 * @return array The list of user IDs 712 */ 713 function getUserColList($prj_id) 714 { 715 $stmt = "SELECT 716 usr_id 717 FROM 718 " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "user, 719 " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "project_user 720 WHERE 721 pru_prj_id=" . Misc::escapeInteger($prj_id) . " AND 722 pru_usr_id=usr_id 723 ORDER BY 724 usr_full_name ASC"; 725 $res = $GLOBALS["db_api"]->dbh->getCol($stmt); 726 if (PEAR::isError($res)) { 727 Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__); 728 return ""; 729 } else { 730 return $res; 731 } 732 } 733 734 735 /** 736 * Method used to get an associative array of project ID and title 737 * of all projects that exist in the system. 738 * 739 * @access public 740 * @param boolean $include_no_customer_association Whether to include in the results projects with customer integration or not 741 * @return array List of projects 742 */ 743 function getAll($include_no_customer_association = TRUE) 744 { 745 $stmt = "SELECT 746 prj_id, 747 prj_title 748 FROM 749 " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "project"; 750 if (!$include_no_customer_association) { 751 $stmt .= " WHERE prj_customer_backend <> '' AND prj_customer_backend IS NOT NULL "; 752 } 753 $stmt .= " 754 ORDER BY 755 prj_title"; 756 $res = $GLOBALS["db_api"]->dbh->getAssoc($stmt); 757 if (PEAR::isError($res)) { 758 Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__); 759 return ""; 760 } else { 761 return $res; 762 } 763 } 764 765 766 /** 767 * Method used to get a list of emails that are associated with a given 768 * project and issue. 769 * 770 * @access public 771 * @param integer $prj_id The project ID 772 * @param integer $issue_id The issue ID 773 * @return array List of emails 774 */ 775 function getAddressBookEmails($prj_id, $issue_id) 776 { 777 $list = Project::getAddressBook($prj_id, $issue_id); 778 $emails = array(); 779 foreach ($list as $address => $name) { 780 $emails[] = Mail_API::getEmailAddress($address); 781 } 782 return $emails; 783 } 784 785 786 /** 787 * Method used to get a list of names and emails that are 788 * associated with a given project and issue. 789 * 790 * @access public 791 * @param integer $prj_id The project ID 792 * @param integer $issue_id The issue ID 793 * @return array List of names and emails 794 */ 795 function getAddressBook($prj_id, $issue_id = FALSE) 796 { 797 static $returns; 798 799 $key = serialize(array($prj_id, $issue_id)); 800 if (!empty($returns[$key])) { 801 return $returns[$key]; 802 } 803 804 $res = Project::getAddressBookAssocList($prj_id, $issue_id); 805 if (empty($res)) { 806 return ""; 807 } else { 808 $temp = array(); 809 foreach ($res as $name => $email) { 810 $temp["$name <$email>"] = $name; 811 } 812 $returns[$key] = $temp; 813 return $temp; 814 } 815 } 816 817 818 /** 819 * Method used to get an associative array of names and emails 820 * that are associated with a given project and issue. 821 * 822 * @access public 823 * @param integer $prj_id The project ID 824 * @param integer $issue_id The issue ID 825 * @return array List of names and emails 826 */ 827 function getAddressBookAssocList($prj_id, $issue_id = FALSE) 828 { 829 if ($issue_id) { 830 $customer_id = Issue::getCustomerID($issue_id); 831 } 832 833 $stmt = "SELECT 834 usr_full_name, 835 usr_email 836 FROM 837 " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "user, 838 " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "project_user 839 WHERE 840 pru_prj_id=" . Misc::escapeInteger($prj_id) . " AND 841 pru_usr_id=usr_id AND 842 usr_status='active' AND 843 usr_id <> " . APP_SYSTEM_USER_ID; 844 if (!empty($customer_id)) { 845 $stmt .= " AND (usr_customer_id IS NULL OR usr_customer_id IN (0, " . Misc::escapeInteger($customer_id) . ")) "; 846 } else { 847 $stmt .= " AND (usr_customer_id IS NULL OR usr_customer_id=0) "; 848 } 849 $stmt .= " 850 ORDER BY 851 usr_customer_id DESC, 852 usr_full_name ASC"; 853 $res = $GLOBALS["db_api"]->dbh->getAssoc($stmt); 854 if (PEAR::isError($res)) { 855 Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__); 856 return ""; 857 } else { 858 return $res; 859 } 860 } 861 862 863 /** 864 * Method used to get the list of projects that allow remote 865 * invocation of issues. 866 * 867 * @access public 868 * @return array The list of projects 869 */ 870 function getRemoteAssocList() 871 { 872 $stmt = "SELECT 873 prj_id, 874 prj_title 875 FROM 876 " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "project 877 WHERE 878 prj_remote_invocation='enabled' 879 ORDER BY 880 prj_title"; 881 $res = $GLOBALS["db_api"]->dbh->getAssoc($stmt); 882 if (PEAR::isError($res)) { 883 Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__); 884 return ""; 885 } else { 886 return $res; 887 } 888 } 889 890 891 /** 892 * Method used to get the list of projects assigned to a given user that 893 * allow remote invocation of issues. 894 * 895 * @access public 896 * @param integer $usr_id The user ID 897 * @param boolean $only_customer_projects Whether to only include projects with customer integration or not 898 * @return array The list of projects 899 */ 900 function getRemoteAssocListByUser($usr_id, $only_customer_projects = FALSE) 901 { 902 static $returns; 903 904 if ((!$only_customer_projects) && (!empty($returns[$usr_id]))) { 905 return $returns[$usr_id]; 906 } 907 908 $stmt = "SELECT 909 prj_id, 910 prj_title 911 FROM 912 " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "project, 913 " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "project_user 914 WHERE 915 prj_id=pru_prj_id AND 916 pru_usr_id=" . Misc::escapeInteger($usr_id) . " AND 917 prj_remote_invocation='enabled'"; 918 if ($only_customer_projects) { 919 $stmt .= " AND prj_customer_backend <> '' AND prj_customer_backend IS NOT NULL "; 920 } 921 $stmt .= " 922 ORDER BY 923 prj_title"; 924 $res = $GLOBALS["db_api"]->dbh->getAssoc($stmt); 925 if (PEAR::isError($res)) { 926 Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__); 927 return ""; 928 } else { 929 // don't cache the results when the optional argument is used to avoid getting bogus results 930 if (!$only_customer_projects) { 931 $returns[$usr_id] = $res; 932 } 933 return $res; 934 } 935 } 936 937 938 /** 939 * Method used to get the list of users associated with a given project. 940 * 941 * @access public 942 * @param integer $prj_id The project ID 943 * @param string $status The desired user status 944 * @return array The list of users 945 */ 946 function getUserEmailAssocList($prj_id, $status = NULL, $role = NULL) 947 { 948 static $returns; 949 950 if (!empty($returns[$prj_id])) { 951 return $returns[$prj_id]; 952 } 953 954 $stmt = "SELECT 955 usr_id, 956 usr_email 957 FROM 958 " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "user, 959 " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "project_user 960 WHERE 961 pru_prj_id=" . Misc::escapeInteger($prj_id) . " AND 962 pru_usr_id=usr_id"; 963 if ($status != NULL) { 964 $stmt .= " AND usr_status='active' "; 965 } 966 if ($role != NULL) { 967 $stmt .= " AND pru_role > $role "; 968 } 969 $stmt .= " 970 ORDER BY 971 usr_email ASC"; 972 $res = $GLOBALS["db_api"]->dbh->getAssoc($stmt); 973 if (PEAR::isError($res)) { 974 Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__); 975 return ""; 976 } else { 977 $returns[$prj_id] = $res; 978 return $res; 979 } 980 } 981 982 983 /** 984 * Method used to get the list of users associated with a given project. 985 * 986 * @access public 987 * @param integer $prj_id The project ID 988 * @param string $status The desired user status 989 * @return array The list of users 990 */ 991 function getReporters($prj_id) 992 { 993 994 $stmt = "SELECT 995 DISTINCT usr_id, 996 usr_full_name 997 FROM 998 " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "user, 999 " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "project_user, 1000 " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue 1001 WHERE 1002 pru_prj_id = " . Misc::escapeInteger($prj_id) . " AND 1003 iss_prj_id = " . Misc::escapeInteger($prj_id) . " AND 1004 pru_usr_id = usr_id AND 1005 usr_id = iss_usr_id 1006 ORDER BY 1007 usr_full_name ASC"; 1008 $res = $GLOBALS["db_api"]->dbh->getAssoc($stmt); 1009 if (PEAR::isError($res)) { 1010 Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__); 1011 return array(); 1012 } else { 1013 return $res; 1014 } 1015 } 1016 1017 1018 /** 1019 * Sets the minimum role needed to view a specific field on the issue creation form. 1020 * 1021 * @access public 1022 * @param integer $prj_id The project ID. 1023 * @param array $settings An array of fields and role is required to view them. 1024 * @return integer 1 if the update worked, -1 otherwise. 1025 */ 1026 function updateFieldDisplaySettings($prj_id, $settings) 1027 { 1028 // delete current settings 1029 $stmt = "DELETE FROM 1030 " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "project_field_display 1031 WHERE 1032 pfd_prj_id = " . Misc::escapeInteger($prj_id); 1033 $res = $GLOBALS["db_api"]->dbh->query($stmt); 1034 if (PEAR::isError($res)) { 1035 Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__); 1036 return -1; 1037 } 1038 1039 // insert new values 1040 foreach ($settings as $field => $min_role) { 1041 $stmt = "INSERT INTO 1042 " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "project_field_display 1043 ( 1044 pfd_prj_id, 1045 pfd_field, 1046 pfd_min_role 1047 ) VALUES ( 1048 " . Misc::escapeInteger($prj_id) . ", 1049 '" . Misc::escapeString($field) . "', 1050 " . Misc::escapeInteger($min_role) . " 1051 )"; 1052 $res = $GLOBALS["db_api"]->dbh->query($stmt); 1053 if (PEAR::isError($res)) { 1054 Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__); 1055 return -1; 1056 } 1057 } 1058 return 1; 1059 } 1060 1061 1062 /** 1063 * Returns display settings for a specific project. 1064 * 1065 * @access public 1066 * @param integer $prj_id The project ID 1067 * @return array An associative array of minimum role required to access a field. 1068 */ 1069 function getFieldDisplaySettings($prj_id) 1070 { 1071 $stmt = "SELECT 1072 pfd_field, 1073 pfd_min_role 1074 FROM 1075 " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "project_field_display 1076 WHERE 1077 pfd_prj_id = " . Misc::escapeInteger($prj_id); 1078 $res = $GLOBALS["db_api"]->dbh->getAssoc($stmt); 1079 if (PEAR::isError($res)) { 1080 Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__); 1081 return -1; 1082 } 1083 $fields = Project::getDisplayFields(); 1084 foreach ($fields as $field_name => $field_title) { 1085 if (!isset($res[$field_name])) { 1086 $res[$field_name] = 0; 1087 } 1088 } 1089 return $res; 1090 } 1091 1092 1093 /** 1094 * Returns an array of fields which can be hidden. 1095 * 1096 * @access public 1097 * @return array 1098 */ 1099 function getDisplayFields() 1100 { 1101 return array( 1102 "category" => ev_gettext("Category"), 1103 "priority" => ev_gettext("Priority"), 1104 "assignment" => ev_gettext("Assignment"), 1105 "release" => ev_gettext("Scheduled Release"), 1106 "estimated_dev_time" => ev_gettext("Estimated Dev. Time"), 1107 "group" => ev_gettext("Group"), 1108 "file" => ev_gettext("File"), 1109 "private" => ev_gettext("Private") 1110 ); 1111 } 1112 } 1113 1114 // benchmarking the included file (aka setup time) 1115 if (APP_BENCHMARK) { 1116 $GLOBALS['bench']->setMarker('Included Project Class'); 1117 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Dec 19 21:21:33 2007 | Cross-referenced by PHPXref 0.7 |