View Issue Details
| ID | Project | Category | View Status | Date Submitted | Last Update |
|---|---|---|---|---|---|
| 0011097 | mantisbt | custom fields | public | 2009-10-29 04:52 | 2010-04-23 23:22 |
| Reporter | liebscher | Assigned To | vboctor | ||
| Priority | high | Severity | minor | Reproducibility | always |
| Status | closed | Resolution | duplicate | ||
| Platform | Linux | ||||
| Product Version | 1.1.6 | ||||
| Summary | 0011097: Offer Custom Fields (String) with maxLength > 255 characters and displayed as TEXTAREA | ||||
| Description | Custom fields should have a maxLength of 1024 characters. | ||||
| Steps To Reproduce | Custom fields can be set to a length > 255 characters, but are always displayed as single line INPUT and cut at 255 characters during save. | ||||
| Additional Information | We customized our Mantis installation this way: Modify the file mantis/core/custom_field_api.php (changed marked with '# MX'): MX START: treat maxLength > 255 as textarea | ||||
| Tags | patch | ||||
| Attached Files | custom_field_api.php.patch (93,489 bytes)
--- C:/mX_fileshares/Projects/mobileX-MIP/Misc/Mantis/custom_field_api.php Mi Okt 28 07:36:07 2009
+++ C:/mX_fileshares/Projects/mobileX-MIP/Misc/Mantis/custom_field_api_1.1.6.php Di Dez 9 20:20:28 2008
@@ -1,1340 +1,1332 @@
-<?php
-# Mantis - a php based bugtracking system
-
-# Copyright (C) 2000 - 2002 Kenzaburo Ito - kenito@300baud.org
-# Copyright (C) 2002 - 2007 Mantis Team - mantisbt-dev@lists.sourceforge.net
-
-# Mantis is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 2 of the License, or
-# (at your option) any later version.
-#
-# Mantis is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Mantis. If not, see <http://www.gnu.org/licenses/>.
-
- # --------------------------------------------------------
- # $Id: custom_field_api.php,v 1.66.2.1 2007-10-13 22:35:21 giallu Exp $
- # --------------------------------------------------------
-
- $t_core_dir = dirname( __FILE__ ).DIRECTORY_SEPARATOR;
-
- require_once( $t_core_dir . 'bug_api.php' );
- require_once( $t_core_dir . 'helper_api.php' );
- require_once( $t_core_dir . 'date_api.php' );
-
- ### Custom Fields API ###
-
-#*******************************************
-# TODO
-# - add an object to store field data like BugData and UserPrefs ?
-# - add caching functions like user, bug, etc
-# - make existing api functions use caching functions
-# - add functions to return individual db columns for a field definition
-#*******************************************
-
- #===================================
- # Caching
- #===================================
-
- #########################################
- # SECURITY NOTE: cache globals are initialized here to prevent them
- # being spoofed if register_globals is turned on
-
- $g_cache_custom_field = array();
- $g_cache_cf_list = NULL;
- $g_cache_cf_linked = array();
-
- # Cache a custom field row if necessary and return the cached copy
- # If the second parameter is true (default), trigger an error
- # if the field can't be found. If the second parameter is
- # false, return false if the field can't be found.
- function custom_field_cache_row( $p_field_id, $p_trigger_errors=true ) {
- global $g_cache_custom_field;
-
- $c_field_id = db_prepare_int( $p_field_id );
-
- $t_custom_field_table = config_get( 'mantis_custom_field_table' );
-
- if ( isset ( $g_cache_custom_field[$c_field_id] ) ) {
- return $g_cache_custom_field[$c_field_id];
- }
-
- $query = "SELECT *
- FROM $t_custom_field_table
- WHERE id='$c_field_id'";
- $result = db_query( $query );
-
- if ( 0 == db_num_rows( $result ) ) {
- if ( $p_trigger_errors ) {
- error_parameters( 'Custom ' . $p_field_id );
- trigger_error( ERROR_CUSTOM_FIELD_NOT_FOUND, ERROR );
- } else {
- return false;
- }
- }
-
- $row = db_fetch_array( $result );
-
- $g_cache_custom_field[$c_field_id] = $row;
-
- return $row;
- }
-
- # --------------------
- # Clear the custom field cache (or just the given id if specified)
- function custom_field_clear_cache( $p_field_id = null ) {
- global $g_cache_custom_field, $g_cached_custom_field_lists;
-
- $g_cached_custom_field_lists = null;
-
- if ( null === $p_field_id ) {
- $g_cache_custom_field = array();
- } else {
- $c_field_id = db_prepare_int( $p_field_id );
- unset( $g_cache_custom_field[$c_field_id] );
- }
-
- return true;
- }
-
-
- #===================================
- # Boolean queries and ensures
- #===================================
-
- # --------------------
- # Check to see whether the field is included in the given project
- # return true if the field is included, false otherwise
- #
- function custom_field_is_linked( $p_field_id, $p_project_id ) {
- $c_project_id = db_prepare_int( $p_project_id );
- $c_field_id = db_prepare_int( $p_field_id );
-
- # figure out if this bug_id/field_id combination exists
- $t_custom_field_project_table = config_get( 'mantis_custom_field_project_table' );
- $query = "SELECT COUNT(*)
- FROM $t_custom_field_project_table
- WHERE field_id='$c_field_id' AND
- project_id='$c_project_id'";
- $result = db_query( $query );
- $count = db_result( $result );
-
- if ( $count > 0 ) {
- return true;
- } else {
- return false;
- }
- }
-
- # --------------------
- # Check to see whether the field id is defined
- # return true if the field is defined, false otherwise
- function custom_field_exists( $p_field_id ) {
- if ( false == custom_field_cache_row( $p_field_id, false ) ) {
- return false;
- } else {
- return true;
- }
- }
-
- # --------------------
- # Return the type of a custom field if it exists.
- function custom_field_type( $p_field_id ) {
- $t_field = custom_field_cache_row( $p_field_id, false ) ;
- if ( $t_field == false ) {
- return -1 ;
- } else {
- return $t_field[ 'type' ] ;
- }
- }
-
- # --------------------
- # Check to see whether the field id is defined
- # return true if the field is defined, error otherwise
- function custom_field_ensure_exists( $p_field_id ) {
- if ( custom_field_exists( $p_field_id ) ) {
- return true;
- } else {
- error_parameters( 'Custom ' . $p_field_id );
- trigger_error( ERROR_CUSTOM_FIELD_NOT_FOUND, ERROR );
- }
- }
-
- # --------------------
- # Check to see whether the name is unique
- # return false if a field with the name already exists, true otherwise
- # if an id is specified, then the corresponding record is excluded from the
- # uniqueness test.
- function custom_field_is_name_unique( $p_name, $p_custom_field_id = null ) {
- $c_name = db_prepare_string( $p_name );
-
- $t_custom_field_table = config_get( 'mantis_custom_field_table' );
- $query = "SELECT COUNT(*)
- FROM $t_custom_field_table
- WHERE name='$c_name'";
- if ( $p_custom_field_id !== null ) {
- $c_id = db_prepare_int( $p_custom_field_id );
- $query .= " AND (id <> $c_id)";
- }
- $result = db_query( $query );
- $count = db_result( $result );
-
- if ( $count > 0 ) {
- return false;
- } else {
- return true;
- }
- }
-
- # --------------------
- # Check to see whether the name is unique
- # return true if the name has not been used, error otherwise
- function custom_field_ensure_name_unique( $p_name ) {
- if ( custom_field_is_name_unique( $p_name ) ) {
- return true;
- } else {
- trigger_error( ERROR_CUSTOM_FIELD_NAME_NOT_UNIQUE, ERROR );
- }
- }
-
- # --------------------
- # Return true if the user can read the value of the field for the given bug,
- # false otherwise.
- function custom_field_has_read_access( $p_field_id, $p_bug_id, $p_user_id = null ) {
- custom_field_ensure_exists( $p_field_id );
-
- if ( null === $p_user_id ) {
- $p_user_id = auth_get_current_user_id();
- }
-
- $t_access_level_r = custom_field_get_field( $p_field_id, 'access_level_r' );
-
- $t_project_id = bug_get_field( $p_bug_id, 'project_id' );
-
- return access_has_project_level( $t_access_level_r, $t_project_id, $p_user_id );
- }
-
- # --------------------
- # Return true if the user can modify the value of the field for the given project,
- # false otherwise.
- function custom_field_has_write_access_to_project( $p_field_id, $p_project_id, $p_user_id = null ) {
- custom_field_ensure_exists( $p_field_id );
-
- if ( null === $p_user_id ) {
- $p_user_id = auth_get_current_user_id();
- }
-
- $t_access_level_rw = custom_field_get_field( $p_field_id, 'access_level_rw' );
-
- return access_has_project_level( $t_access_level_rw, $p_project_id, $p_user_id );
- }
-
- # --------------------
- # Return true if the user can modify the value of the field for the given bug,
- # false otherwise.
- function custom_field_has_write_access( $p_field_id, $p_bug_id, $p_user_id = null ) {
- $t_project_id = bug_get_field( $p_bug_id, 'project_id' );
- return ( custom_field_has_write_access_to_project( $p_field_id, $t_project_id, $p_user_id ) );
- }
-
- #===================================
- # Creation / Deletion / Updating
- #===================================
-
- # --------------------
- # create a new custom field with the name $p_name
- # the definition are the default values and can be changes later
- # return the ID of the new definition
- function custom_field_create( $p_name ) {
- if ( string_contains_scripting_chars( $p_name ) ) {
- trigger_error( ERROR_CUSTOM_FIELD_INVALID_DEFINITION, ERROR );
- }
-
- $c_name = db_prepare_string( trim( $p_name ) );
-
- if ( is_blank( $c_name ) ) {
- error_parameters( 'name' );
- trigger_error( ERROR_EMPTY_FIELD, ERROR );
- }
-
- custom_field_ensure_name_unique( $c_name );
-
- $t_custom_field_table = config_get( 'mantis_custom_field_table' );
- $query = "INSERT INTO $t_custom_field_table
- ( name )
- VALUES
- ( '$c_name' )";
-
- db_query( $query );
-
- return db_insert_id( $t_custom_field_table );
- }
-
- # --------------------
- # Update the field definition
- # return true on success, false on failure
- function custom_field_update( $p_field_id, $p_def_array ) {
- if ( string_contains_scripting_chars( $p_def_array['name'] ) ) {
- trigger_error( ERROR_CUSTOM_FIELD_INVALID_DEFINITION, ERROR );
- }
-
- $c_field_id = db_prepare_int( $p_field_id );
- $c_name = db_prepare_string( trim( $p_def_array['name'] ) );
- $c_type = db_prepare_int( $p_def_array['type'] );
- $c_possible_values = db_prepare_string( $p_def_array['possible_values'] );
- $c_default_value = db_prepare_string( $p_def_array['default_value'] );
- $c_valid_regexp = db_prepare_string( $p_def_array['valid_regexp'] );
- $c_access_level_r = db_prepare_int( $p_def_array['access_level_r'] );
- $c_access_level_rw = db_prepare_int( $p_def_array['access_level_rw'] );
- $c_length_min = db_prepare_int( $p_def_array['length_min'] );
- $c_length_max = db_prepare_int( $p_def_array['length_max'] );
- $c_advanced = db_prepare_bool( $p_def_array['advanced'] );
- $c_display_report = db_prepare_bool( $p_def_array['display_report'] );
- $c_display_update = db_prepare_bool( $p_def_array['display_update'] );
- $c_display_resolved = db_prepare_bool( $p_def_array['display_resolved'] );
- $c_display_closed = db_prepare_bool( $p_def_array['display_closed'] );
- $c_require_report = db_prepare_bool( $p_def_array['require_report'] );
- $c_require_update = db_prepare_bool( $p_def_array['require_update'] );
- $c_require_resolved = db_prepare_bool( $p_def_array['require_resolved'] );
- $c_require_closed = db_prepare_bool( $p_def_array['require_closed'] );
-
- if ( is_blank( $c_name ) ) {
- error_parameters( 'name' );
- trigger_error( ERROR_EMPTY_FIELD, ERROR );
- }
-
- if (( $c_access_level_rw < $c_access_level_r ) ||
- ( $c_length_min < 0 ) ||
- ( ( $c_length_max != 0 ) && ( $c_length_min > $c_length_max ) ) ) {
- trigger_error( ERROR_CUSTOM_FIELD_INVALID_DEFINITION, ERROR );
- }
-
- if ( $c_advanced == true && ( $c_require_report == true || $c_require_update ) ) {
- trigger_error( ERROR_CUSTOM_FIELD_INVALID_DEFINITION, ERROR );
- }
-
- if ( !custom_field_is_name_unique( $c_name, $c_field_id ) ) {
- trigger_error( ERROR_CUSTOM_FIELD_NAME_NOT_UNIQUE, ERROR );
- }
-
- $t_update_something = false;
- $t_mantis_custom_field_table = config_get( 'mantis_custom_field_table' );
- $query = "UPDATE $t_mantis_custom_field_table
- SET ";
- if( array_key_exists( 'name', $p_def_array ) ) {
- if ( !$t_update_something ) {
- $t_update_something = true;
- } else {
- $query .= ', ';
- }
- $query .= "name='$c_name'";
- }
- if( array_key_exists( 'type', $p_def_array ) ) {
- if ( !$t_update_something ) {
- $t_update_something = true;
- } else {
- $query .= ', ';
- }
- $query .= "type='$c_type'";
- }
- if( array_key_exists( 'possible_values', $p_def_array ) ) {
- if ( !$t_update_something ) {
- $t_update_something = true;
- } else {
- $query .= ', ';
- }
- $query .= "possible_values='$c_possible_values'";
- }
- if( array_key_exists( 'default_value', $p_def_array ) ) {
- if ( !$t_update_something ) {
- $t_update_something = true;
- } else {
- $query .= ', ';
- }
- $query .= "default_value='$c_default_value'";
- }
- if( array_key_exists( 'valid_regexp', $p_def_array ) ) {
- if ( !$t_update_something ) {
- $t_update_something = true;
- } else {
- $query .= ', ';
- }
- $query .= "valid_regexp='$c_valid_regexp'";
- }
- if( array_key_exists( 'access_level_r', $p_def_array ) ) {
- if ( !$t_update_something ) {
- $t_update_something = true;
- } else {
- $query .= ', ';
- }
- $query .= "access_level_r='$c_access_level_r'";
- }
- if( array_key_exists( 'access_level_rw', $p_def_array ) ) {
- if ( !$t_update_something ) {
- $t_update_something = true;
- } else {
- $query .= ', ';
- }
- $query .= "access_level_rw='$c_access_level_rw'";
- }
- if( array_key_exists( 'length_min', $p_def_array ) ) {
- if ( !$t_update_something ) {
- $t_update_something = true;
- } else {
- $query .= ', ';
- }
- $query .= "length_min='$c_length_min'";
- }
- if( array_key_exists( 'length_max', $p_def_array ) ) {
- if ( !$t_update_something ) {
- $t_update_something = true;
- } else {
- $query .= ', ';
- }
- $query .= "length_max='$c_length_max'";
- }
- if( array_key_exists( 'advanced', $p_def_array ) ) {
- if ( !$t_update_something ) {
- $t_update_something = true;
- } else {
- $query .= ', ';
- }
- $query .= "advanced='$c_advanced'";
- }
- if( array_key_exists( 'display_report', $p_def_array ) ) {
- if ( !$t_update_something ) {
- $t_update_something = true;
- } else {
- $query .= ', ';
- }
- $query .= "display_report='$c_display_report'";
- }
- if( array_key_exists( 'display_update', $p_def_array ) ) {
- if ( !$t_update_something ) {
- $t_update_something = true;
- } else {
- $query .= ', ';
- }
- $query .= "display_update='$c_display_update'";
- }
- if( array_key_exists( 'display_resolved', $p_def_array ) ) {
- if ( !$t_update_something ) {
- $t_update_something = true;
- } else {
- $query .= ', ';
- }
- $query .= "display_resolved='$c_display_resolved'";
- }
- if( array_key_exists( 'display_closed', $p_def_array ) ) {
- if ( !$t_update_something ) {
- $t_update_something = true;
- } else {
- $query .= ', ';
- }
- $query .= "display_closed='$c_display_closed'";
- }
- if( array_key_exists( 'require_report', $p_def_array ) ) {
- if ( !$t_update_something ) {
- $t_update_something = true;
- } else {
- $query .= ', ';
- }
- $query .= "require_report='$c_require_report'";
- }
- if( array_key_exists( 'require_update', $p_def_array ) ) {
- if ( !$t_update_something ) {
- $t_update_something = true;
- } else {
- $query .= ', ';
- }
- $query .= "require_update='$c_require_update'";
- }
- if( array_key_exists( 'require_resolved', $p_def_array ) ) {
- if ( !$t_update_something ) {
- $t_update_something = true;
- } else {
- $query .= ', ';
- }
- $query .= "require_resolved='$c_require_resolved'";
- }
- if( array_key_exists( 'require_closed', $p_def_array ) ) {
- if ( !$t_update_something ) {
- $t_update_something = true;
- } else {
- $query .= ', ';
- }
- $query .= "require_closed='$c_require_closed'";
- }
-
-
- $query .= " WHERE id='$c_field_id'";
-
- if( $t_update_something ) {
- db_query( $query );
- custom_field_clear_cache( $p_field_id );
- } else {
- return false; # there is nothing to update...
- }
-
- # db_query() errors on failure so:
- return true;
- }
-
- # --------------------
- # Add a custom field to a project
- # return true on success, false on failure or if already added
- function custom_field_link( $p_field_id, $p_project_id ) {
- $c_field_id = db_prepare_int( $p_field_id );
- $c_project_id = db_prepare_int( $p_project_id );
-
- custom_field_ensure_exists( $p_field_id );
- project_ensure_exists( $p_project_id );
-
- if ( custom_field_is_linked( $p_field_id, $p_project_id ) ) {
- return false;
- }
-
- $t_custom_field_project_table = config_get( 'mantis_custom_field_project_table' );
- $query = "INSERT INTO $t_custom_field_project_table
- ( field_id, project_id )
- VALUES
- ( '$c_field_id', '$c_project_id' )";
- db_query( $query );
-
- # db_query() errors on failure so:
- return true;
- }
-
- # --------------------
- # Remove a custom field from a project
- # return true on success, false on failure
- #
- # The values for the custom fields are not deleted. This is to allow for the
- # case where a bug is moved to another project that has the field, or the
- # field is linked again to the project.
- function custom_field_unlink( $p_field_id, $p_project_id ) {
- $c_field_id = db_prepare_int( $p_field_id );
- $c_project_id = db_prepare_int( $p_project_id );
-
- $t_custom_field_project_table = config_get( 'mantis_custom_field_project_table' );
- $query = "DELETE FROM $t_custom_field_project_table
- WHERE field_id = '$c_field_id' AND
- project_id = '$c_project_id'";
- db_query( $query );
-
- # db_query() errors on failure so:
- return true;
- }
-
- # --------------------
- # Delete the field definition and all associated values and project
- # associations
- # return true on success, false on failure
- function custom_field_destroy( $p_field_id ) {
- $c_field_id = db_prepare_int( $p_field_id );
-
- # delete all values
- $t_custom_field_string_table = config_get( 'mantis_custom_field_string_table' );
- $query = "DELETE FROM $t_custom_field_string_table
- WHERE field_id='$c_field_id'";
- db_query( $query );
-
- # delete all project associations
- $t_custom_field_project_table = config_get( 'mantis_custom_field_project_table' );
- $query = "DELETE FROM $t_custom_field_project_table
- WHERE field_id='$c_field_id'";
- db_query( $query );
-
- $t_custom_field_table = config_get( 'mantis_custom_field_table' );
- # delete the definition
- $query = "DELETE FROM $t_custom_field_table
- WHERE id='$c_field_id'";
- db_query( $query );
-
- custom_field_clear_cache( $p_field_id );
-
- # db_query() errors on failure so:
- return true;
- }
-
- # --------------------
- # Delete all associations of custom fields to the specified project
- # return true on success, false on failure
- #
- # To be called from within project_delete().
- function custom_field_unlink_all( $p_project_id ) {
- $c_project_id = db_prepare_int( $p_project_id );
-
- # delete all project associations
- $t_custom_field_project_table = config_get( 'mantis_custom_field_project_table' );
- $query = "DELETE FROM $t_custom_field_project_table
- WHERE project_id='$c_project_id'";
- db_query( $query );
-
- # db_query() errors on failure so:
- return true;
- }
-
- # --------------------
- # Delete all custom values associated with the specified bug.
- # return true on success, false on failure
- #
- # To be called from bug_delete().
- function custom_field_delete_all_values( $p_bug_id ) {
- $c_bug_id = db_prepare_int( $p_bug_id );
-
- $t_custom_field_string_table = config_get( 'mantis_custom_field_string_table' );
- $query = "DELETE FROM $t_custom_field_string_table
- WHERE bug_id='$c_bug_id'";
- db_query( $query );
-
- #db_query() errors on failure so:
- return true;
- }
-
- #===================================
- # Data Access
- #===================================
-
- # --------------------
- # Get the id of the custom field with the specified name.
- # false is returned if no custom field found with the specified name.
- function custom_field_get_id_from_name( $p_field_name, $p_truncated_length = null ) {
- if ( $p_field_name == '' ) {
- return false;
- }
-
- $t_custom_field_table = config_get( 'mantis_custom_field_table' );
-
- $c_field_name = db_prepare_string( $p_field_name );
-
- if ( ( null === $p_truncated_length ) || ( strlen( $c_field_name ) != $p_truncated_length ) ) {
- $query = "SELECT id FROM $t_custom_field_table WHERE name = '$c_field_name'";
- } else {
- # @@@ This is to handle the case where we only have a truncated part of the name. This happens in the case where
- # we are getting the custom field name from the history logs, since history is 32 and custom field name is 64.
- # This fix will handle entries already in the database, future entries should be handled by making the field name max lengths match.
- $query = "SELECT id FROM $t_custom_field_table WHERE name LIKE '$c_field_name%'";
- }
-
- $t_result = db_query( $query, 1 );
-
- if ( db_num_rows( $t_result ) == 0 ) {
- return false;
- }
-
- $row = db_fetch_array( $t_result );
-
- return $row['id'];
- }
-
- # --------------------
- # Return an array of ids of custom fields bound to the specified project
- #
- # The ids will be sorted based on the sequence number associated with the binding
- function custom_field_get_linked_ids( $p_project_id = ALL_PROJECTS ) {
- global $g_cache_cf_linked;
-
- if ( ! isset( $g_cache_cf_linked[$p_project_id] ) ) {
-
- $t_custom_field_table = config_get( 'mantis_custom_field_table' );
- $t_custom_field_project_table = config_get( 'mantis_custom_field_project_table' );
-
- if ( ALL_PROJECTS == $p_project_id ) {
- $t_project_user_list_table = config_get( 'mantis_project_user_list_table' );
- $t_project_table = config_get( 'mantis_project_table' );
- $t_user_table = config_get( 'mantis_user_table' );
- $t_user_id = auth_get_current_user_id();
- $t_pub = VS_PUBLIC;
- $t_priv = VS_PRIVATE;
-
- $t_private_access = config_get( 'private_project_threshold' );
- if ( is_array( $t_private_access ) ) {
- if ( 1 == count( $t_private_access ) ) {
- $t_access_clause = "= " . array_shift( $t_private_access ) . " ";
- } else {
- $t_access_clause = "IN (" . implode( ',', $t_private_access ) . ")";
- }
- } else {
- $t_access_clause = ">= $t_private_access ";
- }
-
-
- # select only the ids that the user has some access to
- # e.g., all fields in public projects, or private projects where the user is listed
- # or private projects where the user is implicitly listed
- $query = "SELECT cft.id as id, cft.name as name
- FROM $t_custom_field_table as cft, $t_user_table ut, $t_project_table pt, $t_custom_field_project_table cfpt
- LEFT JOIN $t_project_user_list_table pult
- on cfpt.project_id = pult.project_id and pult.user_id = $t_user_id
- WHERE cft.id = cfpt.field_id AND cfpt.project_id = pt.id AND ut.id = $t_user_id AND
- ( pt.view_state = $t_pub OR
- ( pt.view_state = $t_priv and pult.user_id = $t_user_id ) OR
- ( pult.user_id is null and ut.access_level $t_access_clause ) )
- GROUP BY cft.id, cft.name
- ORDER BY cft.name ASC";
- } else {
- if ( is_array( $p_project_id ) ) {
- if ( 1 == count( $p_project_id ) ) {
- $t_project_clause = "= " . array_shift( $p_project_id ) . " ";
- } else {
- $t_project_clause = "IN (" . implode( ',', $p_project_id ) . ")";
- }
- } else {
- $t_project_clause = "= $p_project_id ";
- }
- $query = "SELECT cft.id, cft.name, cfpt.sequence
- FROM $t_custom_field_table cft, $t_custom_field_project_table cfpt
- WHERE cfpt.project_id $t_project_clause AND
- cft.id = cfpt.field_id
- ORDER BY sequence ASC, name ASC";
- }
- $result = db_query( $query );
- $t_row_count = db_num_rows( $result );
- $t_ids = array();
-
- for ( $i=0 ; $i < $t_row_count ; $i++ ) {
- $row = db_fetch_array( $result );
-
- array_push( $t_ids, $row['id'] );
- }
- $g_cache_cf_linked[$p_project_id] = $t_ids;
- } else {
- $t_ids = $g_cache_cf_linked[$p_project_id];
- }
-
- return $t_ids;
- }
-
- # --------------------
- # Return an array all custom field ids sorted by name
- function custom_field_get_ids( ) {
- global $g_cache_cf_list;
-
- if ( $g_cache_cf_list === NULL ) {
- $t_custom_field_table = config_get( 'mantis_custom_field_table' );
- $query = "SELECT id, name
- FROM $t_custom_field_table
- ORDER BY name ASC";
- $result = db_query( $query );
- $t_row_count = db_num_rows( $result );
- $t_ids = array();
-
- for ( $i=0 ; $i < $t_row_count ; $i++ ) {
- $row = db_fetch_array( $result );
-
- array_push( $t_ids, $row['id'] );
- }
- $g_cache_cf_list = $t_ids;
-
- } else {
- $t_ids = $g_cache_cf_list;
- }
- return $t_ids;
- }
-
- # --------------------
- # Return an array of ids of projects related to the specified custom field
- # (the array may be empty)
- function custom_field_get_project_ids( $p_field_id ) {
- $c_field_id = db_prepare_int( $p_field_id );
-
- $t_custom_field_project_table = config_get( 'mantis_custom_field_project_table' );
- $query = "SELECT project_id
- FROM $t_custom_field_project_table
- WHERE field_id = '$c_field_id'";
- $result = db_query( $query );
-
- $t_row_count = db_num_rows( $result );
- $t_ids = array();
-
- for ( $i=0 ; $i < $t_row_count ; $i++ ) {
- $row = db_fetch_array( $result );
-
- array_push( $t_ids, $row['project_id'] );
- }
-
- return $t_ids;
- }
-
- # --------------------
- # Return a field definition row for the field or error if the field does
- # not exist
- function custom_field_get_definition( $p_field_id ) {
- return custom_field_cache_row( $p_field_id );
- }
-
- # --------------------
- # Return a single database field from a custom field definition row
- # for the field
- # if the database field does not exist, display a warning and return ''
- function custom_field_get_field( $p_field_id, $p_field_name ) {
- $row = custom_field_get_definition( $p_field_id );
-
- if ( isset( $row[$p_field_name] ) ) {
- return $row[$p_field_name];
- } else {
- error_parameters( $p_field_name );
- trigger_error( ERROR_DB_FIELD_NOT_FOUND, WARNING );
- return '';
- }
- }
-
- # --------------------
- # Get the value of a custom field for the given bug
- #
- # @@@ return values are unclear... should we error when access is denied
- # and provide an api to check whether it will be?
- function custom_field_get_value( $p_field_id, $p_bug_id ) {
- $c_field_id = db_prepare_int( $p_field_id );
- $c_bug_id = db_prepare_int( $p_bug_id );
-
- custom_field_ensure_exists( $p_field_id );
-
- $t_custom_field_table = config_get( 'mantis_custom_field_table' );
- $query = "SELECT access_level_r, default_value, type
- FROM $t_custom_field_table
- WHERE id='$c_field_id'";
- $result = db_query( $query );
- $row = db_fetch_array( $result );
-
- $t_access_level_r = $row['access_level_r'];
- $t_default_value = $row['default_value'];
-
- if( !custom_field_has_read_access( $p_field_id, $p_bug_id, auth_get_current_user_id() ) ) {
- return false;
- }
-
- $t_custom_field_string_table = config_get( 'mantis_custom_field_string_table' );
- $query = "SELECT value
- FROM $t_custom_field_string_table
- WHERE bug_id='$c_bug_id' AND
- field_id='$c_field_id'";
- $result = db_query( $query );
-
- if( db_num_rows( $result ) > 0 ) {
- return custom_field_database_to_value( db_result( $result ) , $row['type'] );
- } else {
- return $t_default_value;
- }
- }
-
- # --------------------
- # Gets the custom fields array for the given bug readable by specified level.
- # Array keys are custom field names. Array is sorted by custom field sequence number;
- # Array items are arrays with the next keys:
- # 'type', 'value', 'access_level_r'
- function custom_field_get_linked_fields( $p_bug_id, $p_user_access_level ) {
- $t_custom_fields = custom_field_get_all_linked_fields( $p_bug_id );
-
- # removing restricted fields
- foreach ( $t_custom_fields as $t_custom_field_name => $t_custom_field_data ) {
- if ( $p_user_access_level < $t_custom_field_data['access_level_r'] ) {
- unset( $t_custom_fields[$t_custom_field_name] );
- }
- }
- return $t_custom_fields;
- }
-
- # --------------------
- # Gets the custom fields array for the given bug. Array keys are custom field names.
- # Array is sorted by custom field sequence number; Array items are arrays with the next keys:
- # 'type', 'value', 'access_level_r'
- function custom_field_get_all_linked_fields( $p_bug_id ) {
- global $g_cached_custom_field_lists;
-
- if ( !is_array( $g_cached_custom_field_lists ) ) {
- $g_cached_custom_field_lists = array();
- }
-
- # is the list in cache ?
- if( !array_key_exists( $p_bug_id, $g_cached_custom_field_lists ) ) {
- $c_bug_id = db_prepare_int( $p_bug_id );
- $c_project_id = db_prepare_int( bug_get_field( $p_bug_id, 'project_id' ) );
-
- $t_custom_field_project_table = config_get( 'mantis_custom_field_project_table' );
- $t_custom_field_table = config_get( 'mantis_custom_field_table' );
- $t_custom_field_string_table = config_get( 'mantis_custom_field_string_table' );
-
- $query = "SELECT f.name, f.type, f.access_level_r, f.default_value, f.type, s.value
- FROM $t_custom_field_project_table p INNER JOIN $t_custom_field_table f
- ON p.field_id = f.id
- LEFT JOIN $t_custom_field_string_table s
- ON p.field_id=s.field_id AND s.bug_id='$c_bug_id'
- WHERE p.project_id = '$c_project_id'
- ORDER BY p.sequence ASC, f.name ASC";
-
- $result = db_query( $query );
-
- $t_row_count = db_num_rows( $result );
-
- $t_custom_fields = array();
-
- for ( $i=0 ; $i < $t_row_count ; ++$i ) {
- $row = db_fetch_array( $result );
-
- if( is_null( $row['value'] ) ) {
- $t_value = $row['default_value'];
- } else {
- $t_value = custom_field_database_to_value( $row['value'], $row['type'] );
- }
-
- $t_custom_fields[$row['name']] = array( 'type' => $row['type'],
- 'value' => $t_value,
- 'access_level_r' => $row['access_level_r'] );
- }
-
- $g_cached_custom_field_lists[$p_bug_id] = $t_custom_fields;
- }
-
- return $g_cached_custom_field_lists[$p_bug_id];
- }
-
-
- # --------------------
- # Gets the sequence number for the specified custom field for the specified
- # project. Returns false in case of error.
- function custom_field_get_sequence( $p_field_id, $p_project_id ) {
- $c_field_id = db_prepare_int( $p_field_id );
- $c_project_id = db_prepare_int( $p_project_id );
-
- $t_custom_field_project_table = config_get( 'mantis_custom_field_project_table' );
- $query = "SELECT sequence
- FROM $t_custom_field_project_table
- WHERE field_id='$c_field_id' AND
- project_id='$c_project_id'";
- $result = db_query( $query, 1 );
-
- if ( 0 == db_num_rows( $result ) ) {
- return false;
- }
-
- $t_row = db_fetch_array( $result );
-
- return $t_row['sequence'];
- }
-
- # --------------------
- # Allows the validation of a custom field value without setting it
- # or needing a bug to exist.
- function custom_field_validate( $p_field_id, $p_value ) {
- $c_field_id = db_prepare_int( $p_field_id );
- $c_value = db_prepare_string( $p_value );
-
- custom_field_ensure_exists( $p_field_id );
-
- $t_custom_field_table = config_get( 'mantis_custom_field_table' );
- $query = "SELECT name, type, possible_values, valid_regexp,
- access_level_rw, length_min, length_max, default_value
- FROM $t_custom_field_table
- WHERE id='$c_field_id'";
- $result = db_query( $query );
- $row = db_fetch_array( $result );
-
- $t_name = $row['name'];
- $t_type = $row['type'];
- $t_possible_values = $row['possible_values'];
- $t_valid_regexp = $row['valid_regexp'];
- $t_length_min = $row['length_min'];
- $t_length_max = $row['length_max'];
- $t_default_value = $row['default_value'];
-
- # check for valid value
- if ( !is_blank( $t_valid_regexp ) ) {
- if ( !ereg( $t_valid_regexp, $p_value ) ) {
- return false;
- }
- }
-
- if ( strlen( $p_value ) < $t_length_min ) {
- return false;
- }
-
- if ( ( 0 != $t_length_max ) && ( strlen( $p_value ) > $t_length_max ) ) {
- return false;
- }
-
- return true;
- }
-
- # --------------------
- # $p_possible_values: possible values to be pre-processed. If it has enum values,
- # it will be left as is. If it has a method, it will be replaced
- # by the list.
- function custom_field_prepare_possible_values( $p_possible_values ) {
- $t_possible_values = $p_possible_values;
-
- if ( !is_blank( $t_possible_values ) && ( $t_possible_values[0] == '=' ) ) {
- $t_possible_values = helper_call_custom_function( 'enum_' . substr( $t_possible_values, 1 ), array() );
- }
-
- return $t_possible_values;
- }
-
- # --------------------
- # Get All Possible Values for a Field.
- function custom_field_distinct_values( $p_field_id, $p_project_id = ALL_PROJECTS ) {
- $c_field_id = db_prepare_int( $p_field_id );
- $c_project_id = db_prepare_int( $p_project_id );
- $t_custom_field_string_table = config_get( 'mantis_custom_field_string_table' );
- $t_custom_field_table = config_get( 'mantis_custom_field_table' );
- $t_mantis_bug_table = config_get( 'mantis_bug_table' );
- $t_return_arr = array();
-
- $query = "SELECT type, possible_values
- FROM $t_custom_field_table
- WHERE id='$c_field_id'";
- $result = db_query( $query );
-
- $t_row_count = db_num_rows( $result );
- if ( 0 == $t_row_count ) {
- return false;
- }
- $row = db_fetch_array( $result );
-
- # If an enumeration type, we get all possible values, not just used values
- if ( CUSTOM_FIELD_TYPE_ENUM == $row['type'] ||
- CUSTOM_FIELD_TYPE_CHECKBOX == $row['type'] ||
- CUSTOM_FIELD_TYPE_LIST == $row['type'] ||
- CUSTOM_FIELD_TYPE_MULTILIST == $row['type']
- ) {
- $t_possible_values = custom_field_prepare_possible_values( $row['possible_values'] );
-
- $t_values_arr = explode( '|', $t_possible_values );
-
- foreach( $t_values_arr as $t_option ) {
- array_push( $t_return_arr, $t_option );
- }
- } else {
- $t_where = '';
- $t_from = $t_custom_field_string_table;
- if ( ALL_PROJECTS != $p_project_id ) {
- $t_where = " AND $t_mantis_bug_table.id = $t_custom_field_string_table.bug_id AND
- $t_mantis_bug_table.project_id = '$p_project_id'";
- $t_from = $t_from . ", $t_mantis_bug_table";
- }
- $query2 = "SELECT $t_custom_field_string_table.value FROM $t_from
- WHERE $t_custom_field_string_table.field_id='$c_field_id' $t_where
- GROUP BY $t_custom_field_string_table.value";
- $result2 = db_query( $query2 );
- $t_row_count = db_num_rows( $result2 );
- if ( 0 == $t_row_count ) {
- return false;
- }
-
- for ( $i = 0; $i < $t_row_count; $i++ ) {
- $row = db_fetch_array( $result2 );
- if( !is_blank( trim( $row['value'] ) ) ) {
- array_push( $t_return_arr, $row['value'] );
- }
- }
- }
- return $t_return_arr;
- }
-
- #===================================
- # Data Modification
- #===================================
-
- # --------------------
- # Convert the value to save it into the database, depending of the type
- # return value for database
- function custom_field_value_to_database( $p_value, $p_type ) {
- switch ($p_type) {
- case CUSTOM_FIELD_TYPE_MULTILIST:
- case CUSTOM_FIELD_TYPE_CHECKBOX:
- if ( '' == $p_value ) {
- $result = '';
- } else {
- $result = '|' . $p_value . '|';
- }
- break;
- default:
- $result = $p_value;
- }
- return $result;
- }
-
- # --------------------
- # Convert the database-value to value, depending of the type
- # return value for further operation
- function custom_field_database_to_value( $p_value, $p_type ) {
- switch ($p_type) {
- case CUSTOM_FIELD_TYPE_MULTILIST:
- case CUSTOM_FIELD_TYPE_CHECKBOX:
- $result = str_replace( '||', '', '|' . $p_value . '|' );
- break;
- default:
- $result = $p_value;
- }
- return $result;
- }
-
- # --------------------
- # Set the value of a custom field for a given bug
- # return true on success, false on failure
- function custom_field_set_value( $p_field_id, $p_bug_id, $p_value ) {
- $c_field_id = db_prepare_int( $p_field_id );
- $c_bug_id = db_prepare_int( $p_bug_id );
-
- custom_field_ensure_exists( $p_field_id );
-
- $t_custom_field_table = config_get( 'mantis_custom_field_table' );
- $query = "SELECT name, type, possible_values, valid_regexp,
- access_level_rw, length_min, length_max, default_value
- FROM $t_custom_field_table
- WHERE id='$c_field_id'";
- $result = db_query( $query );
- $row = db_fetch_array( $result );
-
- $t_name = $row['name'];
- $t_type = $row['type'];
- $t_possible_values = $row['possible_values'];
- $t_valid_regexp = $row['valid_regexp'];
- $t_access_level_rw = $row['access_level_rw'];
- $t_length_min = $row['length_min'];
- $t_length_max = $row['length_max'];
- $t_default_value = $row['default_value'];
-
- $c_value = db_prepare_string( custom_field_value_to_database( $p_value, $t_type ) );
-
- # check for valid value
- if ( !is_blank( $t_valid_regexp ) ) {
- if ( !ereg( $t_valid_regexp, $p_value ) ) {
- return false;
- }
- }
-
- if ( strlen( $p_value ) < $t_length_min ) {
- return false;
- }
-
- if ( ( 0 != $t_length_max ) && ( strlen( $p_value ) > $t_length_max ) ) {
- return false;
- }
-
- if( !custom_field_has_write_access( $p_field_id, $p_bug_id, auth_get_current_user_id() ) ) {
- return false;
- }
-
- $t_custom_field_string_table = config_get( 'mantis_custom_field_string_table' );
-
- # do I need to update or insert this value?
- $query = "SELECT value
- FROM $t_custom_field_string_table
- WHERE field_id='$c_field_id' AND
- bug_id='$c_bug_id'";
- $result = db_query( $query );
-
- if ( db_num_rows( $result ) > 0 ) {
- $query = "UPDATE $t_custom_field_string_table
- SET value='$c_value'
- WHERE field_id='$c_field_id' AND
- bug_id='$c_bug_id'";
- db_query( $query );
-
- $row = db_fetch_array( $result );
- history_log_event_direct( $c_bug_id, $t_name, custom_field_database_to_value( $row['value'], $t_type ), $p_value );
- } else {
- # Always store the value, even if it's the dafault value
- # This is important, as the definitions might change but the
- # values stored with a bug must not change
- $query = "INSERT INTO $t_custom_field_string_table
- ( field_id, bug_id, value )
- VALUES
- ( '$c_field_id', '$c_bug_id', '$c_value' )";
- db_query( $query );
- history_log_event_direct( $c_bug_id, $t_name, '', $p_value );
- }
-
- custom_field_clear_cache( $p_field_id );
-
- #db_query() errors on failure so:
- return true;
- }
-
- # --------------------
- # Sets the sequence number for the specified custom field for the specified
- # project.
- function custom_field_set_sequence( $p_field_id, $p_project_id, $p_sequence ) {
- $c_field_id = db_prepare_int( $p_field_id );
- $c_project_id = db_prepare_int( $p_project_id );
- $c_sequence = db_prepare_int( $p_sequence );
-
- $t_custom_field_project_table = config_get( 'mantis_custom_field_project_table' );
-
- $query = "UPDATE $t_custom_field_project_table
- SET sequence='$c_sequence'
- WHERE field_id='$c_field_id' AND
- project_id='$c_project_id'";
- $result = db_query( $query );
-
- custom_field_clear_cache( $p_field_id );
-
- return true;
- }
-
- #===================================
- # Output
- #===================================
-
- # --------------------
- # Print an input field
- # $p_field_def contains the definition of the custom field (including it's
- # field id
- # $p_bug_id contains the bug where this field belongs to. If it's left
- # away, it'll default to 0 and thus belongs to a new (i.e.
- # non-existant) bug
- # NOTE: This probably belongs in the print_api.php
- function print_custom_field_input( $p_field_def, $p_bug_id = null ) {
- $t_id = $p_field_def['id'];
-
- if( null === $p_bug_id ) {
- $t_custom_field_value = $p_field_def['default_value'];
- } else {
- $t_custom_field_value = custom_field_get_value( $t_id, $p_bug_id );
- }
-
- $t_custom_field_value = string_attribute( $t_custom_field_value );
-
- switch ($p_field_def['type']) {
- case CUSTOM_FIELD_TYPE_ENUM:
- case CUSTOM_FIELD_TYPE_LIST:
- case CUSTOM_FIELD_TYPE_MULTILIST:
- $t_values = explode( '|', custom_field_prepare_possible_values( $p_field_def['possible_values'] ) );
- $t_list_size = $t_possible_values_count = count( $t_values );
-
- if ( $t_possible_values_count > 5 ) {
- $t_list_size = 5;
- }
-
- if ( $p_field_def['type'] == CUSTOM_FIELD_TYPE_ENUM ) {
- $t_list_size = 0; # for enums the size is 0
- }
-
- if ( $p_field_def['type'] == CUSTOM_FIELD_TYPE_MULTILIST ) {
- echo '<select ', helper_get_tab_index(), ' name="custom_field_' . $t_id . '[]" size="' . $t_list_size . '" multiple="multiple">';
- } else {
- echo '<select ', helper_get_tab_index(), ' name="custom_field_' . $t_id . '" size="' . $t_list_size . '">';
- }
-
- $t_selected_values = explode( '|', $t_custom_field_value );
- foreach( $t_values as $t_option ) {
- if( in_array( $t_option, $t_selected_values, true ) ) {
- echo '<option value="' . $t_option . '" selected="selected"> ' . $t_option . '</option>';
- } else {
- echo '<option value="' . $t_option . '">' . $t_option . '</option>';
- }
- }
- echo '</select>';
- break;
- case CUSTOM_FIELD_TYPE_CHECKBOX:
- $t_values = explode( '|', custom_field_prepare_possible_values( $p_field_def['possible_values'] ) );
- $t_checked_values = explode( '|', $t_custom_field_value );
- foreach( $t_values as $t_option ) {
- echo '<input ', helper_get_tab_index(), ' type="checkbox" name="custom_field_' . $t_id . '[]"';
- if( in_array( $t_option, $t_checked_values, true ) ) {
- echo ' value="' . $t_option . '" checked="checked"> ' . $t_option . ' ';
- } else {
- echo ' value="' . $t_option . '"> ' . $t_option . ' ';
- }
- }
- break;
- case CUSTOM_FIELD_TYPE_NUMERIC:
- case CUSTOM_FIELD_TYPE_FLOAT:
- case CUSTOM_FIELD_TYPE_EMAIL:
- case CUSTOM_FIELD_TYPE_STRING:
- # START MX: treat maxLength > 255 as textarea
- if( 255 < $p_field_def['length_max'] ) {
- echo '<textarea cols="80" rows="10" name="custom_field_' . $t_id . '">';
- echo '' . $t_custom_field_value .'';
- echo '</textarea>';
- } else {
- # END MX
- echo '<input ', helper_get_tab_index(), ' type="text" name="custom_field_' . $t_id . '" size="80"';
- if( 0 < $p_field_def['length_max'] ) {
- echo ' maxlength="' . $p_field_def['length_max'] . '"';
- } else {
- echo ' maxlength="255"';
- }
- echo ' value="' . $t_custom_field_value .'"></input>';
- } # MX
- break ;
-
- case CUSTOM_FIELD_TYPE_DATE:
- print_date_selection_set("custom_field_" . $t_id, config_get('short_date_format'), $t_custom_field_value, false, true) ;
- break ;
- }
- }
-
- # --------------------
- # Prepare a string containing a custom field value for display
- # $p_def contains the definition of the custom field
- # $p_field_id contains the id of the field
- # $p_bug_id contains the bug id to display the custom field value for
- # NOTE: This probably belongs in the string_api.php
- function string_custom_field_value( $p_def, $p_field_id, $p_bug_id ) {
- $t_custom_field_value = custom_field_get_value( $p_field_id, $p_bug_id );
- switch( $p_def['type'] ) {
- case CUSTOM_FIELD_TYPE_EMAIL:
- return "<a href=\"mailto:$t_custom_field_value\">$t_custom_field_value</a>";
- break;
- case CUSTOM_FIELD_TYPE_ENUM:
- case CUSTOM_FIELD_TYPE_LIST:
- case CUSTOM_FIELD_TYPE_MULTILIST:
- case CUSTOM_FIELD_TYPE_CHECKBOX:
- return str_replace( '|', ', ', $t_custom_field_value );
- break;
- case CUSTOM_FIELD_TYPE_DATE:
- if ($t_custom_field_value != null) {
- return date( config_get( 'short_date_format'), $t_custom_field_value) ;
- }
- break ;
- default:
- return string_display_links( $t_custom_field_value );
- }
- }
-
- # --------------------
- # Print a custom field value for display
- # $p_def contains the definition of the custom field
- # $p_field_id contains the id of the field
- # $p_bug_id contains the bug id to display the custom field value for
- # NOTE: This probably belongs in the print_api.php
- function print_custom_field_value( $p_def, $p_field_id, $p_bug_id ) {
- echo string_custom_field_value( $p_def, $p_field_id, $p_bug_id );
- }
-
- # --------------------
- # Prepare a string containing a custom field value for email
- # $p_value value of custom field
- # $p_type type of custom field
- # NOTE: This probably belongs in the string_api.php
- function string_custom_field_value_for_email( $p_value, $p_type ) {
- switch( $p_type ) {
- case CUSTOM_FIELD_TYPE_EMAIL:
- return 'mailto:'.$p_value;
- break;
- case CUSTOM_FIELD_TYPE_ENUM:
- case CUSTOM_FIELD_TYPE_LIST:
- case CUSTOM_FIELD_TYPE_MULTILIST:
- case CUSTOM_FIELD_TYPE_CHECKBOX:
- return str_replace( '|', ', ', $p_value );
- break;
- case CUSTOM_FIELD_TYPE_DATE:
- if ($p_value != null) {
- return date( config_get( 'short_date_format' ), $p_value) ;
- }
- break ;
- default:
- return $p_value;
- }
- return $p_value;
- }
-
-?>
+<?php
+# Mantis - a php based bugtracking system
+
+# Copyright (C) 2000 - 2002 Kenzaburo Ito - kenito@300baud.org
+# Copyright (C) 2002 - 2007 Mantis Team - mantisbt-dev@lists.sourceforge.net
+
+# Mantis is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+#
+# Mantis is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Mantis. If not, see <http://www.gnu.org/licenses/>.
+
+ # --------------------------------------------------------
+ # $Id: custom_field_api.php,v 1.66.2.1 2007-10-13 22:35:21 giallu Exp $
+ # --------------------------------------------------------
+
+ $t_core_dir = dirname( __FILE__ ).DIRECTORY_SEPARATOR;
+
+ require_once( $t_core_dir . 'bug_api.php' );
+ require_once( $t_core_dir . 'helper_api.php' );
+ require_once( $t_core_dir . 'date_api.php' );
+
+ ### Custom Fields API ###
+
+#*******************************************
+# TODO
+# - add an object to store field data like BugData and UserPrefs ?
+# - add caching functions like user, bug, etc
+# - make existing api functions use caching functions
+# - add functions to return individual db columns for a field definition
+#*******************************************
+
+ #===================================
+ # Caching
+ #===================================
+
+ #########################################
+ # SECURITY NOTE: cache globals are initialized here to prevent them
+ # being spoofed if register_globals is turned on
+
+ $g_cache_custom_field = array();
+ $g_cache_cf_list = NULL;
+ $g_cache_cf_linked = array();
+
+ # Cache a custom field row if necessary and return the cached copy
+ # If the second parameter is true (default), trigger an error
+ # if the field can't be found. If the second parameter is
+ # false, return false if the field can't be found.
+ function custom_field_cache_row( $p_field_id, $p_trigger_errors=true ) {
+ global $g_cache_custom_field;
+
+ $c_field_id = db_prepare_int( $p_field_id );
+
+ $t_custom_field_table = config_get( 'mantis_custom_field_table' );
+
+ if ( isset ( $g_cache_custom_field[$c_field_id] ) ) {
+ return $g_cache_custom_field[$c_field_id];
+ }
+
+ $query = "SELECT *
+ FROM $t_custom_field_table
+ WHERE id='$c_field_id'";
+ $result = db_query( $query );
+
+ if ( 0 == db_num_rows( $result ) ) {
+ if ( $p_trigger_errors ) {
+ error_parameters( 'Custom ' . $p_field_id );
+ trigger_error( ERROR_CUSTOM_FIELD_NOT_FOUND, ERROR );
+ } else {
+ return false;
+ }
+ }
+
+ $row = db_fetch_array( $result );
+
+ $g_cache_custom_field[$c_field_id] = $row;
+
+ return $row;
+ }
+
+ # --------------------
+ # Clear the custom field cache (or just the given id if specified)
+ function custom_field_clear_cache( $p_field_id = null ) {
+ global $g_cache_custom_field, $g_cached_custom_field_lists;
+
+ $g_cached_custom_field_lists = null;
+
+ if ( null === $p_field_id ) {
+ $g_cache_custom_field = array();
+ } else {
+ $c_field_id = db_prepare_int( $p_field_id );
+ unset( $g_cache_custom_field[$c_field_id] );
+ }
+
+ return true;
+ }
+
+
+ #===================================
+ # Boolean queries and ensures
+ #===================================
+
+ # --------------------
+ # Check to see whether the field is included in the given project
+ # return true if the field is included, false otherwise
+ #
+ function custom_field_is_linked( $p_field_id, $p_project_id ) {
+ $c_project_id = db_prepare_int( $p_project_id );
+ $c_field_id = db_prepare_int( $p_field_id );
+
+ # figure out if this bug_id/field_id combination exists
+ $t_custom_field_project_table = config_get( 'mantis_custom_field_project_table' );
+ $query = "SELECT COUNT(*)
+ FROM $t_custom_field_project_table
+ WHERE field_id='$c_field_id' AND
+ project_id='$c_project_id'";
+ $result = db_query( $query );
+ $count = db_result( $result );
+
+ if ( $count > 0 ) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ # --------------------
+ # Check to see whether the field id is defined
+ # return true if the field is defined, false otherwise
+ function custom_field_exists( $p_field_id ) {
+ if ( false == custom_field_cache_row( $p_field_id, false ) ) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ # --------------------
+ # Return the type of a custom field if it exists.
+ function custom_field_type( $p_field_id ) {
+ $t_field = custom_field_cache_row( $p_field_id, false ) ;
+ if ( $t_field == false ) {
+ return -1 ;
+ } else {
+ return $t_field[ 'type' ] ;
+ }
+ }
+
+ # --------------------
+ # Check to see whether the field id is defined
+ # return true if the field is defined, error otherwise
+ function custom_field_ensure_exists( $p_field_id ) {
+ if ( custom_field_exists( $p_field_id ) ) {
+ return true;
+ } else {
+ error_parameters( 'Custom ' . $p_field_id );
+ trigger_error( ERROR_CUSTOM_FIELD_NOT_FOUND, ERROR );
+ }
+ }
+
+ # --------------------
+ # Check to see whether the name is unique
+ # return false if a field with the name already exists, true otherwise
+ # if an id is specified, then the corresponding record is excluded from the
+ # uniqueness test.
+ function custom_field_is_name_unique( $p_name, $p_custom_field_id = null ) {
+ $c_name = db_prepare_string( $p_name );
+
+ $t_custom_field_table = config_get( 'mantis_custom_field_table' );
+ $query = "SELECT COUNT(*)
+ FROM $t_custom_field_table
+ WHERE name='$c_name'";
+ if ( $p_custom_field_id !== null ) {
+ $c_id = db_prepare_int( $p_custom_field_id );
+ $query .= " AND (id <> $c_id)";
+ }
+ $result = db_query( $query );
+ $count = db_result( $result );
+
+ if ( $count > 0 ) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ # --------------------
+ # Check to see whether the name is unique
+ # return true if the name has not been used, error otherwise
+ function custom_field_ensure_name_unique( $p_name ) {
+ if ( custom_field_is_name_unique( $p_name ) ) {
+ return true;
+ } else {
+ trigger_error( ERROR_CUSTOM_FIELD_NAME_NOT_UNIQUE, ERROR );
+ }
+ }
+
+ # --------------------
+ # Return true if the user can read the value of the field for the given bug,
+ # false otherwise.
+ function custom_field_has_read_access( $p_field_id, $p_bug_id, $p_user_id = null ) {
+ custom_field_ensure_exists( $p_field_id );
+
+ if ( null === $p_user_id ) {
+ $p_user_id = auth_get_current_user_id();
+ }
+
+ $t_access_level_r = custom_field_get_field( $p_field_id, 'access_level_r' );
+
+ $t_project_id = bug_get_field( $p_bug_id, 'project_id' );
+
+ return access_has_project_level( $t_access_level_r, $t_project_id, $p_user_id );
+ }
+
+ # --------------------
+ # Return true if the user can modify the value of the field for the given project,
+ # false otherwise.
+ function custom_field_has_write_access_to_project( $p_field_id, $p_project_id, $p_user_id = null ) {
+ custom_field_ensure_exists( $p_field_id );
+
+ if ( null === $p_user_id ) {
+ $p_user_id = auth_get_current_user_id();
+ }
+
+ $t_access_level_rw = custom_field_get_field( $p_field_id, 'access_level_rw' );
+
+ return access_has_project_level( $t_access_level_rw, $p_project_id, $p_user_id );
+ }
+
+ # --------------------
+ # Return true if the user can modify the value of the field for the given bug,
+ # false otherwise.
+ function custom_field_has_write_access( $p_field_id, $p_bug_id, $p_user_id = null ) {
+ $t_project_id = bug_get_field( $p_bug_id, 'project_id' );
+ return ( custom_field_has_write_access_to_project( $p_field_id, $t_project_id, $p_user_id ) );
+ }
+
+ #===================================
+ # Creation / Deletion / Updating
+ #===================================
+
+ # --------------------
+ # create a new custom field with the name $p_name
+ # the definition are the default values and can be changes later
+ # return the ID of the new definition
+ function custom_field_create( $p_name ) {
+ if ( string_contains_scripting_chars( $p_name ) ) {
+ trigger_error( ERROR_CUSTOM_FIELD_INVALID_DEFINITION, ERROR );
+ }
+
+ $c_name = db_prepare_string( trim( $p_name ) );
+
+ if ( is_blank( $c_name ) ) {
+ error_parameters( 'name' );
+ trigger_error( ERROR_EMPTY_FIELD, ERROR );
+ }
+
+ custom_field_ensure_name_unique( $c_name );
+
+ $t_custom_field_table = config_get( 'mantis_custom_field_table' );
+ $query = "INSERT INTO $t_custom_field_table
+ ( name )
+ VALUES
+ ( '$c_name' )";
+
+ db_query( $query );
+
+ return db_insert_id( $t_custom_field_table );
+ }
+
+ # --------------------
+ # Update the field definition
+ # return true on success, false on failure
+ function custom_field_update( $p_field_id, $p_def_array ) {
+ if ( string_contains_scripting_chars( $p_def_array['name'] ) ) {
+ trigger_error( ERROR_CUSTOM_FIELD_INVALID_DEFINITION, ERROR );
+ }
+
+ $c_field_id = db_prepare_int( $p_field_id );
+ $c_name = db_prepare_string( trim( $p_def_array['name'] ) );
+ $c_type = db_prepare_int( $p_def_array['type'] );
+ $c_possible_values = db_prepare_string( $p_def_array['possible_values'] );
+ $c_default_value = db_prepare_string( $p_def_array['default_value'] );
+ $c_valid_regexp = db_prepare_string( $p_def_array['valid_regexp'] );
+ $c_access_level_r = db_prepare_int( $p_def_array['access_level_r'] );
+ $c_access_level_rw = db_prepare_int( $p_def_array['access_level_rw'] );
+ $c_length_min = db_prepare_int( $p_def_array['length_min'] );
+ $c_length_max = db_prepare_int( $p_def_array['length_max'] );
+ $c_advanced = db_prepare_bool( $p_def_array['advanced'] );
+ $c_display_report = db_prepare_bool( $p_def_array['display_report'] );
+ $c_display_update = db_prepare_bool( $p_def_array['display_update'] );
+ $c_display_resolved = db_prepare_bool( $p_def_array['display_resolved'] );
+ $c_display_closed = db_prepare_bool( $p_def_array['display_closed'] );
+ $c_require_report = db_prepare_bool( $p_def_array['require_report'] );
+ $c_require_update = db_prepare_bool( $p_def_array['require_update'] );
+ $c_require_resolved = db_prepare_bool( $p_def_array['require_resolved'] );
+ $c_require_closed = db_prepare_bool( $p_def_array['require_closed'] );
+
+ if ( is_blank( $c_name ) ) {
+ error_parameters( 'name' );
+ trigger_error( ERROR_EMPTY_FIELD, ERROR );
+ }
+
+ if (( $c_access_level_rw < $c_access_level_r ) ||
+ ( $c_length_min < 0 ) ||
+ ( ( $c_length_max != 0 ) && ( $c_length_min > $c_length_max ) ) ) {
+ trigger_error( ERROR_CUSTOM_FIELD_INVALID_DEFINITION, ERROR );
+ }
+
+ if ( $c_advanced == true && ( $c_require_report == true || $c_require_update ) ) {
+ trigger_error( ERROR_CUSTOM_FIELD_INVALID_DEFINITION, ERROR );
+ }
+
+ if ( !custom_field_is_name_unique( $c_name, $c_field_id ) ) {
+ trigger_error( ERROR_CUSTOM_FIELD_NAME_NOT_UNIQUE, ERROR );
+ }
+
+ $t_update_something = false;
+ $t_mantis_custom_field_table = config_get( 'mantis_custom_field_table' );
+ $query = "UPDATE $t_mantis_custom_field_table
+ SET ";
+ if( array_key_exists( 'name', $p_def_array ) ) {
+ if ( !$t_update_something ) {
+ $t_update_something = true;
+ } else {
+ $query .= ', ';
+ }
+ $query .= "name='$c_name'";
+ }
+ if( array_key_exists( 'type', $p_def_array ) ) {
+ if ( !$t_update_something ) {
+ $t_update_something = true;
+ } else {
+ $query .= ', ';
+ }
+ $query .= "type='$c_type'";
+ }
+ if( array_key_exists( 'possible_values', $p_def_array ) ) {
+ if ( !$t_update_something ) {
+ $t_update_something = true;
+ } else {
+ $query .= ', ';
+ }
+ $query .= "possible_values='$c_possible_values'";
+ }
+ if( array_key_exists( 'default_value', $p_def_array ) ) {
+ if ( !$t_update_something ) {
+ $t_update_something = true;
+ } else {
+ $query .= ', ';
+ }
+ $query .= "default_value='$c_default_value'";
+ }
+ if( array_key_exists( 'valid_regexp', $p_def_array ) ) {
+ if ( !$t_update_something ) {
+ $t_update_something = true;
+ } else {
+ $query .= ', ';
+ }
+ $query .= "valid_regexp='$c_valid_regexp'";
+ }
+ if( array_key_exists( 'access_level_r', $p_def_array ) ) {
+ if ( !$t_update_something ) {
+ $t_update_something = true;
+ } else {
+ $query .= ', ';
+ }
+ $query .= "access_level_r='$c_access_level_r'";
+ }
+ if( array_key_exists( 'access_level_rw', $p_def_array ) ) {
+ if ( !$t_update_something ) {
+ $t_update_something = true;
+ } else {
+ $query .= ', ';
+ }
+ $query .= "access_level_rw='$c_access_level_rw'";
+ }
+ if( array_key_exists( 'length_min', $p_def_array ) ) {
+ if ( !$t_update_something ) {
+ $t_update_something = true;
+ } else {
+ $query .= ', ';
+ }
+ $query .= "length_min='$c_length_min'";
+ }
+ if( array_key_exists( 'length_max', $p_def_array ) ) {
+ if ( !$t_update_something ) {
+ $t_update_something = true;
+ } else {
+ $query .= ', ';
+ }
+ $query .= "length_max='$c_length_max'";
+ }
+ if( array_key_exists( 'advanced', $p_def_array ) ) {
+ if ( !$t_update_something ) {
+ $t_update_something = true;
+ } else {
+ $query .= ', ';
+ }
+ $query .= "advanced='$c_advanced'";
+ }
+ if( array_key_exists( 'display_report', $p_def_array ) ) {
+ if ( !$t_update_something ) {
+ $t_update_something = true;
+ } else {
+ $query .= ', ';
+ }
+ $query .= "display_report='$c_display_report'";
+ }
+ if( array_key_exists( 'display_update', $p_def_array ) ) {
+ if ( !$t_update_something ) {
+ $t_update_something = true;
+ } else {
+ $query .= ', ';
+ }
+ $query .= "display_update='$c_display_update'";
+ }
+ if( array_key_exists( 'display_resolved', $p_def_array ) ) {
+ if ( !$t_update_something ) {
+ $t_update_something = true;
+ } else {
+ $query .= ', ';
+ }
+ $query .= "display_resolved='$c_display_resolved'";
+ }
+ if( array_key_exists( 'display_closed', $p_def_array ) ) {
+ if ( !$t_update_something ) {
+ $t_update_something = true;
+ } else {
+ $query .= ', ';
+ }
+ $query .= "display_closed='$c_display_closed'";
+ }
+ if( array_key_exists( 'require_report', $p_def_array ) ) {
+ if ( !$t_update_something ) {
+ $t_update_something = true;
+ } else {
+ $query .= ', ';
+ }
+ $query .= "require_report='$c_require_report'";
+ }
+ if( array_key_exists( 'require_update', $p_def_array ) ) {
+ if ( !$t_update_something ) {
+ $t_update_something = true;
+ } else {
+ $query .= ', ';
+ }
+ $query .= "require_update='$c_require_update'";
+ }
+ if( array_key_exists( 'require_resolved', $p_def_array ) ) {
+ if ( !$t_update_something ) {
+ $t_update_something = true;
+ } else {
+ $query .= ', ';
+ }
+ $query .= "require_resolved='$c_require_resolved'";
+ }
+ if( array_key_exists( 'require_closed', $p_def_array ) ) {
+ if ( !$t_update_something ) {
+ $t_update_something = true;
+ } else {
+ $query .= ', ';
+ }
+ $query .= "require_closed='$c_require_closed'";
+ }
+
+
+ $query .= " WHERE id='$c_field_id'";
+
+ if( $t_update_something ) {
+ db_query( $query );
+ custom_field_clear_cache( $p_field_id );
+ } else {
+ return false; # there is nothing to update...
+ }
+
+ # db_query() errors on failure so:
+ return true;
+ }
+
+ # --------------------
+ # Add a custom field to a project
+ # return true on success, false on failure or if already added
+ function custom_field_link( $p_field_id, $p_project_id ) {
+ $c_field_id = db_prepare_int( $p_field_id );
+ $c_project_id = db_prepare_int( $p_project_id );
+
+ custom_field_ensure_exists( $p_field_id );
+ project_ensure_exists( $p_project_id );
+
+ if ( custom_field_is_linked( $p_field_id, $p_project_id ) ) {
+ return false;
+ }
+
+ $t_custom_field_project_table = config_get( 'mantis_custom_field_project_table' );
+ $query = "INSERT INTO $t_custom_field_project_table
+ ( field_id, project_id )
+ VALUES
+ ( '$c_field_id', '$c_project_id' )";
+ db_query( $query );
+
+ # db_query() errors on failure so:
+ return true;
+ }
+
+ # --------------------
+ # Remove a custom field from a project
+ # return true on success, false on failure
+ #
+ # The values for the custom fields are not deleted. This is to allow for the
+ # case where a bug is moved to another project that has the field, or the
+ # field is linked again to the project.
+ function custom_field_unlink( $p_field_id, $p_project_id ) {
+ $c_field_id = db_prepare_int( $p_field_id );
+ $c_project_id = db_prepare_int( $p_project_id );
+
+ $t_custom_field_project_table = config_get( 'mantis_custom_field_project_table' );
+ $query = "DELETE FROM $t_custom_field_project_table
+ WHERE field_id = '$c_field_id' AND
+ project_id = '$c_project_id'";
+ db_query( $query );
+
+ # db_query() errors on failure so:
+ return true;
+ }
+
+ # --------------------
+ # Delete the field definition and all associated values and project
+ # associations
+ # return true on success, false on failure
+ function custom_field_destroy( $p_field_id ) {
+ $c_field_id = db_prepare_int( $p_field_id );
+
+ # delete all values
+ $t_custom_field_string_table = config_get( 'mantis_custom_field_string_table' );
+ $query = "DELETE FROM $t_custom_field_string_table
+ WHERE field_id='$c_field_id'";
+ db_query( $query );
+
+ # delete all project associations
+ $t_custom_field_project_table = config_get( 'mantis_custom_field_project_table' );
+ $query = "DELETE FROM $t_custom_field_project_table
+ WHERE field_id='$c_field_id'";
+ db_query( $query );
+
+ $t_custom_field_table = config_get( 'mantis_custom_field_table' );
+ # delete the definition
+ $query = "DELETE FROM $t_custom_field_table
+ WHERE id='$c_field_id'";
+ db_query( $query );
+
+ custom_field_clear_cache( $p_field_id );
+
+ # db_query() errors on failure so:
+ return true;
+ }
+
+ # --------------------
+ # Delete all associations of custom fields to the specified project
+ # return true on success, false on failure
+ #
+ # To be called from within project_delete().
+ function custom_field_unlink_all( $p_project_id ) {
+ $c_project_id = db_prepare_int( $p_project_id );
+
+ # delete all project associations
+ $t_custom_field_project_table = config_get( 'mantis_custom_field_project_table' );
+ $query = "DELETE FROM $t_custom_field_project_table
+ WHERE project_id='$c_project_id'";
+ db_query( $query );
+
+ # db_query() errors on failure so:
+ return true;
+ }
+
+ # --------------------
+ # Delete all custom values associated with the specified bug.
+ # return true on success, false on failure
+ #
+ # To be called from bug_delete().
+ function custom_field_delete_all_values( $p_bug_id ) {
+ $c_bug_id = db_prepare_int( $p_bug_id );
+
+ $t_custom_field_string_table = config_get( 'mantis_custom_field_string_table' );
+ $query = "DELETE FROM $t_custom_field_string_table
+ WHERE bug_id='$c_bug_id'";
+ db_query( $query );
+
+ #db_query() errors on failure so:
+ return true;
+ }
+
+ #===================================
+ # Data Access
+ #===================================
+
+ # --------------------
+ # Get the id of the custom field with the specified name.
+ # false is returned if no custom field found with the specified name.
+ function custom_field_get_id_from_name( $p_field_name, $p_truncated_length = null ) {
+ if ( $p_field_name == '' ) {
+ return false;
+ }
+
+ $t_custom_field_table = config_get( 'mantis_custom_field_table' );
+
+ $c_field_name = db_prepare_string( $p_field_name );
+
+ if ( ( null === $p_truncated_length ) || ( strlen( $c_field_name ) != $p_truncated_length ) ) {
+ $query = "SELECT id FROM $t_custom_field_table WHERE name = '$c_field_name'";
+ } else {
+ # @@@ This is to handle the case where we only have a truncated part of the name. This happens in the case where
+ # we are getting the custom field name from the history logs, since history is 32 and custom field name is 64.
+ # This fix will handle entries already in the database, future entries should be handled by making the field name max lengths match.
+ $query = "SELECT id FROM $t_custom_field_table WHERE name LIKE '$c_field_name%'";
+ }
+
+ $t_result = db_query( $query, 1 );
+
+ if ( db_num_rows( $t_result ) == 0 ) {
+ return false;
+ }
+
+ $row = db_fetch_array( $t_result );
+
+ return $row['id'];
+ }
+
+ # --------------------
+ # Return an array of ids of custom fields bound to the specified project
+ #
+ # The ids will be sorted based on the sequence number associated with the binding
+ function custom_field_get_linked_ids( $p_project_id = ALL_PROJECTS ) {
+ global $g_cache_cf_linked;
+
+ if ( ! isset( $g_cache_cf_linked[$p_project_id] ) ) {
+
+ $t_custom_field_table = config_get( 'mantis_custom_field_table' );
+ $t_custom_field_project_table = config_get( 'mantis_custom_field_project_table' );
+
+ if ( ALL_PROJECTS == $p_project_id ) {
+ $t_project_user_list_table = config_get( 'mantis_project_user_list_table' );
+ $t_project_table = config_get( 'mantis_project_table' );
+ $t_user_table = config_get( 'mantis_user_table' );
+ $t_user_id = auth_get_current_user_id();
+ $t_pub = VS_PUBLIC;
+ $t_priv = VS_PRIVATE;
+
+ $t_private_access = config_get( 'private_project_threshold' );
+ if ( is_array( $t_private_access ) ) {
+ if ( 1 == count( $t_private_access ) ) {
+ $t_access_clause = "= " . array_shift( $t_private_access ) . " ";
+ } else {
+ $t_access_clause = "IN (" . implode( ',', $t_private_access ) . ")";
+ }
+ } else {
+ $t_access_clause = ">= $t_private_access ";
+ }
+
+
+ # select only the ids that the user has some access to
+ # e.g., all fields in public projects, or private projects where the user is listed
+ # or private projects where the user is implicitly listed
+ $query = "SELECT cft.id as id, cft.name as name
+ FROM $t_custom_field_table as cft, $t_user_table ut, $t_project_table pt, $t_custom_field_project_table cfpt
+ LEFT JOIN $t_project_user_list_table pult
+ on cfpt.project_id = pult.project_id and pult.user_id = $t_user_id
+ WHERE cft.id = cfpt.field_id AND cfpt.project_id = pt.id AND ut.id = $t_user_id AND
+ ( pt.view_state = $t_pub OR
+ ( pt.view_state = $t_priv and pult.user_id = $t_user_id ) OR
+ ( pult.user_id is null and ut.access_level $t_access_clause ) )
+ GROUP BY cft.id, cft.name
+ ORDER BY cft.name ASC";
+ } else {
+ if ( is_array( $p_project_id ) ) {
+ if ( 1 == count( $p_project_id ) ) {
+ $t_project_clause = "= " . array_shift( $p_project_id ) . " ";
+ } else {
+ $t_project_clause = "IN (" . implode( ',', $p_project_id ) . ")";
+ }
+ } else {
+ $t_project_clause = "= $p_project_id ";
+ }
+ $query = "SELECT cft.id, cft.name, cfpt.sequence
+ FROM $t_custom_field_table cft, $t_custom_field_project_table cfpt
+ WHERE cfpt.project_id $t_project_clause AND
+ cft.id = cfpt.field_id
+ ORDER BY sequence ASC, name ASC";
+ }
+ $result = db_query( $query );
+ $t_row_count = db_num_rows( $result );
+ $t_ids = array();
+
+ for ( $i=0 ; $i < $t_row_count ; $i++ ) {
+ $row = db_fetch_array( $result );
+
+ array_push( $t_ids, $row['id'] );
+ }
+ $g_cache_cf_linked[$p_project_id] = $t_ids;
+ } else {
+ $t_ids = $g_cache_cf_linked[$p_project_id];
+ }
+
+ return $t_ids;
+ }
+
+ # --------------------
+ # Return an array all custom field ids sorted by name
+ function custom_field_get_ids( ) {
+ global $g_cache_cf_list;
+
+ if ( $g_cache_cf_list === NULL ) {
+ $t_custom_field_table = config_get( 'mantis_custom_field_table' );
+ $query = "SELECT id, name
+ FROM $t_custom_field_table
+ ORDER BY name ASC";
+ $result = db_query( $query );
+ $t_row_count = db_num_rows( $result );
+ $t_ids = array();
+
+ for ( $i=0 ; $i < $t_row_count ; $i++ ) {
+ $row = db_fetch_array( $result );
+
+ array_push( $t_ids, $row['id'] );
+ }
+ $g_cache_cf_list = $t_ids;
+
+ } else {
+ $t_ids = $g_cache_cf_list;
+ }
+ return $t_ids;
+ }
+
+ # --------------------
+ # Return an array of ids of projects related to the specified custom field
+ # (the array may be empty)
+ function custom_field_get_project_ids( $p_field_id ) {
+ $c_field_id = db_prepare_int( $p_field_id );
+
+ $t_custom_field_project_table = config_get( 'mantis_custom_field_project_table' );
+ $query = "SELECT project_id
+ FROM $t_custom_field_project_table
+ WHERE field_id = '$c_field_id'";
+ $result = db_query( $query );
+
+ $t_row_count = db_num_rows( $result );
+ $t_ids = array();
+
+ for ( $i=0 ; $i < $t_row_count ; $i++ ) {
+ $row = db_fetch_array( $result );
+
+ array_push( $t_ids, $row['project_id'] );
+ }
+
+ return $t_ids;
+ }
+
+ # --------------------
+ # Return a field definition row for the field or error if the field does
+ # not exist
+ function custom_field_get_definition( $p_field_id ) {
+ return custom_field_cache_row( $p_field_id );
+ }
+
+ # --------------------
+ # Return a single database field from a custom field definition row
+ # for the field
+ # if the database field does not exist, display a warning and return ''
+ function custom_field_get_field( $p_field_id, $p_field_name ) {
+ $row = custom_field_get_definition( $p_field_id );
+
+ if ( isset( $row[$p_field_name] ) ) {
+ return $row[$p_field_name];
+ } else {
+ error_parameters( $p_field_name );
+ trigger_error( ERROR_DB_FIELD_NOT_FOUND, WARNING );
+ return '';
+ }
+ }
+
+ # --------------------
+ # Get the value of a custom field for the given bug
+ #
+ # @@@ return values are unclear... should we error when access is denied
+ # and provide an api to check whether it will be?
+ function custom_field_get_value( $p_field_id, $p_bug_id ) {
+ $c_field_id = db_prepare_int( $p_field_id );
+ $c_bug_id = db_prepare_int( $p_bug_id );
+
+ custom_field_ensure_exists( $p_field_id );
+
+ $t_custom_field_table = config_get( 'mantis_custom_field_table' );
+ $query = "SELECT access_level_r, default_value, type
+ FROM $t_custom_field_table
+ WHERE id='$c_field_id'";
+ $result = db_query( $query );
+ $row = db_fetch_array( $result );
+
+ $t_access_level_r = $row['access_level_r'];
+ $t_default_value = $row['default_value'];
+
+ if( !custom_field_has_read_access( $p_field_id, $p_bug_id, auth_get_current_user_id() ) ) {
+ return false;
+ }
+
+ $t_custom_field_string_table = config_get( 'mantis_custom_field_string_table' );
+ $query = "SELECT value
+ FROM $t_custom_field_string_table
+ WHERE bug_id='$c_bug_id' AND
+ field_id='$c_field_id'";
+ $result = db_query( $query );
+
+ if( db_num_rows( $result ) > 0 ) {
+ return custom_field_database_to_value( db_result( $result ) , $row['type'] );
+ } else {
+ return $t_default_value;
+ }
+ }
+
+ # --------------------
+ # Gets the custom fields array for the given bug readable by specified level.
+ # Array keys are custom field names. Array is sorted by custom field sequence number;
+ # Array items are arrays with the next keys:
+ # 'type', 'value', 'access_level_r'
+ function custom_field_get_linked_fields( $p_bug_id, $p_user_access_level ) {
+ $t_custom_fields = custom_field_get_all_linked_fields( $p_bug_id );
+
+ # removing restricted fields
+ foreach ( $t_custom_fields as $t_custom_field_name => $t_custom_field_data ) {
+ if ( $p_user_access_level < $t_custom_field_data['access_level_r'] ) {
+ unset( $t_custom_fields[$t_custom_field_name] );
+ }
+ }
+ return $t_custom_fields;
+ }
+
+ # --------------------
+ # Gets the custom fields array for the given bug. Array keys are custom field names.
+ # Array is sorted by custom field sequence number; Array items are arrays with the next keys:
+ # 'type', 'value', 'access_level_r'
+ function custom_field_get_all_linked_fields( $p_bug_id ) {
+ global $g_cached_custom_field_lists;
+
+ if ( !is_array( $g_cached_custom_field_lists ) ) {
+ $g_cached_custom_field_lists = array();
+ }
+
+ # is the list in cache ?
+ if( !array_key_exists( $p_bug_id, $g_cached_custom_field_lists ) ) {
+ $c_bug_id = db_prepare_int( $p_bug_id );
+ $c_project_id = db_prepare_int( bug_get_field( $p_bug_id, 'project_id' ) );
+
+ $t_custom_field_project_table = config_get( 'mantis_custom_field_project_table' );
+ $t_custom_field_table = config_get( 'mantis_custom_field_table' );
+ $t_custom_field_string_table = config_get( 'mantis_custom_field_string_table' );
+
+ $query = "SELECT f.name, f.type, f.access_level_r, f.default_value, f.type, s.value
+ FROM $t_custom_field_project_table p INNER JOIN $t_custom_field_table f
+ ON p.field_id = f.id
+ LEFT JOIN $t_custom_field_string_table s
+ ON p.field_id=s.field_id AND s.bug_id='$c_bug_id'
+ WHERE p.project_id = '$c_project_id'
+ ORDER BY p.sequence ASC, f.name ASC";
+
+ $result = db_query( $query );
+
+ $t_row_count = db_num_rows( $result );
+
+ $t_custom_fields = array();
+
+ for ( $i=0 ; $i < $t_row_count ; ++$i ) {
+ $row = db_fetch_array( $result );
+
+ if( is_null( $row['value'] ) ) {
+ $t_value = $row['default_value'];
+ } else {
+ $t_value = custom_field_database_to_value( $row['value'], $row['type'] );
+ }
+
+ $t_custom_fields[$row['name']] = array( 'type' => $row['type'],
+ 'value' => $t_value,
+ 'access_level_r' => $row['access_level_r'] );
+ }
+
+ $g_cached_custom_field_lists[$p_bug_id] = $t_custom_fields;
+ }
+
+ return $g_cached_custom_field_lists[$p_bug_id];
+ }
+
+
+ # --------------------
+ # Gets the sequence number for the specified custom field for the specified
+ # project. Returns false in case of error.
+ function custom_field_get_sequence( $p_field_id, $p_project_id ) {
+ $c_field_id = db_prepare_int( $p_field_id );
+ $c_project_id = db_prepare_int( $p_project_id );
+
+ $t_custom_field_project_table = config_get( 'mantis_custom_field_project_table' );
+ $query = "SELECT sequence
+ FROM $t_custom_field_project_table
+ WHERE field_id='$c_field_id' AND
+ project_id='$c_project_id'";
+ $result = db_query( $query, 1 );
+
+ if ( 0 == db_num_rows( $result ) ) {
+ return false;
+ }
+
+ $t_row = db_fetch_array( $result );
+
+ return $t_row['sequence'];
+ }
+
+ # --------------------
+ # Allows the validation of a custom field value without setting it
+ # or needing a bug to exist.
+ function custom_field_validate( $p_field_id, $p_value ) {
+ $c_field_id = db_prepare_int( $p_field_id );
+ $c_value = db_prepare_string( $p_value );
+
+ custom_field_ensure_exists( $p_field_id );
+
+ $t_custom_field_table = config_get( 'mantis_custom_field_table' );
+ $query = "SELECT name, type, possible_values, valid_regexp,
+ access_level_rw, length_min, length_max, default_value
+ FROM $t_custom_field_table
+ WHERE id='$c_field_id'";
+ $result = db_query( $query );
+ $row = db_fetch_array( $result );
+
+ $t_name = $row['name'];
+ $t_type = $row['type'];
+ $t_possible_values = $row['possible_values'];
+ $t_valid_regexp = $row['valid_regexp'];
+ $t_length_min = $row['length_min'];
+ $t_length_max = $row['length_max'];
+ $t_default_value = $row['default_value'];
+
+ # check for valid value
+ if ( !is_blank( $t_valid_regexp ) ) {
+ if ( !ereg( $t_valid_regexp, $p_value ) ) {
+ return false;
+ }
+ }
+
+ if ( strlen( $p_value ) < $t_length_min ) {
+ return false;
+ }
+
+ if ( ( 0 != $t_length_max ) && ( strlen( $p_value ) > $t_length_max ) ) {
+ return false;
+ }
+
+ return true;
+ }
+
+ # --------------------
+ # $p_possible_values: possible values to be pre-processed. If it has enum values,
+ # it will be left as is. If it has a method, it will be replaced
+ # by the list.
+ function custom_field_prepare_possible_values( $p_possible_values ) {
+ $t_possible_values = $p_possible_values;
+
+ if ( !is_blank( $t_possible_values ) && ( $t_possible_values[0] == '=' ) ) {
+ $t_possible_values = helper_call_custom_function( 'enum_' . substr( $t_possible_values, 1 ), array() );
+ }
+
+ return $t_possible_values;
+ }
+
+ # --------------------
+ # Get All Possible Values for a Field.
+ function custom_field_distinct_values( $p_field_id, $p_project_id = ALL_PROJECTS ) {
+ $c_field_id = db_prepare_int( $p_field_id );
+ $c_project_id = db_prepare_int( $p_project_id );
+ $t_custom_field_string_table = config_get( 'mantis_custom_field_string_table' );
+ $t_custom_field_table = config_get( 'mantis_custom_field_table' );
+ $t_mantis_bug_table = config_get( 'mantis_bug_table' );
+ $t_return_arr = array();
+
+ $query = "SELECT type, possible_values
+ FROM $t_custom_field_table
+ WHERE id='$c_field_id'";
+ $result = db_query( $query );
+
+ $t_row_count = db_num_rows( $result );
+ if ( 0 == $t_row_count ) {
+ return false;
+ }
+ $row = db_fetch_array( $result );
+
+ # If an enumeration type, we get all possible values, not just used values
+ if ( CUSTOM_FIELD_TYPE_ENUM == $row['type'] ||
+ CUSTOM_FIELD_TYPE_CHECKBOX == $row['type'] ||
+ CUSTOM_FIELD_TYPE_LIST == $row['type'] ||
+ CUSTOM_FIELD_TYPE_MULTILIST == $row['type']
+ ) {
+ $t_possible_values = custom_field_prepare_possible_values( $row['possible_values'] );
+
+ $t_values_arr = explode( '|', $t_possible_values );
+
+ foreach( $t_values_arr as $t_option ) {
+ array_push( $t_return_arr, $t_option );
+ }
+ } else {
+ $t_where = '';
+ $t_from = $t_custom_field_string_table;
+ if ( ALL_PROJECTS != $p_project_id ) {
+ $t_where = " AND $t_mantis_bug_table.id = $t_custom_field_string_table.bug_id AND
+ $t_mantis_bug_table.project_id = '$p_project_id'";
+ $t_from = $t_from . ", $t_mantis_bug_table";
+ }
+ $query2 = "SELECT $t_custom_field_string_table.value FROM $t_from
+ WHERE $t_custom_field_string_table.field_id='$c_field_id' $t_where
+ GROUP BY $t_custom_field_string_table.value";
+ $result2 = db_query( $query2 );
+ $t_row_count = db_num_rows( $result2 );
+ if ( 0 == $t_row_count ) {
+ return false;
+ }
+
+ for ( $i = 0; $i < $t_row_count; $i++ ) {
+ $row = db_fetch_array( $result2 );
+ if( !is_blank( trim( $row['value'] ) ) ) {
+ array_push( $t_return_arr, $row['value'] );
+ }
+ }
+ }
+ return $t_return_arr;
+ }
+
+ #===================================
+ # Data Modification
+ #===================================
+
+ # --------------------
+ # Convert the value to save it into the database, depending of the type
+ # return value for database
+ function custom_field_value_to_database( $p_value, $p_type ) {
+ switch ($p_type) {
+ case CUSTOM_FIELD_TYPE_MULTILIST:
+ case CUSTOM_FIELD_TYPE_CHECKBOX:
+ if ( '' == $p_value ) {
+ $result = '';
+ } else {
+ $result = '|' . $p_value . '|';
+ }
+ break;
+ default:
+ $result = $p_value;
+ }
+ return $result;
+ }
+
+ # --------------------
+ # Convert the database-value to value, depending of the type
+ # return value for further operation
+ function custom_field_database_to_value( $p_value, $p_type ) {
+ switch ($p_type) {
+ case CUSTOM_FIELD_TYPE_MULTILIST:
+ case CUSTOM_FIELD_TYPE_CHECKBOX:
+ $result = str_replace( '||', '', '|' . $p_value . '|' );
+ break;
+ default:
+ $result = $p_value;
+ }
+ return $result;
+ }
+
+ # --------------------
+ # Set the value of a custom field for a given bug
+ # return true on success, false on failure
+ function custom_field_set_value( $p_field_id, $p_bug_id, $p_value ) {
+ $c_field_id = db_prepare_int( $p_field_id );
+ $c_bug_id = db_prepare_int( $p_bug_id );
+
+ custom_field_ensure_exists( $p_field_id );
+
+ $t_custom_field_table = config_get( 'mantis_custom_field_table' );
+ $query = "SELECT name, type, possible_values, valid_regexp,
+ access_level_rw, length_min, length_max, default_value
+ FROM $t_custom_field_table
+ WHERE id='$c_field_id'";
+ $result = db_query( $query );
+ $row = db_fetch_array( $result );
+
+ $t_name = $row['name'];
+ $t_type = $row['type'];
+ $t_possible_values = $row['possible_values'];
+ $t_valid_regexp = $row['valid_regexp'];
+ $t_access_level_rw = $row['access_level_rw'];
+ $t_length_min = $row['length_min'];
+ $t_length_max = $row['length_max'];
+ $t_default_value = $row['default_value'];
+
+ $c_value = db_prepare_string( custom_field_value_to_database( $p_value, $t_type ) );
+
+ # check for valid value
+ if ( !is_blank( $t_valid_regexp ) ) {
+ if ( !ereg( $t_valid_regexp, $p_value ) ) {
+ return false;
+ }
+ }
+
+ if ( strlen( $p_value ) < $t_length_min ) {
+ return false;
+ }
+
+ if ( ( 0 != $t_length_max ) && ( strlen( $p_value ) > $t_length_max ) ) {
+ return false;
+ }
+
+ if( !custom_field_has_write_access( $p_field_id, $p_bug_id, auth_get_current_user_id() ) ) {
+ return false;
+ }
+
+ $t_custom_field_string_table = config_get( 'mantis_custom_field_string_table' );
+
+ # do I need to update or insert this value?
+ $query = "SELECT value
+ FROM $t_custom_field_string_table
+ WHERE field_id='$c_field_id' AND
+ bug_id='$c_bug_id'";
+ $result = db_query( $query );
+
+ if ( db_num_rows( $result ) > 0 ) {
+ $query = "UPDATE $t_custom_field_string_table
+ SET value='$c_value'
+ WHERE field_id='$c_field_id' AND
+ bug_id='$c_bug_id'";
+ db_query( $query );
+
+ $row = db_fetch_array( $result );
+ history_log_event_direct( $c_bug_id, $t_name, custom_field_database_to_value( $row['value'], $t_type ), $p_value );
+ } else {
+ # Always store the value, even if it's the dafault value
+ # This is important, as the definitions might change but the
+ # values stored with a bug must not change
+ $query = "INSERT INTO $t_custom_field_string_table
+ ( field_id, bug_id, value )
+ VALUES
+ ( '$c_field_id', '$c_bug_id', '$c_value' )";
+ db_query( $query );
+ history_log_event_direct( $c_bug_id, $t_name, '', $p_value );
+ }
+
+ custom_field_clear_cache( $p_field_id );
+
+ #db_query() errors on failure so:
+ return true;
+ }
+
+ # --------------------
+ # Sets the sequence number for the specified custom field for the specified
+ # project.
+ function custom_field_set_sequence( $p_field_id, $p_project_id, $p_sequence ) {
+ $c_field_id = db_prepare_int( $p_field_id );
+ $c_project_id = db_prepare_int( $p_project_id );
+ $c_sequence = db_prepare_int( $p_sequence );
+
+ $t_custom_field_project_table = config_get( 'mantis_custom_field_project_table' );
+
+ $query = "UPDATE $t_custom_field_project_table
+ SET sequence='$c_sequence'
+ WHERE field_id='$c_field_id' AND
+ project_id='$c_project_id'";
+ $result = db_query( $query );
+
+ custom_field_clear_cache( $p_field_id );
+
+ return true;
+ }
+
+ #===================================
+ # Output
+ #===================================
+
+ # --------------------
+ # Print an input field
+ # $p_field_def contains the definition of the custom field (including it's
+ # field id
+ # $p_bug_id contains the bug where this field belongs to. If it's left
+ # away, it'll default to 0 and thus belongs to a new (i.e.
+ # non-existant) bug
+ # NOTE: This probably belongs in the print_api.php
+ function print_custom_field_input( $p_field_def, $p_bug_id = null ) {
+ $t_id = $p_field_def['id'];
+
+ if( null === $p_bug_id ) {
+ $t_custom_field_value = $p_field_def['default_value'];
+ } else {
+ $t_custom_field_value = custom_field_get_value( $t_id, $p_bug_id );
+ }
+
+ $t_custom_field_value = string_attribute( $t_custom_field_value );
+
+ switch ($p_field_def['type']) {
+ case CUSTOM_FIELD_TYPE_ENUM:
+ case CUSTOM_FIELD_TYPE_LIST:
+ case CUSTOM_FIELD_TYPE_MULTILIST:
+ $t_values = explode( '|', custom_field_prepare_possible_values( $p_field_def['possible_values'] ) );
+ $t_list_size = $t_possible_values_count = count( $t_values );
+
+ if ( $t_possible_values_count > 5 ) {
+ $t_list_size = 5;
+ }
+
+ if ( $p_field_def['type'] == CUSTOM_FIELD_TYPE_ENUM ) {
+ $t_list_size = 0; # for enums the size is 0
+ }
+
+ if ( $p_field_def['type'] == CUSTOM_FIELD_TYPE_MULTILIST ) {
+ echo '<select ', helper_get_tab_index(), ' name="custom_field_' . $t_id . '[]" size="' . $t_list_size . '" multiple="multiple">';
+ } else {
+ echo '<select ', helper_get_tab_index(), ' name="custom_field_' . $t_id . '" size="' . $t_list_size . '">';
+ }
+
+ $t_selected_values = explode( '|', $t_custom_field_value );
+ foreach( $t_values as $t_option ) {
+ if( in_array( $t_option, $t_selected_values, true ) ) {
+ echo '<option value="' . $t_option . '" selected="selected"> ' . $t_option . '</option>';
+ } else {
+ echo '<option value="' . $t_option . '">' . $t_option . '</option>';
+ }
+ }
+ echo '</select>';
+ break;
+ case CUSTOM_FIELD_TYPE_CHECKBOX:
+ $t_values = explode( '|', custom_field_prepare_possible_values( $p_field_def['possible_values'] ) );
+ $t_checked_values = explode( '|', $t_custom_field_value );
+ foreach( $t_values as $t_option ) {
+ echo '<input ', helper_get_tab_index(), ' type="checkbox" name="custom_field_' . $t_id . '[]"';
+ if( in_array( $t_option, $t_checked_values, true ) ) {
+ echo ' value="' . $t_option . '" checked="checked"> ' . $t_option . ' ';
+ } else {
+ echo ' value="' . $t_option . '"> ' . $t_option . ' ';
+ }
+ }
+ break;
+ case CUSTOM_FIELD_TYPE_NUMERIC:
+ case CUSTOM_FIELD_TYPE_FLOAT:
+ case CUSTOM_FIELD_TYPE_EMAIL:
+ case CUSTOM_FIELD_TYPE_STRING:
+ echo '<input ', helper_get_tab_index(), ' type="text" name="custom_field_' . $t_id . '" size="80"';
+ if( 0 < $p_field_def['length_max'] ) {
+ echo ' maxlength="' . $p_field_def['length_max'] . '"';
+ } else {
+ echo ' maxlength="255"';
+ }
+ echo ' value="' . $t_custom_field_value .'"></input>';
+ break ;
+
+ case CUSTOM_FIELD_TYPE_DATE:
+ print_date_selection_set("custom_field_" . $t_id, config_get('short_date_format'), $t_custom_field_value, false, true) ;
+ break ;
+ }
+ }
+
+ # --------------------
+ # Prepare a string containing a custom field value for display
+ # $p_def contains the definition of the custom field
+ # $p_field_id contains the id of the field
+ # $p_bug_id contains the bug id to display the custom field value for
+ # NOTE: This probably belongs in the string_api.php
+ function string_custom_field_value( $p_def, $p_field_id, $p_bug_id ) {
+ $t_custom_field_value = custom_field_get_value( $p_field_id, $p_bug_id );
+ switch( $p_def['type'] ) {
+ case CUSTOM_FIELD_TYPE_EMAIL:
+ return "<a href=\"mailto:$t_custom_field_value\">$t_custom_field_value</a>";
+ break;
+ case CUSTOM_FIELD_TYPE_ENUM:
+ case CUSTOM_FIELD_TYPE_LIST:
+ case CUSTOM_FIELD_TYPE_MULTILIST:
+ case CUSTOM_FIELD_TYPE_CHECKBOX:
+ return str_replace( '|', ', ', $t_custom_field_value );
+ break;
+ case CUSTOM_FIELD_TYPE_DATE:
+ if ($t_custom_field_value != null) {
+ return date( config_get( 'short_date_format'), $t_custom_field_value) ;
+ }
+ break ;
+ default:
+ return string_display_links( $t_custom_field_value );
+ }
+ }
+
+ # --------------------
+ # Print a custom field value for display
+ # $p_def contains the definition of the custom field
+ # $p_field_id contains the id of the field
+ # $p_bug_id contains the bug id to display the custom field value for
+ # NOTE: This probably belongs in the print_api.php
+ function print_custom_field_value( $p_def, $p_field_id, $p_bug_id ) {
+ echo string_custom_field_value( $p_def, $p_field_id, $p_bug_id );
+ }
+
+ # --------------------
+ # Prepare a string containing a custom field value for email
+ # $p_value value of custom field
+ # $p_type type of custom field
+ # NOTE: This probably belongs in the string_api.php
+ function string_custom_field_value_for_email( $p_value, $p_type ) {
+ switch( $p_type ) {
+ case CUSTOM_FIELD_TYPE_EMAIL:
+ return 'mailto:'.$p_value;
+ break;
+ case CUSTOM_FIELD_TYPE_ENUM:
+ case CUSTOM_FIELD_TYPE_LIST:
+ case CUSTOM_FIELD_TYPE_MULTILIST:
+ case CUSTOM_FIELD_TYPE_CHECKBOX:
+ return str_replace( '|', ', ', $p_value );
+ break;
+ case CUSTOM_FIELD_TYPE_DATE:
+ if ($p_value != null) {
+ return date( config_get( 'short_date_format' ), $p_value) ;
+ }
+ break ;
+ default:
+ return $p_value;
+ }
+ return $p_value;
+ }
+
+?>
| ||||
|
@liebscher, thanks for your contribution. Why does it look like each line in the file has changed? Will you be able to provide a new patch that doesn't have this issue? |
|
|
Resolved as duplicate of 0006626. Please add the new patch there. |
|