[Rt-commit] [svn] r1201 - in rt/branches/rt-3.1: . bin etc
etc/upgrade/3.1.0 etc/upgrade/3.3.0 html html/Admin
html/Admin/CustomFields html/Admin/Elements html/Admin/Global
html/Admin/Groups html/Admin/Queues html/Admin/Users
html/Download html/Download/CustomFieldValue
html/Download/Tabular html/Elements html/NoAuth html/Search
html/Search/Elements html/SelfService html/Ticket
html/Ticket/Elements html/User lib lib/RT lib/RT/Action
lib/RT/I18N lib/RT/Interface sbin spec
jesse at pallas.eruditorum.org
jesse at pallas.eruditorum.org
Sat Jul 10 02:05:29 EDT 2004
Author: jesse
Date: Sat Jul 10 02:05:15 2004
New Revision: 1201
Added:
rt/branches/rt-3.1/etc/upgrade/3.3.0/
rt/branches/rt-3.1/etc/upgrade/3.3.0/acl.Informix
rt/branches/rt-3.1/etc/upgrade/3.3.0/acl.Oracle
rt/branches/rt-3.1/etc/upgrade/3.3.0/acl.Pg
rt/branches/rt-3.1/etc/upgrade/3.3.0/acl.SQLite
rt/branches/rt-3.1/etc/upgrade/3.3.0/acl.mysql
rt/branches/rt-3.1/etc/upgrade/3.3.0/schema.Pg
rt/branches/rt-3.1/etc/upgrade/3.3.0/schema.mysql
rt/branches/rt-3.1/html/Admin/CustomFields/
rt/branches/rt-3.1/html/Admin/CustomFields/GroupRights.html
rt/branches/rt-3.1/html/Admin/CustomFields/Modify.html
rt/branches/rt-3.1/html/Admin/CustomFields/Objects.html
rt/branches/rt-3.1/html/Admin/CustomFields/UserRights.html
rt/branches/rt-3.1/html/Admin/CustomFields/index.html
rt/branches/rt-3.1/html/Admin/Elements/CustomFieldTabs
rt/branches/rt-3.1/html/Admin/Elements/ObjectCustomFields
rt/branches/rt-3.1/html/Admin/Elements/PickCustomFields
rt/branches/rt-3.1/html/Admin/Elements/PickObjects
rt/branches/rt-3.1/html/Admin/Elements/SelectCustomFieldLookupType
rt/branches/rt-3.1/html/Admin/Groups/CustomFields.html
rt/branches/rt-3.1/html/Admin/Groups/History.html
rt/branches/rt-3.1/html/Admin/Users/CustomFields.html
rt/branches/rt-3.1/html/Admin/Users/History.html
rt/branches/rt-3.1/html/Admin/Users/Memberships.html
rt/branches/rt-3.1/html/Download/
rt/branches/rt-3.1/html/Download/CustomFieldValue/
rt/branches/rt-3.1/html/Download/CustomFieldValue/dhandler
rt/branches/rt-3.1/html/Download/Tabular/
rt/branches/rt-3.1/html/Download/Tabular/dhandler
rt/branches/rt-3.1/html/Elements/EditCustomField
rt/branches/rt-3.1/html/Elements/EditCustomFieldBinary
rt/branches/rt-3.1/html/Elements/EditCustomFieldFreeform
rt/branches/rt-3.1/html/Elements/EditCustomFieldImage
rt/branches/rt-3.1/html/Elements/EditCustomFieldSelect
rt/branches/rt-3.1/html/Elements/EditCustomFieldText
rt/branches/rt-3.1/html/Elements/ShowCustomFieldImage
rt/branches/rt-3.1/html/Elements/ShowCustomFields
rt/branches/rt-3.1/html/Elements/ShowMemberships
rt/branches/rt-3.1/html/Search/Elements/SelectGroup
rt/branches/rt-3.1/lib/RT/ObjectCustomField.pm
rt/branches/rt-3.1/lib/RT/ObjectCustomFieldValue.pm
rt/branches/rt-3.1/lib/RT/ObjectCustomFieldValue_Overlay.pm
rt/branches/rt-3.1/lib/RT/ObjectCustomFieldValues.pm
rt/branches/rt-3.1/lib/RT/ObjectCustomFieldValues_Overlay.pm
rt/branches/rt-3.1/lib/RT/ObjectCustomField_Overlay.pm
rt/branches/rt-3.1/lib/RT/ObjectCustomFields.pm
rt/branches/rt-3.1/lib/RT/ObjectCustomFields_Overlay.pm
rt/branches/rt-3.1/sbin/rt-dump-database.in
rt/branches/rt-3.1/spec/
rt/branches/rt-3.1/spec/schema.txt
Removed:
rt/branches/rt-3.1/html/Admin/Global/CustomField.html
rt/branches/rt-3.1/html/Admin/Global/CustomFields.html
Modified:
rt/branches/rt-3.1/ (props changed)
rt/branches/rt-3.1/README
rt/branches/rt-3.1/bin/standalone_httpd.in
rt/branches/rt-3.1/bin/webmux.pl.in
rt/branches/rt-3.1/configure.ac
rt/branches/rt-3.1/etc/RT_Config.pm.in
rt/branches/rt-3.1/etc/acl.Pg
rt/branches/rt-3.1/etc/acl.mysql
rt/branches/rt-3.1/etc/schema.Informix
rt/branches/rt-3.1/etc/schema.Oracle
rt/branches/rt-3.1/etc/schema.Pg
rt/branches/rt-3.1/etc/schema.SQLite
rt/branches/rt-3.1/etc/schema.Sybase
rt/branches/rt-3.1/etc/schema.mysql
rt/branches/rt-3.1/etc/upgrade/3.1.0/acl.Oracle (props changed)
rt/branches/rt-3.1/etc/upgrade/3.1.0/acl.Pg (props changed)
rt/branches/rt-3.1/etc/upgrade/3.1.0/acl.SQLite (props changed)
rt/branches/rt-3.1/etc/upgrade/3.1.0/acl.mysql (props changed)
rt/branches/rt-3.1/etc/upgrade/3.1.0/schema.Pg (props changed)
rt/branches/rt-3.1/etc/upgrade/3.1.0/schema.mysql (props changed)
rt/branches/rt-3.1/html/Admin/Elements/AddCustomFieldValue
rt/branches/rt-3.1/html/Admin/Elements/EditCustomFieldValues
rt/branches/rt-3.1/html/Admin/Elements/EditCustomFields
rt/branches/rt-3.1/html/Admin/Elements/EditScrip
rt/branches/rt-3.1/html/Admin/Elements/GroupTabs
rt/branches/rt-3.1/html/Admin/Elements/Header
rt/branches/rt-3.1/html/Admin/Elements/QueueTabs
rt/branches/rt-3.1/html/Admin/Elements/SelectCustomFieldType
rt/branches/rt-3.1/html/Admin/Elements/SelectRights
rt/branches/rt-3.1/html/Admin/Elements/SystemTabs
rt/branches/rt-3.1/html/Admin/Elements/Tabs
rt/branches/rt-3.1/html/Admin/Elements/UserTabs
rt/branches/rt-3.1/html/Admin/Global/Templates.html
rt/branches/rt-3.1/html/Admin/Global/index.html
rt/branches/rt-3.1/html/Admin/Groups/Modify.html
rt/branches/rt-3.1/html/Admin/Groups/index.html
rt/branches/rt-3.1/html/Admin/Queues/CustomField.html
rt/branches/rt-3.1/html/Admin/Queues/CustomFields.html
rt/branches/rt-3.1/html/Admin/Queues/Modify.html
rt/branches/rt-3.1/html/Admin/Queues/People.html
rt/branches/rt-3.1/html/Admin/Users/Modify.html
rt/branches/rt-3.1/html/Admin/Users/index.html
rt/branches/rt-3.1/html/Admin/index.html
rt/branches/rt-3.1/html/Elements/Header
rt/branches/rt-3.1/html/Elements/SelectGroups
rt/branches/rt-3.1/html/Elements/SelectUsers
rt/branches/rt-3.1/html/Elements/SetupSessionCookie
rt/branches/rt-3.1/html/Elements/Submit
rt/branches/rt-3.1/html/NoAuth/webrt.css
rt/branches/rt-3.1/html/Search/Bulk.html
rt/branches/rt-3.1/html/Search/Elements/PickBasics
rt/branches/rt-3.1/html/Search/Elements/PickCFs
rt/branches/rt-3.1/html/Search/Elements/SelectPersonType
rt/branches/rt-3.1/html/SelfService/Closed.html
rt/branches/rt-3.1/html/SelfService/Display.html
rt/branches/rt-3.1/html/Ticket/Create.html
rt/branches/rt-3.1/html/Ticket/Elements/EditCustomFields
rt/branches/rt-3.1/html/Ticket/Elements/EditPeople
rt/branches/rt-3.1/html/Ticket/Elements/FindAttachments (contents, props changed)
rt/branches/rt-3.1/html/Ticket/Elements/LoadTextAttachments
rt/branches/rt-3.1/html/Ticket/Elements/ShowCustomFields
rt/branches/rt-3.1/html/Ticket/Elements/ShowRequestor
rt/branches/rt-3.1/html/Ticket/Elements/ShowTransaction
rt/branches/rt-3.1/html/Ticket/Modify.html
rt/branches/rt-3.1/html/Ticket/ModifyAll.html
rt/branches/rt-3.1/html/Ticket/Update.html
rt/branches/rt-3.1/html/User/Prefs.html
rt/branches/rt-3.1/html/autohandler
rt/branches/rt-3.1/lib/RT.pm.in
rt/branches/rt-3.1/lib/RT/Action/CreateTickets.pm
rt/branches/rt-3.1/lib/RT/Attachment_Overlay.pm
rt/branches/rt-3.1/lib/RT/Base.pm
rt/branches/rt-3.1/lib/RT/CurrentUser.pm
rt/branches/rt-3.1/lib/RT/CustomField.pm
rt/branches/rt-3.1/lib/RT/CustomField_Overlay.pm
rt/branches/rt-3.1/lib/RT/CustomFields_Overlay.pm
rt/branches/rt-3.1/lib/RT/Group_Overlay.pm
rt/branches/rt-3.1/lib/RT/Groups_Overlay.pm
rt/branches/rt-3.1/lib/RT/I18N.pm
rt/branches/rt-3.1/lib/RT/I18N/cs.po
rt/branches/rt-3.1/lib/RT/I18N/de.po
rt/branches/rt-3.1/lib/RT/I18N/en.po
rt/branches/rt-3.1/lib/RT/I18N/es.po
rt/branches/rt-3.1/lib/RT/I18N/fr.po
rt/branches/rt-3.1/lib/RT/I18N/he.po
rt/branches/rt-3.1/lib/RT/I18N/it.po
rt/branches/rt-3.1/lib/RT/I18N/ja.po
rt/branches/rt-3.1/lib/RT/I18N/nl.po
rt/branches/rt-3.1/lib/RT/I18N/pt_br.po
rt/branches/rt-3.1/lib/RT/I18N/ru.po
rt/branches/rt-3.1/lib/RT/Interface/Web.pm
rt/branches/rt-3.1/lib/RT/Link_Overlay.pm
rt/branches/rt-3.1/lib/RT/Queue_Overlay.pm
rt/branches/rt-3.1/lib/RT/Record.pm
rt/branches/rt-3.1/lib/RT/SearchBuilder.pm
rt/branches/rt-3.1/lib/RT/StyleGuide.pod
rt/branches/rt-3.1/lib/RT/System.pm
rt/branches/rt-3.1/lib/RT/Template_Overlay.pm
rt/branches/rt-3.1/lib/RT/Ticket_Overlay.pm
rt/branches/rt-3.1/lib/RT/Tickets_Overlay.pm
rt/branches/rt-3.1/lib/RT/Tickets_Overlay_SQL.pm
rt/branches/rt-3.1/lib/RT/Transaction.pm
rt/branches/rt-3.1/lib/RT/Transaction_Overlay.pm
rt/branches/rt-3.1/lib/RT/Transactions_Overlay.pm
rt/branches/rt-3.1/lib/RT/User_Overlay.pm
rt/branches/rt-3.1/releng.cnf
rt/branches/rt-3.1/sbin/extract-message-catalog
Log:
----------------------------------------------------------------------
r2112 at tinbook: jesse | 2004-07-10T04:32:28.577645Z
----------------------------------------------------------------------
r1996 at tinbook: jesse | 2004-06-28T03:08:01.495343Z
----------------------------------------------------------------------
r1769 at tinbook: jesse | 2004-06-01T20:22:38.640731Z
----------------------------------------------------------------------
r1902 at tinbook: jesse | 2004-06-17T01:08:53.996154Z
----------------------------------------------------------------------
r1991 at tinbook: jesse | 2004-06-28T02:03:57.669851Z
----------------------------------------------------------------------
r1992 at tinbook: jesse | 2004-06-28T02:19:36.386707Z
Pulling forward from RT 3.1
----------------------------------------------------------------------
r1993 at tinbook: jesse | 2004-06-28T03:06:56.930396Z
Merging forward from 3.1
----------------------------------------------------------------------
----------------------------------------------------------------------
r1998 at tinbook: jesse | 2004-06-28T03:10:54.232175Z
----------------------------------------------------------------------
r1997 at tinbook: jesse | 2004-06-28T03:10:36.434329Z
Bumping to 3.3.4
----------------------------------------------------------------------
----------------------------------------------------------------------
r2058 at tinbook: autrijus | 2004-07-05T16:56:22.344051Z
----------------------------------------------------------------------
r5899 at not: autrijus | 2004-07-05T15:13:55.850880Z
* correct the documentation for CreateTickets; it was still referring
to the archaic "Approvals" queue and "Approval" type, whereas now we're
using "___Approvals" and "approval" now.
----------------------------------------------------------------------
----------------------------------------------------------------------
r2059 at tinbook: autrijus | 2004-07-05T19:43:17.347835Z
----------------------------------------------------------------------
r5913 at not: autrijus | 2004-07-05T19:41:37.720057Z
* add rt-dump-database, a tool to dump config data to initialdata format.
----------------------------------------------------------------------
----------------------------------------------------------------------
----------------------------------------------------------------------
r2113 at tinbook: jesse | 2004-07-10T04:40:37.142269Z
----------------------------------------------------------------------
r2012 at tinbook: jesse | 2004-06-28T21:51:20.545520Z
Fixed bugs in CreateTickets (Approvals) system, both preexisting and introduced in 3.2.0rc3
----------------------------------------------------------------------
r2014 at tinbook: jesse | 2004-06-29T02:46:58.362406Z
----------------------------------------------------------------------
r2015 at tinbook: jesse | 2004-06-29T02:47:32.464100Z
3.2.0rc4
----------------------------------------------------------------------
r2022 at tinbook: jesse | 2004-06-29T17:50:48.925379Z
----------------------------------------------------------------------
r2023 at tinbook: jesse | 2004-06-29T17:55:34.408001Z
RT-Ticket: 5787
RT-Status: resolved
RT-UpdateType: correspond
Added ticket absolute urls for the various actions one can take on searches.
----------------------------------------------------------------------
r2030 at tinbook: jesse | 2004-06-30T04:36:01.943950Z
Bumping to 3.2.0
----------------------------------------------------------------------
r2067 at tinbook: jesse | 2004-07-06T20:25:17.528316Z
----------------------------------------------------------------------
r2068 at tinbook: jesse | 2004-07-06T20:59:43.336929Z
Explicit 'Bookmark this search' functionality has been added back to RT 3.2
----------------------------------------------------------------------
r2070 at tinbook: jesse | 2004-07-06T21:13:17.298878Z
RT-Ticket: 5815
RT-Status: resolved
RT-Update-Type: correspond
RT now advises users about how to set the DBA and DBA Password when upgrading
----------------------------------------------------------------------
r2072 at tinbook: jesse | 2004-07-06T22:04:15.878370Z
* "Negative" Ticket searches (for all tickets which don't have a
certain custom field value) now find tickets which have _no_ custom
field value for that ticket.
* Custom Field searches should now work better with non-ascii
custom field names. (Needs user verification)
----------------------------------------------------------------------
r2095 at tinbook: jesse | 2004-07-09T17:06:56.744260Z
----------------------------------------------------------------------
r2096 at tinbook: jesse | 2004-07-09T17:55:13.811842Z
RT-Ticket: 5800
RT-Status: resolved
RT now stores sent messages in the database as utf-8.
----------------------------------------------------------------------
r2098 at tinbook: jesse | 2004-07-09T19:19:39.944163Z
Fixups to Attributes to work with lack of access, rather than just falling over.
----------------------------------------------------------------------
r2099 at tinbook: jesse | 2004-07-09T19:21:06.127719Z
By default, use verbose mode for reporting missing modules.
----------------------------------------------------------------------
r2100 at tinbook: jesse | 2004-07-09T19:25:51.061318Z
Added a note about the fact that you'll be happier if you blow away your old RT
instance.
----------------------------------------------------------------------
r2101 at tinbook: jesse | 2004-07-09T19:27:27.455452Z
Fixing tests to conform to linda"s fixed code
----------------------------------------------------------------------
r2102 at tinbook: jesse | 2004-07-09T19:29:51.316623Z
(Merging 3.0 to 3.2)
----------------------------------------------------------------------
r2081 at tinbook: huberth | 2004-07-08T16:28:17.266000Z
RT-Ticket: 5773
RT-Status: resolved
* DBIx::SearchBuilder dependency bumped from 0.97 to 1.01.
----------------------------------------------------------------------
r2089 at tinbook: alexmv | 2004-07-08T19:40:10.002177Z
* @ARGV _is_ allowed to be empty; it is $search which must not be.
Thanks to jdwitt at the domain of software.umn.edu for the catch.
----------------------------------------------------------------------
----------------------------------------------------------------------
r2103 at tinbook: jesse | 2004-07-09T19:39:27.276636Z
Updated French translation from sebastien.person at easter-eggs.com
----------------------------------------------------------------------
r2105 at tinbook: jesse | 2004-07-09T20:58:36.771281Z
Made recording outgoing email optional.
Stopped recording attachments multiple times.
----------------------------------------------------------------------
r2106 at tinbook: jesse | 2004-07-09T21:00:30.401132Z
----------------------------------------------------------------------
r2107 at tinbook: jesse | 2004-07-09T21:00:41.498447Z
Removing debugging output
----------------------------------------------------------------------
r2110 at tinbook: jesse | 2004-07-10T04:20:46.424456Z
Message catalogs updated
----------------------------------------------------------------------
----------------------------------------------------------------------
r2114 at tinbook: jesse | 2004-07-10T06:03:00.790969Z
Custom field searching now works again on 3.3
----------------------------------------------------------------------
Modified: rt/branches/rt-3.1/README
==============================================================================
--- rt/branches/rt-3.1/README (original)
+++ rt/branches/rt-3.1/README Sat Jul 10 02:05:15 2004
@@ -197,12 +197,8 @@
DocumentRoot /opt/rt3/share/html
AddDefaultCharset UTF-8
- # these four lines apply to Apache2+mod_perl2 only: {{{
- PerlSetVar MasonArgsMethod CGI
- PerlModule Apache2 Apache::compat
- RewriteEngine On
- RewriteRule ^(.*)/$ $1/index.html
- # }}}
+ # This line applies to Apache2+mod_perl2 only:
+ RedirectMatch permanent (.*)/$ $1/index.html
PerlModule Apache::DBI
PerlRequire /opt/rt3/bin/webmux.pl
Modified: rt/branches/rt-3.1/bin/standalone_httpd.in
==============================================================================
--- rt/branches/rt-3.1/bin/standalone_httpd.in (original)
+++ rt/branches/rt-3.1/bin/standalone_httpd.in Sat Jul 10 02:05:15 2004
@@ -8,6 +8,9 @@
use Socket;
+$SIG{CHLD} = "IGNORE"; # reap child processes
+
+
RT::Init();
my $port = shift || '8080';
@@ -32,6 +35,8 @@
for ( ; accept( Remote, HTTPDaemon ); close Remote ) {
+ fork and next;
+
*STDIN = *Remote;
*STDOUT = *Remote;
@@ -85,7 +90,7 @@
$RT::Handle->ForceRollback;
$RT::Logger->crit( "Transaction not committed. Usually indicates a software fault. Data loss may have occurred");
}
-
+ exit(); # our forked process
}
}
Modified: rt/branches/rt-3.1/bin/webmux.pl.in
==============================================================================
--- rt/branches/rt-3.1/bin/webmux.pl.in (original)
+++ rt/branches/rt-3.1/bin/webmux.pl.in Sat Jul 10 02:05:15 2004
@@ -1,26 +1,26 @@
#!@PERL@
# BEGIN LICENSE BLOCK
-#
+#
# Copyright (c) 1996-2003 Jesse Vincent <jesse at bestpractical.com>
-#
+#
# (Except where explictly superceded by other copyright notices)
-#
+#
# This work is made available to you under the terms of Version 2 of
# the GNU General Public License. A copy of that license should have
# been provided with this software, but in any event can be snarfed
# from www.gnu.org.
-#
+#
# This work 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.
-#
+#
# Unless otherwise specified, all modifications, corrections or
# extensions to this work which alter its source code become the
# property of Best Practical Solutions, LLC when submitted for
# inclusion in the work.
-#
-#
+#
+#
# END LICENSE BLOCK
use strict;
@@ -32,10 +32,9 @@
$ENV{'ENV'} = '' if defined $ENV{'ENV'};
$ENV{'IFS'} = '' if defined $ENV{'IFS'};
- eval { require Apache2; require Apache::compat }
- if $ENV{'MOD_PERL'}
- and $ENV{'MOD_PERL'} =~ m{mod_perl/(?:2|1\.9)};
-
+ eval { require Apache2; require APR::Table; require MasonX::Apache2Handler; 1 } or
+ eval { require Apache2; require Apache::compat; 1 } or die $@
+ if $ENV{'MOD_PERL'} and $ENV{'MOD_PERL'} =~ m{mod_perl/(?:2|1\.9)};
}
use lib ( "@LOCAL_LIB_PATH@", "@RT_LIB_PATH@" );
@@ -47,23 +46,29 @@
#set private_tempfiles
BEGIN {
- if ( $mod_perl::VERSION && ( $mod_perl::VERSION >= 1.9908 ) ) {
- require Apache::RequestUtil;
- no warnings 'redefine';
- my $sub = *Apache::request{CODE};
- *Apache::request = sub {
- my $r;
- eval { $r = $sub->('Apache'); };
-
- # warn $@ if $@;
- return $r;
- };
+ if ($MasonX::Apache2Handler::VERSION) {
+ $RT::MasonHandlerClass = 'MasonX::Apache2Handler';
}
- if ($CGI::MOD_PERL) {
- require HTML::Mason::ApacheHandler;
+ elsif ($mod_perl::VERSION && ($mod_perl::VERSION >= 1.9908)) {
+ require Apache::RequestUtil;
+ no warnings 'redefine';
+ my $sub = *Apache::request{CODE};
+ *Apache::request = sub {
+ my $r;
+ eval { $r = $sub->('Apache'); };
+ # warn $@ if $@;
+ return $r;
+ };
+ require HTML::Mason::ApacheHandler;
+ $RT::MasonHandlerClass = 'HTML::Mason::ApacheHandler';
+ }
+ elsif ($CGI::MOD_PERL) {
+ require HTML::Mason::ApacheHandler;
+ $RT::MasonHandlerClass = 'HTML::Mason::ApacheHandler';
}
else {
- require HTML::Mason::CGIHandler;
+ require HTML::Mason::CGIHandler;
+ $RT::MasonHandlerClass = 'HTML::Mason::CGIHandler';
}
}
@@ -81,21 +86,6 @@
package HTML::Mason::Commands;
use vars qw(%session);
- use RT::Tickets;
- use RT::Transactions;
- use RT::Users;
- use RT::CurrentUser;
- use RT::Templates;
- use RT::Queues;
- use RT::ScripActions;
- use RT::ScripConditions;
- use RT::Scrips;
- use RT::Groups;
- use RT::GroupMembers;
- use RT::CustomFields;
- use RT::CustomFieldValues;
- use RT::TicketCustomFieldValues;
-
use RT::Interface::Web;
use MIME::Entity;
use Text::Wrapper;
Modified: rt/branches/rt-3.1/configure.ac
==============================================================================
--- rt/branches/rt-3.1/configure.ac (original)
+++ rt/branches/rt-3.1/configure.ac Sat Jul 10 02:05:15 2004
@@ -7,7 +7,7 @@
dnl Setup autoconf
AC_PREREQ(2.53)
-AC_INIT(RT, [3.2.HEAD], [rt-bugs at fsck.com])
+AC_INIT(RT, [3.3.HEAD], [rt-3.1-bugs at fsck.com])
AC_CONFIG_SRCDIR([lib/RT.pm.in])
dnl Extract RT version number components
Modified: rt/branches/rt-3.1/etc/RT_Config.pm.in
==============================================================================
--- rt/branches/rt-3.1/etc/RT_Config.pm.in (original)
+++ rt/branches/rt-3.1/etc/RT_Config.pm.in Sat Jul 10 02:05:15 2004
@@ -362,8 +362,9 @@
# @MasonParameters is the list of parameters for the constructor of
# HTML::Mason's Apache or CGI Handler. This is normally only useful
-# for debugging, eg. profiling individual components with
-# (preamble => 'my $p = MasonX::Profiler->new($m, $r);');
+# for debugging, eg. profiling individual components with:
+# use MasonX::Profiler; # available on CPAN
+# @MasonParameters = (preamble => 'my $p = MasonX::Profiler->new($m, $r);');
@MasonParameters = () unless (@MasonParameters);
Modified: rt/branches/rt-3.1/etc/acl.Pg
==============================================================================
--- rt/branches/rt-3.1/etc/acl.Pg (original)
+++ rt/branches/rt-3.1/etc/acl.Pg Sat Jul 10 02:05:15 2004
@@ -10,37 +10,39 @@
Attributes
attributes_id_seq
queues_id_seq
- Queues
+ Queues
links_id_seq
- Links
+ Links
principals_id_seq
- Principals
+ Principals
groups_id_seq
- Groups
+ Groups
scripconditions_id_seq
- ScripConditions
+ ScripConditions
transactions_id_seq
- Transactions
+ Transactions
scrips_id_seq
- Scrips
+ Scrips
acl_id_seq
- ACL
+ ACL
groupmembers_id_seq
- GroupMembers
+ GroupMembers
cachedgroupmembers_id_seq
- CachedGroupMembers
+ CachedGroupMembers
users_id_seq
- Users
+ Users
tickets_id_seq
- Tickets
+ Tickets
scripactions_id_seq
- ScripActions
+ ScripActions
templates_id_seq
- Templates
- ticketcustomfieldvalues_id_s
- TicketCustomFieldValues
+ Templates
+ objectcustomfieldvalues_id_s
+ ObjectCustomFieldValues
customfields_id_seq
- CustomFields
+ CustomFields
+ objectcustomfields_id_s
+ ObjectCustomFields
customfieldvalues_id_seq
CustomFieldValues
sessions
Modified: rt/branches/rt-3.1/etc/acl.mysql
==============================================================================
--- rt/branches/rt-3.1/etc/acl.mysql (original)
+++ rt/branches/rt-3.1/etc/acl.mysql Sat Jul 10 02:05:15 2004
@@ -1,4 +1,5 @@
sub acl {
+return () if !$RT::DatabaseUser or $RT::DatabaseUser eq 'root';
return (
"USE mysql;",
"DELETE FROM user WHERE user = '${RT::DatabaseUser}';",
Modified: rt/branches/rt-3.1/etc/schema.Informix
==============================================================================
--- rt/branches/rt-3.1/etc/schema.Informix (original)
+++ rt/branches/rt-3.1/etc/schema.Informix Sat Jul 10 02:05:15 2004
@@ -103,20 +103,22 @@
CREATE TABLE Transactions (
id SERIAL,
- EffectiveTicket INTEGER DEFAULT 0 NOT NULL,
- Ticket INTEGER DEFAULT 0 NOT NULL,
+ ObjectType VARCHAR(255),
+ ObjectId INTEGER DEFAULT 0 NOT NULL,
TimeTaken INTEGER DEFAULT 0 NOT NULL,
Type VARCHAR(20),
Field VARCHAR(40),
OldValue VARCHAR(255),
NewValue VARCHAR(255),
+ ReferenceType VARCHAR(255),
+ OldReference INTEGER DEFAULT 0,
+ NewReference INTEGER DEFAULT 0,
Data VARCHAR(255),
Creator INTEGER DEFAULT 0 NOT NULL,
Created DATETIME YEAR TO SECOND,
PRIMARY KEY (id)
);
-CREATE INDEX Transactions1 ON Transactions (Ticket);
-CREATE INDEX Transactions2 ON Transactions (EffectiveTicket);
+CREATE INDEX Transactions1 ON Transactions (ObjectType, ObjectId);
CREATE TABLE Scrips (
@@ -305,7 +307,9 @@
id SERIAL,
Name VARCHAR(200),
Type VARCHAR(200),
- Queue INTEGER DEFAULT 0 NOT NULL,
+ MaxValues INTEGER DEFAULT 0 NOT NULL,
+ Pattern VARCHAR(255),
+ LookupType VARCHAR(255),
Description VARCHAR(255),
SortOrder INTEGER DEFAULT 0 NOT NULL,
Creator INTEGER DEFAULT 0 NOT NULL,
@@ -315,7 +319,6 @@
Disabled SMALLINT DEFAULT 0 NOT NULL,
PRIMARY KEY (id)
);
-CREATE INDEX CustomFields1 ON CustomFields (Disabled, Queue);
CREATE TABLE CustomFieldValues (
Modified: rt/branches/rt-3.1/etc/schema.Oracle
==============================================================================
--- rt/branches/rt-3.1/etc/schema.Oracle (original)
+++ rt/branches/rt-3.1/etc/schema.Oracle Sat Jul 10 02:05:15 2004
@@ -105,19 +105,21 @@
CREATE TABLE Transactions (
id NUMBER(11,0)
CONSTRAINT Transactions_Key PRIMARY KEY,
- EffectiveTicket NUMBER(11,0) DEFAULT 0 NOT NULL,
- Ticket NUMBER(11,0) DEFAULT 0 NOT NULL,
+ ObjectType VARCHAR2(255),
+ ObjectId NUMBER(11,0) DEFAULT 0 NOT NULL,
TimeTaken NUMBER(11,0) DEFAULT 0 NOT NULL,
Type VARCHAR2(20),
Field VARCHAR2(40),
OldValue VARCHAR2(255),
NewValue VARCHAR2(255),
+ ReferenceType VARCHAR2(255),
+ OldReference NUMBER(11,0),
+ NewReference NUMBER(11,0),
Data VARCHAR2(255),
Creator NUMBER(11,0) DEFAULT 0 NOT NULL,
Created DATE
);
-CREATE INDEX Transactions1 ON Transactions (Ticket);
-CREATE INDEX Transactions2 ON Transactions (EffectiveTicket);
+CREATE INDEX Transactions1 ON Transactions (ObjectType, ObjectId);
CREATE SEQUENCE SCRIPS_seq;
@@ -317,7 +319,9 @@
CONSTRAINT CustomFields_Key PRIMARY KEY,
Name VARCHAR2(200),
Type VARCHAR2(200),
- Queue NUMBER(11,0) DEFAULT 0 NOT NULL,
+ MaxValues NUMBER(11,0) DEFAULT 0 NOT NULL,
+ Pattern VARCHAR2(255),
+ LookupType VARCHAR2(255),
Description VARCHAR2(255),
SortOrder NUMBER(11,0) DEFAULT 0 NOT NULL,
Creator NUMBER(11,0) DEFAULT 0 NOT NULL,
@@ -326,7 +330,6 @@
LastUpdated DATE,
Disabled NUMBER(11,0) DEFAULT 0 NOT NULL
);
-CREATE INDEX CustomFields1 ON CustomFields (Disabled, Queue);
CREATE SEQUENCE CUSTOMFIELDVALUES_seq;
Modified: rt/branches/rt-3.1/etc/schema.Pg
==============================================================================
--- rt/branches/rt-3.1/etc/schema.Pg (original)
+++ rt/branches/rt-3.1/etc/schema.Pg Sat Jul 10 02:05:15 2004
@@ -57,7 +57,7 @@
Created TIMESTAMP NULL ,
LastUpdatedBy integer NOT NULL DEFAULT 0 ,
LastUpdated TIMESTAMP NULL ,
- Disabled int2 NOT NULL DEFAULT 0 ,
+ Disabled integer NOT NULL DEFAULT 0 ,
PRIMARY KEY (id)
);
@@ -108,7 +108,7 @@
id INTEGER DEFAULT nextval('principals_id_seq') not null,
PrincipalType VARCHAR(16) not null,
ObjectId integer,
- Disabled int2 NOT NULL DEFAULT 0 ,
+ Disabled integer NOT NULL DEFAULT 0 ,
PRIMARY KEY (id)
);
@@ -183,13 +183,16 @@
CREATE TABLE Transactions (
id INTEGER DEFAULT nextval('transactions_id_seq'),
- EffectiveTicket integer NOT NULL DEFAULT 0 ,
- Ticket integer NOT NULL DEFAULT 0 ,
+ ObjectType varchar(255) NOT NULL ,
+ ObjectId integer NOT NULL DEFAULT 0 ,
TimeTaken integer NOT NULL DEFAULT 0 ,
Type varchar(20) NULL ,
Field varchar(40) NULL ,
OldValue varchar(255) NULL ,
NewValue varchar(255) NULL ,
+ ReferenceType varchar(255) NULL,
+ OldReference integer NULL ,
+ NewReference integer NULL ,
Data varchar(255) NULL ,
Creator integer NOT NULL DEFAULT 0 ,
@@ -197,8 +200,7 @@
PRIMARY KEY (id)
);
-CREATE INDEX Transactions1 ON Transactions (Ticket);
-CREATE INDEX Transactions2 ON Transactions (EffectiveTicket);
+CREATE INDEX Transactions1 ON Transactions (ObjectType, ObjectId);
-- }}}
@@ -299,7 +301,7 @@
MemberId int,
Via int,
ImmediateParentId int,
- Disabled int2 NOT NULL DEFAULT 0 ,
+ Disabled integer NOT NULL DEFAULT 0 ,
PRIMARY KEY (id)
);
@@ -406,7 +408,7 @@
LastUpdated TIMESTAMP NULL ,
Creator integer NOT NULL DEFAULT 0 ,
Created TIMESTAMP NULL ,
- Disabled int2 NOT NULL DEFAULT 0 ,
+ Disabled integer NOT NULL DEFAULT 0 ,
PRIMARY KEY (id)
);
@@ -474,7 +476,7 @@
-- }}}
--- {{{ TicketCustomFieldValues
+-- {{{ ObjectCustomFieldValues
@@ -482,13 +484,18 @@
-- Sequences for table TICKETCUSTOMFIELDVALUES
--
-CREATE SEQUENCE ticketcustomfieldvalues_id_s;
+CREATE SEQUENCE objectcustomfieldvalues_id_s;
-CREATE TABLE TicketCustomFieldValues (
- id INTEGER DEFAULT nextval('ticketcustomfieldvalues_id_s'),
- Ticket int NOT NULL ,
+CREATE TABLE ObjectCustomFieldValues (
+ id INTEGER DEFAULT nextval('objectcustomfieldvalues_id_s'),
CustomField int NOT NULL ,
+ ObjectType varchar(255) NULL ,
+ ObjectId int NOT NULL ,
+ Current int DEFAULT 1,
Content varchar(255) NULL ,
+ LargeContent text NULL,
+ ContentType varchar(80) NULL,
+ ContentEncoding varchar(80) NULL ,
Creator integer NOT NULL DEFAULT 0 ,
Created TIMESTAMP NULL ,
@@ -498,8 +505,8 @@
);
-CREATE INDEX TicketCustomFieldValues1 ON TicketCustomFieldValues (CustomField,Ticket,Content);
-CREATE INDEX TicketCustomFieldValues2 ON TicketCustomFieldValues (CustomField,Ticket);
+CREATE INDEX ObjectCustomFieldValues1 ON ObjectCustomFieldValues (CustomField,ObjectType,ObjectId,Content);
+CREATE INDEX ObjectCustomFieldValues2 ON ObjectCustomFieldValues (CustomField,ObjectType,ObjectId);
-- }}}
@@ -517,7 +524,10 @@
id INTEGER DEFAULT nextval('customfields_id_seq'),
Name varchar(200) NULL ,
Type varchar(200) NULL ,
- Queue integer NOT NULL DEFAULT 0 ,
+ MaxValues integer NOT NULL DEFAULT 0 ,
+ Repeated integer NOT NULL DEFAULT 0 ,
+ Pattern varchar(255) NULL ,
+ LookupType varchar(255) NOT NULL ,
Description varchar(255) NULL ,
SortOrder integer NOT NULL DEFAULT 0 ,
@@ -525,7 +535,27 @@
Created TIMESTAMP NULL ,
LastUpdatedBy integer NOT NULL DEFAULT 0 ,
LastUpdated TIMESTAMP NULL ,
- Disabled int2 NOT NULL DEFAULT 0 ,
+ Disabled integer NOT NULL DEFAULT 0 ,
+ PRIMARY KEY (id)
+
+);
+
+-- }}}
+
+-- {{{ ObjectCustomFields
+
+CREATE SEQUENCE objectcustomfields_id_s;
+
+CREATE TABLE ObjectCustomFields (
+ id INTEGER DEFAULT nextval('objectcustomfields_id_s'),
+ CustomField integer NOT NULL,
+ ObjectId integer NOT NULL,
+ SortOrder integer NOT NULL DEFAULT 0 ,
+
+ Creator integer NOT NULL DEFAULT 0 ,
+ Created TIMESTAMP NULL ,
+ LastUpdatedBy integer NOT NULL DEFAULT 0 ,
+ LastUpdated TIMESTAMP NULL ,
PRIMARY KEY (id)
);
Modified: rt/branches/rt-3.1/etc/schema.SQLite
==============================================================================
--- rt/branches/rt-3.1/etc/schema.SQLite (original)
+++ rt/branches/rt-3.1/etc/schema.SQLite Sat Jul 10 02:05:15 2004
@@ -112,21 +112,23 @@
--- {{{ Transactions
CREATE TABLE Transactions (
id INTEGER PRIMARY KEY ,
- EffectiveTicket integer NULL ,
- Ticket integer NULL ,
+ ObjectType varchar(255) NULL ,
+ ObjectId integer NULL ,
TimeTaken integer NULL ,
Type varchar(20) NULL ,
Field varchar(40) NULL ,
OldValue varchar(255) NULL ,
NewValue varchar(255) NULL ,
+ ReferenceType varchar(255) NULL ,
+ OldReference integer NULL ,
+ NewReference integer NULL ,
Data varchar(255) NULL ,
Creator integer NULL ,
Created DATETIME NULL
) ;
-CREATE INDEX Transactions1 ON Transactions (Ticket);
-CREATE INDEX Transactions2 ON Transactions (EffectiveTicket);
+CREATE INDEX Transactions1 ON Transactions (ObjectType, ObjectId);
--- }}}
@@ -355,7 +357,9 @@
id INTEGER PRIMARY KEY ,
Name varchar(200) NULL ,
Type varchar(200) NULL ,
- Queue int NULL ,
+ MaxValues int NULL ,
+ Pattern varchar(255) NULL ,
+ LookupType varchar(255) NULL ,
Description varchar(255) NULL ,
SortOrder integer NULL ,
Modified: rt/branches/rt-3.1/etc/schema.Sybase
==============================================================================
--- rt/branches/rt-3.1/etc/schema.Sybase (original)
+++ rt/branches/rt-3.1/etc/schema.Sybase Sat Jul 10 02:05:15 2004
@@ -1,3 +1,5 @@
+NEEDS UPDATE FOR 3.3
+
# {{{ Attachments
CREATE TABLE rt3.Attachments (
Modified: rt/branches/rt-3.1/etc/schema.mysql
==============================================================================
--- rt/branches/rt-3.1/etc/schema.mysql (original)
+++ rt/branches/rt-3.1/etc/schema.mysql Sat Jul 10 02:05:15 2004
@@ -118,21 +118,23 @@
# {{{ Transactions
CREATE TABLE Transactions (
id INTEGER NOT NULL AUTO_INCREMENT,
- EffectiveTicket integer NOT NULL DEFAULT 0 ,
- Ticket integer NOT NULL DEFAULT 0 ,
+ ObjectType varchar(64) NOT NULL,
+ ObjectId integer NOT NULL DEFAULT 0 ,
TimeTaken integer NOT NULL DEFAULT 0 ,
Type varchar(20) NULL ,
Field varchar(40) NULL ,
OldValue varchar(255) NULL ,
NewValue varchar(255) NULL ,
+ ReferenceType varchar(255) NULL,
+ OldReference integer NULL ,
+ NewReference integer NULL ,
Data varchar(255) NULL ,
Creator integer NOT NULL DEFAULT 0 ,
Created DATETIME NULL ,
PRIMARY KEY (id)
) TYPE=InnoDB;
-CREATE INDEX Transactions1 ON Transactions (Ticket);
-CREATE INDEX Transactions2 ON Transactions (EffectiveTicket);
+CREATE INDEX Transactions1 ON Transactions (ObjectType, ObjectId);
# }}}
@@ -337,13 +339,19 @@
# }}}
-# {{{ TicketCustomFieldValues
+# {{{ ObjectCustomFieldValues
-CREATE TABLE TicketCustomFieldValues (
+CREATE TABLE ObjectCustomFieldValues (
id INTEGER NOT NULL AUTO_INCREMENT,
- Ticket int NOT NULL ,
CustomField int NOT NULL ,
+ ObjectType varchar(255) NOT NULL, # Final target of the Object
+ ObjectId int NOT NULL , # New -- Replaces Ticket
+
+ Current BOOL DEFAULT 1, # New -- whether the value was current
Content varchar(255) NULL ,
+ LargeContent LONGTEXT NULL, # New -- to hold 255+ strings
+ ContentType varchar(80) NULL, # New -- only text/* gets searched
+ ContentEncoding varchar(80) NULL , # New -- for binary Content
Creator integer NOT NULL DEFAULT 0 ,
Created DATETIME NULL ,
@@ -352,7 +360,8 @@
PRIMARY KEY (id)
) TYPE=InnoDB;
-CREATE INDEX TicketCustomFieldValues1 ON TicketCustomFieldValues (CustomField,Ticket,Content);
+CREATE INDEX ObjectCustomFieldValues1 ON ObjectCustomFieldValues (Content);
+CREATE INDEX ObjectCustomFieldValues2 ON ObjectCustomFieldValues (CustomField,ObjectType,ObjectId);
# }}}
@@ -361,10 +370,13 @@
CREATE TABLE CustomFields (
id INTEGER NOT NULL AUTO_INCREMENT,
Name varchar(200) NULL ,
- Type varchar(200) NULL ,
- Queue integer NOT NULL DEFAULT 0 ,
+ Type varchar(200) NULL , # Changed -- 'Single' and 'Multiple' is moved out
+ MaxValues integer, # New -- was 'Single'(1) and 'Multiple'(0)
+ Pattern varchar(255) NULL , # New -- Must validate against this
+ Repeated int2 NOT NULL DEFAULT 0 , # New -- repeated table entry
Description varchar(255) NULL ,
SortOrder integer NOT NULL DEFAULT 0 ,
+ LookupType varchar(255) NOT NULL,
Creator integer NOT NULL DEFAULT 0 ,
Created DATETIME NULL ,
@@ -374,8 +386,22 @@
PRIMARY KEY (id)
) TYPE=InnoDB;
-CREATE INDEX CustomFields1 on CustomFields (Disabled, Queue);
+# }}}
+
+# {{{ ObjectCustomFields
+
+CREATE TABLE ObjectCustomFields (
+ id INTEGER NOT NULL AUTO_INCREMENT,
+ CustomField int NOT NULL ,
+ ObjectId integer NOT NULL,
+ SortOrder integer NOT NULL DEFAULT 0 ,
+ Creator integer NOT NULL DEFAULT 0 ,
+ Created DATETIME NULL ,
+ LastUpdatedBy integer NOT NULL DEFAULT 0 ,
+ LastUpdated DATETIME NULL ,
+ PRIMARY KEY (id)
+) TYPE=InnoDB;
# }}}
Added: rt/branches/rt-3.1/etc/upgrade/3.3.0/acl.Informix
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.1/etc/upgrade/3.3.0/acl.Informix Sat Jul 10 02:05:15 2004
@@ -0,0 +1,4 @@
+sub acl {
+ return ();
+}
+1;
Added: rt/branches/rt-3.1/etc/upgrade/3.3.0/acl.Oracle
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.1/etc/upgrade/3.3.0/acl.Oracle Sat Jul 10 02:05:15 2004
@@ -0,0 +1,4 @@
+sub acl {
+ return ();
+}
+1;
Added: rt/branches/rt-3.1/etc/upgrade/3.3.0/acl.Pg
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.1/etc/upgrade/3.3.0/acl.Pg Sat Jul 10 02:05:15 2004
@@ -0,0 +1,20 @@
+sub acl {
+ my $dbh = shift;
+
+ my @acls;
+
+ my @tables = qw (
+ objectcustomfieldvalues
+ objectcustomfields_id_s
+ objectcustomfields
+ );
+
+ foreach my $table (@tables) {
+ push @acls,
+ "GRANT SELECT, INSERT, UPDATE, DELETE ON $table to "
+ . $RT::DatabaseUser . ";";
+
+ }
+ return (@acls);
+}
+1;
Added: rt/branches/rt-3.1/etc/upgrade/3.3.0/acl.SQLite
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.1/etc/upgrade/3.3.0/acl.SQLite Sat Jul 10 02:05:15 2004
@@ -0,0 +1,4 @@
+sub acl {
+ return ();
+}
+1;
Added: rt/branches/rt-3.1/etc/upgrade/3.3.0/acl.mysql
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.1/etc/upgrade/3.3.0/acl.mysql Sat Jul 10 02:05:15 2004
@@ -0,0 +1,4 @@
+sub acl {
+ return ();
+}
+1;
Added: rt/branches/rt-3.1/etc/upgrade/3.3.0/schema.Pg
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.1/etc/upgrade/3.3.0/schema.Pg Sat Jul 10 02:05:15 2004
@@ -0,0 +1,78 @@
+alter Table Transactions ADD Column ObjectType varchar(64);
+update Transactions set ObjectType = 'RT::Ticket';
+ALTER TABLE Transactions ALTER COLUMN ObjectType SET NOT NULL;
+alter table Transactions drop column EffectiveTicket;
+alter table Transactions add column ReferenceType varchar(255) NULL;
+alter table Transactions add column OldReference integer NULL;
+alter table Transactions add column NewReference integer NULL;
+drop index transactions1;
+alter table Transactions rename column Ticket to ObjectId;
+
+
+CREATE INDEX Transactions1 ON Transactions (ObjectType, ObjectId);
+
+alter table TicketCustomFieldValues rename to ObjectCustomFieldValues;
+
+alter table ObjectCustomFieldValues rename column Ticket to ObjectId;
+
+alter table objectcustomfieldvalues add column ObjectType varchar(255);
+
+update objectcustomfieldvalues set ObjectType = 'RT::Ticket';
+
+ALTER TABLE objectcustomfieldvalues ALTER COLUMN ObjectType SET NOT NULL;
+
+alter table objectcustomfieldvalues add column Current int;
+
+alter table objectcustomfieldvalues alter column Current SET default 1;
+
+UPDATE objectcustomfieldvalues SET Current = 1;
+
+alter table objectcustomfieldvalues add column LargeContent TEXT NULL;
+
+alter table objectcustomfieldvalues add column ContentType varchar(80) NULL;
+
+alter table objectcustomfieldvalues add column ContentEncoding varchar(80) NULL;
+
+drop index ticketcustomfieldvalues1;
+
+drop index ticketcustomfieldvalues2;
+
+create index ObjectCustomFieldValues1 on objectcustomfieldvalues (CustomField,ObjectType,ObjectId,Content);
+
+create index ObjectCustomFieldValues2 on objectcustomfieldvalues (CustomField,ObjectType,ObjectId);
+
+
+CREATE SEQUENCE objectcustomfields_id_s;
+
+CREATE TABLE ObjectCustomFields (
+ id INTEGER DEFAULT nextval('objectcustomfields_id_s'),
+ CustomField integer NOT NULL,
+ ObjectId integer NOT NULL,
+ SortOrder integer NOT NULL DEFAULT 0 ,
+
+ Creator integer NOT NULL DEFAULT 0 ,
+ Created TIMESTAMP NULL ,
+ LastUpdatedBy integer NOT NULL DEFAULT 0 ,
+ LastUpdated TIMESTAMP NULL ,
+ PRIMARY KEY (id)
+
+);
+
+
+INSERT into ObjectCustomFields (CustomField, ObjectId, SortOrder, Creator, LastUpdatedBy) SELECT id, Queue, SortOrder, Creator, LastUpdatedBy from CustomFields;
+
+alter table CustomFields add column LookupType varchar(255);
+alter table CustomFields add column Repeated int2;
+alter table CustomFields add column Pattern varchar(255) NULL;
+alter table CustomFields add column MaxValues integer;
+
+UPDATE CustomFields SET MaxValues = 0 WHERE Type LIKE '%Multiple';
+UPDATE CustomFields SET MaxValues = 1 WHERE Type LIKE '%Single';
+UPDATE CustomFields SET Type = 'Select' WHERE Type LIKE 'Select%';
+UPDATE CustomFields SET Type = 'Freeform' WHERE Type LIKE 'Freeform%';
+UPDATE CustomFields Set LookupType = 'RT::Queue-RT::Ticket';
+ALTER TABLE CustomFields ALTER COLUMN LookupType SET NOT NULL;
+UPDATE CustomFields Set Repeated = 0;
+ALTER TABLE CustomFields ALTER COLUMN Repeated SET DEFAULT 0;
+ALTER TABLE CustomFields ALTER COLUMN Repeated SET NOT NULL;
+alter table CustomFields drop column Queue;
Added: rt/branches/rt-3.1/etc/upgrade/3.3.0/schema.mysql
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.1/etc/upgrade/3.3.0/schema.mysql Sat Jul 10 02:05:15 2004
@@ -0,0 +1,64 @@
+alter Table Transactions ADD Column (ObjectType varchar(64) not null);
+update Transactions set ObjectType = 'RT::Ticket';
+alter table Transactions drop column EffectiveTicket;
+alter table Transactions add column ReferenceType varchar(255) NULL;
+alter table Transactions add column OldReference integer NULL;
+alter table Transactions add column NewReference integer NULL;
+alter table Transactions drop index transactions1;
+alter table Transactions change Ticket ObjectId integer NOT NULL DEFAULT 0 ;
+
+CREATE INDEX Transactions1 ON Transactions (ObjectType, ObjectId);
+
+alter table TicketCustomFieldValues rename ObjectCustomFieldValues;
+
+alter table ObjectCustomFieldValues change Ticket ObjectId integer NOT NULL DEFAULT 0 ;
+
+alter table objectcustomfieldvalues add column ObjectType varchar(255) not null;
+
+update objectcustomfieldvalues set ObjectType = 'RT::Ticket';
+
+alter table objectcustomfieldvalues add column Current bool default 1;
+
+alter table objectcustomfieldvalues add column LargeContent LONGTEXT NULL;
+
+alter table objectcustomfieldvalues add column ContentType varchar(80) NULL;
+
+alter table objectcustomfieldvalues add column ContentEncoding varchar(80) NULL;
+
+alter table objectcustomfieldvalues drop index ticketcustomfieldvalues1;
+
+alter table objectcustomfieldvalues drop index ticketcustomfieldvalues2;
+
+alter table objectcustomfieldvalues add index ObjectCustomFieldValues1 (Content);
+
+alter table objectcustomfieldvalues add index ObjectCustomFieldValues2 (CustomField,ObjectType,ObjectId);
+
+
+CREATE TABLE ObjectCustomFields (
+ id INTEGER NOT NULL AUTO_INCREMENT,
+ CustomField int NOT NULL ,
+ ObjectId integer NOT NULL,
+ SortOrder integer NOT NULL DEFAULT 0 ,
+
+ Creator integer NOT NULL DEFAULT 0 ,
+ Created DATETIME NULL ,
+ LastUpdatedBy integer NOT NULL DEFAULT 0 ,
+ LastUpdated DATETIME NULL ,
+ PRIMARY KEY (id)
+) TYPE=InnoDB;
+
+
+INSERT into ObjectCustomFields (id, CustomField, ObjectId, SortOrder, Creator, LastUpdatedBy) SELECT null, id, Queue, SortOrder, Creator, LastUpdatedBy from CustomFields;
+
+alter table CustomFields add column LookupType varchar(255) NOT NULL;
+alter table CustomFields add column Repeated int2 NOT NULL DEFAULT 0 ;
+alter table CustomFields add column Pattern varchar(255) NULL;
+alter table CustomFields add column MaxValues integer;
+alter table CustomFields drop index CustomFields1;
+
+UPDATE CustomFields SET MaxValues = 0 WHERE Type LIKE '%Multiple';
+UPDATE CustomFields SET MaxValues = 1 WHERE Type LIKE '%Single';
+UPDATE CustomFields SET Type = 'Select' WHERE Type LIKE 'Select%';
+UPDATE CustomFields SET Type = 'Freeform' WHERE Type LIKE 'Freeform%';
+UPDATE CustomFields Set LookupType = 'RT::Queue-RT::Ticket';
+alter table CustomFields drop column Queue;
Added: rt/branches/rt-3.1/html/Admin/CustomFields/GroupRights.html
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.1/html/Admin/CustomFields/GroupRights.html Sat Jul 10 02:05:15 2004
@@ -0,0 +1,140 @@
+%# BEGIN LICENSE BLOCK
+%#
+%# Copyright (c) 2002-2003 Jesse Vincent <jesse at bestpractical.com>
+%#
+%# This program is free software; you can redistribute it and/or modify
+%# it under the terms of version 2 of the GNU General Public License
+%# as published by the Free Software Foundation.
+%#
+%# A copy of that license should have arrived with this
+%# software, but in any event can be snarfed from www.gnu.org.
+%#
+%# This program 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.
+%#
+%# END LICENSE BLOCK
+
+<& /Admin/Elements/Header, Title => $title &>
+<& /Admin/Elements/CustomFieldTabs, id => $id, current_subtab =>
+"Admin/CustomFields/UserRights.html?id=".$id, Title => $title &>
+<& /Elements/ListActions, actions => \@results &>
+
+ <FORM METHOD=POST ACTION="GroupRights.html">
+ <INPUT TYPE=HIDDEN NAME=id VALUE="<% $CustomFieldObj->id %>">
+
+
+<h1><&|/l&>System groups</&></h1>
+<TABLE>
+% $Groups = RT::Groups->new($session{'CurrentUser'});
+% $Groups->LimitToSystemInternalGroups();
+% while (my $Group = $Groups->Next()) {
+ <TR ALIGN=RIGHT>
+ <TD VALIGN=TOP>
+ <% loc($Group->Type) %>
+ </TD>
+ <TD>
+ <& /Admin/Elements/SelectRights, PrincipalId => $Group->PrincipalId,
+ Object => $CustomFieldObj &>
+ </TD>
+ </TR>
+% }
+</TABLE>
+<h1><&|/l&>User defined groups</&></h1>
+<TABLE>
+% $Groups = RT::Groups->new($session{'CurrentUser'});
+% $Groups->LimitToUserDefinedGroups();
+% while (my $Group = $Groups->Next()) {
+ <TR ALIGN=RIGHT>
+ <TD VALIGN=TOP>
+ <% $Group->Name %>
+ </TD>
+ <TD>
+ <& /Admin/Elements/SelectRights, PrincipalId => $Group->PrincipalId,
+ Object => $CustomFieldObj &>
+ </TD>
+ </TR>
+% }
+</TABLE>
+
+ <& /Elements/Submit, Caption => loc("Be sure to save your changes"), Reset => 1 &>
+
+ </FORM>
+
+<%INIT>
+
+
+
+
+
+
+if (!defined $id) {
+ $m->comp("/Elements/Error", Why => loc("No CustomField defined"));
+}
+
+my $CustomFieldObj = RT::CustomField->new($session{'CurrentUser'});
+$CustomFieldObj->Load($id) || $m->comp("/Elements/Error", Why => loc("Couldn't load CustomField [_1]",$id));
+
+my $Groups;
+
+ my ( $ACL, @results );
+
+ foreach my $arg (keys %ARGS) {
+ if ($arg =~ /GrantRight-(\d+)-(.*?)-(\d+)$/) {
+ my $principal_id = $1;
+ my $object_type = $2;
+ my $object_id = $3;
+ my $rights = $ARGS{$arg};
+
+ my $principal = RT::Principal->new($session{'CurrentUser'});
+ $principal->Load($principal_id);
+ my $obj;
+
+ if ($object_type eq 'RT::CustomField') {
+ $obj = RT::CustomField->new($session{'CurrentUser'});
+ $obj->Load($object_id);
+ } else {
+ push (@results, loc("System Error").
+ loc("Rights could not be granted for [_1]", $object_type));
+ next;
+ }
+
+ my @rights = ref($ARGS{$arg}) eq 'ARRAY' ? @{$ARGS{$arg}} : ($ARGS{$arg});
+ foreach my $right (@rights) {
+ next unless ($right);
+ my ($val, $msg) = $principal->GrantRight(Object => $obj, Right => $right);
+ push (@results, $msg);
+ }
+ }
+ elsif ($arg =~ /RevokeRight-(\d+)-(.*?)-(\d+)-(.*?)$/) {
+ my $principal_id = $1;
+ my $object_type = $2;
+ my $object_id = $3;
+ my $right = $4;
+
+ my $principal = RT::Principal->new($session{'CurrentUser'});
+ $principal->Load($principal_id);
+ next unless ($right);
+ my $obj;
+
+ if ($object_type eq 'RT::CustomField') {
+ $obj = RT::CustomField->new($session{'CurrentUser'});
+ $obj->Load($object_id);
+ } else {
+ push (@results, loc("System Error").
+ loc("Rights could not be revoked for [_1]", $object_type));
+ next;
+ }
+ my ($val, $msg) = $principal->RevokeRight(Object => $obj, Right => $right);
+ push (@results, $msg);
+ }
+}
+
+my $title = loc('Modify group rights for custom field [_1]', $CustomFieldObj->Name);
+
+</%INIT>
+
+<%ARGS>
+$id => undef
+</%ARGS>
Added: rt/branches/rt-3.1/html/Admin/CustomFields/Modify.html
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.1/html/Admin/CustomFields/Modify.html Sat Jul 10 02:05:15 2004
@@ -0,0 +1,166 @@
+<& /Admin/Elements/Header, Title => $title &>
+<& /Admin/Elements/CustomFieldTabs, id => $CustomFieldObj->Id ,
+current_subtab => $current_subtab,
+Title => $title &>
+<& /Elements/ListActions, actions => \@results &>
+
+
+<FORM METHOD="POST" ACTION="Modify.html">
+<INPUT TYPE=HIDDEN NAME="id" VALUE="<%$id %>">
+<table>
+<tr>
+<td class="label"><&|/l&>Name</&></td>
+<td><input name="Name" VALUE="<%$CustomFieldObj->Name%>" SIZE=20></td></tr>
+<tr>
+<td class="label"><&|/l&>Description</&></td>
+<td><input name="Description" VALUE="<%$CustomFieldObj->Description%>" SIZE=80></td>
+</tr>
+
+<tr>
+<td class="label"><&|/l&>Type</&></td>
+<td><& /Admin/Elements/SelectCustomFieldType,
+ Name => "TypeComposite",
+ Default => $CustomFieldObj->TypeComposite, &>
+</td>
+</tr>
+<tr>
+<td class="label"><&|/l&>Applies to</&></td>
+<td><& /Admin/Elements/SelectCustomFieldLookupType,
+ Name => "LookupType",
+ Default => $CustomFieldObj->LookupType, &>
+</td>
+</tr>
+<tr>
+<td class="label"> </td>
+<td>
+<INPUT TYPE=HIDDEN NAME="SetEnabled" VALUE="1">
+<INPUT TYPE=CHECKBOX NAME="Enabled" VALUE="1" <%$EnabledChecked%>> <&|/l&>Enabled (Unchecking this box disables this custom field)</&>
+</td>
+</tr>
+</table>
+<BR>
+% if ($CustomFieldObj->Id && $CustomFieldObj->Type =~ /^Select/i) {
+<H2><&|/l&>Values</&></H2>
+<div>
+<& /Admin/Elements/EditCustomFieldValues, CustomField => $CustomFieldObj &>
+<& /Admin/Elements/AddCustomFieldValue, CustomField => $CustomFieldObj &>
+</div>
+% }
+<&/Elements/Submit&>
+</FORM>
+
+
+
+<%INIT>
+
+
+
+my $CustomFieldObj = RT::CustomField->new( $session{'CurrentUser'} );
+my ( $title, @results, $EnabledChecked, $Disabled);
+$EnabledChecked = "CHECKED";
+
+if ( !$id ) {
+ $title = loc("Create a CustomField");
+ $id = 'new';
+}
+else {
+
+ if ( $id eq 'new' ) {
+ my ( $val, $msg ) = $CustomFieldObj->Create(Name => $Name,
+ TypeComposite => $TypeComposite,
+ LookupType => $LookupType,
+ Description => $Description,);
+ $m->comp("/Elements/Error", Why => loc( "Could not create CustomField", $msg ) ) unless ($val);
+ push @results, $msg;
+ $title = loc( 'Created CustomField [_1]', $CustomFieldObj->Name() );
+ }
+ else {
+ $CustomFieldObj->Load($id) || $m->comp("/Elements/Error", Why => loc('No CustomField') );
+ $title = loc( 'Editing CustomField [_1]', $CustomFieldObj->Name() );
+
+ my @attribs = qw( Name TypeComposite LookupType Description);
+ my @aresults = UpdateRecordObject( AttributesRef => \@attribs,
+ Object => $CustomFieldObj,
+ ARGSRef => \%ARGS );
+
+ push @results, @aresults;
+
+ #we're asking about enabled on the web page but really care about disabled.
+ if ($Enabled == 1) {
+ $Disabled = 0;
+ }
+ else {
+ $Disabled = 1;
+ }
+ if ( ($SetEnabled) and ( $Disabled != $CustomFieldObj->Disabled) ) {
+ my ($code, $msg) = $CustomFieldObj->SetDisabled($Disabled);
+ push @results, loc('Enabled status: [_1]', loc_fuzzy($msg));
+ }
+
+ if ($CustomFieldObj->Disabled()) {
+ $EnabledChecked ="";
+ }
+ }
+
+ $id = $CustomFieldObj->id;
+}
+
+
+
+
+my $paramtag = "CustomField-".$CustomFieldObj->Id."-Value-";
+# Delete any fields that want to be deleted
+foreach my $key (keys %ARGS) {
+
+ next unless ($key =~ /^Delete-$paramtag(\d+)$/);
+ my ($val, $msg) = $CustomFieldObj->DeleteValue($1);
+ push (@results, $msg);
+
+
+}
+# Update any existing values
+my $values = $CustomFieldObj->ValuesObj;
+while (my $value = $values->Next) {
+ foreach my $attr qw(Name Description SortOrder) {
+ my $param = $paramtag.$value->Id."-".$attr;
+
+ if ( $ARGS{$param} && ($value->$attr() ne $ARGS{$param})) {
+ my $mutator = "Set$attr";
+ my ($id, $msg) = $value->$mutator($ARGS{$param});
+ push (@results, $msg);
+ }
+ }
+
+
+}
+
+
+
+# Add any new values
+if ($ARGS{$paramtag."new-Name"}) {
+ my ($id, $msg) = $CustomFieldObj->AddValue ( Name => $ARGS{$paramtag."new-Name"},
+ Description => $ARGS{$paramtag."new-Description"},
+ SortOrder => $ARGS{$paramtag."new-SortOrder"});
+ push (@results, $msg);
+}
+
+my $current_subtab;
+if ($ARGS{'Create'}){
+ $current_subtab = "Admin/CustomFields/Modify.html?Create=1";
+} else {
+ $current_subtab = "Admin/CustomFields/Modify.html?id=".$id;
+ }
+
+
+</%INIT>
+<%ARGS>
+$id => undef
+$TypeComposite => undef
+$LookupType => undef
+$MaxValues => undef
+$SortOrder => undef
+$Description => undef
+$Name => undef
+$SetEnabled => undef
+$Enabled => undef
+</%ARGS>
Added: rt/branches/rt-3.1/html/Admin/CustomFields/Objects.html
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.1/html/Admin/CustomFields/Objects.html Sat Jul 10 02:05:15 2004
@@ -0,0 +1,111 @@
+%# BEGIN LICENSE BLOCK
+%#
+%# Copyright (c) 1996-2003 Jesse Vincent <jesse at bestpractical.com>
+%#
+%# (Except where explictly superceded by other copyright notices)
+%#
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%#
+%# This work 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.
+%#
+%# Unless otherwise specified, all modifications, corrections or
+%# extensions to this work which alter its source code become the
+%# property of Best Practical Solutions, LLC when submitted for
+%# inclusion in the work.
+%#
+%#
+%# END LICENSE BLOCK
+<& /Admin/Elements/Header, Title => $title &>
+<& /Admin/Elements/CustomFieldTabs,
+ id => $id,
+ current_subtab => "Admin/CustomFields/Modify.html?id=".$id,
+ Title => $title
+ &>
+
+<& /Elements/ListActions, actions => \@results &>
+
+<FORM ACTION="Objects.html" METHOD=POST>
+<INPUT TYPE=HIDDEN NAME="id" VALUE="<% $id %>">
+<INPUT TYPE=HIDDEN NAME="UpdateObjs" VALUE="1">
+
+<h2><&|/l&>Selected objects</&></h2>
+<& /Admin/Elements/PickObjects, Objects => \@AssignedObjs, id => $id, Checked => 1 &>
+<h2><&|/l&>Unselected objects</&></h2>
+<& /Admin/Elements/PickObjects, Objects => \@UnassignedObjs, id => $id &>
+
+<& /Elements/Submit, CheckAll => 1, ClearAll => 1 &>
+</FORM>
+
+<%INIT>
+my $CF = RT::CustomField->new($session{'CurrentUser'});
+$CF->Load($id) or Abort(loc("Could not load CustomField [_1]"), $id);
+my $LookupType = $CF->LookupType;
+$LookupType =~ /^(RT::(\w+))/
+ or Abort(loc("Object of type [_1] cannot take custom fields", $LookupType));
+
+my $Type = $2;
+my $Class = $1;
+my $CollectionType = $2.'s';
+my $CollectionClass = $Class.'s';
+my $title = loc('Modify associated objects for [_1]', $CF->Name);
+
+my $Objects = $CollectionClass->new($session{'CurrentUser'});
+my (@results);
+my (@AssignedObjs, @UnassignedObjs);
+
+$Objects->UnLimit;
+$Objects->OrderBy( FIELD => 'Name' );
+
+
+my $ObjectCFs;
+$ObjectCFs = RT::ObjectCustomFields->new($session{'CurrentUser'});
+$ObjectCFs->UnLimit;
+$ObjectCFs->LimitToCustomField($id);
+
+my %seen;
+while (my $OCF = $ObjectCFs->Next) {
+ $seen{$OCF->ObjectId}++;
+}
+
+while (my $obj = $Objects->Next) {
+ my $obj_id = $obj->Id;
+
+ if ($UpdateObjs) {
+ # Go through and delete all the custom field relationships that this object
+ # no longer has
+ my $key = "Object-$obj_id-CF-$id";
+ if ($ARGS{$key}) {
+ if (!$seen{$obj_id}) {
+ my ($val, $msg) = $CF->AddToObject($obj);
+ push (@results, $msg);
+ push @UnassignedObjs, $obj if !$val;
+ }
+ }
+ else {
+ push @UnassignedObjs, $obj;
+ if ($seen{$obj_id}) {
+ my ($val, $msg) = $CF->RemoveFromObject($obj);
+ push (@results, $msg);
+ pop @UnassignedObjs if !$val;
+ }
+ }
+ }
+ elsif (!$seen{$obj_id}) {
+ push @UnassignedObjs, $obj;
+ }
+ next if @UnassignedObjs and $UnassignedObjs[-1] == $obj;
+ push @AssignedObjs, $obj;
+}
+
+</%INIT>
+<%ARGS>
+$id => undef
+$FindDisabledObjects => 0
+$UpdateObjs => 0
+</%ARGS>
Added: rt/branches/rt-3.1/html/Admin/CustomFields/UserRights.html
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.1/html/Admin/CustomFields/UserRights.html Sat Jul 10 02:05:15 2004
@@ -0,0 +1,141 @@
+%# BEGIN LICENSE BLOCK
+%#
+%# Copyright (c) 2002-2003 Jesse Vincent <jesse at bestpractical.com>
+%#
+%# This program is free software; you can redistribute it and/or modify
+%# it under the terms of version 2 of the GNU General Public License
+%# as published by the Free Software Foundation.
+%#
+%# A copy of that license should have arrived with this
+%# software, but in any event can be snarfed from www.gnu.org.
+%#
+%# This program 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.
+%#
+%# END LICENSE BLOCK
+
+<& /Admin/Elements/Header, Title => $title &>
+<& /Admin/Elements/CustomFieldTabs, id => $id,
+current_subtab => "Admin/CustomFields/UserRights.html?id=".$id,
+Title => $title, &>
+<& /Elements/ListActions, actions => \@results &>
+
+ <FORM METHOD=POST ACTION="UserRights.html">
+ <INPUT TYPE=HIDDEN NAME=id VALUE="<% $CustomFieldObj->id %>">
+
+
+<TABLE>
+
+% while (my $Member = $Users->Next()) {
+% my $UserObj = $Member->MemberObj->Object();
+% my $group = RT::Group->new($session{'CurrentUser'});
+% $group->LoadACLEquivalenceGroup($Member->MemberObj);
+ <TR ALIGN=RIGHT>
+ <TD VALIGN=TOP>
+ <% $UserObj->Name %>
+ </TD>
+ <TD>
+ <& /Admin/Elements/SelectRights, PrincipalId=> $group->PrincipalId,
+ Object => $CustomFieldObj &>
+ </TD>
+ </TR>
+% }
+ </TABLE>
+
+ <& /Elements/Submit, Caption => loc("Be sure to save your changes"), Reset => 1 &>
+
+ </FORM>
+
+<%INIT>
+
+ #Update the acls.
+ my @results;
+foreach my $arg (keys %ARGS) {
+ if ($arg =~ /GrantRight-(\d+)-(.*?)-(\d+)$/) {
+ my $principal_id = $1;
+ my $object_type = $2;
+ my $object_id = $3;
+ my $rights = $ARGS{$arg};
+
+ my $principal = RT::Principal->new($session{'CurrentUser'});
+ $principal->Load($principal_id);
+ my $obj;
+
+ if ($object_type eq 'RT::CustomField') {
+ $obj = RT::CustomField->new($session{'CurrentUser'});
+ $obj->Load($object_id);
+
+ } else {
+ push (@results, loc("System Error").
+ loc("Rights could not be granted for [_1]",
+$object_type));
+ next;
+ }
+
+ my @rights = ref($ARGS{$arg}) eq 'ARRAY' ? @{$ARGS{$arg}} :
+($ARGS{$arg});
+ foreach my $right (@rights) {
+ next unless ($right);
+ my ($val, $msg) = $principal->GrantRight(Object => $obj, Right
+=> $right);
+ push (@results, $msg);
+ }
+ }
+ elsif ($arg =~ /RevokeRight-(\d+)-(.*?)-(\d+)-(.*?)$/) {
+ my $principal_id = $1;
+ my $object_type = $2;
+ my $object_id = $3;
+ my $right = $4;
+
+ my $principal = RT::Principal->new($session{'CurrentUser'});
+ $principal->Load($principal_id);
+ next unless ($right);
+ my $obj;
+
+ if ($object_type eq 'RT::Class') {
+ $obj = RT::Class->new($session{'CurrentUser'});
+ $obj->Load($object_id);
+ } else {
+ push (@results, loc("System Error").
+ loc("Rights could not be revoked for [_1]",
+$object_type));
+ next;
+ }
+ my ($val, $msg) = $principal->RevokeRight(Object => $obj, Right =>
+$right);
+ push (@results, $msg);
+ }
+}
+
+
+# {{{ Deal with setting up the display of current rights.
+
+
+
+if (!defined $id) {
+ $m->comp("/Elements/Error", Why => loc("No Class defined"));
+}
+
+my $CustomFieldObj = RT::CustomField->new($session{'CurrentUser'});
+$CustomFieldObj->Load($id) || $m->comp("/Elements/Error", Why => loc("Couldn't load Class [_1]",$id));
+
+# Find out which users we want to display ACL selects for
+my $Privileged = RT::Group->new($session{'CurrentUser'});
+$Privileged->LoadSystemInternalGroup('Privileged');
+my $Users = $Privileged->MembersObj();
+
+
+my $title = loc('Modify user rights for custom field [_1]', $CustomFieldObj->Name);
+
+# }}}
+
+</%INIT>
+
+<%ARGS>
+$id => undef
+$UserString => undef
+$UserOp => undef
+$UserField => undef
+</%ARGS>
Added: rt/branches/rt-3.1/html/Admin/CustomFields/index.html
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.1/html/Admin/CustomFields/index.html Sat Jul 10 02:05:15 2004
@@ -0,0 +1,31 @@
+<& /Admin/Elements/Header, Title => loc('Select a Custom Field') &>
+<& /Admin/Elements/CustomFieldTabs, current_tab => 'Admin/CustomFields/',
+ current_subtab => 'Admin/CustomFields/',
+ Title => loc('Select a Custom Field') &>
+
+% my $prev_lookup = '';
+% while (my $CustomFieldObj = $CustomFields->Next) {
+% $CustomFieldObj->CurrentUserHasRight('AdminCustomField') or next;
+% my $lookup = $CustomFieldObj->FriendlyLookupType;
+% if ($lookup ne $prev_lookup) {
+% if ($prev_lookup) {
+</UL>
+% }
+<H2><% loc("Custom Fields for [_1]", $lookup) %></H2>
+<UL>
+% $prev_lookup = $lookup;
+% }
+%
+<LI>
+<A HREF="Modify.html?id=<%$CustomFieldObj->id()%>"><%$CustomFieldObj->Name%>: <%$CustomFieldObj->Description%></a>
+</LI>
+% }
+% if ($prev_lookup) {
+</UL>
+% }
+
+<%INIT>
+my $CustomFields = RT::CustomFields->new($session{'CurrentUser'});
+$CustomFields->UnLimit();
+$CustomFields->OrderByCols( { FIELD => 'LookupType' }, { FIELD => 'Name' } );
+</%INIT>
Modified: rt/branches/rt-3.1/html/Admin/Elements/AddCustomFieldValue
==============================================================================
--- rt/branches/rt-3.1/html/Admin/Elements/AddCustomFieldValue (original)
+++ rt/branches/rt-3.1/html/Admin/Elements/AddCustomFieldValue Sat Jul 10 02:05:15 2004
@@ -25,15 +25,15 @@
<TABLE BORDER="0">
<TR><TD><small>
<&|/l&>Sort</&>:<br>
-<input name="CustomField-<% $CustomField->Id %>-AddValue-SortOrder" size="5">
+<input size=3 name="CustomField-<%$CustomField->Id%>-Value-new-SortOrder" >
</TD>
<TD><small>
<&|/l&>Name</&>:<br>
-<input size=20 name="CustomField-<% $CustomField->Id %>-AddValue-Name">
+<input type="text" size=30 name="CustomField-<%$CustomField->Id%>-Value-new-Name" >
</TD>
<TD><small>
<&|/l&>Description</&>:<br>
-<input size="60" name="CustomField-<% $CustomField->Id %>-AddValue-Description">
+<input type="text" size=50 name="CustomField-<%$CustomField->Id%>-Value-new-Description">
</TD></TR>
</TABLE>
Added: rt/branches/rt-3.1/html/Admin/Elements/CustomFieldTabs
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.1/html/Admin/Elements/CustomFieldTabs Sat Jul 10 02:05:15 2004
@@ -0,0 +1,69 @@
+<& /Admin/Elements/Tabs,
+ subtabs => $tabs,
+ current_tab => 'Admin/CustomFields/',
+ current_subtab => $current_subtab,
+ Title => $Title &>
+<%INIT>
+my $tabs;
+
+if ($id) {
+ my $cf = RT::CustomField->new( $session{'CurrentUser'} );
+ $cf->Load($id);
+ $tabs = {
+ C => {
+ title => $cf->Name,
+ path => "Admin/CustomFields/Modify.html?id=" . $id,
+
+ subtabs => {
+
+ C => { title => loc('Basics'),
+ path => "Admin/CustomFields/Modify.html?id=" . $id,
+ },
+ D => { title => loc('Applies to'),
+ path => "Admin/CustomFields/Objects.html?id=" . $id,
+ },
+
+ F => { title => loc('Group Rights'),
+ path => "Admin/CustomFields/GroupRights.html?id="
+ . $id, },
+ G => {
+ title => loc('User Rights'),
+ path => "Admin/CustomFields/UserRights.html?id=" . $id,
+ },
+
+ } }
+
+ };
+}
+
+if ($session{'CurrentUser'}->HasRight( Object => $RT::System, Right => 'AdminCustomField')) {
+ $tabs->{"A"} = { title => loc('Select custom field'),
+ path => "Admin/CustomFields/",
+ };
+ $tabs->{"B"} = { title => loc('New custom field'),
+ path => "Admin/CustomFields/Modify.html?Create=1",
+ separator => 1,
+ };
+}
+
+ # Now let callbacks add their extra tabs
+ $m->comp('/Elements/Callback', tabs => $tabs, %ARGS);
+
+foreach my $tab ( sort keys %{$tabs} ) {
+ if ( $tabs->{$tab}->{'path'} eq $current_subtab ) {
+ $tabs->{$tab}->{"current_subtab"} = $current_subtab;
+ }
+ foreach my $subtab (sort keys %{$tabs->{'subtabs'}}) {
+ if ($tabs->{$tab}->{subtabs}->{$subtab}->{'path'} eq $current_tab) {
+ $tabs->{$tab}->{subtabs}->{$subtab}->{"current_subtab"} = $current_subtab;
+ }
+ }
+}
+
+</%INIT>
+<%ARGS>
+$id => undef
+$current_subtab => undef
+$current_tab => undef
+$Title => undef
+</%ARGS>
Modified: rt/branches/rt-3.1/html/Admin/Elements/EditCustomFieldValues
==============================================================================
--- rt/branches/rt-3.1/html/Admin/Elements/EditCustomFieldValues (original)
+++ rt/branches/rt-3.1/html/Admin/Elements/EditCustomFieldValues Sat Jul 10 02:05:15 2004
@@ -21,21 +21,41 @@
%#
%#
%# END LICENSE BLOCK
-<i><&|/l&>(Check box to delete)</&></i>
-<ul>
-% while (my $v = $values->Next) {
-<li>
-<INPUT TYPE="text" SIZE="2" NAME="CustomField-<%$CustomField->Id%>-SortOrder<%$v->Id()%>" VALUE="<%$v->SortOrder()%>">
-<input type="checkbox" name="CustomField-<%$CustomField->Id%>-DeleteValue" value="<%$v->id%>">
-<%$v->Name%>
-% if ($v->Description) {
-<i>(<%$v->Description%>)</i>
+% if (!$values->Count) {
+<p><em><&|/l&>(no values)</&></em></p>
+% return;
% }
-</li>
+<i><&|/l&>(Check box to delete)</&></i>
+<table>
+<tr>
+<td> </td>
+<td><&|/l&>Sort</&></td>
+<td><&|/l&>Name</&></td>
+<td><&|/l&>Description</&></td>
+</tr>
+% while (my $value = $values->Next) {
+<tr>
+<td>
+<input type="checkbox" name="Delete-CustomField-<%$CustomField->Id%>-Value-<%$value->Id%>">
+</td>
+<td>
+<input size=3 name="CustomField-<%$CustomField->Id%>-Value-<%$value->Id%>-SortOrder" value="<%$value->SortOrder%>">
+</td>
+<td>
+<input type="text" size=30 name="CustomField-<%$CustomField->Id%>-Value-<%$value->Id%>-Name" value="<%$value->Name%>">
+</td>
+<td>
+<font size="-1">
+<input type="text" size=50 name="CustomField-<%$CustomField->Id%>-Value-<%$value->Id%>-Description" value="<%$value->Description%>">
+</font>
+</td>
+</tr>
% }
-</ul>
+</table>
<%init>
-my $values = $CustomField->Values();
+
+my $values = $CustomField->ValuesObj();
+
</%init>
<%args>
$CustomField => undef
Modified: rt/branches/rt-3.1/html/Admin/Elements/EditCustomFields
==============================================================================
--- rt/branches/rt-3.1/html/Admin/Elements/EditCustomFields (original)
+++ rt/branches/rt-3.1/html/Admin/Elements/EditCustomFields Sat Jul 10 02:05:15 2004
@@ -21,94 +21,63 @@
%#
%#
%# END LICENSE BLOCK
-<& /Elements/ListActions, actions => \@actions &>
+<& /Elements/ListActions, actions => \@results &>
-<TABLE>
-<TR>
-<TD VALIGN=TOP>
-<h2><%$caption%></h2>
-</TD></TR></TABLE>
-% if ($CustomFields->Count == 0 ) {
-<P><i><&|/l&>(No custom fields)</&></i></P>
-% } else {
-<TABLE cellspacing=0 cellpadding=2>
-% my $count;
-% while (my $CustomFieldObj = $CustomFields->Next) {
-<TR>
- <TD valign="TOP">
-% if ($CustomFieldObj->Name) {
- <A HREF="CustomField.html?Queue=<%$id%>&CustomField=<%$CustomFieldObj->id()%>"><b><%$CustomFieldObj->Name%></b></a><br>
-% } else {
- <A HREF="CustomField.html?Queue=<%$id%>&CustomField=<%$CustomFieldObj->id()%>"><i>(<%loc("no name")%>)</i></a><br>
-% }
- <%$CustomFieldObj->Description%>
- </TD>
- <TD valign="TOP">
- <i><% $CustomFieldObj->FriendlyType %></i>
- </TD>
-% # show 'move up' unless it's the first item
-% if ($count++) {
- <TD valign="TOP">
- <a href="CustomFields.html?id=<%$id%>&CustomField=<%$CustomFieldObj->id%>&Move=-1"><&|/l&>Move up</&></a>
-% } else {
- <TD valign="TOP" ALIGN=RIGHT>
-% }
-
-% # show 'move down' unless it's the last item
-% if (!$CustomFields->IsLast) {
-% $m->print(' | ') if $count > 1;
- <a href="CustomFields.html?id=<%$id%>&CustomField=<%$CustomFieldObj->id%>&Move=1"><&|/l&>Move down</&></a>
-% }
-</TD>
-</TR>
+<FORM ACTION="CustomFields.html" METHOD=POST>
+<INPUT TYPE=HIDDEN NAME="id" VALUE="<% $Object->Id %>">
+<INPUT TYPE=HIDDEN NAME="ObjectType" VALUE="<% $ObjectType %>">
+<INPUT TYPE=HIDDEN NAME="SubType" VALUE="<% $SubType %>">
+<INPUT TYPE=HIDDEN NAME="UpdateCFs" VALUE="1">
+
+% if ($Object->Id) {
+<h2><&|/l&>Global Custom Fields</&></h2>
+<& PickCustomFields, CustomFields => \@GlobalCFs, ReadOnly => 1, id => $id &>
% }
+<h2><&|/l&>Selected Custom Fields</&></h2>
+<& PickCustomFields, CustomFields => [$ObjectCFs->CustomFields], id => $id, Checked => 1 &>
+<h2><&|/l&>Unselected Custom Fields</&></h2>
+<& PickCustomFields, CustomFields => \@UnassignedCFs, id => $id &>
-</TABLE>
-% }
-<FORM METHOD=GET ACTION="CustomFields.html">
-% if ($id) {
-<INPUT TYPE="Hidden" NAME="id" VALUE="<%$id%>">
-% }
-<input type="checkbox" name="FindDisabledCustomFields"> <&|/l&>Include disabled custom fields in listing.</&>
-<input type=submit value="<&|/l&>Go!</&>">
+<& /Elements/Submit, CheckAll => 1, ClearAll => 1 &>
</FORM>
<%INIT>
my $CustomFields = RT::CustomFields->new($session{'CurrentUser'});
-my $QueueObj = RT::Queue->new($session{'CurrentUser'});
-my $caption;
+my @results;
+my (@GlobalCFs, @UnassignedCFs);
-if ($id) {
- $QueueObj->Load($id);
+my $id = $Object->Id;
+if ($id and !$Object->CurrentUserHasRight('AssignCustomFields')) {
+ $m->print('<P><i>', loc('(No custom fields)'), '</i></P>');
+ return;
}
-if ($QueueObj->id) {
- $CustomFields->LimitToQueue($id);
-}
-else {
- $CustomFields->LimitToGlobal();
-}
-
-if ($FindDisabledCustomFields) {
- $caption = loc("All Custom Fields");
- $CustomFields->{'find_disabled_rows'} = 1;
-} else {
- $caption = loc("Enabled Custom Fields");
-}
+my $lookup = $ObjectType;
+$lookup .= "-$SubType" if $SubType;
+
+$CustomFields->LimitToLookupType($lookup);
+$CustomFields->OrderBy( FIELD => 'Name' );
+
+
+my ($GlobalCFs, $ObjectCFs);
+$ObjectCFs = RT::ObjectCustomFields->new($session{'CurrentUser'});
+$ObjectCFs->UnLimit;
+$ObjectCFs->LimitToObjectId($id);
+$ObjectCFs->LimitToLookupType($lookup);
# {{{ deal with moving sortorder of custom fields
if ($CustomField and $Move) {
- my $SourceObj = RT::CustomField->new($session{'CurrentUser'});
- $SourceObj->Load($CustomField) || Abort(loc('No CustomField'));
+ my $SourceObj = RT::ObjectCustomField->new($session{'CurrentUser'});
+ $SourceObj->LoadByCols( ObjectId => $id, CustomField => $CustomField );
my $TargetObj;
my $target_order = $SourceObj->SortOrder + $Move;
- while (my $CustomFieldObj = $CustomFields->Next) {
- my $this_order = $CustomFieldObj->SortOrder;
+ while (my $ObjectCF = $ObjectCFs->Next) {
+ my $this_order = $ObjectCF->SortOrder;
# if we have an exact match, finish the loop now
- ($TargetObj = $CustomFieldObj, last) if $this_order == $target_order;
+ ($TargetObj = $ObjectCF, last) if $this_order == $target_order;
# otherwise, we need to apropos toward the general direction
# ... first, check the sign is correct
@@ -122,7 +91,7 @@
next if $orig_delta < $this_delta;
}
- $TargetObj = $CustomFieldObj;
+ $TargetObj = $ObjectCF;
}
if ($TargetObj) {
@@ -131,83 +100,66 @@
$TargetObj->SetSortOrder($s);
$SourceObj->SetSortOrder($t);
# because order changed, we must redo search for subsequent uses
- $CustomFields->RedoSearch;
}
- $CustomFields->GotoFirstItem;
+ $ObjectCFs->GotoFirstItem;
}
# }}}
-# {{{ now process the 'copy queue' action
-my @actions;
-if ($Source and $Source ne $id) {
- my $SourceQueue = RT::Queue->new($session{'CurrentUser'});
- $SourceQueue->Load($Source) || Abort(loc("Couldn't load queue"));
- my $SourceCustomFields = RT::CustomFields->new($session{'CurrentUser'});
- $SourceCustomFields->LimitToQueue($SourceQueue->id);
-
- # delete old fields
- foreach my $CustomFieldObj ( @{$CustomFields->ItemsArrayRef} ) {
- $CustomFieldObj->Delete;
- }
-
- # add new fields
- while (my $SourceCustomFieldObj = $SourceCustomFields->Next) {
- my $CustomFieldObj = RT::CustomField->new($session{'CurrentUser'});
- my ($val, $msg) = $CustomFieldObj->Create(
- id => $SourceCustomFieldObj->id,
- Queue => $id,
- Name => $SourceCustomFieldObj->Name,
- Type => $SourceCustomFieldObj->Type,
- Description => $SourceCustomFieldObj->Description,
- );
- Abort(loc("Could not create CustomField") . ": $msg") unless ($val);
- push @actions, $msg;
-
- $CustomFieldObj->SetSortOrder($SourceCustomFieldObj->SortOrder);
-
- # add new values
- my $values = $SourceCustomFieldObj->Values();
- while (my $v = $values->Next) {
- my ( $addval, $addmsg ) = $CustomFieldObj->AddValue(
- Name => $v->Name,
- Description => $v->Description,
- SortOrder => $v->SortOrder
- );
- }
- }
-
- # because content changed, we must redo search for subsequent uses
- $CustomFields->RedoSearch;
- $CustomFields->GotoFirstItem;
+if ($id) {
+ $GlobalCFs = RT::ObjectCustomFields->new($session{'CurrentUser'});
+ $GlobalCFs->LimitToObjectId(0);
+ $GlobalCFs->LimitToLookupType($lookup);
}
-# }}}
-# {{{ deal with deleting existing custom fields
-foreach my $key (keys %ARGS) {
- # {{{ if we're trying to delete the custom field
- if ($key =~ /^DeleteCustomField-(\d+)/) {
- my $id = $1;
- my $CustomFieldObj = RT::CustomField->new($session{'CurrentUser'});
- $CustomFieldObj->Load($id);
- my ($retval, $msg) = $CustomFieldObj->Delete;
- if ($retval) {
- push @actions, loc("Custom field deleted");
+while (my $cf = $CustomFields->Next) {
+ my $cf_id = $cf->Id;
+
+ if ($GlobalCFs and $GlobalCFs->HasEntryForCustomField($cf_id)) {
+ push @GlobalCFs, $cf;
+ next;
+ }
+
+ if ($UpdateCFs) {
+ # Go through and delete all the custom field relationships that this object
+ # no longer has
+ my $key = "Object-$id-CF-$cf_id";
+ if ($ARGS{$key}) {
+ if (!$ObjectCFs->HasEntryForCustomField($cf_id)) {
+ my ($val, $msg) = $cf->AddToObject($Object);
+ push (@results, $msg);
+ push @UnassignedCFs, $cf if !$val;
+ }
+ }
+ else {
+ push @UnassignedCFs, $cf;
+ if ($ObjectCFs->HasEntryForCustomField($cf_id)) {
+ my ($val, $msg) = $cf->RemoveFromObject($Object);
+ push (@results, $msg);
+ pop @UnassignedCFs if !$val;
+ }
+ }
}
- else {
- push @actions, $msg;
+ elsif (!$ObjectCFs->HasEntryForCustomField($cf_id)) {
+ push @UnassignedCFs, $cf;
}
- }
- # }}}
}
-# }}}
+
+# redo search...
+$ObjectCFs = RT::ObjectCustomFields->new($session{'CurrentUser'});
+$ObjectCFs->UnLimit;
+$ObjectCFs->LimitToObjectId($id);
+$ObjectCFs->LimitToLookupType($lookup);
</%INIT>
<%ARGS>
-$id => 0
$title => undef
$Move => undef
$Source => undef
$CustomField => undef
$FindDisabledCustomFields => undef
+$UpdateCFs => 0
+$Object
+$ObjectType
+$SubType => ''
</%ARGS>
Modified: rt/branches/rt-3.1/html/Admin/Elements/EditScrip
==============================================================================
--- rt/branches/rt-3.1/html/Admin/Elements/EditScrip (original)
+++ rt/branches/rt-3.1/html/Admin/Elements/EditScrip Sat Jul 10 02:05:15 2004
@@ -109,6 +109,7 @@
<& /Elements/Submit, Label => loc('Create'), Reset => 1 &>
+
</FORM>
<%init>
my (@actions);
Modified: rt/branches/rt-3.1/html/Admin/Elements/GroupTabs
==============================================================================
--- rt/branches/rt-3.1/html/Admin/Elements/GroupTabs (original)
+++ rt/branches/rt-3.1/html/Admin/Elements/GroupTabs Sat Jul 10 02:05:15 2004
@@ -45,14 +45,18 @@
path => "Admin/Groups/GroupRights.html?id=" . $GroupObj->id, },
G => { title => loc('User Rights'),
path => "Admin/Groups/UserRights.html?id=" . $GroupObj->id, },
+ H => { title => loc('History'),
+ path => "Admin/Groups/History.html?id=" . $GroupObj->id },
}
}
}
$tabs->{"A"} = { title => loc('Select group'),
path => "Admin/Groups/", };
$tabs->{"B"} = { title => loc('New group'),
- path => "Admin/Groups/Modify.html?Create=1",
- separator => 1, };
+ path => "Admin/Groups/Modify.html?Create=1", };
+$tabs->{"C"} = { title => loc('Custom Fields'),
+ path => "Admin/Groups/CustomFields.html",
+ separator => 1, };
# Now let callbacks add their extra tabs
$m->comp( '/Elements/Callback', tabs => $tabs, %ARGS );
Modified: rt/branches/rt-3.1/html/Admin/Elements/Header
==============================================================================
--- rt/branches/rt-3.1/html/Admin/Elements/Header (original)
+++ rt/branches/rt-3.1/html/Admin/Elements/Header Sat Jul 10 02:05:15 2004
@@ -21,7 +21,7 @@
%#
%#
%# END LICENSE BLOCK
-<& /Elements/Header, Title => $Title &>
+<& /Elements/Header, %ARGS &>
<%ARGS>
$Title => undef
Added: rt/branches/rt-3.1/html/Admin/Elements/ObjectCustomFields
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.1/html/Admin/Elements/ObjectCustomFields Sat Jul 10 02:05:15 2004
@@ -0,0 +1,60 @@
+%# BEGIN LICENSE BLOCK
+%#
+%# Copyright (c) 1996-2003 Jesse Vincent <jesse at bestpractical.com>
+%#
+%# (Except where explictly superceded by other copyright notices)
+%#
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%#
+%# This work 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.
+%#
+%# Unless otherwise specified, all modifications, corrections or
+%# extensions to this work which alter its source code become the
+%# property of Best Practical Solutions, LLC when submitted for
+%# inclusion in the work.
+%#
+%#
+%# END LICENSE BLOCK
+<& /Admin/Elements/Header, Title => $title &>
+<& $ObjectTabs,
+$id ? (
+ id => $Object->id,
+ current_tab => "Admin/$Types/CustomFields.html?$sub_type_url&id=".$id,
+ current_subtab => "Admin/$Types/CustomFields.html?$sub_type_url&id=".$id,
+ "${Type}Obj" => $Object,
+) : (
+ current_tab => "Admin/$Types/CustomFields.html?$sub_type_url",
+ current_subtab => "Admin/$Types/CustomFields.html?$sub_type_url",
+),
+ Title => $title
+ &>
+
+<& /Admin/Elements/EditCustomFields, %ARGS, title => $title, Object => $Object &>
+<%INIT>
+$ObjectType =~ /^RT::(Queue|User|Group)$/
+ or Abort(loc("Object of type [_1] cannot take custom fields", $ObjectType));
+
+my $Type = $1;
+my $Types = $Type.'s';
+my $ObjectTabs = "/Admin/Elements/${Type}Tabs";
+my $Object = $ObjectType->new($session{'CurrentUser'});
+$Object->Load($id) || Abort(loc("Couldn't load object [_1]", $id)) if $id;
+
+my $title = ($id ? loc('Edit Custom Fields for [_1]', $Object->Name)
+ : loc("Modify Custom Fields which apply to all [_1]", loc($Types)));
+
+my $sub_type_url;
+$sub_type_url = "SubType=$SubType" if $SubType;
+
+</%INIT>
+<%ARGS>
+$id => undef
+$ObjectType
+$SubType => undef
+</%ARGS>
Added: rt/branches/rt-3.1/html/Admin/Elements/PickCustomFields
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.1/html/Admin/Elements/PickCustomFields Sat Jul 10 02:05:15 2004
@@ -0,0 +1,74 @@
+%# BEGIN LICENSE BLOCK
+%#
+%# Copyright (c) 1996-2003 Jesse Vincent <jesse at bestpractical.com>
+%#
+%# (Except where explictly superceded by other copyright notices)
+%#
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%#
+%# This work 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.
+%#
+%# Unless otherwise specified, all modifications, corrections or
+%# extensions to this work which alter its source code become the
+%# property of Best Practical Solutions, LLC when submitted for
+%# inclusion in the work.
+%#
+%#
+%# END LICENSE BLOCK
+% if (@CustomFields == 0) {
+<p><i><&|/l&>(None)</&></i></p>
+% } else {
+<TABLE cellspacing=0 cellpadding=2>
+% my $count;
+% foreach my $CustomFieldObj (@CustomFields) {
+<TR>
+% if (!$ReadOnly) {
+ <TD valign="TOP">
+<input type="checkbox"
+name="Object-<%$id%>-CF-<%$CustomFieldObj->Id%>"
+value="1"
+<% $Checked && 'CHECKED' %>
+>
+ </TD>
+% }
+ <TD valign="TOP">
+% if ($CustomFieldObj->Name) {
+ <A HREF="/Admin/CustomFields/Modify.html?id=<%$CustomFieldObj->id()%>"><b><%$CustomFieldObj->Name%></b></a><br>
+% } else {
+ <A HREF="/Admin/CustomFields/Modify.html?id=<%$CustomFieldObj->id()%>"><i>(<%loc("no name")%>)</i></a><br>
+% }
+ <%$CustomFieldObj->Description%>
+ </TD>
+ <TD valign="TOP">
+ <i><% $CustomFieldObj->FriendlyTypeComposite %></i>
+ </TD>
+% # show 'move up' unless it's the first item
+% if ($count++ and $Checked) {
+ <TD valign="TOP">
+ [<a href="CustomFields.html?id=<%$id%>&CustomField=<%$CustomFieldObj->id%>&Move=-1"><&|/l&>Move up</&></a>]
+% } else {
+ <TD valign="TOP" ALIGN=RIGHT>
+% }
+
+% # show 'move down' unless it's the last item
+% if ($count != @CustomFields and $Checked) {
+% $m->print(' | ') if $count > 1;
+ [<a href="CustomFields.html?id=<%$id%>&CustomField=<%$CustomFieldObj->id%>&Move=1"><&|/l&>Move down</&></a>]
+% }
+ </TD>
+</TR>
+% }
+</TABLE>
+% }
+<%ARGS>
+ at CustomFields
+$id
+$ReadOnly => 0
+$Checked => 0
+</%ARGS>
Added: rt/branches/rt-3.1/html/Admin/Elements/PickObjects
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.1/html/Admin/Elements/PickObjects Sat Jul 10 02:05:15 2004
@@ -0,0 +1,61 @@
+%# BEGIN LICENSE BLOCK
+%#
+%# Copyright (c) 1996-2003 Jesse Vincent <jesse at bestpractical.com>
+%#
+%# (Except where explictly superceded by other copyright notices)
+%#
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%#
+%# This work 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.
+%#
+%# Unless otherwise specified, all modifications, corrections or
+%# extensions to this work which alter its source code become the
+%# property of Best Practical Solutions, LLC when submitted for
+%# inclusion in the work.
+%#
+%#
+%# END LICENSE BLOCK
+% if (@Objects == 0) {
+<P><i><&|/l&>(None)</&></i></P>
+% } else {
+<TABLE cellspacing=0 cellpadding=2>
+% my $count;
+% foreach my $Object (@Objects) {
+<TR>
+% if (!$ReadOnly) {
+ <TD valign="TOP">
+<input type="checkbox"
+name="Object-<%$Object->id%>-CF-<%$id%>"
+value="1"
+<% $Checked && 'CHECKED' %>
+>
+ </TD>
+% }
+ <TD valign="TOP">
+% if ($Object->Name) {
+ <b><%$Object->Name%></b><br>
+% } else {
+ <i>(<%loc("no name")%>)</i><br>
+% }
+ <%$Object->can('Description') && $Object->Description%>
+ </TD>
+%# <TD valign="TOP">
+%# <i><% $CustomFieldObj->FriendlyTypeComposite %></i>
+%# </TD>
+ </TD>
+</TR>
+% }
+</TABLE>
+% }
+<%ARGS>
+ at Objects
+$id
+$ReadOnly => 0
+$Checked => 0
+</%ARGS>
Modified: rt/branches/rt-3.1/html/Admin/Elements/QueueTabs
==============================================================================
--- rt/branches/rt-3.1/html/Admin/Elements/QueueTabs (original)
+++ rt/branches/rt-3.1/html/Admin/Elements/QueueTabs Sat Jul 10 02:05:15 2004
@@ -49,8 +49,12 @@
path => "Admin/Queues/Templates.html?id=".$id,
},
- G => { title => loc('Custom Fields'),
- path => 'Admin/Queues/CustomFields.html?id='.$id,
+ G1 => { title => loc('Ticket Custom Fields'),
+ path => 'Admin/Queues/CustomFields.html?SubType=RT::Ticket&id='.$id,
+ },
+
+ G2 => { title => loc('Transaction Custom Fields'),
+ path => 'Admin/Queues/CustomFields.html?SubType=RT::Ticket-RT::Transaction&id='.$id,
},
H => { title => loc('Group Rights'),
@@ -68,8 +72,13 @@
};
$tabs->{"B"} = { title => loc('New queue'),
path => "Admin/Queues/Modify.html?Create=1",
- separator => 1,
};
+ $tabs->{"G1"} = { title => loc('Ticket Custom Fields'),
+ path => 'Admin/Queues/CustomFields.html?SubType=RT::Ticket',
+ };
+ $tabs->{"G2"} = { title => loc('Transaction Custom Fields'),
+ path => 'Admin/Queues/CustomFields.html?SubType=RT::Ticket-RT::Transaction',
+ separator => 1, };
}
# Now let callbacks add their extra tabs
Added: rt/branches/rt-3.1/html/Admin/Elements/SelectCustomFieldLookupType
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.1/html/Admin/Elements/SelectCustomFieldLookupType Sat Jul 10 02:05:15 2004
@@ -0,0 +1,36 @@
+%# BEGIN LICENSE BLOCK
+%#
+%# Copyright (c) 1996-2003 Jesse Vincent <jesse at bestpractical.com>
+%#
+%# (Except where explictly superceded by other copyright notices)
+%#
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%#
+%# This work 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.
+%#
+%# Unless otherwise specified, all modifications, corrections or
+%# extensions to this work which alter its source code become the
+%# property of Best Practical Solutions, LLC when submitted for
+%# inclusion in the work.
+%#
+%#
+%# END LICENSE BLOCK
+<SELECT NAME ="<%$Name%>">
+%for my $option ($cf->LookupTypes) {
+<OPTION VALUE="<%$option%>" <%$option eq $Default && "SELECTED"%>><% $cf->FriendlyLookupType($option) %></OPTION>
+%}
+</SELECT>
+<%INIT>
+my $cf = RT::CustomField->new($session{'CurrentUser'});
+
+</%INIT>
+<%ARGS>
+$Default=>undef
+$Name => 'LookupType'
+</%ARGS>
Modified: rt/branches/rt-3.1/html/Admin/Elements/SelectCustomFieldType
==============================================================================
--- rt/branches/rt-3.1/html/Admin/Elements/SelectCustomFieldType (original)
+++ rt/branches/rt-3.1/html/Admin/Elements/SelectCustomFieldType Sat Jul 10 02:05:15 2004
@@ -22,8 +22,8 @@
%#
%# END LICENSE BLOCK
<SELECT NAME ="<%$Name%>">
-%for my $option ($cf->Types) {
-<OPTION VALUE="<%$option%>" <%$option eq $Default && "SELECTED"%>><% $cf->FriendlyType($option) %></OPTION>
+%for my $option ($cf->TypeComposites) {
+<OPTION VALUE="<%$option%>" <%$option eq $Default && "SELECTED"%>><% $cf->FriendlyTypeComposite($option) %></OPTION>
%}
</SELECT>
<%INIT>
@@ -32,5 +32,5 @@
</%INIT>
<%ARGS>
$Default=>undef
-$Name => 'Type'
+$Name => 'TypeComposite'
</%ARGS>
Modified: rt/branches/rt-3.1/html/Admin/Elements/SelectRights
==============================================================================
--- rt/branches/rt-3.1/html/Admin/Elements/SelectRights (original)
+++ rt/branches/rt-3.1/html/Admin/Elements/SelectRights Sat Jul 10 02:05:15 2004
@@ -78,7 +78,7 @@
}
else {
- %Rights = { loc('System Error') => loc("No rights found")};
+ %Rights = ( loc('System Error') => loc("No rights found") );
}
$ACLDesc = "$PrincipalId-".ref($Object)."-".$Object->Id;
Modified: rt/branches/rt-3.1/html/Admin/Elements/SystemTabs
==============================================================================
--- rt/branches/rt-3.1/html/Admin/Elements/SystemTabs (original)
+++ rt/branches/rt-3.1/html/Admin/Elements/SystemTabs Sat Jul 10 02:05:15 2004
@@ -36,9 +36,9 @@
path => 'Admin/Global/Templates.html',
},
- F => { title => loc('Custom Fields'),
- path => 'Admin/Global/CustomFields.html',
- },
+# F => { title => loc('Custom Fields'),
+# path => 'Admin/Global/CustomFields.html',
+# },
G => { title => loc('Group Rights'),
path => 'Admin/Global/GroupRights.html',
Modified: rt/branches/rt-3.1/html/Admin/Elements/Tabs
==============================================================================
--- rt/branches/rt-3.1/html/Admin/Elements/Tabs (original)
+++ rt/branches/rt-3.1/html/Admin/Elements/Tabs Sat Jul 10 02:05:15 2004
@@ -37,10 +37,13 @@
C => { title => loc('Queues'),
path => 'Admin/Queues/',
},
- D => { 'title' => loc('Global'),
+ D => { 'title' => loc('Custom Fields'),
+ path => 'Admin/CustomFields/',
+ },
+ E => { 'title' => loc('Global'),
path => 'Admin/Global/',
},
- E => { 'title' => loc('Tools'),
+ F => { 'title' => loc('Tools'),
path => 'Admin/Tools/',
},
};
Modified: rt/branches/rt-3.1/html/Admin/Elements/UserTabs
==============================================================================
--- rt/branches/rt-3.1/html/Admin/Elements/UserTabs (original)
+++ rt/branches/rt-3.1/html/Admin/Elements/UserTabs Sat Jul 10 02:05:15 2004
@@ -21,51 +21,63 @@
%#
%#
%# END LICENSE BLOCK
-<& /Admin/Elements/Tabs,
+<& /Admin/Elements/Tabs,
subtabs => $tabs,
- current_tab => 'Admin/Users/',
- current_subtab => $current_tab,
+ current_tab => 'Admin/Users/',
+ current_subtab => $current_tab,
Title => $Title &>
<%INIT>
my $tabs;
if ($id) {
- $tabs->{'this'} = {
- title => eval { $UserObj->Name },
+$tabs->{'this'} = { title => eval { $UserObj->Name },
+
path => "Admin/Users/Modify.html?id=".$id,
- current_subtab => $current_tab,
- subtabs => {
- A => { title => loc('Basics'),
+subtabs => {
+ Basics => { title => loc('Basics'),
path => "Admin/Users/Modify.html?id=".$id
},
- }
+ Memberships => { title => loc('Memberships'),
+ path => "Admin/Users/Memberships.html?id=".$id
+ },
+ History => { title => loc('History'),
+ path => "Admin/Users/History.html?id=".$id
+ },
+# Scrips => { title => loc('Rights'),
+# path => "Admin/Users/Rights.html?id=".$id
+# }
+
}
}
-
-if ( $session{'CurrentUser'}->HasRight( Object => $RT::System, Right => 'AdminUsers') ) {
- $tabs->{"A"} = {
- title => loc('Select user'),
- path => "Admin/Users/",
+}
+if ($session{'CurrentUser'}->HasRight( Object => $RT::System, Right => 'AdminUsers')) {
+ $tabs->{"A"} = { title => loc('Select user'),
+ path => "Admin/Users/",
+ };
+ $tabs->{"B"} = { title => loc('New user'),
+ path => "Admin/Users/Modify.html?Create=1",
};
- $tabs->{"B"} = {
- title => loc('New user'),
- path => "Admin/Users/Modify.html?Create=1",
+ $tabs->{"C"} = { title => loc('Custom Fields'),
+ path => "Admin/Users/CustomFields.html",
separator => 1,
};
}
-# Now let callbacks add their extra tabs
-$m->comp('/Elements/Callback', tabs => $tabs, %ARGS);
-
-foreach my $tab ( sort keys %{$tabs->{'this'}->{'subtabs'}} ) {
- if ( $tabs->{'this'}->{'subtabs'}->{$tab}->{'path'} eq $current_tab ) {
- $tabs->{'this'}->{"current_subtab"} = $current_tab;
- $tabs->{'this'}->{'subtabs'}->{$tab}->{"current_subtab"} = $current_subtab;
- $tabs->{'this'}->{'subtabs'}->{$tab}->{"subtabs"} = $subtabs;
- }
-}
-
+ # Now let callbacks add their extra tabs
+ $m->comp('/Elements/Callback', tabs => $tabs, %ARGS);
+
+#foreach my $tab ( sort keys %{$tabs} ) {
+# if ( $tabs->{$tab}->{'path'} eq $current_subtab ) {
+# $tabs->{$tab}->{"current_subtab"} = $current_subtab;
+# }
+#}
+foreach my $tab ( sort keys %{$tabs->{'this'}->{'subtabs'}} ) {
+ if ( $tabs->{'this'}->{'subtabs'}->{$tab}->{'path'} eq $current_tab ) {
+ $tabs->{'this'}->{'subtabs'}->{$tab}->{"subtabs"} = $subtabs;
+ $tabs->{'this'}->{'subtabs'}->{$tab}->{"current_subtab"} = $current_subtab;
+ }
+}
+$tabs->{'this'}->{"current_subtab"} = $current_tab;
$current_tab = "Admin/Users/Modify.html?id=".$id if $id;
-
</%INIT>
<%ARGS>
$UserObj => undef
Modified: rt/branches/rt-3.1/html/Admin/Global/Templates.html
==============================================================================
--- rt/branches/rt-3.1/html/Admin/Global/Templates.html (original)
+++ rt/branches/rt-3.1/html/Admin/Global/Templates.html Sat Jul 10 02:05:15 2004
@@ -21,7 +21,7 @@
%#
%#
%# END LICENSE BLOCK
-<& /Admin/Elements/Header, Title => $title &>
+<& /Admin/Elements/Header, Title => $title, FeedURI => 'templates' &>
<& /Admin/Elements/SystemTabs,
current_tab => 'Admin/Global/Templates.html',
current_subtab => 'Admin/Global/Templates.html',
Modified: rt/branches/rt-3.1/html/Admin/Global/index.html
==============================================================================
--- rt/branches/rt-3.1/html/Admin/Global/index.html (original)
+++ rt/branches/rt-3.1/html/Admin/Global/index.html Sat Jul 10 02:05:15 2004
@@ -46,10 +46,10 @@
path => 'Templates.html',
},
- F => { title => loc('Custom Fields'),
- text => loc('Modify Custom Fields which apply to all queues'),
- path => 'CustomFields.html',
- },
+# F => { title => loc('Custom Fields'),
+# text => loc('Modify Custom Fields which apply to all queues'),
+# path => 'CustomFields.html',
+# },
G => { title => loc('Group Rights'),
text => loc('Modify global group rights'),
Added: rt/branches/rt-3.1/html/Admin/Groups/CustomFields.html
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.1/html/Admin/Groups/CustomFields.html Sat Jul 10 02:05:15 2004
@@ -0,0 +1,24 @@
+%# BEGIN LICENSE BLOCK
+%#
+%# Copyright (c) 1996-2003 Jesse Vincent <jesse at bestpractical.com>
+%#
+%# (Except where explictly superceded by other copyright notices)
+%#
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%#
+%# This work 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.
+%#
+%# Unless otherwise specified, all modifications, corrections or
+%# extensions to this work which alter its source code become the
+%# property of Best Practical Solutions, LLC when submitted for
+%# inclusion in the work.
+%#
+%#
+%# END LICENSE BLOCK
+<& /Admin/Elements/ObjectCustomFields, %ARGS, ObjectType => 'RT::Group' &>
Added: rt/branches/rt-3.1/html/Admin/Groups/History.html
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.1/html/Admin/Groups/History.html Sat Jul 10 02:05:15 2004
@@ -0,0 +1,44 @@
+%# BEGIN LICENSE BLOCK
+%#
+%# Copyright (c) 1996-2003 Jesse Vincent <jesse at bestpractical.com>
+%#
+%# (Except where explictly superceded by other copyright notices)
+%#
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%#
+%# This work 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.
+%#
+%# Unless otherwise specified, all modifications, corrections or
+%# extensions to this work which alter its source code become the
+%# property of Best Practical Solutions, LLC when submitted for
+%# inclusion in the work.
+%#
+%#
+%# END LICENSE BLOCK
+<& /Admin/Elements/Header, Title => $title &>
+<& /Admin/Elements/GroupTabs,
+ id => $id,
+ GroupObj => $GroupObj,
+ current_subtab => $current_tab,
+ Title => $title &>
+
+<& /Ticket/Elements/ShowHistory,
+ Ticket => $GroupObj,
+ ShowHeaderModes => 0,
+&>
+
+<%INIT>
+my $current_tab = 'Admin/Groups/History.html?id='.$id;
+my $GroupObj = new RT::Group($session{'CurrentUser'});
+$GroupObj->Load($id) || Abort("Couldn't load group '$id'");
+my $title = loc("History of the group [_1]", $GroupObj->Name);
+</%INIT>
+<%ARGS>
+$id => undef
+</%ARGS>
Modified: rt/branches/rt-3.1/html/Admin/Groups/Modify.html
==============================================================================
--- rt/branches/rt-3.1/html/Admin/Groups/Modify.html (original)
+++ rt/branches/rt-3.1/html/Admin/Groups/Modify.html Sat Jul 10 02:05:15 2004
@@ -31,7 +31,7 @@
-<FORM ACTION="<%$RT::WebPath%>/Admin/Groups/Modify.html" METHOD=POST>
+<FORM ACTION="<%$RT::WebPath%>/Admin/Groups/Modify.html" METHOD=POST ENCTYPE="multipart/form-data">
%unless ($Group->Id) {
<INPUT TYPE=HIDDEN NAME=id VALUE="new">
@@ -43,10 +43,20 @@
<&|/l&>Name</&>:
</TD>
<TD><INPUT name="Name" value="<%$Group->Name%>"></TD>
-</TR><TR>
+</TR>
+<TR>
<TD ALIGN=RIGHT>
<&|/l&>Description</&>:</TD><TD COLSPAN=3><INPUT name="Description" value="<%$Group->Description%>" size=60></TD>
-</TR><TR>
+</TR>
+% my $CFs = $Group->CustomFields;
+% while (my $CF = $CFs->Next) {
+<TR VALIGN="TOP"><TD ALIGN="RIGHT">
+<% $CF->Name %>:
+</TD><TD>
+<& /Elements/EditCustomField, CustomField => $CF, Object => $Group &>
+</TD></TR>
+% }
+<TR>
<TD COLSPAN=2>
<INPUT TYPE=HIDDEN NAME="SetEnabled" VALUE="1">
<INPUT TYPE=CHECKBOX NAME="Enabled" VALUE="1" <%$EnabledChecked%>> <&|/l&>Enabled (Unchecking this box disables this group)</&><BR>
@@ -102,6 +112,7 @@
Object => $Group,
ARGSRef => \%ARGS );
push (@results, at fieldresults);
+ push @results, ProcessObjectCustomFieldUpdates( ARGSRef => \%ARGS, Object => $Group );
}
#we're asking about enabled on the web page but really care about disabled.
Modified: rt/branches/rt-3.1/html/Admin/Groups/index.html
==============================================================================
--- rt/branches/rt-3.1/html/Admin/Groups/index.html (original)
+++ rt/branches/rt-3.1/html/Admin/Groups/index.html Sat Jul 10 02:05:15 2004
@@ -25,13 +25,19 @@
<& /Admin/Elements/GroupTabs, current_tab => 'Admin/Groups/',
current_subtab => 'Admin/Groups/',
Title => $title &>
-
-
-<UL>
+<%$caption%>:<BR> <UL>
+%if ($Groups->Count == 0) {
+<LI> <i><&|/l&>No groups matching search criteria found.</&></i>
+% }
+%my @ids;
%while ( my $Group = $Groups->Next) {
+% push @ids, $Group->Id;
<LI><A HREF="Modify.html?id=<%$Group->id%>"><%$Group->Name || loc('(empty)')%></a><BR>
%}
</UL>
+%if (my $ids = join(',', @ids)) {
+<em>(<a href="/Download/Tabular/Group/<% $ids %>/Groups.tsv"><&|/l&>Download as a tab-delimited file</&></a>)</em><br>
+%}
<br><br>
<FORM METHOD=POST ACTION="<% $RT::WebPath %>/Admin/Groups/index.html">
<input type="checkbox" name="FindDisabledGroups"> <&|/l&>Include disabled groups in listing.</&>
@@ -39,17 +45,41 @@
<div align=right><input type=submit value="<&|/l&>Go!</&>"></div>
</FORM>
+<br><br>
+<FORM METHOD=POST ACTION="<% $RT::WebPath %>/Admin/Groups/index.html">
+<&|/l&>Find groups whose</&> <& /Elements/SelectGroups &><BR>
+<div align=right><input type=submit value="<&|/l&>Go!</&>"></div>
+</FORM>
<%INIT>
my $Groups = RT::Groups->new($session{'CurrentUser'});
-
-if ($FindDisabledGroups) {
- $Groups->{'find_disabled_rows'} = 1;
-}
-
$Groups->LimitToUserDefinedGroups();
my $title = loc('Select a group');
+my $caption;
+if (length $GroupString) {
+ $caption = loc("Groups matching search criteria");
+ if ($GroupField =~ /^CustomField-(\d+)/) {
+ $Groups->LimitCustomField(
+ CUSTOMFIELD => $1,
+ OPERATOR => $GroupOp,
+ VALUE => $GroupString,
+ );
+ }
+ else {
+ $Groups->Limit(
+ FIELD => $GroupField,
+ OPERATOR => $GroupOp,
+ VALUE => $GroupString,
+ );
+ }
+}
+else {
+ $caption = loc("User-defined groups");
+}
</%INIT>
<%ARGS>
+$GroupString => undef
+$GroupOp => '='
+$GroupField => 'Name'
$FindDisabledGroups => 0
</%ARGS>
Modified: rt/branches/rt-3.1/html/Admin/Queues/CustomField.html
==============================================================================
--- rt/branches/rt-3.1/html/Admin/Queues/CustomField.html (original)
+++ rt/branches/rt-3.1/html/Admin/Queues/CustomField.html Sat Jul 10 02:05:15 2004
@@ -56,5 +56,5 @@
</%INIT>
<%ARGS>
$CustomField => undef
-$Queue => undef
+$Queue => 0
</%ARGS>
Modified: rt/branches/rt-3.1/html/Admin/Queues/CustomFields.html
==============================================================================
--- rt/branches/rt-3.1/html/Admin/Queues/CustomFields.html (original)
+++ rt/branches/rt-3.1/html/Admin/Queues/CustomFields.html Sat Jul 10 02:05:15 2004
@@ -21,29 +21,4 @@
%#
%#
%# END LICENSE BLOCK
-<& /Admin/Elements/Header, Title => $title &>
-<& /Admin/Elements/QueueTabs, id => $Queue->id,
- current_tab => 'Admin/Queues/CustomFields.html?id='.$id,
- QueueObj => $Queue,
- subtabs => $subtabs,
- Title => $title
- &>
-
-<& /Admin/Elements/EditCustomFields, title => $title, %ARGS &>
-<%INIT>
-my $Queue = new RT::Queue($session{'CurrentUser'});
-$Queue->Load($id) || Abort(loc("Couldn't load queue", $id));
-
-my $CustomFields = RT::CustomFields->new($RT::SystemUser);
-$CustomFields->LimitToQueue($Queue->Id);
-my $subtabs = {
- A => { title => loc('New custom field'),
- path => "Admin/Queues/CustomField.html?create=1&Queue=".$id,
- }
- };
-
-my $title= loc('Edit Custom Fields for [_1]', $Queue->Name);
-</%INIT>
-<%ARGS>
-$id => undef
-</%ARGS>
+<& /Admin/Elements/ObjectCustomFields, %ARGS, ObjectType => 'RT::Queue' &>
Modified: rt/branches/rt-3.1/html/Admin/Queues/Modify.html
==============================================================================
--- rt/branches/rt-3.1/html/Admin/Queues/Modify.html (original)
+++ rt/branches/rt-3.1/html/Admin/Queues/Modify.html Sat Jul 10 02:05:15 2004
@@ -137,7 +137,7 @@
}
if ( ($SetEnabled) and ( $Disabled != $QueueObj->Disabled) ) {
my ($code, $msg) = $QueueObj->SetDisabled($Disabled);
- push @results, loc('Enabled status [_1]', loc_fuzzy($msg));
+ push @results, loc('Enabled status: [_1]', loc_fuzzy($msg));
}
if ($QueueObj->Disabled()) {
Modified: rt/branches/rt-3.1/html/Admin/Queues/People.html
==============================================================================
--- rt/branches/rt-3.1/html/Admin/Queues/People.html (original)
+++ rt/branches/rt-3.1/html/Admin/Queues/People.html Sat Jul 10 02:05:15 2004
@@ -57,7 +57,7 @@
<& /Elements/SelectUsers &>
<input type=submit name="OnlySearchForPeople" value="<&|/l&>Go!</&>">
<BR>
-<&|/l&>Find group whose</&><BR>
+<&|/l&>Find groups whose</&><BR>
<& /Elements/SelectGroups &>
<input type=submit name="OnlySearchForGroup" value="<&|/l&>Go!</&>">
Added: rt/branches/rt-3.1/html/Admin/Users/CustomFields.html
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.1/html/Admin/Users/CustomFields.html Sat Jul 10 02:05:15 2004
@@ -0,0 +1,24 @@
+%# BEGIN LICENSE BLOCK
+%#
+%# Copyright (c) 1996-2003 Jesse Vincent <jesse at bestpractical.com>
+%#
+%# (Except where explictly superceded by other copyright notices)
+%#
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%#
+%# This work 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.
+%#
+%# Unless otherwise specified, all modifications, corrections or
+%# extensions to this work which alter its source code become the
+%# property of Best Practical Solutions, LLC when submitted for
+%# inclusion in the work.
+%#
+%#
+%# END LICENSE BLOCK
+<& /Admin/Elements/ObjectCustomFields, %ARGS, ObjectType => 'RT::User' &>
Added: rt/branches/rt-3.1/html/Admin/Users/History.html
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.1/html/Admin/Users/History.html Sat Jul 10 02:05:15 2004
@@ -0,0 +1,44 @@
+%# BEGIN LICENSE BLOCK
+%#
+%# Copyright (c) 1996-2003 Jesse Vincent <jesse at bestpractical.com>
+%#
+%# (Except where explictly superceded by other copyright notices)
+%#
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%#
+%# This work 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.
+%#
+%# Unless otherwise specified, all modifications, corrections or
+%# extensions to this work which alter its source code become the
+%# property of Best Practical Solutions, LLC when submitted for
+%# inclusion in the work.
+%#
+%#
+%# END LICENSE BLOCK
+<& /Admin/Elements/Header, Title => $title &>
+<& /Admin/Elements/UserTabs,
+ id => $id,
+ UserObj => $UserObj,
+ current_tab => $current_tab,
+ Title => $title &>
+
+<& /Ticket/Elements/ShowHistory,
+ Ticket => $UserObj,
+ ShowHeaderModes => 0,
+&>
+
+<%INIT>
+my $current_tab = 'Admin/Users/History.html?id='.$id;
+my $UserObj = new RT::User($session{'CurrentUser'});
+$UserObj->Load($id) || Abort("Couldn't load user '$id'");
+my $title = loc("History of the user [_1]", $UserObj->Name);
+</%INIT>
+<%ARGS>
+$id => undef
+</%ARGS>
Added: rt/branches/rt-3.1/html/Admin/Users/Memberships.html
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.1/html/Admin/Users/Memberships.html Sat Jul 10 02:05:15 2004
@@ -0,0 +1,43 @@
+%# BEGIN LICENSE BLOCK
+%#
+%# Copyright (c) 1996-2003 Jesse Vincent <jesse at bestpractical.com>
+%#
+%# (Except where explictly superceded by other copyright notices)
+%#
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%#
+%# This work 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.
+%#
+%# Unless otherwise specified, all modifications, corrections or
+%# extensions to this work which alter its source code become the
+%# property of Best Practical Solutions, LLC when submitted for
+%# inclusion in the work.
+%#
+%#
+%# END LICENSE BLOCK
+<& /Admin/Elements/Header, Title => $title &>
+<& /Admin/Elements/UserTabs,
+ id => $id,
+ UserObj => $UserObj,
+ current_tab => $current_tab,
+ Title => $title &>
+
+<h2><&|/l&>Groups</&></h2>
+
+<& /Elements/ShowMemberships, UserObj => $UserObj &>
+
+<%INIT>
+my $UserObj = RT::User->new($session{'CurrentUser'});
+$UserObj->Load($id) || Abort("Couldn't load user '$id'");
+my $title = loc("Memberships of the user [_1]", $UserObj->Name);
+my $current_tab = 'Admin/Users/Memberships.html?id='.$id;
+</%INIT>
+<%ARGS>
+$id => undef
+</%ARGS>
Modified: rt/branches/rt-3.1/html/Admin/Users/Modify.html
==============================================================================
--- rt/branches/rt-3.1/html/Admin/Users/Modify.html (original)
+++ rt/branches/rt-3.1/html/Admin/Users/Modify.html Sat Jul 10 02:05:15 2004
@@ -30,7 +30,7 @@
<& /Elements/ListActions, actions => \@results &>
-<FORM ACTION="<%$RT::WebPath%>/Admin/Users/Modify.html" METHOD=POST>
+<FORM ACTION="<%$RT::WebPath%>/Admin/Users/Modify.html" METHOD=POST ENCTYPE="multipart/form-data">
%if ($Create) {
<INPUT TYPE=HIDDEN NAME=id VALUE="new">
% } else {
@@ -69,6 +69,11 @@
<input name="Gecos" value="<%$UserObj->Gecos%>">
</TD></TR>
<TR><TD ALIGN="RIGHT">
+<&|/l&>Language</&>:
+</TD><TD>
+<& /Elements/SelectLang, Name => 'Lang', Default => $UserObj->Lang &>
+</TD></TR>
+<TR><TD ALIGN="RIGHT">
<&|/l&>Extra info</&>:
</TD><TD>
<textarea name="FreeformContactInfo" cols=20 rows=5><%$UserObj->FreeformContactInfo%></TEXTAREA>
@@ -177,6 +182,21 @@
<TR>
</TR>
</TABLE>
+<BR>
+<& /Elements/TitleBoxStart, title => loc('Custom Fields') &>
+<TABLE>
+% my $CFs = $UserObj->CustomFields;
+% while (my $CF = $CFs->Next) {
+<TR VALIGN="TOP"><TD ALIGN="RIGHT">
+<% $CF->Name %>:
+</TD><TD>
+<& /Elements/EditCustomField, %ARGS, Object => $UserObj, CustomField => $CF &>
+</TD></TR>
+% }
+<TR>
+</TR>
+</TABLE>
+<& /Elements/TitleBoxEnd &>
<TR>
<TD colspan="2">
<& /Elements/TitleBoxStart, title => loc('Comments about this user') &>
@@ -288,6 +308,7 @@
Object => $UserObj,
ARGSRef => \%ARGS );
push (@results, at fieldresults);
+ push @results, ProcessObjectCustomFieldUpdates( ARGSRef => \%ARGS, Object => $UserObj );
# {{{ Deal with special fields: Privileged, Enabled and Password
Modified: rt/branches/rt-3.1/html/Admin/Users/index.html
==============================================================================
--- rt/branches/rt-3.1/html/Admin/Users/index.html (original)
+++ rt/branches/rt-3.1/html/Admin/Users/index.html Sat Jul 10 02:05:15 2004
@@ -34,11 +34,16 @@
%if ($users->Count == 0) {
<LI> <i><&|/l&>No users matching search criteria found.</&></i>
% }
+%my @ids;
%while ( $user = $users->Next) {
+% push @ids, $user->Id;
<LI><A HREF="Modify.html?id=<%$user->id%>"><%$user->Name || loc('(no name listed)')%></a></LI>
%}
-
</UL>
+%if (my $ids = join(',', @ids)) {
+<em>(<a href="/Download/Tabular/User/<% $ids %>/Users.tsv"><&|/l&>Download as a tab-delimited file</&></a>)</em><br>
+%}
+
<br><br>
<FORM METHOD=POST ACTION="<% $RT::WebPath %>/Admin/Users/index.html">
@@ -56,19 +61,26 @@
$users->{'find_disabled_rows'} = 1;
}
-unless (defined $UserString) {
- $users->LimitToPrivileged();
- $caption = loc("Privileged users");
-}
-else {
+if (length $UserString) {
$caption = loc("Users matching search criteria");
-
- if ($UserString) {
- $users->Limit( FIELD => $UserField,
- OPERATOR => $UserOp,
- VALUE => $UserString);
-
+ if ($UserField =~ /^CustomField-(\d+)/) {
+ $users->LimitCustomField(
+ CUSTOMFIELD => $1,
+ OPERATOR => $UserOp,
+ VALUE => $UserString,
+ );
+ }
+ else {
+ $users->Limit(
+ FIELD => $UserField,
+ OPERATOR => $UserOp,
+ VALUE => $UserString,
+ );
+ }
}
+else {
+ $caption = loc("Privileged users");
+ $users->LimitToPrivileged;
}
</%INIT>
<%ARGS>
Modified: rt/branches/rt-3.1/html/Admin/index.html
==============================================================================
--- rt/branches/rt-3.1/html/Admin/index.html (original)
+++ rt/branches/rt-3.1/html/Admin/index.html Sat Jul 10 02:05:15 2004
@@ -34,6 +34,9 @@
<li><font size="+2"><a href="Queues/"><&|/l&>Queues</&></a></font><br>
<&|/l&>Manage queues and queue-specific properties</&>
</li>
+<li><font size="+2"><a href="CustomFields/"><&|/l&>Custom Fields</&></a></font><br>
+<&|/l&>Manage custom fields and custom field values</&>
+</li>
<li><font size="+2"><a href="Global/"><&|/l&>Global</&></a></font><br>
<&|/l&>Manage properties and configuration which apply to all queues</&>
</li>
Added: rt/branches/rt-3.1/html/Download/CustomFieldValue/dhandler
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.1/html/Download/CustomFieldValue/dhandler Sat Jul 10 02:05:15 2004
@@ -0,0 +1,53 @@
+%# BEGIN LICENSE BLOCK
+%#
+%# Copyright (c) 1996-2003 Jesse Vincent <jesse at bestpractical.com>
+%#
+%# (Except where explictly superceded by other copyright notices)
+%#
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%#
+%# This work 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.
+%#
+%# Unless otherwise specified, all modifications, corrections or
+%# extensions to this work which alter its source code become the
+%# property of Best Practical Solutions, LLC when submitted for
+%# inclusion in the work.
+%#
+%#
+%# END LICENSE BLOCK
+<%perl>
+my $id;
+my $arg = $m->dhandler_arg; # get rest of path
+if ($arg =~ /^(\d+)\//) {
+ $id = $1;
+}
+else {
+ Abort("Corrupted customfieldvalue URL.");
+}
+my $OCFV = RT::ObjectCustomFieldValue->new($session{'CurrentUser'});
+$OCFV->Load($id) || Abort("OCFV '$id' could not be loaded");
+
+unless ($OCFV->id) {
+ Abort("Bad OCFV id. Couldn't find OCFV '$id'\n");
+}
+
+my $content_type = $OCFV->ContentType || 'text/plain';
+
+unless ($RT::TrustHTMLAttachments) {
+ $content_type = 'text/plain' if ($content_type =~ /^text\/html/i);
+}
+
+$r->content_type( $content_type );
+$m->clear_buffer();
+$m->out($OCFV->LargeContent);
+$m->abort;
+</%perl>
+<%attr>
+AutoFlush => 0
+</%attr>
Added: rt/branches/rt-3.1/html/Download/Tabular/dhandler
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.1/html/Download/Tabular/dhandler Sat Jul 10 02:05:15 2004
@@ -0,0 +1,52 @@
+%# BEGIN LICENSE BLOCK
+%#
+%# Copyright (c) 1996-2003 Jesse Vincent <jesse at bestpractical.com>
+%#
+%# (Except where explictly superceded by other copyright notices)
+%#
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%#
+%# This work 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.
+%#
+%# Unless otherwise specified, all modifications, corrections or
+%# extensions to this work which alter its source code become the
+%# property of Best Practical Solutions, LLC when submitted for
+%# inclusion in the work.
+%#
+%#
+%# END LICENSE BLOCK
+<%perl>
+my ($class, $filename, @ids);
+my $arg = $m->dhandler_arg; # get rest of path
+if ($arg =~ /^(\w+)\/([,\d]+)(?:\/([^\/]+))?/) {
+ $class = "RT::$1";
+ $filename = $3 || "$1s.tsv";
+ @ids = sort split(/,+/, $2);
+}
+else {
+ Abort("Corrupted tabular URL.");
+}
+
+my @cols = $class->BasicColumns or return;
+
+#$r->content_type( 'application/octet-stream' );
+$r->content_type( 'text/plain' );
+$r->header_out( 'Content-Disposition' => "attachment; filename=$filename" );
+$m->clear_buffer();
+$m->out(join("\t", "Id", map $_->[1], @cols), "\n");
+foreach my $id (@ids) {
+ my $obj = $class->new;
+ $obj->Load($id) or next;
+ $m->out(join("\t", map $obj->$_, "Id", map $_->[0], @cols), "\n");
+}
+$m->abort;
+</%perl>
+<%attr>
+AutoFlush => 0
+</%attr>
Added: rt/branches/rt-3.1/html/Elements/EditCustomField
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.1/html/Elements/EditCustomField Sat Jul 10 02:05:15 2004
@@ -0,0 +1,97 @@
+%# BEGIN LICENSE BLOCK
+%#
+%# Copyright (c) 1996-2003 Jesse Vincent <jesse at bestpractical.com>
+%#
+%# (Except where explictly superceded by other copyright notices)
+%#
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%#
+%# This work 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.
+%#
+%# Unless otherwise specified, all modifications, corrections or
+%# extensions to this work which alter its source code become the
+%# property of Best Practical Solutions, LLC when submitted for
+%# inclusion in the work.
+%#
+%#
+%# END LICENSE BLOCK
+% if ($CustomField->Type eq 'FreeformSingle') {
+ <input name="<%$NamePrefix%><%$CustomField->Id%>-Value"
+ size="<%$Cols%>"
+% if ($Object) {
+ value="<%$Values->Count ? $Values->First->Content : ''%>"
+% } elsif ($Default) {
+ value="<%$Default ? $Default : ''%>"
+% }
+>
+% } elsif ($CustomField->Type eq 'FreeformMultiple') {
+% my $content;
+% if ($Object) {
+% while (my $value = $Values->Next ) {
+% $content .= $value->Content;
+% }
+% } elsif ($Default) {
+ value="<%$Default ? $Default : ''%>"
+% }
+<input type="hidden" name="<%$NamePrefix%><%$CustomField->Id%>-Values-Magic" value="1">
+<textarea cols=<%$Cols%> rows=<%$Rows%> name="<%$NamePrefix%><%$CustomField->Id%>-Values"><%$content%></textarea>
+% } elsif ($CustomField->Type =~ /^Select/) {
+ <input type="hidden" name="<%$NamePrefix%><%$CustomField->Id%>-Values-Magic" value="1">
+ <select name="<%$NamePrefix%><%$CustomField->Id%>-Values"
+ size="<%$Rows%>"
+ <%$CustomField->Type eq 'SelectMultiple' && 'MULTIPLE'%>>
+% my $CustomFieldValues = $CustomField->Values();
+% my $selected;
+% while (my $value = $CustomFieldValues->Next) {
+ <option value="<% $value->Name %>"
+% if ($Object) {
+ <% $Values->HasEntry($value->Name) && ($selected = 1) && 'SELECTED' %>
+% } elsif ($Default) {
+ <% ($Default eq $value->Name) && ($selected = 1) && 'SELECTED' %>
+% }
+ ><% $value->Name%></option>
+% }
+ <option value="" <% !$selected && 'SELECTED' %>><&|/l&>(no value)</&></option>
+ </select>
+% }
+<%INIT>
+my $Values;
+if ($Object) {
+ $Values = $Object->CustomFieldValues($CustomField->id);
+ $Values->Columns( qw( id CustomField ObjectType ObjectId Current Content ContentType ContentEncoding ) );
+ $NamePrefix ||= join('-', 'Object', ref($Object), $Object->Id, 'CustomField', '');
+}
+my $Type = $CustomField->Type;
+my $MaxValues = $CustomField->MaxValues;
+if ($MaxValues == 1 and $Object and $Values) {
+ $Default = ($Values->First ? $Values->First->Content : '');
+ $Values->GotoFirstItem;
+}
+return $m->comp(
+ "EditCustomField$Type",
+ %ARGS,
+ Rows => $Rows,
+ Cols => $Cols,
+ Default => $Default,
+ Object => $Object,
+ Values => $Values,
+ MaxValues => $MaxValues,
+ Multiple => ($MaxValues != 1),
+ NamePrefix => $NamePrefix,
+ CustomField => $CustomField,
+);
+</%INIT>
+<%ARGS>
+$Object => undef
+$CustomField => undef
+$NamePrefix => undef
+$Rows => 5
+$Cols => 15
+$Default => undef
+</%ARGS>
Added: rt/branches/rt-3.1/html/Elements/EditCustomFieldBinary
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.1/html/Elements/EditCustomFieldBinary Sat Jul 10 02:05:15 2004
@@ -0,0 +1,38 @@
+%# BEGIN LICENSE BLOCK
+%#
+%# Copyright (c) 1996-2003 Jesse Vincent <jesse at bestpractical.com>
+%#
+%# (Except where explictly superceded by other copyright notices)
+%#
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%#
+%# This work 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.
+%#
+%# Unless otherwise specified, all modifications, corrections or
+%# extensions to this work which alter its source code become the
+%# property of Best Practical Solutions, LLC when submitted for
+%# inclusion in the work.
+%#
+%#
+%# END LICENSE BLOCK
+% while ($Values and my $value = $Values->Next ) {
+%# XXX - let user download the file(s) here?
+<input type="checkbox" name="<%$NamePrefix%><%$CustomField->Id%>-DeleteValueIds" value="<% $value->Id %>"><a href="<%$RT::WebPath%>/Download/CustomFieldValue/<% $value->Id %>/<% $value->Content %>"><% $value->Content %></a><br>
+% }
+% if (!$MaxValues or !$Values or $Values->Count < $MaxValues) {
+<input type="file" name="<%$NamePrefix%><%$CustomField->Id%>-Upload">
+% }
+<%ARGS>
+$Object => undef
+$CustomField => undef
+$NamePrefix => undef
+$Default => undef
+$Values => undef
+$MaxValues => undef
+</%ARGS>
Added: rt/branches/rt-3.1/html/Elements/EditCustomFieldFreeform
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.1/html/Elements/EditCustomFieldFreeform Sat Jul 10 02:05:15 2004
@@ -0,0 +1,47 @@
+%# BEGIN LICENSE BLOCK
+%#
+%# Copyright (c) 1996-2003 Jesse Vincent <jesse at bestpractical.com>
+%#
+%# (Except where explictly superceded by other copyright notices)
+%#
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%#
+%# This work 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.
+%#
+%# Unless otherwise specified, all modifications, corrections or
+%# extensions to this work which alter its source code become the
+%# property of Best Practical Solutions, LLC when submitted for
+%# inclusion in the work.
+%#
+%#
+%# END LICENSE BLOCK
+% if ($Multiple) {
+<input type="hidden" name="<%$NamePrefix%><%$CustomField->Id%>-Values-Magic" value="1">
+<textarea cols=<%$Cols%> rows=<%$Rows%> name="<%$NamePrefix%><%$CustomField->Id%>-Values"><%$Default%></textarea>
+% } else {
+<input name="<%$NamePrefix%><%$CustomField->Id%>-Value" size="<%$Cols%>" value="<%$Default ? $Default : ''%>">
+% }
+<%INIT>
+if ($Multiple and $Values) {
+ $Default = '';
+ while (my $value = $Values->Next ) {
+ $Default .= $value->Content;
+ }
+}
+</%INIT>
+<%ARGS>
+$Object => undef
+$CustomField => undef
+$NamePrefix => undef
+$Default => undef
+$Values => undef
+$Multiple => undef
+$Cols
+$Rows
+</%ARGS>
Added: rt/branches/rt-3.1/html/Elements/EditCustomFieldImage
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.1/html/Elements/EditCustomFieldImage Sat Jul 10 02:05:15 2004
@@ -0,0 +1,38 @@
+%# BEGIN LICENSE BLOCK
+%#
+%# Copyright (c) 1996-2003 Jesse Vincent <jesse at bestpractical.com>
+%#
+%# (Except where explictly superceded by other copyright notices)
+%#
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%#
+%# This work 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.
+%#
+%# Unless otherwise specified, all modifications, corrections or
+%# extensions to this work which alter its source code become the
+%# property of Best Practical Solutions, LLC when submitted for
+%# inclusion in the work.
+%#
+%#
+%# END LICENSE BLOCK
+% while ($Values and my $value = $Values->Next ) {
+<input type="checkbox" name="<%$NamePrefix%><%$CustomField->Id%>-DeleteValueIds" value="<% $value->Id %>"><& ShowCustomFieldImage, Object => $value &>
+<br>
+% }
+% if (!$MaxValues or !$Values or $Values->Count < $MaxValues) {
+<input type="file" name="<%$NamePrefix%><%$CustomField->Id%>-Upload">
+% }
+<%ARGS>
+$Object => undef
+$CustomField => undef
+$NamePrefix => undef
+$Default => undef
+$Values => undef
+$MaxValues => undef
+</%ARGS>
Added: rt/branches/rt-3.1/html/Elements/EditCustomFieldSelect
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.1/html/Elements/EditCustomFieldSelect Sat Jul 10 02:05:15 2004
@@ -0,0 +1,50 @@
+%# BEGIN LICENSE BLOCK
+%#
+%# Copyright (c) 1996-2003 Jesse Vincent <jesse at bestpractical.com>
+%#
+%# (Except where explictly superceded by other copyright notices)
+%#
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%#
+%# This work 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.
+%#
+%# Unless otherwise specified, all modifications, corrections or
+%# extensions to this work which alter its source code become the
+%# property of Best Practical Solutions, LLC when submitted for
+%# inclusion in the work.
+%#
+%#
+%# END LICENSE BLOCK
+ <input type="hidden" name="<%$NamePrefix%><%$CustomField->Id%>-Values-Magic" value="1">
+ <select name="<%$NamePrefix%><%$CustomField->Id%>-Values"
+ size="<%$Rows%>"
+ <% $Multiple && 'MULTIPLE' %>>
+% my $selected;
+% my $CFVs = $CustomField->Values;
+% while ($CFVs and my $value = $CFVs->Next ) {
+ <option value="<%$value->Name%>"
+% if ($Values) {
+ <% $Values->HasEntry($value->Name) && ($selected = 1) && 'SELECTED' %>
+% } elsif ($Default) {
+ <% ($Default eq $value->Name) && ($selected = 1) && 'SELECTED' %>
+% }
+ ><% $value->Name%></option>
+% }
+ <option value="" <% !$selected && 'SELECTED' %>><&|/l&>(no value)</&></option>
+ </select>
+<%ARGS>
+$Object => undef
+$CustomField => undef
+$NamePrefix => undef
+$Default => undef
+$Values => undef
+$Multiple => 0
+$Cols
+$Rows
+</%ARGS>
Added: rt/branches/rt-3.1/html/Elements/EditCustomFieldText
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.1/html/Elements/EditCustomFieldText Sat Jul 10 02:05:15 2004
@@ -0,0 +1,44 @@
+%# BEGIN LICENSE BLOCK
+%#
+%# Copyright (c) 1996-2003 Jesse Vincent <jesse at bestpractical.com>
+%#
+%# (Except where explictly superceded by other copyright notices)
+%#
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%#
+%# This work 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.
+%#
+%# Unless otherwise specified, all modifications, corrections or
+%# extensions to this work which alter its source code become the
+%# property of Best Practical Solutions, LLC when submitted for
+%# inclusion in the work.
+%#
+%#
+%# END LICENSE BLOCK
+% while ($Values and my $value = $Values->Next ) {
+<textarea cols=<%$Cols%> rows=<%$Rows%> name="<%$NamePrefix%><%$CustomField->Id%>-Values"><% $value->Content %></textarea><br>
+% }
+% if (!$MaxValues or !$Values or $Values->Count < $MaxValues) {
+<input type="hidden" name="<%$NamePrefix%><%$CustomField->Id%>-Values-Magic" value="1">
+<textarea cols=<%$Cols%> rows=<%$Rows%> name="<%$NamePrefix%><%$CustomField->Id%>-Values"></textarea>
+% }
+<%INIT>
+# XXX - MultiValue textarea is for now outlawed.
+$MaxValues = 1;
+</%INIT>
+<%ARGS>
+$Object => undef
+$CustomField => undef
+$NamePrefix => undef
+$Default => undef
+$Values => undef
+$MaxValues => undef
+$Cols
+$Rows
+</%ARGS>
Modified: rt/branches/rt-3.1/html/Elements/Header
==============================================================================
--- rt/branches/rt-3.1/html/Elements/Header (original)
+++ rt/branches/rt-3.1/html/Elements/Header Sat Jul 10 02:05:15 2004
@@ -31,6 +31,11 @@
<link rel="shortcut icon" href="<%$RT::WebImagesURL%>/favicon.png" type="image/png">
<link rel="stylesheet" href="<%$RT::WebPath%>/NoAuth/webrt.css" type="text/css">
+<link rel="" href="<%$RT::WebImagesURL%>/favicon.png" type="image/png">
+% foreach my $service (qw( Feed Post Edit )) {
+% my $uri = $ARGS{$service."URI"} or next;
+<link rel="service.<% lc($service) %>" type="application/x.atom+xml" href="<% $RT::WebPath %>/REST/2.0/<% $uri %>" title="Atom <% $service %>" />
+% }
<script>
function hideshow(num) {
idstring = "element-" + num;
@@ -75,8 +80,8 @@
</table>
<%INIT>
-$r->header_out('Pragma' => 'no-cache');
-$r->header_out('Cache-control' => 'no-cache');
+$r->headers_out->{'Pragma'} = 'no-cache';
+$r->headers_out->{'Cache-control'} = 'no-cache';
</%INIT>
<%ARGS>
Modified: rt/branches/rt-3.1/html/Elements/SelectGroups
==============================================================================
--- rt/branches/rt-3.1/html/Elements/SelectGroups (original)
+++ rt/branches/rt-3.1/html/Elements/SelectGroups Sat Jul 10 02:05:15 2004
@@ -22,8 +22,17 @@
%#
%# END LICENSE BLOCK
<select name="GroupField">
-<option value="Name"><&|/l&>Name</&>
-<option value="Description"><&|/l&>Description</&>
+% foreach my $col (RT::Group->BasicColumns) {
+<option value="<% $col->[0] %>"><% loc($col->[1]) %>
+% }
+% while (my $CF = $CFs->Next) {
+<option value="CustomField-<% $CF->Id %>"><&|/l&>CustomField</&>: <% $CF->Name %>
+% }
</select>
<& /Elements/SelectMatch, Name=> 'GroupOp' &>
<input size=8 name="GroupString">
+<%INIT>
+my $CFs = RT::CustomFields->new($session{'CurrentUser'});
+$CFs->LimitToChildType('RT::Group');
+$CFs->OrderBy( FIELD => 'Name' );
+</%INIT>
Modified: rt/branches/rt-3.1/html/Elements/SelectUsers
==============================================================================
--- rt/branches/rt-3.1/html/Elements/SelectUsers (original)
+++ rt/branches/rt-3.1/html/Elements/SelectUsers Sat Jul 10 02:05:15 2004
@@ -22,10 +22,17 @@
%#
%# END LICENSE BLOCK
<select name="UserField">
-<option value="Name"><&|/l&>User Id</&>
-<option value="EmailAddress"><&|/l&>Email</&>
-<option value="RealName"><&|/l&>Name</&>
-<option value="Organization"><&|/l&>Organization</&>
+% foreach my $col (RT::User->BasicColumns) {
+<option value="<% $col->[0] %>"><% loc($col->[1]) %>
+% }
+% while (my $CF = $CFs->Next) {
+<option value="CustomField-<% $CF->Id %>"><&|/l&>CustomField</&>: <% $CF->Name %>
+% }
</select>
<& /Elements/SelectMatch, Name=> 'UserOp' &>
<input size=8 name="UserString">
+<%INIT>
+my $CFs = RT::CustomFields->new($session{'CurrentUser'});
+$CFs->LimitToChildType('RT::User');
+$CFs->OrderBy( FIELD => 'Name' );
+</%INIT>
Modified: rt/branches/rt-3.1/html/Elements/SetupSessionCookie
==============================================================================
--- rt/branches/rt-3.1/html/Elements/SetupSessionCookie (original)
+++ rt/branches/rt-3.1/html/Elements/SetupSessionCookie Sat Jul 10 02:05:15 2004
@@ -74,7 +74,7 @@
-value => $session{_session_id},
-path => '/',
);
- $r->header_out('Set-Cookie', $cookie->as_string);
+ $r->headers_out->{'Set-Cookie'} = $cookie->as_string;
}
Added: rt/branches/rt-3.1/html/Elements/ShowCustomFieldImage
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.1/html/Elements/ShowCustomFieldImage Sat Jul 10 02:05:15 2004
@@ -0,0 +1,6 @@
+% my $url = $RT::WebPath . "/Download/CustomFieldValue/".$Object->Id.'/'.$Object->Content;
+<a href="<% $url %>"><% $Object->Content %></a>
+<img type="<% $Object->ContentType %>" height=64 src="<% $url %>" align="middle">
+<%ARGS>
+$Object
+</%ARGS>
Added: rt/branches/rt-3.1/html/Elements/ShowCustomFields
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.1/html/Elements/ShowCustomFields Sat Jul 10 02:05:15 2004
@@ -0,0 +1,50 @@
+%# BEGIN LICENSE BLOCK
+%#
+%# Copyright (c) 1996-2003 Jesse Vincent <jesse at bestpractical.com>
+%#
+%# (Except where explictly superceded by other copyright notices)
+%#
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%#
+%# This work 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.
+%#
+%# Unless otherwise specified, all modifications, corrections or
+%# extensions to this work which alter its source code become the
+%# property of Best Practical Solutions, LLC when submitted for
+%# inclusion in the work.
+%#
+%#
+%# END LICENSE BLOCK
+<table>
+% my @entry_fields;
+% while (my $CustomField = $CustomFields->Next()) {
+% my $Values = $Object->CustomFieldValues($CustomField->Id);
+ <tr>
+ <td class="label"><%$CustomField->Name%>:</td>
+ <td class="value">
+% while (my $Value = $Values->Next()) {
+% if ($CustomField->Type eq 'Image') {
+<& ShowCustomFieldImage, Object => $Value &>
+% } else {
+<%$Value->Content%><br>
+% }
+% }
+% unless ($Values->Count()) {
+<i><&|/l&>(no value)</&></i>
+% }
+ </td>
+ </tr>
+% }
+</table>
+<%INIT>
+my $CustomFields = $Object->CustomFields;
+</%INIT>
+<%ARGS>
+$Object => undef
+</%ARGS>
Added: rt/branches/rt-3.1/html/Elements/ShowMemberships
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.1/html/Elements/ShowMemberships Sat Jul 10 02:05:15 2004
@@ -0,0 +1,64 @@
+%# BEGIN LICENSE BLOCK
+%#
+%# Copyright (c) 1996-2003 Jesse Vincent <jesse at bestpractical.com>
+%#
+%# (Except where explictly superceded by other copyright notices)
+%#
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%#
+%# This work 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.
+%#
+%# Unless otherwise specified, all modifications, corrections or
+%# extensions to this work which alter its source code become the
+%# property of Best Practical Solutions, LLC when submitted for
+%# inclusion in the work.
+%#
+%#
+%# END LICENSE BLOCK
+<ul>
+% while ( my $GroupMember = $GroupMembers->Next ) {
+% my $Group = RT::Group->new($session{'CurrentUser'});
+% $Group->Load($GroupMember->GroupId) or next;
+% if ($Group->Domain eq 'UserDefined') {
+<li><a href="/Admin/Groups/Modify.html?id=<% $Group->Id %>"><% $Group->Name %></a></li>
+% } elsif ($Group->Domain eq 'SystemInternal') {
+<li><em><% loc($Group->Type) %></em></li>
+% }
+% }
+</ul>
+<%INIT>
+my $GroupMembers = RT::GroupMembers->new($session{'CurrentUser'});
+$GroupMembers->Limit( FIELD => 'MemberId', VALUE => $UserObj->Id );
+my $alias = $GroupMembers->Join(
+ TYPE => 'left',
+ ALIAS1 => 'main',
+ FIELD1 => 'GroupId',
+ TABLE2 => 'Groups',
+ FIELD2 => 'id'
+);
+$GroupMembers->Limit(
+ ALIAS => $alias,
+ FIELD => 'Domain',
+ OPERATOR => '=',
+ VALUE => 'SystemInternal',
+);
+$GroupMembers->Limit(
+ ALIAS => $alias,
+ FIELD => 'Domain',
+ OPERATOR => '=',
+ VALUE => 'UserDefined',
+);
+$GroupMembers->OrderByCols(
+ { ALIAS => $alias, FIELD => 'Domain' },
+ { ALIAS => $alias, FIELD => 'Name' },
+);
+</%INIT>
+<%ARGS>
+$UserObj
+</%ARGS>
Modified: rt/branches/rt-3.1/html/Elements/Submit
==============================================================================
--- rt/branches/rt-3.1/html/Elements/Submit (original)
+++ rt/branches/rt-3.1/html/Elements/Submit Sat Jul 10 02:05:15 2004
@@ -21,15 +21,32 @@
%#
%#
%# END LICENSE BLOCK
+% if ($CheckAll or $ClearAll) {
+<script><!--
+function set_checkbox (obj, val) {
+ var i;
+ var myfield = obj.form.getElementsByTagName('input');
+ for (i = 0; i < myfield.length; i++) {
+ if (myfield[i].type == 'checkbox') {
+ myfield[i].checked = val;
+ }
+ }
+}
+--></script>
+% }
<TABLE WIDTH=100% BGCOLOR="<%$color%>" CELLSPACING=0 BORDER=0 CELLPADDING=0 >
<TR>
-% if ($Reset) {
<TD>
-<FONT COLOR=#ffd800 >
+% if ($CheckAll) {
+<INPUT TYPE=BUTTON VALUE="<%$CheckAllLabel%>" ONCLICK="set_checkbox(this, true)">
+% }
+% if ($ClearAll) {
+<INPUT TYPE=BUTTON VALUE="<%$ClearAllLabel%>" ONCLICK="set_checkbox(this, false)">
+% }
+% if ($Reset) {
<INPUT TYPE=RESET VALUE="<%$ResetLabel%>">
-</FONT>
-</TD>
%}
+</TD>
<TD>
</TD>
@@ -57,6 +74,10 @@
$AlternateLabel => undef
$Label => loc('Submit')
$Name => undef
+$CheckAll => undef
+$CheckAllLabel => loc('Check All')
+$ClearAll => undef
+$ClearAllLabel => loc('Clear All')
$Reset => undef
$ResetLabel => loc('Reset')
</%ARGS>
Modified: rt/branches/rt-3.1/html/NoAuth/webrt.css
==============================================================================
--- rt/branches/rt-3.1/html/NoAuth/webrt.css (original)
+++ rt/branches/rt-3.1/html/NoAuth/webrt.css Sat Jul 10 02:05:15 2004
@@ -359,5 +359,5 @@
</%flags>
<%init>
$r->content_type('text/css');
-$r->header_out('Expires' ,'+30m');
+$r->headers_out->{'Expires'} = '+30m';
</%init>
Modified: rt/branches/rt-3.1/html/Search/Bulk.html
==============================================================================
--- rt/branches/rt-3.1/html/Search/Bulk.html (original)
+++ rt/branches/rt-3.1/html/Search/Bulk.html Sat Jul 10 02:05:15 2004
@@ -131,6 +131,12 @@
</select>
</td></tr>
<tr><td align=right><&|/l&>Subject</&>:</td><td> <input name="UpdateSubject" size=60 value=""></td></tr>
+% while (my $CF = $TxnCFs->Next()) {
+<TR>
+<TD ALIGN=RIGHT><% $CF->Name %>:</TD>
+<TD><& /Elements/EditCustomField, CustomField => $CF, NamePrefix => "TransactionCustomField-" &><em><% $CF->FriendlyType %></em></TD>
+</TD></TR>
+% } # end if while
<tr><td align=right><&|/l&>Attach</&>:</td><td><input name="UpdateAttachment" type="file"></td></tr>
<tr><td class=labeltop><&|/l&>Message</&>:</td><td>
<& /Elements/MessageBox, Name=>"UpdateContent"&>
@@ -178,7 +184,10 @@
my @linkresults;
$Tickets->RedoSearch();
+
+my %queues;
while (my $Ticket = $Tickets->Next) {
+ $queues{$Ticket->Queue}++;
$RT::Logger->debug( "Checking Ticket ".$Ticket->Id ."\n");
next unless ($ARGS{"UpdateTicket".$Ticket->Id});
$RT::Logger->debug ("Matched\n");
@@ -218,4 +227,8 @@
@results = (@results, @tempresults);
}
+my $TxnCFs = RT::CustomFields->new($session{CurrentUser});
+$TxnCFs->LimitToLookupType("RT::Queue-RT::Ticket-RT::Transaction");
+$TxnCFs->LimitToGlobalOrObjectId(sort keys %queues);
+
</%INIT>
Modified: rt/branches/rt-3.1/html/Search/Elements/PickBasics
==============================================================================
--- rt/branches/rt-3.1/html/Search/Elements/PickBasics (original)
+++ rt/branches/rt-3.1/html/Search/Elements/PickBasics Sat Jul 10 02:05:15 2004
@@ -128,15 +128,26 @@
<& /Elements/SelectMatch, Name => "WatcherOp" &>
</td><td>
<Input Name="ValueOfWatcher" Size=20>
+% } elsif ($field eq 'WatcherGroup') {
+<& SelectPersonType, Name => 'WatcherGroupField', Default => 'RequestorGroup', Suffix => 'Group' &>
+</td><td>
+<& /Elements/SelectBoolean, Name => "WatcherGroupOp",
+ True=> 'belongs to',
+ False=> 'does not belong to',
+ TrueVal=> '=',
+ FalseVal => '!='
+&>
+</td><td>
+<& SelectGroup, Name => 'ValueOfWatcherGroup' &>
% } else {
-<&|/l&><%$field%></&>
+<% loc($field) %>
<& /Elements/SelectMatch, Name => "$field" . "Op" &>
<INPUT Name="<%"ValueOf" . $field%>" value=""SIZE=20>
% }
</td></tr>
% }
% } else {
-<&|/l&><%$field%></&>
+<% loc($field) %>
</td><td>
<& /Elements/SelectMatch, Name => "$field" . "Op" &>
</td><td>
@@ -160,5 +171,6 @@
my @people = ('Actor',
'Watcher',
+ 'WatcherGroup',
);
</%INIT>
Modified: rt/branches/rt-3.1/html/Search/Elements/PickCFs
==============================================================================
--- rt/branches/rt-3.1/html/Search/Elements/PickCFs (original)
+++ rt/branches/rt-3.1/html/Search/Elements/PickCFs Sat Jul 10 02:05:15 2004
@@ -24,14 +24,7 @@
<table cellspacing=0 border=0>
% while ( my $CustomField = $CustomFields->Next ) {
<tr><td>
-
-% my $name;
-% if ($CustomField->QueueObj->id) {
-% $name = "'CF." . $CustomField->QueueObj->Name .
-% ".{" . $CustomField->Name . "}'";
-% } else {
-% $name = "'CF." . $CustomField->Name . "'";
-% }
+% my $name = "'CF." . $CustomField->Name . "'";
<% $CustomField->Name %>
<& /Elements/SelectCustomFieldOperator, Name => $name . "Op",
True => loc("is"),
@@ -47,10 +40,9 @@
<%INIT>
my $CustomFields = RT::CustomFields->new( $session{'CurrentUser'});
-foreach (keys %cfqueues) {
- my $id = $_;
+foreach my $id (keys %cfqueues) {
$id =~ s/^.'*(.*).'*$/$1/;
- # Gotta load up the $queue object, since queues get stored by name now.
+ # Gotta load up the $queue object, since queues get stored by name now. my $id
my $queue = RT::Queue->new($session{'CurrentUser'});
$queue->Load($id);
$CustomFields->LimitToQueue($queue->Id);
Added: rt/branches/rt-3.1/html/Search/Elements/SelectGroup
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.1/html/Search/Elements/SelectGroup Sat Jul 10 02:05:15 2004
@@ -0,0 +1,43 @@
+%# BEGIN LICENSE BLOCK
+%#
+%# Copyright (c) 1996-2003 Jesse Vincent <jesse at bestpractical.com>
+%#
+%# (Except where explictly superceded by other copyright notices)
+%#
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%#
+%# This work 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.
+%#
+%# Unless otherwise specified, all modifications, corrections or
+%# extensions to this work which alter its source code become the
+%# property of Best Practical Solutions, LLC when submitted for
+%# inclusion in the work.
+%#
+%#
+%# END LICENSE BLOCK
+<SELECT NAME="<%$Name%>">
+% if ($AllowNull) {
+<OPTION VALUE="">-</OPTION>
+% }
+%while (my $group = $groups->Next) {
+<OPTION VALUE="<%$group->id%>" <%$group->id eq $Default && "SELECTED"%>><%$group->Name%></OPTION>
+%}
+</SELECT>
+
+<%INIT>
+my $groups = new RT::Groups($session{'CurrentUser'});
+$groups->Limit(FIELD => 'Domain', OPERATOR => '=', VALUE => $Domain);
+
+</%INIT>
+<%ARGS>
+$AllowNull => 1
+$Default=>undef
+$Name => 'Group'
+$Domain => 'UserDefined';
+</%ARGS>
Modified: rt/branches/rt-3.1/html/Search/Elements/SelectPersonType
==============================================================================
--- rt/branches/rt-3.1/html/Search/Elements/SelectPersonType (original)
+++ rt/branches/rt-3.1/html/Search/Elements/SelectPersonType Sat Jul 10 02:05:15 2004
@@ -25,11 +25,15 @@
% if ($AllowNull) {
<OPTION VALUE="">-</OPTION>
% }
-%for my $option (@types) {
-%foreach my $subtype (@subtypes) {
+% for my $option (@types) {
+% if ($Suffix) {
+<OPTION VALUE="<% $option %><% $Suffix %>" <%$option eq $Default && "SELECTED"%> ><%loc($option)%></OPTION>
+% next;
+% }
+% foreach my $subtype (@subtypes) {
<OPTION VALUE="<%"$option.$subtype"%>" <%$option eq $Default && $subtype eq 'EmailAddress' && "SELECTED"%> ><%loc("[_1] [_2]",$option, $subtype)%></OPTION>
+% }
% }
-%}
</SELECT>
<%INIT>
@@ -37,6 +41,9 @@
if ($Scope =~ 'queue') {
@types = qw(Cc AdminCc);
}
+elsif ($Suffix eq 'Group') {
+ @types = qw(Requestor Cc AdminCc Watcher);
+}
else {
@types = qw(Requestor Cc AdminCc Watcher Owner);
}
@@ -46,6 +53,7 @@
</%INIT>
<%ARGS>
$AllowNull => 1
+$Suffix => ''
$Default=>undef
$Scope => 'ticket'
$Name => 'WatcherType'
Modified: rt/branches/rt-3.1/html/SelfService/Closed.html
==============================================================================
--- rt/branches/rt-3.1/html/SelfService/Closed.html (original)
+++ rt/branches/rt-3.1/html/SelfService/Closed.html Sat Jul 10 02:05:15 2004
@@ -21,7 +21,7 @@
%#
%#
%# END LICENSE BLOCK
-<& /SelfService/Elements/Header, Title => loc('Closed Tickets') &>
+<& /SelfService/Elements/Header, Title => loc('Closed tickets') &>
<& /SelfService/Elements/MyRequests, status => ['rejected', 'resolved'], friendly_status =>
loc('closed') &>
Modified: rt/branches/rt-3.1/html/SelfService/Display.html
==============================================================================
--- rt/branches/rt-3.1/html/SelfService/Display.html (original)
+++ rt/branches/rt-3.1/html/SelfService/Display.html Sat Jul 10 02:05:15 2004
@@ -174,9 +174,7 @@
my $Transactions = $Ticket->Transactions;
-#!!pape: selfservice_find_attachments.patch {{
my $attachments = $m->comp('/Ticket/Elements/FindAttachments', Ticket => $Ticket);
-#!!pape: selfservice_find_attachments.patch }}
</%INIT>
Modified: rt/branches/rt-3.1/html/Ticket/Create.html
==============================================================================
--- rt/branches/rt-3.1/html/Ticket/Create.html (original)
+++ rt/branches/rt-3.1/html/Ticket/Create.html Sat Jul 10 02:05:15 2004
@@ -91,6 +91,14 @@
<& /Ticket/Elements/EditCustomFields, QueueObj => $QueueObj &>
</TD>
</TR>
+% if ($TxnCFs->Count) {
+% while (my $CF = $TxnCFs->Next()) {
+<TR>
+<TD ALIGN=RIGHT><% $CF->Name %>:</TD>
+<TD><& /Elements/EditCustomField, CustomField => $CF, NamePrefix => "TransactionCustomField-" &><em><% $CF->FriendlyType %></em></TD>
+</TD></TR>
+% }
+% }
<TR>
% if (exists $session{'Attachments'}) {
<TD class=label>
@@ -206,7 +214,8 @@
my $QueueObj = new RT::Queue($session{'CurrentUser'});
$QueueObj->Load($Queue) || Abort(loc("Queue could not be loaded."));
-my $CFs = $QueueObj->CustomFields();
+my $CFs = $QueueObj->TicketCustomFields();
+my $TxnCFs = $QueueObj->TicketTransactionCustomFields();
# if no due date has been set explicitly, then use the
# queue's default if it exists
Modified: rt/branches/rt-3.1/html/Ticket/Elements/EditCustomFields
==============================================================================
--- rt/branches/rt-3.1/html/Ticket/Elements/EditCustomFields (original)
+++ rt/branches/rt-3.1/html/Ticket/Elements/EditCustomFields Sat Jul 10 02:05:15 2004
@@ -44,7 +44,7 @@
<b><%$CustomField->Name%></b><br>
<i><%$CustomField->FriendlyType%></i>
</td>
- <td class="entry"><& EditCustomField, TicketObj => $TicketObj, CustomField => $CustomField, NamePrefix => $NamePrefix &></td>
+ <td class="entry"><& /Elements/EditCustomField, Object => $TicketObj, CustomField => $CustomField, NamePrefix => $NamePrefix &></td>
</tr>
% }
</table>
@@ -57,12 +57,12 @@
my $NamePrefix;
if ($TicketObj) {
- $CustomFields = $TicketObj->QueueObj->CustomFields();
- $NamePrefix = "Ticket-".$TicketObj->Id."-CustomField-";
+ $CustomFields = $TicketObj->CustomFields();
+ $NamePrefix = "Object-RT::Ticket-".$TicketObj->Id."-CustomField-";
} else {
- $CustomFields = $QueueObj->CustomFields();
- $NamePrefix = "CustomField-";
+ $CustomFields = $QueueObj->TicketCustomFields();
+ $NamePrefix = "Object-RT::Ticket--CustomField-";
}
Modified: rt/branches/rt-3.1/html/Ticket/Elements/EditPeople
==============================================================================
--- rt/branches/rt-3.1/html/Ticket/Elements/EditPeople (original)
+++ rt/branches/rt-3.1/html/Ticket/Elements/EditPeople Sat Jul 10 02:05:15 2004
@@ -30,7 +30,7 @@
<& /Elements/SelectUsers &>
<input type=submit name="OnlySearchForPeople" value="<&|/l&>Go!</&>">
<BR>
-<&|/l&>Find group whose</&><BR>
+<&|/l&>Find groups whose</&><BR>
<& /Elements/SelectGroups &>
<input type=submit name="OnlySearchForGroup" value="<&|/l&>Go!</&>">
Modified: rt/branches/rt-3.1/html/Ticket/Elements/FindAttachments
==============================================================================
--- rt/branches/rt-3.1/html/Ticket/Elements/FindAttachments (original)
+++ rt/branches/rt-3.1/html/Ticket/Elements/FindAttachments Sat Jul 10 02:05:15 2004
@@ -18,11 +18,14 @@
my $tickets = $attachments->NewAlias('Tickets');
-$attachments->Join( ALIAS1 => $transactions,
- FIELD1 => 'Ticket',
- ALIAS2 => $tickets,
- FIELD2 => 'id' );
-
+ $attachments->Join( ALIAS1 => $transactions,
+ FIELD1 => 'ObjectId',
+ ALIAS2 => $tickets,
+ FIELD2 => 'id' );
+
+ $attachments->Limit( ALIAS => $transactions,
+ FIELD => 'ObjectType',
+ VALUE => 'RT::Ticket');
if ($Tickets) {
while ($Ticket = $Tickets->Next) {
$attachments->Limit( ALIAS => $tickets,
Modified: rt/branches/rt-3.1/html/Ticket/Elements/LoadTextAttachments
==============================================================================
--- rt/branches/rt-3.1/html/Ticket/Elements/LoadTextAttachments (original)
+++ rt/branches/rt-3.1/html/Ticket/Elements/LoadTextAttachments Sat Jul 10 02:05:15 2004
@@ -13,11 +13,17 @@
my $tickets = $attachments->NewAlias('Tickets');
+
$attachments->Join( ALIAS1 => $transactions,
- FIELD1 => 'Ticket',
+ FIELD1 => 'ObjectId',
ALIAS2 => $tickets,
FIELD2 => 'id' );
+ $attachments->Limit( ALIAS => $transactions,
+ FIELD => 'ObjectType',
+ VALUE => 'RT::Ticket');
+
+
$attachments->Limit( ALIAS => $tickets,
FIELD => 'EffectiveId',
VALUE => $Ticket->id() );
Modified: rt/branches/rt-3.1/html/Ticket/Elements/ShowCustomFields
==============================================================================
--- rt/branches/rt-3.1/html/Ticket/Elements/ShowCustomFields (original)
+++ rt/branches/rt-3.1/html/Ticket/Elements/ShowCustomFields Sat Jul 10 02:05:15 2004
@@ -21,26 +21,7 @@
%#
%#
%# END LICENSE BLOCK
-<table>
-% my @entry_fields;
-% while (my $CustomField = $CustomFields->Next()) {
-% my $Values = $Ticket->CustomFieldValues($CustomField->Id);
- <tr>
- <td class="label"><%$CustomField->Name%>:</td>
- <td class="value">
-% while (my $Value = $Values->Next()) {
-<%$Value->Content%><br>
-% }
-% unless ($Values->Count()) {
-<i><&|/l&>(no value)</&></i>
-% }
- </td>
- </tr>
-% }
-</table>
-<%INIT>
-my $CustomFields = $Ticket->QueueObj->CustomFields();
-</%INIT>
+<& /Elements/ShowCustomFields, Object => $Ticket &>
<%ARGS>
$Ticket => undef
</%ARGS>
Modified: rt/branches/rt-3.1/html/Ticket/Elements/ShowRequestor
==============================================================================
--- rt/branches/rt-3.1/html/Ticket/Elements/ShowRequestor (original)
+++ rt/branches/rt-3.1/html/Ticket/Elements/ShowRequestor Sat Jul 10 02:05:15 2004
@@ -51,6 +51,11 @@
<LI><a href="<%$RT::WebPath%><%$DisplayPath%>?id=<%$w->id%>"><%$w->Id%>: <%$w->Subject%></a> (<%$w->Status%>)
%}
</UL>
+
+<&|/l&>Groups this user belongs to</&>:<BR>
+
+<& /Elements/ShowMemberships, UserObj => $requestor &>
+
<& /Elements/TitleBoxEnd &>
% }
Modified: rt/branches/rt-3.1/html/Ticket/Elements/ShowTransaction
==============================================================================
--- rt/branches/rt-3.1/html/Ticket/Elements/ShowTransaction (original)
+++ rt/branches/rt-3.1/html/Ticket/Elements/ShowTransaction Sat Jul 10 02:05:15 2004
@@ -34,6 +34,9 @@
<TD ALIGN="RIGHT"><font size=-1><%$titlebar_commands|n%></font></TD>
</TR>
<TR class="<% $RowNum%2 ? 'oddline' : 'evenline'%>"><TD colspan=5>
+% if ($Transaction->CustomFieldValues->Count) {
+<& /Elements/ShowCustomFields, Object => $Transaction &>
+% }
% $m->comp('ShowTransactionAttachments', %ARGS, Parent => 0) unless ($Collapsed ||!$ShowBody);
</TD>
</TR>
Modified: rt/branches/rt-3.1/html/Ticket/Modify.html
==============================================================================
--- rt/branches/rt-3.1/html/Ticket/Modify.html (original)
+++ rt/branches/rt-3.1/html/Ticket/Modify.html Sat Jul 10 02:05:15 2004
@@ -27,7 +27,7 @@
Title => loc('Modify ticket #[_1]', $TicketObj->Id) &>
<& /Elements/ListActions, actions => \@results &>
-<FORM METHOD=POST ACTION="Modify.html">
+<FORM METHOD=POST ACTION="Modify.html" ENCTYPE="multipart/form-data">
<INPUT TYPE=HIDDEN NAME=id VALUE="<%$TicketObj->Id%>">
<& /Elements/TitleBoxStart, title => loc('Modify ticket #[_1]',$TicketObj->Id), color=> "#993333", width => "100%" &>
@@ -46,7 +46,7 @@
$m->comp('/Elements/Callback', TicketObj => $TicketObj, CustomFields => $CustomFields, %ARGS);
my @results = ProcessTicketBasics(TicketObj => $TicketObj, ARGSRef => \%ARGS);
-my @cf_results = ProcessTicketCustomFieldUpdates(TicketObj => $TicketObj, ARGSRef => \%ARGS);
+my @cf_results = ProcessObjectCustomFieldUpdates(Object => $TicketObj, ARGSRef => \%ARGS);
push (@results, @cf_results);
# TODO: display the results, even if we can't display the ticket
Modified: rt/branches/rt-3.1/html/Ticket/ModifyAll.html
==============================================================================
--- rt/branches/rt-3.1/html/Ticket/ModifyAll.html (original)
+++ rt/branches/rt-3.1/html/Ticket/ModifyAll.html Sat Jul 10 02:05:15 2004
@@ -78,6 +78,14 @@
<td class="label"><&|/l&>Subject</&>:</td>
<td class="entry"><input name="UpdateSubject" size=60 value="<%$Ticket->Subject%>"></td>
</tr>
+% if (my $TxnCFs = $Ticket->TransactionCustomFields) {
+% while (my $CF = $TxnCFs->Next()) {
+<TR>
+<TD class="label"><% $CF->Name %>:</TD>
+<TD class="entry"><& /Elements/EditCustomField, CustomField => $CF, NamePrefix => "TransactionCustomField-" &><em><% $CF->FriendlyType %></em></TD>
+</TD></TR>
+% } # end if while
+% } # end of if
<tr>
<td class="label"><&|/l&>Attach</&>:</td>
<td class="entry"><input name="UpdateAttachment" type=file></td>
@@ -115,7 +123,7 @@
unless ($OnlySearchForPeople) {
@wresults = ProcessTicketWatchers( TicketObj => $Ticket, ARGSRef => \%ARGS);
@results = ProcessTicketBasics( TicketObj => $Ticket, ARGSRef => \%ARGS);
- @cf_results = ProcessTicketCustomFieldUpdates( TicketObj => $Ticket, ARGSRef => \%ARGS);
+ @cf_results = ProcessObjectCustomFieldUpdates( Object => $Ticket, ARGSRef => \%ARGS);
@dresults = ProcessTicketDates( TicketObj => $Ticket, ARGSRef => \%ARGS);
@lresults = ProcessTicketLinks( TicketObj => $Ticket, ARGSRef => \%ARGS);
Modified: rt/branches/rt-3.1/html/Ticket/Update.html
==============================================================================
--- rt/branches/rt-3.1/html/Ticket/Update.html (original)
+++ rt/branches/rt-3.1/html/Ticket/Update.html Sat Jul 10 02:05:15 2004
@@ -78,6 +78,16 @@
</TR>
<TR>
% } # end of if
+
+% if (my $TxnCFs = $TicketObj->TransactionCustomFields) {
+% while (my $CF = $TxnCFs->Next()) {
+<TR>
+<TD ALIGN=RIGHT><% $CF->Name %>:</TD>
+<TD><& /Elements/EditCustomField, CustomField => $CF, NamePrefix => "TransactionCustomField-" &><em><% $CF->FriendlyType %></em></TD>
+</TD></TR>
+% } # end if while
+% } # end of if
+
<tr><td align=right><&|/l&>Attach</&>:</td><td><input name="Attach" type="file"><INPUT TYPE=SUBMIT NAME="AddMoreAttach" VALUE="<&|/l&>Add More Files</&>"><input type="hidden" name="UpdateAttach" value="1">
</td></tr>
<tr><td align="right" valign="top"><&|/l&>Message</&>:</td><td>
@@ -178,6 +188,7 @@
$m->comp('Display.html', TicketObj => $TicketObj, %ARGS);
return;
}
+
</%INIT>
<%ARGS>
Modified: rt/branches/rt-3.1/html/User/Prefs.html
==============================================================================
--- rt/branches/rt-3.1/html/User/Prefs.html (original)
+++ rt/branches/rt-3.1/html/User/Prefs.html Sat Jul 10 02:05:15 2004
@@ -188,9 +188,10 @@
Object => $UserObj,
ARGSRef => \%ARGS );
if ($Lang) {
- $session{'CurrentUser'}->LanguageHandle($Lang);
- $session{'CurrentUser'}= $session{'CurrentUser'}; # Force writeback
+ $session{'CurrentUser'}->LanguageHandle($Lang);
+ $session{'CurrentUser'} = $session{'CurrentUser'}; # force writeback
}
+
push (@results, at fieldresults);
Modified: rt/branches/rt-3.1/html/autohandler
==============================================================================
--- rt/branches/rt-3.1/html/autohandler (original)
+++ rt/branches/rt-3.1/html/autohandler Sat Jul 10 02:05:15 2004
@@ -147,7 +147,7 @@
elsif ($RT::WebFallbackToInternalAuth) {
unless (defined($session{'CurrentUser'})) {
$m->comp('/Elements/Login', %ARGS,
- Error=> loc('XXX CHANGEME You are not an authorized user'));
+ Error=> loc('You are not an authorized user'));
$m->abort();
}
} else {
Modified: rt/branches/rt-3.1/lib/RT.pm.in
==============================================================================
--- rt/branches/rt-3.1/lib/RT.pm.in (original)
+++ rt/branches/rt-3.1/lib/RT.pm.in Sat Jul 10 02:05:15 2004
@@ -131,7 +131,8 @@
$System = RT::System->new();
- InitLogging();
+ InitClasses();
+ InitLogging();
}
@@ -267,6 +268,29 @@
}
+=head2 InitClasses
+
+Load all modules that define base classes
+
+=cut
+sub InitClasses {
+ require RT::Tickets;
+ require RT::Transactions;
+ require RT::Users;
+ require RT::CurrentUser;
+ require RT::Templates;
+ require RT::Queues;
+ require RT::ScripActions;
+ require RT::ScripConditions;
+ require RT::Scrips;
+ require RT::Groups;
+ require RT::GroupMembers;
+ require RT::CustomFields;
+ require RT::CustomFieldValues;
+ require RT::ObjectCustomFields;
+ require RT::ObjectCustomFieldValues;
+}
+
# }}}
Modified: rt/branches/rt-3.1/lib/RT/Action/CreateTickets.pm
==============================================================================
--- rt/branches/rt-3.1/lib/RT/Action/CreateTickets.pm (original)
+++ rt/branches/rt-3.1/lib/RT/Action/CreateTickets.pm Sat Jul 10 02:05:15 2004
@@ -126,8 +126,8 @@
push (@admins, $admin->EmailAddress);
}
}
- Queue: Approvals
- Type: Approval
+ Queue: ___Approvals
+ Type: approval
AdminCc: {join ("\nAdminCc: ", at admins) }
Depended-On-By: TOP
Refers-To: TOP
@@ -142,7 +142,7 @@
Subject: Manager approval
Depended-On-By: TOP
Refers-On: {$Tickets{"approval"}->Id}
- Queue: Approvals
+ Queue: ___Approvals
Content-Type: text/plain
Content:
Your approval is requred for this ticket, too.
@@ -221,8 +221,8 @@
my $approvals =
'===Create-Ticket: approval
-Queue: Approvals
-Type: Approval
+Queue: ___Approvals
+Type: approval
AdminCc: {join ("\nAdminCc: ", at admins) }
Depended-On-By: {$Tickets{"TOP"}->Id}
Refers-To: TOP
@@ -236,7 +236,7 @@
===Create-Ticket: two
Subject: Manager approval.
Depended-On-By: approval
-Queue: Approvals
+Queue: ___Approvals
Content-Type: text/plain
Content:
Your minion approved ticket {$Tickets{"TOP"}->Id}. you ok with that?
Modified: rt/branches/rt-3.1/lib/RT/Attachment_Overlay.pm
==============================================================================
--- rt/branches/rt-3.1/lib/RT/Attachment_Overlay.pm (original)
+++ rt/branches/rt-3.1/lib/RT/Attachment_Overlay.pm Sat Jul 10 02:05:15 2004
@@ -212,26 +212,7 @@
sub Content {
my $self = shift;
- my $decode_utf8 = (($self->ContentType =~ qr{^text/plain}i) ? 1 : 0);
-
- if ( $self->ContentEncoding eq 'none' || ! $self->ContentEncoding ) {
- return $self->_Value(
- 'Content',
- decode_utf8 => $decode_utf8,
- );
- } elsif ( $self->ContentEncoding eq 'base64' ) {
- return ( $decode_utf8
- ? Encode::decode_utf8(MIME::Base64::decode_base64($self->_Value('Content')))
- : MIME::Base64::decode_base64($self->_Value('Content'))
- );
- } elsif ( $self->ContentEncoding eq 'quoted-printable' ) {
- return ( $decode_utf8
- ? Encode::decode_utf8(MIME::QuotedPrint::decode($self->_Value('Content')))
- : MIME::QuotedPrint::decode($self->_Value('Content'))
- );
- } else {
- return( $self->loc("Unknown ContentEncoding [_1]", $self->ContentEncoding));
- }
+ $self->_DecodeLOB($self->ContentType, $self->ContentEncoding, $self->_Value('Content', decode_utf8 => 0));
}
Modified: rt/branches/rt-3.1/lib/RT/Base.pm
==============================================================================
--- rt/branches/rt-3.1/lib/RT/Base.pm (original)
+++ rt/branches/rt-3.1/lib/RT/Base.pm Sat Jul 10 02:05:15 2004
@@ -103,6 +103,18 @@
}
}
+sub loc_fuzzy {
+ my $self = shift;
+ if (my $user = $self->OriginalUser) {
+ return $user->loc_fuzzy(@_);
+ }
+ else {
+ use Carp;
+ Carp::confess("No currentuser");
+ return ("Critical error:$self has no CurrentUser", $self);
+ }
+}
+
eval "require RT::Base_Vendor";
die $@ if ($@ && $@ !~ qr{^Can't locate RT/Base_Vendor.pm});
eval "require RT::Base_Local";
Modified: rt/branches/rt-3.1/lib/RT/CurrentUser.pm
==============================================================================
--- rt/branches/rt-3.1/lib/RT/CurrentUser.pm (original)
+++ rt/branches/rt-3.1/lib/RT/CurrentUser.pm Sat Jul 10 02:05:15 2004
@@ -328,12 +328,12 @@
=begin testing
ok (my $cu = RT::CurrentUser->new('root'));
-ok (my $lh = $cu->LanguageHandle);
+ok (my $lh = $cu->LanguageHandle('en-us'));
ok ($lh != undef);
ok ($lh->isa('Locale::Maketext'));
-ok ($cu->loc('TEST_STRING') eq "Concrete Mixer", "Localized TEST_STRING into English");
+is ($cu->loc('TEST_STRING'), "Concrete Mixer", "Localized TEST_STRING into English");
ok ($lh = $cu->LanguageHandle('fr'));
-ok ($cu->loc('Before') eq "Avant", "Localized TEST_STRING into Frenc");
+is ($cu->loc('Before'), "Avant", "Localized TEST_STRING into Frenc");
=end testing
@@ -401,6 +401,48 @@
}
+=head2 Authenticate
+
+Takes $password, $created and $nonce, and returns a boolean value
+representing whether the authentication succeeded.
+
+If both $nonce and $created are specified, validate $password against:
+
+ encode_base64(sha1(
+ $nonce .
+ $created .
+ sha1_hex( "$username:$realm:$server_pass" )
+ ))
+
+where $server_pass is the md5_hex(password) digest stored in the
+database, $created is in ISO time format, and $nonce is a random
+string no longer than 32 bytes.
+
+=cut
+
+sub Authenticate {
+ my ($self, $password, $created, $nonce, $realm) = @_;
+
+ require Digest::MD5;
+ require Digest::SHA1;
+ require MIME::Base64;
+
+ my $username = $self->UserObj->Name or return;
+ my $server_pass = $self->UserObj->__Value('Password') or return;
+ my $auth_digest = MIME::Base64::encode_base64(Digest::SHA1::sha1(
+ $nonce .
+ $created .
+ Digest::MD5::md5_hex("$username:$realm:$server_pass")
+ ));
+
+ chomp($password);
+ chomp($auth_digest);
+
+ return ($password eq $auth_digest);
+}
+
+# }}}
+
eval "require RT::CurrentUser_Vendor";
die $@ if ($@ && $@ !~ qr{^Can't locate RT/CurrentUser_Vendor.pm});
Modified: rt/branches/rt-3.1/lib/RT/CustomField.pm
==============================================================================
--- rt/branches/rt-3.1/lib/RT/CustomField.pm (original)
+++ rt/branches/rt-3.1/lib/RT/CustomField.pm Sat Jul 10 02:05:15 2004
@@ -46,7 +46,6 @@
package RT::CustomField;
use RT::Record;
-use RT::Queue;
use vars qw( @ISA );
@@ -69,9 +68,12 @@
varchar(200) 'Name'.
varchar(200) 'Type'.
- int(11) 'Queue'.
+ int(11) 'MaxValues'.
+ varchar(255) 'Pattern'.
+ smallint(6) 'Repeated'.
varchar(255) 'Description'.
int(11) 'SortOrder'.
+ varchar(255) 'LookupType'.
smallint(6) 'Disabled'.
=cut
@@ -84,18 +86,24 @@
my %args = (
Name => '',
Type => '',
- Queue => '0',
+ MaxValues => '',
+ Pattern => '',
+ Repeated => '0',
Description => '',
SortOrder => '0',
+ LookupType => '',
Disabled => '0',
@_);
$self->SUPER::Create(
Name => $args{'Name'},
Type => $args{'Type'},
- Queue => $args{'Queue'},
+ MaxValues => $args{'MaxValues'},
+ Pattern => $args{'Pattern'},
+ Repeated => $args{'Repeated'},
Description => $args{'Description'},
SortOrder => $args{'SortOrder'},
+ LookupType => $args{'LookupType'},
Disabled => $args{'Disabled'},
);
@@ -148,37 +156,59 @@
=cut
-=head2 Queue
+=head2 MaxValues
-Returns the current value of Queue.
-(In the database, Queue is stored as int(11).)
+Returns the current value of MaxValues.
+(In the database, MaxValues is stored as int(11).)
-=head2 SetQueue VALUE
+=head2 SetMaxValues VALUE
-Set Queue to VALUE.
+Set MaxValues to VALUE.
Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
-(In the database, Queue will be stored as a int(11).)
+(In the database, MaxValues will be stored as a int(11).)
=cut
-=head2 QueueObj
+=head2 Pattern
-Returns the Queue Object which has the id returned by Queue
+Returns the current value of Pattern.
+(In the database, Pattern is stored as varchar(255).)
+
+
+
+=head2 SetPattern VALUE
+
+
+Set Pattern to VALUE.
+Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
+(In the database, Pattern will be stored as a varchar(255).)
+
+
+=cut
+
+
+=head2 Repeated
+
+Returns the current value of Repeated.
+(In the database, Repeated is stored as smallint(6).)
+
+
+
+=head2 SetRepeated VALUE
+
+
+Set Repeated to VALUE.
+Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
+(In the database, Repeated will be stored as a smallint(6).)
=cut
-sub QueueObj {
- my $self = shift;
- my $Queue = RT::Queue->new($self->CurrentUser);
- $Queue->Load($self->__Value('Queue'));
- return($Queue);
-}
=head2 Description
@@ -216,6 +246,24 @@
=cut
+=head2 LookupType
+
+Returns the current value of LookupType.
+(In the database, LookupType is stored as varchar(255).)
+
+
+
+=head2 SetLookupType VALUE
+
+
+Set LookupType to VALUE.
+Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
+(In the database, LookupType will be stored as a varchar(255).)
+
+
+=cut
+
+
=head2 Creator
Returns the current value of Creator.
@@ -280,12 +328,18 @@
{read => 1, write => 1, type => 'varchar(200)', default => ''},
Type =>
{read => 1, write => 1, type => 'varchar(200)', default => ''},
- Queue =>
- {read => 1, write => 1, type => 'int(11)', default => '0'},
+ MaxValues =>
+ {read => 1, write => 1, type => 'int(11)', default => ''},
+ Pattern =>
+ {read => 1, write => 1, type => 'varchar(255)', default => ''},
+ Repeated =>
+ {read => 1, write => 1, type => 'smallint(6)', default => '0'},
Description =>
{read => 1, write => 1, type => 'varchar(255)', default => ''},
SortOrder =>
{read => 1, write => 1, type => 'int(11)', default => '0'},
+ LookupType =>
+ {read => 1, write => 1, type => 'varchar(255)', default => ''},
Creator =>
{read => 1, auto => 1, type => 'int(11)', default => '0'},
Created =>
Modified: rt/branches/rt-3.1/lib/RT/CustomField_Overlay.pm
==============================================================================
--- rt/branches/rt-3.1/lib/RT/CustomField_Overlay.pm (original)
+++ rt/branches/rt-3.1/lib/RT/CustomField_Overlay.pm Sat Jul 10 02:05:15 2004
@@ -24,24 +24,47 @@
use strict;
no warnings qw(redefine);
-use vars qw(@TYPES %TYPES);
+use vars qw(@TYPES %TYPES $RIGHTS %FRIENDLY_OBJECT_TYPES);
use RT::CustomFieldValues;
-use RT::TicketCustomFieldValues;
+use RT::ObjectCustomFieldValues;
# Enumerate all valid types for this custom field
@TYPES = (
- 'SelectSingle', # loc
- 'SelectMultiple', # loc
- 'FreeformSingle', # loc
- 'FreeformMultiple', # loc
+ 'Freeform', # loc
+ 'Select', # loc
+ 'Text', # loc
+ 'Image', # loc
+ 'Binary', # loc
);
# Populate a hash of types of easier validation
for (@TYPES) { $TYPES{$_} = 1};
+%FRIENDLY_OBJECT_TYPES = (
+ 'RT::Queue-RT::Ticket' => "Tickets", # loc
+ 'RT::Queue-RT::Ticket-RT::Transaction' => "Ticket Transactions", # loc
+ 'RT::User' => "Users", # loc
+ 'RT::Group' => "Groups", # loc
+);
+
+$RIGHTS = {
+ SeeCustomField => 'See custom fields', # loc_pair
+ AdminCustomField => 'Create, delete and modify custom fields', # loc_pair
+};
+
+# Tell RT::ACE that this sort of object can get acls granted
+$RT::ACE::OBJECT_TYPES{'RT::CustomField'} = 1;
+
+foreach my $right ( keys %{$RIGHTS} ) {
+ $RT::ACE::LOWERCASERIGHTNAMES{ lc $right } = $right;
+}
+sub AvailableRights {
+ my $self = shift;
+ return($RIGHTS);
+}
=head1 NAME
@@ -61,7 +84,8 @@
varchar(200) 'Name'.
varchar(200) 'Type'.
- int(11) 'Queue'.
+ int(11) 'MaxValues'.
+ varchar(255) 'Pattern'.
varchar(255) 'Description'.
int(11) 'SortOrder'.
smallint(6) 'Disabled'.
@@ -76,19 +100,31 @@
my %args = (
Name => '',
Type => '',
- Queue => '0',
+ MaxValues => '0',
+ Pattern => '',
Description => '',
- SortOrder => '0',
Disabled => '0',
+ LookupType => '',
+ Repeated => '0',
@_);
+ if ($args{TypeComposite}) {
+ @args{'Type', 'MaxValues'} = split(/-/, $args{TypeComposite}, 2);
+ }
+ elsif ($args{Type} =~ s/(?:(Single)|Multiple)$//) {
+ # old style Type string
+ $args{'MaxValues'} = $1 ? 1 : 0;
+ }
-
- if ( ! $args{'Queue'} ) {
- unless ( $self->CurrentUser->HasRight( Object => $RT::System, Right => 'AdminCustomFields') ) {
+ if ( !exists $args{'Queue'}) {
+ # do nothing -- things below are strictly backward compat
+ }
+ elsif ( ! $args{'Queue'} ) {
+ unless ( $self->CurrentUser->HasRight( Object => $RT::System, Right => 'AssignCustomFields') ) {
return ( 0, $self->loc('Permission Denied') );
}
+ $args{'LookupType'} = 'RT::Queue-RT::Ticket';
}
else {
my $queue = RT::Queue->new($self->CurrentUser);
@@ -96,19 +132,32 @@
unless ($queue->Id) {
return (0, $self->loc("Queue not found"));
}
- unless ( $queue->CurrentUserHasRight('AdminCustomFields') ) {
+ unless ( $queue->CurrentUserHasRight('AssignCustomFields') ) {
return ( 0, $self->loc('Permission Denied') );
}
+ $args{'LookupType'} = 'RT::Queue-RT::Ticket';
}
- $self->SUPER::Create(
+ my $rv = $self->SUPER::Create(
Name => $args{'Name'},
Type => $args{'Type'},
- Queue => $args{'Queue'},
+ MaxValues => $args{'MaxValues'},
+ Pattern => $args{'Pattern'},
Description => $args{'Description'},
- SortOrder => $args{'SortOrder'},
Disabled => $args{'Disabled'},
+ LookupType => $args{'LookupType'},
+ Repeated => $args{'Repeated'},
);
+ return $rv unless exists $args{'Queue'};
+
+ # Compat code -- create a new ObjectCustomField mapping
+ my $OCF = RT::ObjectCustomField->new($self->CurrentUser);
+ $OCF->Create(
+ CustomField => $self->Id,
+ ObjectId => $args{'Queue'},
+ );
+
+ return $rv;
}
@@ -138,7 +187,15 @@
$args{'Queue'} = $QueueObj->Id;
}
- return ( $self->LoadByCols( Name => $args{'Name'}, Queue => $args{'Queue'} ) );
+ # XXX - really naive implementation. Slow.
+
+ my $CFs = RT::CustomFields->new($self->CurrentUser);
+ $CFs->Limit( FIELD => 'Name', VALUE => $args{'Name'} );
+ $CFs->LimitToQueue( $args{'Queue'} );
+ $CFs->RowsPerPage(1);
+
+ my $CF = $CFs->First or return;
+ return $self->Load($CF->Id);
}
@@ -156,10 +213,12 @@
Type=> 'SelectSingle'), 'Created a global CustomField');
ok($id != 0, 'Global custom field correctly created');
ok ($cf->SingleValue);
-ok($cf->Type eq 'SelectSingle');
+is($cf->Type, 'Select');
+is($cf->MaxValues, 1);
ok($cf->SetType('SelectMultiple'));
-ok($cf->Type eq 'SelectMultiple');
+is($cf->Type, 'Select');
+is($cf->MaxValues, 0);
ok(!$cf->SingleValue );
ok(my ($bogus_val, $bogus_msg) = $cf->SetType('BogusType') , "Trying to set a custom field's type to a bogus type");
ok($bogus_val == 0, "Unable to set a custom field's type to a bogus type");
@@ -203,7 +262,7 @@
SortOrder => undef,
@_ );
- unless ($self->CurrentUserHasRight('AdminCustomFields')) {
+ unless ($self->CurrentUserHasRight('AdminCustomField')) {
return (0, $self->loc('Permission Denied'));
}
@@ -235,7 +294,7 @@
sub DeleteValue {
my $self = shift;
my $id = shift;
- unless ($self->CurrentUserHasRight('AdminCustomFields')) {
+ unless ($self->CurrentUserHasRight('AdminCustomField')) {
return (0, $self->loc('Permission Denied'));
}
@@ -271,12 +330,17 @@
my $self = shift;
my $cf_values = RT::CustomFieldValues->new($self->CurrentUser);
- if ( $self->__Value('Queue') == 0 || $self->CurrentUserHasRight( 'SeeQueue') ) {
+ if ( $self->CurrentUserHasRight( 'SeeCustomField') ) {
$cf_values->LimitToCustomField($self->Id);
}
return ($cf_values);
}
+sub ValuesObj {
+ my $self = shift;
+ return $self->Values(@_);
+}
+
# }}}
# }}}
@@ -287,7 +351,7 @@
=head2 ValuesForTicket TICKET
-Returns a RT::TicketCustomFieldValues object of this Field's values for TICKET.
+Returns a RT::ObjectCustomFieldValues object of this Field's values for TICKET.
TICKET is a ticket id.
@@ -297,7 +361,7 @@
my $self = shift;
my $ticket_id = shift;
- my $values = new RT::TicketCustomFieldValues($self->CurrentUser);
+ my $values = new RT::ObjectCustomFieldValues($self->CurrentUser);
$values->LimitToCustomField($self->Id);
$values->LimitToTicket($ticket_id);
@@ -320,8 +384,9 @@
Content => undef,
@_ );
- my $newval = RT::TicketCustomFieldValue->new($self->CurrentUser);
- my $val = $newval->Create(Ticket => $args{'Ticket'},
+ my $newval = RT::ObjectCustomFieldValue->new($self->CurrentUser);
+ my $val = $newval->Create(ObjectType => 'RT::Ticket',
+ ObjectId => $args{'Ticket'},
Content => $args{'Content'},
CustomField => $self->Id);
@@ -346,7 +411,7 @@
Content => undef,
@_ );
- my $oldval = RT::TicketCustomFieldValue->new($self->CurrentUser);
+ my $oldval = RT::ObjectCustomFieldValue->new($self->CurrentUser);
$oldval->LoadByTicketContentAndCustomField (Ticket => $args{'Ticket'},
Content => $args{'Content'},
CustomField => $self->Id );
@@ -408,35 +473,61 @@
# }}}
-=head2 FriendlyType [TYPE]
+=head2 FriendlyType [TYPE, MAX_VALUES]
Returns a localized human-readable version of the custom field type.
If a custom field type is specified as the parameter, the friendly type for that type will be returned
=cut
+my %FriendlyTypes = (
+ Select => [
+ 'Select multiple values', # loc
+ 'Select one value', # loc
+ 'Select up to [_1] values', # loc
+ ],
+ Freeform => [
+ 'Enter multiple values', # loc
+ 'Enter one value', # loc
+ 'Enter up to [_1] values', # loc
+ ],
+ Text => [
+ 'Fill in multiple text areas', # loc
+ 'Fill in one text area', # loc
+ 'Fill in up to [_1] text areas',# loc
+ ],
+ Image => [
+ 'Upload multiple images', # loc
+ 'Upload one image', # loc
+ 'Upload up to [_1] images', # loc
+ ],
+ Binary => [
+ 'Upload multiple files', # loc
+ 'Upload one file', # loc
+ 'Upload up to [_1] files', # loc
+ ],
+);
+
sub FriendlyType {
my $self = shift;
- my $type = shift || $self->Type;
+ my $type = @_ ? shift : $self->Type;
+ my $max = @_ ? shift : $self->MaxValues;
- if ( $type eq 'SelectSingle' ) {
- return ( $self->loc('Select one value') );
- }
- elsif ( $type eq 'SelectMultiple' ) {
- return ( $self->loc('Select multiple values') );
- }
- elsif ( $type eq 'FreeformSingle' ) {
- return ( $self->loc('Enter one value') );
- }
- elsif ( $type eq 'FreeformMultiple' ) {
- return ( $self->loc('Enter multiple values') );
+ if (my $friendly_type = $FriendlyTypes{$type}[$max>2 ? 2 : $max]) {
+ return ( $self->loc( $friendly_type, $max ) );
}
else {
- return ( $self->loc( $self->Type ) );
+ return ( $self->loc( $type ) );
}
}
+sub FriendlyTypeComposite {
+ my $self = shift;
+ my $composite = shift || $self->TypeComposite;
+ return $self->FriendlyType(split(/-/, $composite, 2));
+}
+
=head2 ValidateType TYPE
@@ -458,6 +549,10 @@
my $self = shift;
my $type = shift;
+ if ($type =~ s/(?:Single|Multiple)$//) {
+ warn "Prefix 'Single' and 'Multiple' to Type deprecated, use MaxValues instead";
+ }
+
if( $TYPES{$type}) {
return(1);
}
@@ -466,6 +561,17 @@
}
}
+
+sub SetType {
+ my $self = shift;
+ my $type = shift;
+ if ($type =~ s/(?:(Single)|Multiple)$//) {
+ warn "'Single' and 'Multiple' on SetType deprecated, use SetMaxValues instead";
+ $self->SetMaxValues($1 ? 1 : 0);
+ }
+ $self->SUPER::SetType($type);
+}
+
# {{{ SingleValue
=head2 SingleValue
@@ -477,7 +583,17 @@
sub SingleValue {
my $self = shift;
- if ($self->Type =~ /Single$/) {
+ if ($self->MaxValues == 1) {
+ return 1;
+ }
+ else {
+ return undef;
+ }
+}
+
+sub UnlimitedValues {
+ my $self = shift;
+ if ($self->MaxValues == 0) {
return 1;
}
else {
@@ -496,14 +612,13 @@
=cut
sub CurrentUserHasRight {
- my $self = shift;
+ my $self = shift;
my $right = shift;
- # if there's no queue, we want to know about a global right
- if ( ( !defined $self->__Value('Queue') ) || ( $self->__Value('Queue') == 0 ) ) {
- return $self->CurrentUser->HasRight( Object => $RT::System, Right => $right);
- } else {
- return ( $self->QueueObj->CurrentUserHasRight($right) );
- }
+
+ return $self->CurrentUser->HasRight(
+ Object => $self,
+ Right => $right,
+ );
}
# }}}
@@ -513,7 +628,7 @@
sub _Set {
my $self = shift;
- unless ( $self->CurrentUserHasRight('AdminCustomFields') ) {
+ unless ( $self->CurrentUserHasRight('AdminCustomField') ) {
return ( 0, $self->loc('Permission Denied') );
}
return ( $self->SUPER::_Set(@_) );
@@ -536,16 +651,10 @@
my $self = shift;
my $field = shift;
- # We need to expose the queue so that we can do things like ACL checks
- if ( $field eq 'Queue') {
- return ( $self->SUPER::_Value($field) );
- }
-
-
- #Anybody can see global custom fields, otherwise we need to do the rights check
- unless ( $self->__Value('Queue') == 0 || $self->CurrentUserHasRight( 'SeeQueue') ) {
- return (undef);
- }
+ # we need to do the rights check
+ unless ( $self->CurrentUserHasRight( 'SeeCustomField') ) {
+ return (undef);
+ }
return ( $self->__Value($field) );
}
@@ -563,4 +672,212 @@
# }}}
+sub Queue {
+ return 0;
+}
+
+sub SetQueue {
+ return 0;
+}
+
+sub QueueObj {
+ return undef;
+}
+
+sub SetTypeComposite {
+ my $self = shift;
+ my $composite = shift;
+ my ($type, $max_values) = split(/-/, $composite, 2);
+ $self->SetType($type);
+ $self->SetMaxValues($max_values);
+}
+
+sub SetLookupType {
+ my $self = shift;
+ my $lookup = shift;
+ if ($lookup ne $self->LookupType) {
+ # Okay... We need to invalidate our existing relationships
+ my $ObjectCustomFields = RT::ObjectCustomFields->new($self->CurrentUser);
+ $ObjectCustomFields->LimitToCustomField($self->Id);
+ $_->Delete foreach @{$ObjectCustomFields->ItemsArrayRef};
+ }
+ $self->SUPER::SetLookupType($lookup);
+}
+
+sub TypeComposite {
+ my $self = shift;
+ join('-', $self->Type, $self->MaxValues);
+}
+
+sub TypeComposites {
+ my $self = shift;
+ return grep !/Text-0/, map { ("$_-1", "$_-0") } $self->Types;
+}
+
+sub LookupTypes {
+ my $self = shift;
+ qw(
+ RT::Queue-RT::Ticket
+ RT::Queue-RT::Ticket-RT::Transaction
+ RT::User
+ RT::Group
+ );
+}
+
+my @FriendlyObjectTypes = (
+ "[_1] objects", # loc
+ "[_1]'s [_2] objects", # loc
+ "[_1]'s [_2]'s [_3] objects", # loc
+);
+
+sub FriendlyLookupType {
+ my $self = shift;
+ my $lookup = shift || $self->LookupType;
+
+ return ($self->loc( $FRIENDLY_OBJECT_TYPES{$lookup} ))
+ if (defined $FRIENDLY_OBJECT_TYPES{$lookup} );
+
+ my @types = map { s/^RT::// ? $self->loc($_) : $_ }
+ grep { defined and length }
+ split( /-/, $lookup )
+ or return;
+ return ( $self->loc( $FriendlyObjectTypes[$#types], @types ) );
+}
+
+sub AddToObject {
+ my $self = shift;
+ my $object = shift;
+ my $id = $object->Id || 0;
+
+ unless (index($self->LookupType, ref($object)) == 0) {
+ return ( 0, $self->loc('Lookup type mismatch') );
+ }
+
+ unless ( $object->CurrentUserHasRight('AssignCustomFields') ) {
+ return ( 0, $self->loc('Permission Denied') );
+ }
+
+ my $ObjectCF = RT::ObjectCustomField->new( $self->CurrentUser );
+
+ $ObjectCF->LoadByCols( ObjectId => $id, CustomField => $self->Id );
+ if ( $ObjectCF->Id ) {
+ return ( 0, $self->loc("That is already the current value") );
+ }
+ my ( $id, $msg ) =
+ $ObjectCF->Create( ObjectId => $id, CustomField => $self->Id );
+
+ return ( $id, $msg );
+}
+
+sub RemoveFromObject {
+ my $self = shift;
+ my $object = shift;
+ my $id = $object->Id || 0;
+
+ unless (index($self->LookupType, ref($object)) == 0) {
+ return ( 0, $self->loc('Object type mismatch') );
+ }
+
+ unless ( $object->CurrentUserHasRight('AssignCustomFields') ) {
+ return ( 0, $self->loc('Permission Denied') );
+ }
+
+ my $ObjectCF = RT::ObjectCustomField->new( $self->CurrentUser );
+
+ $ObjectCF->LoadByCols( ObjectId => $id, CustomField => $self->Id );
+ unless ( $ObjectCF->Id ) {
+ return ( 0, $self->loc("This custom field does not apply to that object") );
+ }
+ my ( $id, $msg ) = $ObjectCF->Delete;
+
+ return ( $id, $msg );
+}
+
+# {{{ AddValueForObject
+
+=head2 AddValueForObject HASH
+
+Adds a custom field value for a ticket. Takes a param hash of Object and Content
+
+=cut
+
+sub AddValueForObject {
+ my $self = shift;
+ my %args = ( Object => undef,
+ Content => undef,
+ LargeContent => undef,
+ ContentType => undef,
+ @_ );
+ my $obj = $args{'Object'} or return;
+
+ my $newval = RT::ObjectCustomFieldValue->new($self->CurrentUser);
+ my $val = $newval->Create(ObjectType => ref($obj),
+ ObjectId => $obj->Id,
+ Content => $args{'Content'},
+ LargeContent => $args{'LargeContent'},
+ ContentType => $args{'ContentType'},
+ CustomField => $self->Id);
+
+ return($val);
+
+}
+
+
+# }}}
+
+# {{{ DeleteValueForObject
+
+=head2 DeleteValueForObject HASH
+
+Adds a custom field value for a ticket. Takes a param hash of Object and Content
+
+=cut
+
+sub DeleteValueForObject {
+ my $self = shift;
+ my %args = ( Object => undef,
+ Content => undef,
+ Id => undef,
+ @_ );
+
+ my $oldval = RT::ObjectCustomFieldValue->new($self->CurrentUser);
+
+ if (my $id = $args{'Id'}) {
+ $oldval->Load($id);
+ }
+ else {
+ $oldval->LoadByObjectContentAndCustomField(
+ Object => $args{'Object'},
+ Content => $args{'Content'},
+ CustomField => $self->Id
+ );
+ }
+
+ # check ot make sure we found it
+ unless ($oldval->Id) {
+ return(0, $self->loc("Custom field value [_1] could not be found for custom field [_2]", $args{'Content'}, $self->Name));
+ }
+ # delete it
+
+ my $ret = $oldval->Delete();
+ unless ($ret) {
+ return(0, $self->loc("Custom field value could not be found"));
+ }
+ return($oldval->Id, $self->loc("Custom field value deleted"));
+}
+
+sub ValuesForObject {
+ my $self = shift;
+ my $object = shift;
+
+ my $values = new RT::ObjectCustomFieldValues($self->CurrentUser);
+ $values->LimitToCustomField($self->Id);
+ $values->LimitToObject($object);
+
+ return ($values);
+}
+
+
+# }}}
+
1;
Modified: rt/branches/rt-3.1/lib/RT/CustomFields_Overlay.pm
==============================================================================
--- rt/branches/rt-3.1/lib/RT/CustomFields_Overlay.pm (original)
+++ rt/branches/rt-3.1/lib/RT/CustomFields_Overlay.pm Sat Jul 10 02:05:15 2004
@@ -46,6 +46,12 @@
no warnings qw(redefine);
+sub _OCFAlias {
+ my $self = shift;
+ $self->{_sql_ocfalias} ||= $self->NewAlias('ObjectCustomFields');
+}
+
+
# {{{ sub LimitToGlobalOrQueue
=item LimitToGlobalOrQueue QUEUEID
@@ -57,8 +63,8 @@
sub LimitToGlobalOrQueue {
my $self = shift;
my $queue = shift;
- $self->LimitToQueue($queue);
- $self->LimitToGlobal();
+ $self->LimitToGlobalOrObjectId( $queue );
+ $self->LimitToLookupType( 'RT::Queue-RT::Ticket' );
}
# }}}
@@ -77,11 +83,12 @@
my $self = shift;
my $queue = shift;
- $self->Limit (ENTRYAGGREGATOR => 'OR',
- FIELD => 'Queue',
+ $self->Limit (ALIAS => $self->_OCFAlias,
+ ENTRYAGGREGATOR => 'OR',
+ FIELD => 'ObjectId',
VALUE => "$queue")
if defined $queue;
-
+ $self->LimitToLookupType( 'RT::Queue-RT::Ticket' );
}
# }}}
@@ -99,13 +106,24 @@
sub LimitToGlobal {
my $self = shift;
- $self->Limit (ENTRYAGGREGATOR => 'OR',
- FIELD => 'Queue',
+ $self->Limit (ALIAS => $self->_OCFAlias,
+ ENTRYAGGREGATOR => 'OR',
+ FIELD => 'ObjectId',
VALUE => 0);
-
+ $self->LimitToLookupType( 'RT::Queue-RT::Ticket' );
}
# }}}
+sub LimitToObjectType {
+ my $self = shift;
+ my $type = shift;
+
+ return if $self->{_sql_limit_objectype}{$type}++;
+ $self->Limit (ALIAS => $self->_OCFAlias,
+ ENTRYAGGREGATOR => 'OR',
+ FIELD => 'ObjectType',
+ VALUE => $type);
+}
# {{{ sub _DoSearch
@@ -130,6 +148,95 @@
}
# }}}
+
+# {{{ sub Next
+
+=head2 Next
+
+Returns the next custom field that this user can see.
+
+=cut
+
+sub Next {
+ my $self = shift;
+
+
+ my $CF = $self->SUPER::Next();
+ if ((defined($CF)) and (ref($CF))) {
+
+ if ($CF->CurrentUserHasRight('SeeCustomField')) {
+ return($CF);
+ }
+
+ #If the user doesn't have the right to show this queue
+ else {
+ return($self->Next());
+ }
+ }
+ #if there never was any queue
+ else {
+ return(undef);
+ }
+
+}
+# }}}
+
+sub LimitToLookupType {
+ my $self = shift;
+ my $lookup = shift;
+
+ $self->Limit( FIELD => 'LookupType', VALUE => "$lookup" );
+}
+
+sub LimitToChildType {
+ my $self = shift;
+ my $lookup = shift;
+
+ $self->Limit( FIELD => 'LookupType', VALUE => "$lookup" );
+ $self->Limit( FIELD => 'LookupType', ENDSWITH => "$lookup" );
+}
+
+sub LimitToParentType {
+ my $self = shift;
+ my $lookup = shift;
+
+ $self->Limit( FIELD => 'LookupType', VALUE => "$lookup" );
+ $self->Limit( FIELD => 'LookupType', STARTSWITH => "$lookup" );
+}
+
+sub LimitToGlobalOrObjectId {
+ my $self = shift;
+ my $global_only = 1;
+
+ $self->Join( ALIAS1 => 'main',
+ FIELD1 => 'id',
+ ALIAS2 => $self->_OCFAlias,
+ FIELD2 => 'CustomField' );
+
+ foreach my $id (@_) {
+ $self->Limit( ALIAS => $self->_OCFAlias,
+ FIELD => 'ObjectId',
+ OPERATOR => '=',
+ VALUE => $id || 0,
+ ENTRYAGGREGATOR => 'OR' );
+ $global_only = 0 if $id;
+ }
+
+ $self->Limit( ALIAS => $self->_OCFAlias,
+ FIELD => 'ObjectId',
+ OPERATOR => '=',
+ VALUE => 0,
+ ENTRYAGGREGATOR => 'OR' ) unless $global_only;
+
+ $self->OrderByCols(
+ { ALIAS => $self->_OCFAlias, FIELD => 'ObjectId' },
+ { ALIAS => $self->_OCFAlias, FIELD => 'SortOrder' },
+ );
+
+ # This doesn't work on postgres.
+ #$self->OrderBy( ALIAS => $class_cfs , FIELD => "SortOrder", ORDER => 'ASC');
+
+}
1;
Modified: rt/branches/rt-3.1/lib/RT/Group_Overlay.pm
==============================================================================
--- rt/branches/rt-3.1/lib/RT/Group_Overlay.pm (original)
+++ rt/branches/rt-3.1/lib/RT/Group_Overlay.pm Sat Jul 10 02:05:15 2004
@@ -447,6 +447,7 @@
Type => undef,
Instance => '0',
InsideTransaction => undef,
+ _RecordTransaction => 1,
@_
);
@@ -492,8 +493,12 @@
$cgm->Create(Group =>$self->PrincipalObj, Member => $self->PrincipalObj, ImmediateParent => $self->PrincipalObj);
+ if ( $args{'_RecordTransaction'} ) {
+ $self->_NewTransaction( Type => "Create" );
+ }
$RT::Handle->Commit() unless ($args{'InsideTransaction'});
+
return ( $id, $self->loc("Group created") );
}
@@ -1148,6 +1153,13 @@
# {{{ sub _Set
sub _Set {
my $self = shift;
+ my %args = (
+ Field => undef,
+ Value => undef,
+ TransactionType => 'Set',
+ RecordTransaction => 1,
+ @_
+ );
if ($self->Domain eq 'Personal') {
if ($self->CurrentUser->PrincipalId == $self->Instance) {
@@ -1165,7 +1177,30 @@
return ( 0, $self->loc('Permission Denied') );
}
}
- return ( $self->SUPER::_Set(@_) );
+
+ my $Old = $self->SUPER::_Value("$args{'Field'}");
+
+ my ($ret, $msg) = $self->SUPER::_Set( Field => $args{'Field'},
+ Value => $args{'Value'} );
+
+ #If we can't actually set the field to the value, don't record
+ # a transaction. instead, get out of here.
+ if ( $ret == 0 ) { return ( 0, $msg ); }
+
+ if ( $args{'RecordTransaction'} == 1 ) {
+
+ my ( $Trans, $Msg, $TransObj ) = $self->_NewTransaction(
+ Type => $args{'TransactionType'},
+ Field => $args{'Field'},
+ NewValue => $args{'Value'},
+ OldValue => $Old,
+ TimeTaken => $args{'TimeTaken'},
+ );
+ return ( $Trans, scalar $TransObj->Description );
+ }
+ else {
+ return ( $ret, $msg );
+ }
}
# }}}
@@ -1253,5 +1288,13 @@
}
# }}}
+
+sub BasicColumns {
+ (
+ [ Name => 'Name' ],
+ [ Description => 'Description' ],
+ );
+}
+
1;
Modified: rt/branches/rt-3.1/lib/RT/Groups_Overlay.pm
==============================================================================
--- rt/branches/rt-3.1/lib/RT/Groups_Overlay.pm (original)
+++ rt/branches/rt-3.1/lib/RT/Groups_Overlay.pm Sat Jul 10 02:05:15 2004
@@ -123,8 +123,7 @@
$self->Limit(FIELD => 'Domain', OPERATOR => '=', VALUE => 'Personal');
$self->Limit( FIELD => 'Instance',
OPERATOR => '=',
- VALUE => $princ,
- ENTRY_AGGREGATOR => 'OR');
+ VALUE => $princ);
}
Modified: rt/branches/rt-3.1/lib/RT/I18N.pm
==============================================================================
--- rt/branches/rt-3.1/lib/RT/I18N.pm (original)
+++ rt/branches/rt-3.1/lib/RT/I18N.pm Sat Jul 10 02:05:15 2004
@@ -76,9 +76,11 @@
=cut
sub Init {
+ require File::Glob;
+
# Load language-specific functions
- foreach my $language ( glob(substr(__FILE__, 0, -3) . "/*.pm")) {
- if ($language =~ /^([-\w.\/\\~:]+)$/) {
+ foreach my $language ( File::Glob::bsd_glob(substr(__FILE__, 0, -3) . "/*.pm")) {
+ if ($language =~ /^([-\w\s.\/\\~:]+)$/) {
require $1;
}
else {
@@ -95,6 +97,7 @@
$_ => [
Gettext => (substr(__FILE__, 0, -3) . "/$_.po"),
Gettext => "$RT::LocalLexiconPath/*/$_.po",
+ Gettext => "$RT::LocalLexiconPath/$_.po",
],
} @lang
});
Modified: rt/branches/rt-3.1/lib/RT/I18N/cs.po
==============================================================================
--- rt/branches/rt-3.1/lib/RT/I18N/cs.po (original)
+++ rt/branches/rt-3.1/lib/RT/I18N/cs.po Sat Jul 10 02:05:15 2004
@@ -16,7 +16,7 @@
#: NOT FOUND IN SOURCE
msgid "#%1"
-msgstr "#%1"
+msgstr "#%1"
#: html/Approvals/Elements/Approve:26 html/Approvals/Elements/ShowDependency:49 html/SelfService/Display.html:24 html/Ticket/Display.html:25 html/Ticket/Display.html:29
#. ($TicketObj->Id, $TicketObj->Subject)
Modified: rt/branches/rt-3.1/lib/RT/I18N/de.po
==============================================================================
--- rt/branches/rt-3.1/lib/RT/I18N/de.po (original)
+++ rt/branches/rt-3.1/lib/RT/I18N/de.po Sat Jul 10 02:05:15 2004
@@ -344,7 +344,7 @@
msgstr ""
#: html/Ticket/Create.html:178
-msgid "(Enter ticket ids or URLs, separated with spaces)"
+msgid "(Enter ticket ids or URLs, seperated with spaces)"
msgstr "(Gib Anfragenummern oder URLs getrennt durch Leerzeichen ein)"
#: NOT FOUND IN SOURCE
Modified: rt/branches/rt-3.1/lib/RT/I18N/en.po
==============================================================================
--- rt/branches/rt-3.1/lib/RT/I18N/en.po (original)
+++ rt/branches/rt-3.1/lib/RT/I18N/en.po Sat Jul 10 02:05:15 2004
@@ -58,7 +58,7 @@
msgid "Open it"
msgstr "Open"
-#: html/Admin/Users/Modify.html:156 html/User/Prefs.html:63
+#: html/Admin/Users/Modify.html:163 html/User/Prefs.html:63
msgid "Residence"
msgstr "Home"
Modified: rt/branches/rt-3.1/lib/RT/I18N/es.po
==============================================================================
--- rt/branches/rt-3.1/lib/RT/I18N/es.po (original)
+++ rt/branches/rt-3.1/lib/RT/I18N/es.po Sat Jul 10 02:05:15 2004
@@ -357,7 +357,7 @@
msgstr ""
#: html/Ticket/Create.html:178
-msgid "(Enter ticket ids or URLs, separated with spaces)"
+msgid "(Enter ticket ids or URLs, seperated with spaces)"
msgstr "(Introduzca los identificadores de ticket o URLs, separados por espacios)"
#: NOT FOUND IN SOURCE
Modified: rt/branches/rt-3.1/lib/RT/I18N/fr.po
==============================================================================
--- rt/branches/rt-3.1/lib/RT/I18N/fr.po (original)
+++ rt/branches/rt-3.1/lib/RT/I18N/fr.po Sat Jul 10 02:05:15 2004
@@ -379,7 +379,7 @@
msgstr "(Cocher les cases pour activer les notifications aux destinataires listés)"
#: html/Ticket/Create.html:178
-msgid "(Enter ticket ids or URLs, separated with spaces)"
+msgid "(Enter ticket ids or URLs, seperated with spaces)"
msgstr "(Entrer les numéros de tickets ou les URLs, séparés par des espaces)"
#: NOT FOUND IN SOURCE
Modified: rt/branches/rt-3.1/lib/RT/I18N/he.po
==============================================================================
--- rt/branches/rt-3.1/lib/RT/I18N/he.po (original)
+++ rt/branches/rt-3.1/lib/RT/I18N/he.po Sat Jul 10 02:05:15 2004
@@ -442,7 +442,7 @@
msgstr ""
#: html/Ticket/Create.html:178
-msgid "(Enter ticket ids or URLs, separated with spaces)"
+msgid "(Enter ticket ids or URLs, seperated with spaces)"
msgstr ""
#: NOT FOUND IN SOURCE
Modified: rt/branches/rt-3.1/lib/RT/I18N/it.po
==============================================================================
--- rt/branches/rt-3.1/lib/RT/I18N/it.po (original)
+++ rt/branches/rt-3.1/lib/RT/I18N/it.po Sat Jul 10 02:05:15 2004
@@ -440,7 +440,7 @@
msgstr ""
#: html/Ticket/Create.html:178
-msgid "(Enter ticket ids or URLs, separated with spaces)"
+msgid "(Enter ticket ids or URLs, seperated with spaces)"
msgstr "(Inserire il numero di tickets o gli URL, separati da spazi)"
#: NOT FOUND IN SOURCE
Modified: rt/branches/rt-3.1/lib/RT/I18N/ja.po
==============================================================================
--- rt/branches/rt-3.1/lib/RT/I18N/ja.po (original)
+++ rt/branches/rt-3.1/lib/RT/I18N/ja.po Sat Jul 10 02:05:15 2004
@@ -446,7 +446,7 @@
msgstr ""
#: html/Ticket/Create.html:178
-msgid "(Enter ticket ids or URLs, separated with spaces)"
+msgid "(Enter ticket ids or URLs, seperated with spaces)"
msgstr "(チケットIDまたはURLsを空欄で区切って入力してください)"
#: NOT FOUND IN SOURCE
Modified: rt/branches/rt-3.1/lib/RT/I18N/nl.po
==============================================================================
--- rt/branches/rt-3.1/lib/RT/I18N/nl.po (original)
+++ rt/branches/rt-3.1/lib/RT/I18N/nl.po Sat Jul 10 02:05:15 2004
@@ -440,7 +440,7 @@
msgstr ""
#: html/Ticket/Create.html:178
-msgid "(Enter ticket ids or URLs, separated with spaces)"
+msgid "(Enter ticket ids or URLs, seperated with spaces)"
msgstr "(Vul ticket ids of URLs in, gescheiden door spaties)"
#: NOT FOUND IN SOURCE
Modified: rt/branches/rt-3.1/lib/RT/I18N/pt_br.po
==============================================================================
--- rt/branches/rt-3.1/lib/RT/I18N/pt_br.po (original)
+++ rt/branches/rt-3.1/lib/RT/I18N/pt_br.po Sat Jul 10 02:05:15 2004
@@ -445,7 +445,7 @@
msgstr ""
#: html/Ticket/Create.html:178
-msgid "(Enter ticket ids or URLs, separated with spaces)"
+msgid "(Enter ticket ids or URLs, seperated with spaces)"
msgstr "(Entre com identificadores de tíquetes ou URLs, separados por espaços)"
#: NOT FOUND IN SOURCE
Modified: rt/branches/rt-3.1/lib/RT/I18N/ru.po
==============================================================================
--- rt/branches/rt-3.1/lib/RT/I18N/ru.po (original)
+++ rt/branches/rt-3.1/lib/RT/I18N/ru.po Sat Jul 10 02:05:15 2004
@@ -442,7 +442,7 @@
msgstr ""
#: html/Ticket/Create.html:178
-msgid "(Enter ticket ids or URLs, separated with spaces)"
+msgid "(Enter ticket ids or URLs, seperated with spaces)"
msgstr "(Введите номера или ссылки на тикеты. Несколько тикетов разделяются пробелами.)"
#: NOT FOUND IN SOURCE
Modified: rt/branches/rt-3.1/lib/RT/Interface/Web.pm
==============================================================================
--- rt/branches/rt-3.1/lib/RT/Interface/Web.pm (original)
+++ rt/branches/rt-3.1/lib/RT/Interface/Web.pm Sat Jul 10 02:05:15 2004
@@ -462,6 +462,7 @@
TimeTaken => $args{ARGSRef}->{'UpdateTimeWorked'}
);
push ( @{ $args{Actions} }, $Description );
+ $Object->UpdateCustomFields( ARGSRef => $args{ARGSRef} ) if $Object;
}
elsif ( $args{ARGSRef}->{'UpdateType'} eq 'response' ) {
my ( $Transaction, $Description, $Object ) = $args{TicketObj}->Correspond(
@@ -471,6 +472,7 @@
TimeTaken => $args{ARGSRef}->{'UpdateTimeWorked'}
);
push ( @{ $args{Actions} }, $Description );
+ $Object->UpdateCustomFields( ARGSRef => $args{ARGSRef} ) if $Object;
}
else {
push ( @{ $args{'Actions'} },
@@ -1070,112 +1072,145 @@
# }}}
-# {{{ Sub ProcessTicketCustomFieldUpdates
-
sub ProcessTicketCustomFieldUpdates {
- my %args = (
- ARGSRef => undef,
- @_
- );
+ my %args = @_;
+ $args{'Object'} = delete $args{'TicketObj'};
+ my $ARGSRef = { %{ $args{'ARGSRef'} } };
- my @results;
+ # Build up a list of objects that we want to work with
+ my %custom_fields_to_mod;
+ foreach my $arg ( keys %$ARGSRef ) {
+ if ( $arg =~ /^Ticket-(\d+-.*)/) {
+ $ARGSRef->{"Object-RT::Ticket-$1"} = delete $ARGSRef->{$arg};
+ }
+ elsif ( $arg =~ /^CustomField-(\d+-.*)/) {
+ $ARGSRef->{"Object-RT::Ticket--$1"} = delete $ARGSRef->{$arg};
+ }
+ }
+ return ProcessObjectCustomFieldUpdates(%args, ARGSRef => $ARGSRef);
+}
+
+sub ProcessObjectCustomFieldUpdates {
+ my %args = @_;
my $ARGSRef = $args{'ARGSRef'};
+ my @results;
- # Build up a list of tickets that we want to work with
- my %tickets_to_mod;
+ # Build up a list of objects that we want to work with
my %custom_fields_to_mod;
- foreach my $arg ( keys %{$ARGSRef} ) {
- if ( $arg =~ /^Ticket-(\d+)-CustomField-(\d+)-/ ) {
-
- # For each of those tickets, find out what custom fields we want to work with.
- $custom_fields_to_mod{$1}{$2} = 1;
+ foreach my $arg ( keys %$ARGSRef ) {
+ if ( $arg =~ /^Object-([\w:]+)-(\d*)-CustomField-(\d+)-/ ) {
+ # For each of those objects, find out what custom fields we want to work with.
+ $custom_fields_to_mod{$1}{$2 || $args{'Object'}->Id}{$3} = 1;
}
}
- # For each of those tickets
- foreach my $tick ( keys %custom_fields_to_mod ) {
- my $Ticket = $args{'TicketObj'};
- if (!$Ticket or $Ticket->id != $tick) {
- $Ticket = RT::Ticket->new( $session{'CurrentUser'} );
- $Ticket->Load($tick);
+ # For each of those objects
+ foreach my $class ( keys %custom_fields_to_mod ) {
+ foreach my $id ( keys %{$custom_fields_to_mod{$class}} ) {
+ my $Object = $args{'Object'};
+ if (!$Object or ref($Object) ne $class or $Object->id != $id) {
+ $Object = $class->new( $session{'CurrentUser'} );
+ $Object->Load($id);
}
- # For each custom field
- foreach my $cf ( keys %{ $custom_fields_to_mod{$tick} } ) {
-
+ # For each custom field
+ foreach my $cf ( keys %{ $custom_fields_to_mod{$class}{$id} } ) {
my $CustomFieldObj = RT::CustomField->new($session{'CurrentUser'});
$CustomFieldObj->LoadById($cf);
- foreach my $arg ( keys %{$ARGSRef} ) {
- # since http won't pass in a form element with a null value, we need
- # to fake it
- if ($arg =~ /^(.*?)-Values-Magic$/ ) {
- # We don't care about the magic, if there's really a values element;
- next if (exists $ARGSRef->{$1.'-Values'}) ;
-
- $arg = $1."-Values";
- $ARGSRef->{$1."-Values"} = undef;
-
- }
- next unless ( $arg =~ /^Ticket-$tick-CustomField-$cf-/ );
- my @values =
- ( ref( $ARGSRef->{$arg} ) eq 'ARRAY' )
- ? @{ $ARGSRef->{$arg} }
- : split /\n/, $ARGSRef->{$arg} ;
- if ( ( $arg =~ /-AddValue$/ ) || ( $arg =~ /-Value$/ ) ) {
- foreach my $value (@values) {
- next unless length($value);
- my ( $val, $msg ) = $Ticket->AddCustomFieldValue(
- Field => $cf,
- Value => $value
- );
- push ( @results, $msg );
- }
- }
- elsif ( $arg =~ /-DeleteValues$/ ) {
- foreach my $value (@values) {
- next unless length($value);
- my ( $val, $msg ) = $Ticket->DeleteCustomFieldValue(
- Field => $cf,
- Value => $value
- );
- push ( @results, $msg );
- }
- }
- elsif ( $arg =~ /-Values$/ and $CustomFieldObj->Type !~ /Entry/) {
- my $cf_values = $Ticket->CustomFieldValues($cf);
-
- my %values_hash;
- foreach my $value (@values) {
- next unless length($value);
-
- # build up a hash of values that the new set has
- $values_hash{$value} = 1;
-
- unless ( $cf_values->HasEntry($value) ) {
- my ( $val, $msg ) = $Ticket->AddCustomFieldValue(
- Field => $cf,
- Value => $value
- );
- push ( @results, $msg );
- }
-
- }
- while ( my $cf_value = $cf_values->Next ) {
- unless ( $values_hash{ $cf_value->Content } == 1 ) {
- my ( $val, $msg ) = $Ticket->DeleteCustomFieldValue(
- Field => $cf,
- Value => $cf_value->Content
- );
- push ( @results, $msg);
-
- }
-
- }
- }
- elsif ( $arg =~ /-Values$/ ) {
- my $cf_values = $Ticket->CustomFieldValues($cf);
+ foreach my $arg ( keys %{$ARGSRef} ) {
+ # since http won't pass in a form element with a null value, we need
+ # to fake it
+ if ($arg =~ /^(.*?)-Values-Magic$/ ) {
+ # We don't care about the magic, if there's really a values element;
+ next if (exists $ARGSRef->{$1.'-Values'}) ;
+
+ $arg = $1."-Values";
+ $ARGSRef->{$1."-Values"} = undef;
+
+ }
+ next unless ( $arg =~ /^Object-$class-(?:$id)?-CustomField-$cf-/ );
+ my @values =
+ ( ref( $ARGSRef->{$arg} ) eq 'ARRAY' )
+ ? @{ $ARGSRef->{$arg} }
+ : split /\n/, $ARGSRef->{$arg} ;
+ if ( ( $arg =~ /-AddValue$/ ) || ( $arg =~ /-Value$/ ) ) {
+ foreach my $value (@values) {
+ next unless length($value);
+ my ( $val, $msg ) = $Object->AddCustomFieldValue(
+ Field => $cf,
+ Value => $value
+ );
+ push ( @results, $msg );
+ }
+ }
+ elsif ( $arg =~ /-Upload$/ ) {
+ my $cgi_object = $m->cgi_object;
+ my $fh = $cgi_object->upload($arg) or next;
+ my $upload_info = $cgi_object->uploadInfo($fh);
+ my $filename = "$fh";
+ $filename =~ s#^.*[\\/]##;
+ my ( $val, $msg ) = $Object->AddCustomFieldValue(
+ Field => $cf,
+ Value => $filename,
+ LargeContent => do { local $/; scalar <$fh> },
+ ContentType => $upload_info->{'Content-Type'},
+ );
+ push ( @results, $msg );
+ }
+ elsif ( $arg =~ /-DeleteValues$/ ) {
+ foreach my $value (@values) {
+ next unless length($value);
+ my ( $val, $msg ) = $Object->DeleteCustomFieldValue(
+ Field => $cf,
+ Value => $value
+ );
+ push ( @results, $msg );
+ }
+ }
+ elsif ( $arg =~ /-DeleteValueIds$/ ) {
+ foreach my $value (@values) {
+ next unless length($value);
+ my ( $val, $msg ) = $Object->DeleteCustomFieldValue(
+ Field => $cf,
+ ValueId => $value,
+ );
+ push ( @results, $msg );
+ }
+ }
+ elsif ( $arg =~ /-Values$/ and !$CustomFieldObj->Repeated) {
+ my $cf_values = $Object->CustomFieldValues($cf);
+
+ my %values_hash;
+ foreach my $value (@values) {
+ next unless length($value);
+
+ # build up a hash of values that the new set has
+ $values_hash{$value} = 1;
+
+ unless ( $cf_values->HasEntry($value) ) {
+ my ( $val, $msg ) = $Object->AddCustomFieldValue(
+ Field => $cf,
+ Value => $value
+ );
+ push ( @results, $msg );
+ }
+
+ }
+ while ( my $cf_value = $cf_values->Next ) {
+ unless ( $values_hash{ $cf_value->Content } == 1 ) {
+ my ( $val, $msg ) = $Object->DeleteCustomFieldValue(
+ Field => $cf,
+ Value => $cf_value->Content
+ );
+ push ( @results, $msg);
+
+ }
+ }
+ }
+ elsif ( $arg =~ /-Values$/ ) {
+ my $cf_values = $Object->CustomFieldValues($cf);
# keep everything up to the point of difference, delete the rest
my $delete_flag;
@@ -1191,24 +1226,23 @@
# now add/replace extra things, if any
foreach my $value (@values) {
- my ( $val, $msg ) = $Ticket->AddCustomFieldValue(
+ my ( $val, $msg ) = $Object->AddCustomFieldValue(
Field => $cf,
Value => $value
);
push ( @results, $msg );
}
}
- else {
- push ( @results, "User asked for an unknown update type for custom field " . $cf->Name . " for ticket " . $Ticket->id );
- }
- }
- }
- return (@results);
+ else {
+ push ( @results, loc("User asked for an unknown update type for custom field [_1] for [_2] object #[_3]", $cf->Name, $class, $Object->id ) );
+ }
+ }
+ }
+ return (@results);
+ }
}
}
-# }}}
-
# {{{ sub ProcessTicketWatchers
=head2 ProcessTicketWatchers ( TicketObj => $Ticket, ARGSRef => \%ARGS );
Modified: rt/branches/rt-3.1/lib/RT/Link_Overlay.pm
==============================================================================
--- rt/branches/rt-3.1/lib/RT/Link_Overlay.pm (original)
+++ rt/branches/rt-3.1/lib/RT/Link_Overlay.pm Sat Jul 10 02:05:15 2004
@@ -81,23 +81,31 @@
my $base = RT::URI->new( $self->CurrentUser );
$base->FromURI( $args{'Base'} );
- unless ( $base->Resolver and $base->Scheme ) {
- $RT::Logger->warning( "$self couldn't resolve base:'"
- . $args{'Base'} . " - "
- . "' into a URI\n" );
-
- return (undef);
+ unless ( $base->Resolver && $base->Scheme ) {
+ my $msg = $self->loc("Couldn't resolve base '[_1]' into a URI.",
+ $args{'Base'});
+ $RT::Logger->warning( "$self $msg\n" );
+
+ if (wantarray) {
+ return(undef, $msg);
+ } else {
+ return (undef);
+ }
}
my $target = RT::URI->new( $self->CurrentUser );
$target->FromURI( $args{'Target'} );
unless ( $target->Resolver ) {
- $RT::Logger->warning( "$self couldn't resolve target:'"
- . $args{'Target'} . " - "
- . "' into a URI\n" );
-
- return (undef);
+ my $msg = $self->loc("Couldn't resolve target '[_1]' into a URI.",
+ $args{'Target'});
+ $RT::Logger->warning( "$self $msg\n" );
+
+ if (wantarray) {
+ return(undef, $msg);
+ } else {
+ return (undef);
+ }
}
my $base_id = 0;
Added: rt/branches/rt-3.1/lib/RT/ObjectCustomField.pm
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.1/lib/RT/ObjectCustomField.pm Sat Jul 10 02:05:15 2004
@@ -0,0 +1,272 @@
+# BEGIN LICENSE BLOCK
+#
+# Copyright (c) 1996-2003 Jesse Vincent <jesse at bestpractical.com>
+#
+# (Except where explictly superceded by other copyright notices)
+#
+# This work is made available to you under the terms of Version 2 of
+# the GNU General Public License. A copy of that license should have
+# been provided with this software, but in any event can be snarfed
+# from www.gnu.org.
+#
+# This work 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.
+#
+# Unless otherwise specified, all modifications, corrections or
+# extensions to this work which alter its source code become the
+# property of Best Practical Solutions, LLC when submitted for
+# inclusion in the work.
+#
+#
+# END LICENSE BLOCK
+
+# Autogenerated by DBIx::SearchBuilder factory (by <jesse at bestpractical.com>)
+# WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST.
+#
+# !! DO NOT EDIT THIS FILE !!
+#
+
+use strict;
+
+
+=head1 NAME
+
+RT::ObjectCustomField
+
+
+=head1 SYNOPSIS
+
+=head1 DESCRIPTION
+
+=head1 METHODS
+
+=cut
+
+package RT::ObjectCustomField;
+use RT::Record;
+use RT::CustomField;
+
+
+use vars qw( @ISA );
+ at ISA= qw( RT::Record );
+
+sub _Init {
+ my $self = shift;
+
+ $self->Table('ObjectCustomFields');
+ $self->SUPER::_Init(@_);
+}
+
+
+
+
+
+=head2 Create PARAMHASH
+
+Create takes a hash of values and creates a row in the database:
+
+ int(11) 'CustomField'.
+ int(11) 'ObjectId'.
+ int(11) 'SortOrder'.
+
+=cut
+
+
+
+
+sub Create {
+ my $self = shift;
+ my %args = (
+ CustomField => '0',
+ ObjectId => '0',
+ SortOrder => '0',
+
+ @_);
+ $self->SUPER::Create(
+ CustomField => $args{'CustomField'},
+ ObjectId => $args{'ObjectId'},
+ SortOrder => $args{'SortOrder'},
+);
+
+}
+
+
+
+=head2 id
+
+Returns the current value of id.
+(In the database, id is stored as int(11).)
+
+
+=cut
+
+
+=head2 CustomField
+
+Returns the current value of CustomField.
+(In the database, CustomField is stored as int(11).)
+
+
+
+=head2 SetCustomField VALUE
+
+
+Set CustomField to VALUE.
+Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
+(In the database, CustomField will be stored as a int(11).)
+
+
+=cut
+
+
+=head2 CustomFieldObj
+
+Returns the CustomField Object which has the id returned by CustomField
+
+
+=cut
+
+sub CustomFieldObj {
+ my $self = shift;
+ my $CustomField = RT::CustomField->new($self->CurrentUser);
+ $CustomField->Load($self->__Value('CustomField'));
+ return($CustomField);
+}
+
+=head2 ObjectId
+
+Returns the current value of ObjectId.
+(In the database, ObjectId is stored as int(11).)
+
+
+
+=head2 SetObjectId VALUE
+
+
+Set ObjectId to VALUE.
+Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
+(In the database, ObjectId will be stored as a int(11).)
+
+
+=cut
+
+
+=head2 SortOrder
+
+Returns the current value of SortOrder.
+(In the database, SortOrder is stored as int(11).)
+
+
+
+=head2 SetSortOrder VALUE
+
+
+Set SortOrder to VALUE.
+Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
+(In the database, SortOrder will be stored as a int(11).)
+
+
+=cut
+
+
+=head2 Creator
+
+Returns the current value of Creator.
+(In the database, Creator is stored as int(11).)
+
+
+=cut
+
+
+=head2 Created
+
+Returns the current value of Created.
+(In the database, Created is stored as datetime.)
+
+
+=cut
+
+
+=head2 LastUpdatedBy
+
+Returns the current value of LastUpdatedBy.
+(In the database, LastUpdatedBy is stored as int(11).)
+
+
+=cut
+
+
+=head2 LastUpdated
+
+Returns the current value of LastUpdated.
+(In the database, LastUpdated is stored as datetime.)
+
+
+=cut
+
+
+
+sub _CoreAccessible {
+ {
+
+ id =>
+ {read => 1, type => 'int(11)', default => ''},
+ CustomField =>
+ {read => 1, write => 1, type => 'int(11)', default => '0'},
+ ObjectId =>
+ {read => 1, write => 1, type => 'int(11)', default => '0'},
+ SortOrder =>
+ {read => 1, write => 1, type => 'int(11)', default => '0'},
+ Creator =>
+ {read => 1, auto => 1, type => 'int(11)', default => '0'},
+ Created =>
+ {read => 1, auto => 1, type => 'datetime', default => ''},
+ LastUpdatedBy =>
+ {read => 1, auto => 1, type => 'int(11)', default => '0'},
+ LastUpdated =>
+ {read => 1, auto => 1, type => 'datetime', default => ''},
+
+ }
+};
+
+
+ eval "require RT::ObjectCustomField_Overlay";
+ if ($@ && $@ !~ qr{^Can't locate RT/ObjectCustomField_Overlay.pm}) {
+ die $@;
+ };
+
+ eval "require RT::ObjectCustomField_Vendor";
+ if ($@ && $@ !~ qr{^Can't locate RT/ObjectCustomField_Vendor.pm}) {
+ die $@;
+ };
+
+ eval "require RT::ObjectCustomField_Local";
+ if ($@ && $@ !~ qr{^Can't locate RT/ObjectCustomField_Local.pm}) {
+ die $@;
+ };
+
+
+
+
+=head1 SEE ALSO
+
+This class allows "overlay" methods to be placed
+into the following files _Overlay is for a System overlay by the original author,
+_Vendor is for 3rd-party vendor add-ons, while _Local is for site-local customizations.
+
+These overlay files can contain new subs or subs to replace existing subs in this module.
+
+If you'll be working with perl 5.6.0 or greater, each of these files should begin with the line
+
+ no warnings qw(redefine);
+
+so that perl does not kick and scream when you redefine a subroutine or variable in your overlay.
+
+RT::ObjectCustomField_Overlay, RT::ObjectCustomField_Vendor, RT::ObjectCustomField_Local
+
+=cut
+
+
+1;
Added: rt/branches/rt-3.1/lib/RT/ObjectCustomFieldValue.pm
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.1/lib/RT/ObjectCustomFieldValue.pm Sat Jul 10 02:05:15 2004
@@ -0,0 +1,387 @@
+# BEGIN LICENSE BLOCK
+#
+# Copyright (c) 1996-2003 Jesse Vincent <jesse at bestpractical.com>
+#
+# (Except where explictly superceded by other copyright notices)
+#
+# This work is made available to you under the terms of Version 2 of
+# the GNU General Public License. A copy of that license should have
+# been provided with this software, but in any event can be snarfed
+# from www.gnu.org.
+#
+# This work 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.
+#
+# Unless otherwise specified, all modifications, corrections or
+# extensions to this work which alter its source code become the
+# property of Best Practical Solutions, LLC when submitted for
+# inclusion in the work.
+#
+#
+# END LICENSE BLOCK
+
+# Autogenerated by DBIx::SearchBuilder factory (by <jesse at bestpractical.com>)
+# WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST.
+#
+# !! DO NOT EDIT THIS FILE !!
+#
+
+use strict;
+
+
+=head1 NAME
+
+RT::ObjectCustomFieldValue
+
+
+=head1 SYNOPSIS
+
+=head1 DESCRIPTION
+
+=head1 METHODS
+
+=cut
+
+package RT::ObjectCustomFieldValue;
+use RT::Record;
+use RT::CustomField;
+
+
+use vars qw( @ISA );
+ at ISA= qw( RT::Record );
+
+sub _Init {
+ my $self = shift;
+
+ $self->Table('ObjectCustomFieldValues');
+ $self->SUPER::_Init(@_);
+}
+
+
+
+
+
+=head2 Create PARAMHASH
+
+Create takes a hash of values and creates a row in the database:
+
+ int(11) 'CustomField'.
+ varchar(255) 'ObjectType'.
+ int(11) 'ObjectId'.
+ tinyint(1) 'Current' defaults to '1'.
+ varchar(255) 'Content'.
+ longtext 'LargeContent'.
+ varchar(80) 'ContentType'.
+ varchar(80) 'ContentEncoding'.
+
+=cut
+
+
+
+
+sub Create {
+ my $self = shift;
+ my %args = (
+ CustomField => '0',
+ ObjectType => '',
+ ObjectId => '0',
+ Current => '1',
+ Content => '',
+ LargeContent => '',
+ ContentType => '',
+ ContentEncoding => '',
+
+ @_);
+ $self->SUPER::Create(
+ CustomField => $args{'CustomField'},
+ ObjectType => $args{'ObjectType'},
+ ObjectId => $args{'ObjectId'},
+ Current => $args{'Current'},
+ Content => $args{'Content'},
+ LargeContent => $args{'LargeContent'},
+ ContentType => $args{'ContentType'},
+ ContentEncoding => $args{'ContentEncoding'},
+);
+
+}
+
+
+
+=head2 id
+
+Returns the current value of id.
+(In the database, id is stored as int(11).)
+
+
+=cut
+
+
+=head2 CustomField
+
+Returns the current value of CustomField.
+(In the database, CustomField is stored as int(11).)
+
+
+
+=head2 SetCustomField VALUE
+
+
+Set CustomField to VALUE.
+Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
+(In the database, CustomField will be stored as a int(11).)
+
+
+=cut
+
+
+=head2 CustomFieldObj
+
+Returns the CustomField Object which has the id returned by CustomField
+
+
+=cut
+
+sub CustomFieldObj {
+ my $self = shift;
+ my $CustomField = RT::CustomField->new($self->CurrentUser);
+ $CustomField->Load($self->__Value('CustomField'));
+ return($CustomField);
+}
+
+=head2 ObjectType
+
+Returns the current value of ObjectType.
+(In the database, ObjectType is stored as varchar(255).)
+
+
+
+=head2 SetObjectType VALUE
+
+
+Set ObjectType to VALUE.
+Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
+(In the database, ObjectType will be stored as a varchar(255).)
+
+
+=cut
+
+
+=head2 ObjectId
+
+Returns the current value of ObjectId.
+(In the database, ObjectId is stored as int(11).)
+
+
+
+=head2 SetObjectId VALUE
+
+
+Set ObjectId to VALUE.
+Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
+(In the database, ObjectId will be stored as a int(11).)
+
+
+=cut
+
+
+=head2 Current
+
+Returns the current value of Current.
+(In the database, Current is stored as tinyint(1).)
+
+
+
+=head2 SetCurrent VALUE
+
+
+Set Current to VALUE.
+Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
+(In the database, Current will be stored as a tinyint(1).)
+
+
+=cut
+
+
+=head2 Content
+
+Returns the current value of Content.
+(In the database, Content is stored as varchar(255).)
+
+
+
+=head2 SetContent VALUE
+
+
+Set Content to VALUE.
+Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
+(In the database, Content will be stored as a varchar(255).)
+
+
+=cut
+
+
+=head2 LargeContent
+
+Returns the current value of LargeContent.
+(In the database, LargeContent is stored as longtext.)
+
+
+
+=head2 SetLargeContent VALUE
+
+
+Set LargeContent to VALUE.
+Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
+(In the database, LargeContent will be stored as a longtext.)
+
+
+=cut
+
+
+=head2 ContentType
+
+Returns the current value of ContentType.
+(In the database, ContentType is stored as varchar(80).)
+
+
+
+=head2 SetContentType VALUE
+
+
+Set ContentType to VALUE.
+Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
+(In the database, ContentType will be stored as a varchar(80).)
+
+
+=cut
+
+
+=head2 ContentEncoding
+
+Returns the current value of ContentEncoding.
+(In the database, ContentEncoding is stored as varchar(80).)
+
+
+
+=head2 SetContentEncoding VALUE
+
+
+Set ContentEncoding to VALUE.
+Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
+(In the database, ContentEncoding will be stored as a varchar(80).)
+
+
+=cut
+
+
+=head2 Creator
+
+Returns the current value of Creator.
+(In the database, Creator is stored as int(11).)
+
+
+=cut
+
+
+=head2 Created
+
+Returns the current value of Created.
+(In the database, Created is stored as datetime.)
+
+
+=cut
+
+
+=head2 LastUpdatedBy
+
+Returns the current value of LastUpdatedBy.
+(In the database, LastUpdatedBy is stored as int(11).)
+
+
+=cut
+
+
+=head2 LastUpdated
+
+Returns the current value of LastUpdated.
+(In the database, LastUpdated is stored as datetime.)
+
+
+=cut
+
+
+
+sub _CoreAccessible {
+ {
+
+ id =>
+ {read => 1, type => 'int(11)', default => ''},
+ CustomField =>
+ {read => 1, write => 1, type => 'int(11)', default => '0'},
+ ObjectType =>
+ {read => 1, write => 1, type => 'varchar(255)', default => ''},
+ ObjectId =>
+ {read => 1, write => 1, type => 'int(11)', default => '0'},
+ Current =>
+ {read => 1, write => 1, type => 'tinyint(1)', default => '1'},
+ Content =>
+ {read => 1, write => 1, type => 'varchar(255)', default => ''},
+ LargeContent =>
+ {read => 1, write => 1, type => 'longtext', default => ''},
+ ContentType =>
+ {read => 1, write => 1, type => 'varchar(80)', default => ''},
+ ContentEncoding =>
+ {read => 1, write => 1, type => 'varchar(80)', default => ''},
+ Creator =>
+ {read => 1, auto => 1, type => 'int(11)', default => '0'},
+ Created =>
+ {read => 1, auto => 1, type => 'datetime', default => ''},
+ LastUpdatedBy =>
+ {read => 1, auto => 1, type => 'int(11)', default => '0'},
+ LastUpdated =>
+ {read => 1, auto => 1, type => 'datetime', default => ''},
+
+ }
+};
+
+
+ eval "require RT::ObjectCustomFieldValue_Overlay";
+ if ($@ && $@ !~ qr{^Can't locate RT/ObjectCustomFieldValue_Overlay.pm}) {
+ die $@;
+ };
+
+ eval "require RT::ObjectCustomFieldValue_Vendor";
+ if ($@ && $@ !~ qr{^Can't locate RT/ObjectCustomFieldValue_Vendor.pm}) {
+ die $@;
+ };
+
+ eval "require RT::ObjectCustomFieldValue_Local";
+ if ($@ && $@ !~ qr{^Can't locate RT/ObjectCustomFieldValue_Local.pm}) {
+ die $@;
+ };
+
+
+
+
+=head1 SEE ALSO
+
+This class allows "overlay" methods to be placed
+into the following files _Overlay is for a System overlay by the original author,
+_Vendor is for 3rd-party vendor add-ons, while _Local is for site-local customizations.
+
+These overlay files can contain new subs or subs to replace existing subs in this module.
+
+If you'll be working with perl 5.6.0 or greater, each of these files should begin with the line
+
+ no warnings qw(redefine);
+
+so that perl does not kick and scream when you redefine a subroutine or variable in your overlay.
+
+RT::ObjectCustomFieldValue_Overlay, RT::ObjectCustomFieldValue_Vendor, RT::ObjectCustomFieldValue_Local
+
+=cut
+
+
+1;
Added: rt/branches/rt-3.1/lib/RT/ObjectCustomFieldValue_Overlay.pm
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.1/lib/RT/ObjectCustomFieldValue_Overlay.pm Sat Jul 10 02:05:15 2004
@@ -0,0 +1,115 @@
+# BEGIN LICENSE BLOCK
+#
+# Copyright (c) 1996-2003 Jesse Vincent <jesse at bestpractical.com>
+#
+# (Except where explictly superceded by other copyright notices)
+#
+# This work is made available to you under the terms of Version 2 of
+# the GNU General Public License. A copy of that license should have
+# been provided with this software, but in any event can be snarfed
+# from www.gnu.org.
+#
+# This work 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.
+#
+# Unless otherwise specified, all modifications, corrections or
+# extensions to this work which alter its source code become the
+# property of Best Practical Solutions, LLC when submitted for
+# inclusion in the work.
+#
+#
+# END LICENSE BLOCK
+use strict;
+no warnings qw(redefine);
+
+
+sub Create {
+ my $self = shift;
+ my %args = (
+ CustomField => '0',
+ ObjectType => '',
+ ObjectId => '0',
+ Current => '1',
+ Content => '',
+ LargeContent => '',
+ ContentType => '',
+ ContentEncoding => '',
+
+ @_);
+ ($args{'ContentEncoding'}, $args{'LargeContent'}) = $self->_EncodeLOB($args{'LargeContent'}, $args{'ContentType'}) if ($args{'LargeContent'});
+ $self->SUPER::Create(
+ CustomField => $args{'CustomField'},
+ ObjectType => $args{'ObjectType'},
+ ObjectId => $args{'ObjectId'},
+ Current => $args{'Current'},
+ Content => $args{'Content'},
+ LargeContent => $args{'LargeContent'},
+ ContentType => $args{'ContentType'},
+ ContentEncoding => $args{'ContentEncoding'},
+);
+
+
+
+}
+
+
+sub LargeContent {
+ my $self = shift;
+ $self->_DecodeLOB( $self->ContentType, $self->ContentEncoding,
+ $self->_Value( 'LargeContent', decode_utf8 => 0 ) );
+
+}
+
+
+
+
+=head2 LoadByTicketContentAndCustomField { Ticket => TICKET, CustomField => CUSTOMFIELD, Content => CONTENT }
+
+Loads a custom field value by Ticket, Content and which CustomField it's tied to
+
+=cut
+
+
+sub LoadByTicketContentAndCustomField {
+ my $self = shift;
+ my %args = ( Ticket => undef,
+ CustomField => undef,
+ Content => undef,
+ @_
+ );
+
+
+ $self->LoadByCols( Content => $args{'Content'},
+ CustomField => $args{'CustomField'},
+ ObjectType => 'RT::Ticket',
+ ObjectId => $args{'Ticket'},);
+
+
+}
+
+sub LoadByObjectContentAndCustomField {
+ my $self = shift;
+ my %args = ( Object => undef,
+ CustomField => undef,
+ Content => undef,
+ @_
+ );
+
+ my $obj = $args{'Object'} or return;
+
+ $self->LoadByCols( Content => $args{'Content'},
+ CustomField => $args{'CustomField'},
+ ObjectType => ref($obj),
+ ObjectId => $obj->Id,);
+
+
+}
+
+sub Delete {
+ my $self = shift;
+ $self->SetCurrent(0);
+}
+
+1;
Added: rt/branches/rt-3.1/lib/RT/ObjectCustomFieldValues.pm
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.1/lib/RT/ObjectCustomFieldValues.pm Sat Jul 10 02:05:15 2004
@@ -0,0 +1,116 @@
+# BEGIN LICENSE BLOCK
+#
+# Copyright (c) 1996-2003 Jesse Vincent <jesse at bestpractical.com>
+#
+# (Except where explictly superceded by other copyright notices)
+#
+# This work is made available to you under the terms of Version 2 of
+# the GNU General Public License. A copy of that license should have
+# been provided with this software, but in any event can be snarfed
+# from www.gnu.org.
+#
+# This work 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.
+#
+# Unless otherwise specified, all modifications, corrections or
+# extensions to this work which alter its source code become the
+# property of Best Practical Solutions, LLC when submitted for
+# inclusion in the work.
+#
+#
+# END LICENSE BLOCK
+
+# Autogenerated by DBIx::SearchBuilder factory (by <jesse at bestpractical.com>)
+# WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST.
+#
+# !! DO NOT EDIT THIS FILE !!
+#
+
+use strict;
+
+
+=head1 NAME
+
+ RT::ObjectCustomFieldValues -- Class Description
+
+=head1 SYNOPSIS
+
+ use RT::ObjectCustomFieldValues
+
+=head1 DESCRIPTION
+
+
+=head1 METHODS
+
+=cut
+
+package RT::ObjectCustomFieldValues;
+
+use RT::SearchBuilder;
+use RT::ObjectCustomFieldValue;
+
+use vars qw( @ISA );
+ at ISA= qw(RT::SearchBuilder);
+
+
+sub _Init {
+ my $self = shift;
+ $self->{'table'} = 'ObjectCustomFieldValues';
+ $self->{'primary_key'} = 'id';
+
+
+ return ( $self->SUPER::_Init(@_) );
+}
+
+
+=head2 NewItem
+
+Returns an empty new RT::ObjectCustomFieldValue item
+
+=cut
+
+sub NewItem {
+ my $self = shift;
+ return(RT::ObjectCustomFieldValue->new($self->CurrentUser));
+}
+
+ eval "require RT::ObjectCustomFieldValues_Overlay";
+ if ($@ && $@ !~ qr{^Can't locate RT/ObjectCustomFieldValues_Overlay.pm}) {
+ die $@;
+ };
+
+ eval "require RT::ObjectCustomFieldValues_Vendor";
+ if ($@ && $@ !~ qr{^Can't locate RT/ObjectCustomFieldValues_Vendor.pm}) {
+ die $@;
+ };
+
+ eval "require RT::ObjectCustomFieldValues_Local";
+ if ($@ && $@ !~ qr{^Can't locate RT/ObjectCustomFieldValues_Local.pm}) {
+ die $@;
+ };
+
+
+
+
+=head1 SEE ALSO
+
+This class allows "overlay" methods to be placed
+into the following files _Overlay is for a System overlay by the original author,
+_Vendor is for 3rd-party vendor add-ons, while _Local is for site-local customizations.
+
+These overlay files can contain new subs or subs to replace existing subs in this module.
+
+If you'll be working with perl 5.6.0 or greater, each of these files should begin with the line
+
+ no warnings qw(redefine);
+
+so that perl does not kick and scream when you redefine a subroutine or variable in your overlay.
+
+RT::ObjectCustomFieldValues_Overlay, RT::ObjectCustomFieldValues_Vendor, RT::ObjectCustomFieldValues_Local
+
+=cut
+
+
+1;
Added: rt/branches/rt-3.1/lib/RT/ObjectCustomFieldValues_Overlay.pm
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.1/lib/RT/ObjectCustomFieldValues_Overlay.pm Sat Jul 10 02:05:15 2004
@@ -0,0 +1,133 @@
+# BEGIN LICENSE BLOCK
+#
+# Copyright (c) 1996-2003 Jesse Vincent <jesse at bestpractical.com>
+#
+# (Except where explictly superceded by other copyright notices)
+#
+# This work is made available to you under the terms of Version 2 of
+# the GNU General Public License. A copy of that license should have
+# been provided with this software, but in any event can be snarfed
+# from www.gnu.org.
+#
+# This work 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.
+#
+# Unless otherwise specified, all modifications, corrections or
+# extensions to this work which alter its source code become the
+# property of Best Practical Solutions, LLC when submitted for
+# inclusion in the work.
+#
+#
+# END LICENSE BLOCK
+use strict;
+no warnings qw(redefine);
+
+# {{{ sub LimitToCustomField
+
+=head2 LimitToCustomField FIELD
+
+Limits the returned set to values for the custom field with Id FIELD
+
+=cut
+
+sub LimitToCustomField {
+ my $self = shift;
+ my $cf = shift;
+ return ($self->Limit( FIELD => 'CustomField',
+ VALUE => $cf,
+ OPERATOR => '='));
+
+}
+
+# }}}
+
+# {{{ sub LimitToTicket
+
+=head2 LimitToTicket TICKETID
+
+Limits the returned set to values for the ticket with Id TICKETID
+
+=cut
+
+sub LimitToTicket {
+ my $self = shift;
+ my $ticket = shift;
+ $self->Limit( FIELD => 'ObjectType',
+ VALUE => 'RT::Ticket',
+ OPERATOR => '=');
+ return ($self->Limit( FIELD => 'ObjectId',
+ VALUE => $ticket,
+ OPERATOR => '='));
+
+}
+
+# }}}
+
+
+sub LimitToObject {
+ my $self = shift;
+ my $object = shift;
+ $self->Limit( FIELD => 'ObjectType',
+ VALUE => ref($object),
+ OPERATOR => '=');
+ return ($self->Limit( FIELD => 'ObjectId',
+ VALUE => $object->Id,
+ OPERATOR => '='));
+
+}
+
+=sub HasEntry VALUE
+
+Returns true if this CustomFieldValues collection has an entry with content that eq VALUE
+
+=cut
+
+
+sub HasEntry {
+ my $self = shift;
+ my $value = shift;
+
+ #TODO: this could cache and optimize a fair bit.
+ foreach my $item (@{$self->ItemsArrayRef}) {
+ return(1) if ($item->Content eq $value);
+ }
+ return undef;
+
+}
+
+sub _DoSearch {
+ my $self = shift;
+
+ #unless we really want to find disabled rows, make sure we\'re only finding enabled ones.
+ unless($self->{'find_expired_rows'}) {
+ $self->LimitToCurrent();
+ }
+
+ return($self->SUPER::_DoSearch(@_));
+
+}
+
+sub _DoCount {
+ my $self = shift;
+
+ #unless we really want to find disabled rows, make sure we\'re only finding enabled ones.
+ unless($self->{'find_expired_rows'}) {
+ $self->LimitToCurrent();
+ }
+
+ return($self->SUPER::_DoCount(@_));
+
+}
+
+sub LimitToCurrent {
+ my $self = shift;
+
+ $self->Limit( FIELD => 'Current',
+ VALUE => '1',
+ OPERATOR => '=' );
+}
+
+1;
+
Added: rt/branches/rt-3.1/lib/RT/ObjectCustomField_Overlay.pm
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.1/lib/RT/ObjectCustomField_Overlay.pm Sat Jul 10 02:05:15 2004
@@ -0,0 +1,78 @@
+# BEGIN LICENSE BLOCK
+#
+# Copyright (c) 1996-2003 Jesse Vincent <jesse at bestpractical.com>
+#
+# (Except where explictly superceded by other copyright notices)
+#
+# This work is made available to you under the terms of Version 2 of
+# the GNU General Public License. A copy of that license should have
+# been provided with this software, but in any event can be snarfed
+# from www.gnu.org.
+#
+# This work 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.
+#
+# Unless otherwise specified, all modifications, corrections or
+# extensions to this work which alter its source code become the
+# property of Best Practical Solutions, LLC when submitted for
+# inclusion in the work.
+#
+#
+# END LICENSE BLOCK
+
+use strict;
+no warnings qw(redefine);
+
+sub Create {
+ my $self = shift;
+ my %args = (
+ CustomField => '0',
+ ObjectId => '0',
+ SortOrder => undef,
+ @_);
+
+ if (!defined $args{SortOrder}) {
+ my $CF = $self->CustomFieldObj($args{'CustomField'});
+ my $ObjectCFs = RT::ObjectCustomFields->new($self->CurrentUser);
+ $ObjectCFs->LimitToObjectId($args{'ObjectId'});
+ $ObjectCFs->LimitToLookupType($CF->LookupType);
+
+ $args{SortOrder} = $ObjectCFs->Count + 1;
+ }
+
+ $self->SUPER::Create(
+ CustomField => $args{'CustomField'},
+ ObjectId => $args{'ObjectId'},
+ SortOrder => $args{'SortOrder'},
+ );
+}
+
+sub Delete {
+ my $self = shift;
+
+ my $ObjectCFs = RT::ObjectCustomFields->new($self->CurrentUser);
+ $ObjectCFs->LimitToObjectId($self->ObjectId);
+ $ObjectCFs->LimitToLookupType($self->CustomFieldObj->LookupType);
+
+ # Move everything below us up
+ my $sort_order = $self->SortOrder;
+ while (my $OCF = $ObjectCFs->Next) {
+ my $this_order = $OCF->SortOrder;
+ next if $this_order <= $sort_order;
+ $OCF->SetSortOrder($this_order - 1);
+ }
+
+ $self->SUPER::Delete;
+}
+
+sub CustomFieldObj {
+ my $self = shift;
+ my $id = shift || $self->CustomField;
+ my $CF = RT::CustomField->new($self->CurrentUser);
+ $CF->Load($id) or die "Cannot load CustomField $id";
+ return $CF;
+}
+
+1;
Added: rt/branches/rt-3.1/lib/RT/ObjectCustomFields.pm
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.1/lib/RT/ObjectCustomFields.pm Sat Jul 10 02:05:15 2004
@@ -0,0 +1,122 @@
+# BEGIN LICENSE BLOCK
+#
+# Copyright (c) 1996-2003 Jesse Vincent <jesse at bestpractical.com>
+#
+# (Except where explictly superceded by other copyright notices)
+#
+# This work is made available to you under the terms of Version 2 of
+# the GNU General Public License. A copy of that license should have
+# been provided with this software, but in any event can be snarfed
+# from www.gnu.org.
+#
+# This work 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.
+#
+# Unless otherwise specified, all modifications, corrections or
+# extensions to this work which alter its source code become the
+# property of Best Practical Solutions, LLC when submitted for
+# inclusion in the work.
+#
+#
+# END LICENSE BLOCK
+
+# Autogenerated by DBIx::SearchBuilder factory (by <jesse at bestpractical.com>)
+# WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST.
+#
+# !! DO NOT EDIT THIS FILE !!
+#
+
+use strict;
+
+
+=head1 NAME
+
+ RT::ObjectCustomFields -- Class Description
+
+=head1 SYNOPSIS
+
+ use RT::ObjectCustomFields
+
+=head1 DESCRIPTION
+
+
+=head1 METHODS
+
+=cut
+
+package RT::ObjectCustomFields;
+
+use RT::SearchBuilder;
+use RT::ObjectCustomField;
+
+use vars qw( @ISA );
+ at ISA= qw(RT::SearchBuilder);
+
+
+sub _Init {
+ my $self = shift;
+ $self->{'table'} = 'ObjectCustomFields';
+ $self->{'primary_key'} = 'id';
+
+
+
+ # By default, order by name
+ $self->OrderBy( ALIAS => 'main',
+ FIELD => 'SortOrder',
+ ORDER => 'ASC');
+
+ return ( $self->SUPER::_Init(@_) );
+}
+
+
+=head2 NewItem
+
+Returns an empty new RT::ObjectCustomField item
+
+=cut
+
+sub NewItem {
+ my $self = shift;
+ return(RT::ObjectCustomField->new($self->CurrentUser));
+}
+
+ eval "require RT::ObjectCustomFields_Overlay";
+ if ($@ && $@ !~ qr{^Can't locate RT/ObjectCustomFields_Overlay.pm}) {
+ die $@;
+ };
+
+ eval "require RT::ObjectCustomFields_Vendor";
+ if ($@ && $@ !~ qr{^Can't locate RT/ObjectCustomFields_Vendor.pm}) {
+ die $@;
+ };
+
+ eval "require RT::ObjectCustomFields_Local";
+ if ($@ && $@ !~ qr{^Can't locate RT/ObjectCustomFields_Local.pm}) {
+ die $@;
+ };
+
+
+
+
+=head1 SEE ALSO
+
+This class allows "overlay" methods to be placed
+into the following files _Overlay is for a System overlay by the original author,
+_Vendor is for 3rd-party vendor add-ons, while _Local is for site-local customizations.
+
+These overlay files can contain new subs or subs to replace existing subs in this module.
+
+If you'll be working with perl 5.6.0 or greater, each of these files should begin with the line
+
+ no warnings qw(redefine);
+
+so that perl does not kick and scream when you redefine a subroutine or variable in your overlay.
+
+RT::ObjectCustomFields_Overlay, RT::ObjectCustomFields_Vendor, RT::ObjectCustomFields_Local
+
+=cut
+
+
+1;
Added: rt/branches/rt-3.1/lib/RT/ObjectCustomFields_Overlay.pm
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.1/lib/RT/ObjectCustomFields_Overlay.pm Sat Jul 10 02:05:15 2004
@@ -0,0 +1,77 @@
+# BEGIN LICENSE BLOCK
+#
+# Copyright (c) 1996-2003 Jesse Vincent <jesse at bestpractical.com>
+#
+# (Except where explictly superceded by other copyright notices)
+#
+# This work is made available to you under the terms of Version 2 of
+# the GNU General Public License. A copy of that license should have
+# been provided with this software, but in any event can be snarfed
+# from www.gnu.org.
+#
+# This work 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.
+#
+# Unless otherwise specified, all modifications, corrections or
+# extensions to this work which alter its source code become the
+# property of Best Practical Solutions, LLC when submitted for
+# inclusion in the work.
+#
+#
+# END LICENSE BLOCK
+
+use strict;
+no warnings qw(redefine);
+
+sub LimitToCustomField {
+ my $self = shift;
+ my $id = shift;
+ $self->Limit( FIELD => 'CustomField', VALUE => $id );
+}
+
+sub LimitToObjectId {
+ my $self = shift;
+ my $id = shift || 0;
+ $self->Limit( FIELD => 'ObjectId', VALUE => $id );
+}
+
+sub LimitToLookupType {
+ my $self = shift;
+ my $lookup = shift;
+ my $cfs = $self->NewAlias('CustomFields');
+ $self->Join( ALIAS1 => 'main',
+ FIELD1 => 'CustomField',
+ ALIAS2 => $cfs,
+ FIELD2 => 'id' );
+ $self->Limit( ALIAS => $cfs,
+ FIELD => 'LookupType',
+ OPERATOR => '=',
+ VALUE => $lookup );
+}
+
+sub HasEntryForCustomField {
+ my $self = shift;
+ my $id = shift;
+
+ my @items = grep {$_->CustomField == $id } @{$self->ItemsArrayRef};
+
+ if ($#items > 1) {
+ die "$self HasEntry had a list with more than one of $id in it. this can never happen";
+ }
+ if ($#items == -1 ) {
+ return undef;
+ }
+ else {
+ return ($items[0]);
+ }
+}
+
+sub CustomFields {
+ my $self = shift;
+ my %seen;
+ map { $_->CustomFieldObj } @{$self->ItemsArrayRef};
+}
+
+1;
Modified: rt/branches/rt-3.1/lib/RT/Queue_Overlay.pm
==============================================================================
--- rt/branches/rt-3.1/lib/RT/Queue_Overlay.pm (original)
+++ rt/branches/rt-3.1/lib/RT/Queue_Overlay.pm Sat Jul 10 02:05:15 2004
@@ -70,7 +70,7 @@
ShowACL => 'Display Access Control List', # loc_pair
ModifyACL => 'Modify Access Control List', # loc_pair
ModifyQueueWatchers => 'Modify the queue watchers', # loc_pair
- AdminCustomFields => 'Create, delete and modify custom fields', # loc_pair
+ AssignCustomFields => 'Assign and remove custom fields', # loc_pair
ModifyTemplate => 'Modify Scrip templates for this queue', # loc_pair
ShowTemplate => 'Display Scrip templates for this queue', # loc_pair
@@ -457,12 +457,32 @@
=cut
+# XXX XXX - this should become TicketCustomFields
+
sub CustomFields {
my $self = shift;
+ warn "Queue->CustomFields is deprecated, use Queue->TicketCustomFields instead";
+ return $self->TicketCustomFields(@_);
+}
+
+sub TicketCustomFields {
+ my $self = shift;
+
+ my $cfs = RT::CustomFields->new( $self->CurrentUser );
+ if ( $self->CurrentUserHasRight('SeeQueue') ) {
+ $cfs->LimitToGlobalOrObjectId( $self->Id );
+ $cfs->LimitToLookupType( 'RT::Queue-RT::Ticket' );
+ }
+ return ($cfs);
+}
+
+sub TicketTransactionCustomFields {
+ my $self = shift;
my $cfs = RT::CustomFields->new( $self->CurrentUser );
if ( $self->CurrentUserHasRight('SeeQueue') ) {
- $cfs->LimitToGlobalOrQueue( $self->Id );
+ $cfs->LimitToGlobalOrObjectId( $self->Id );
+ $cfs->LimitToLookupType( 'RT::Queue-RT::Ticket-RT::Transaction' );
}
return ($cfs);
}
@@ -1043,7 +1063,7 @@
}
return (
$args{'Principal'}->HasRight(
- Object => $self,
+ Object => $self->Id ? $self : $RT::System,
Right => $args{'Right'}
)
);
Modified: rt/branches/rt-3.1/lib/RT/Record.pm
==============================================================================
--- rt/branches/rt-3.1/lib/RT/Record.pm (original)
+++ rt/branches/rt-3.1/lib/RT/Record.pm Sat Jul 10 02:05:15 2004
@@ -676,6 +676,28 @@
}
+sub _DecodeLOB {
+ my $self = shift;
+ my $ContentType = shift;
+ my $ContentEncoding = shift;
+ my $Content = shift;
+
+ if ( $ContentEncoding eq 'base64' ) {
+ $Content = MIME::Base64::decode_base64($Content);
+ }
+ elsif ( $ContentEncoding eq 'quoted-printable' ) {
+ $Content = MIME::QuotedPrint::decode($Content);
+ }
+ elsif ( $ContentEncoding && $ContentEncoding ne 'none' ) {
+ return ( $self->loc( "Unknown ContentEncoding [_1]", $ContentEncoding ) );
+ }
+ if ( $ContentType eq 'text/plain' ) {
+ return Encode::decode_utf8($Content);
+ }
+ else {
+ return ($Content);
+ }
+}
# {{{ LINKDIRMAP
# A helper table for links mapping to make it easier
@@ -1176,6 +1198,431 @@
# }}}
+# {{{ sub _NewTransaction
+
+=head2 _NewTransaction PARAMHASH
+
+Private function to create a new RT::Transaction object for this ticket update
+
+=cut
+
+sub _NewTransaction {
+ my $self = shift;
+ my %args = (
+ TimeTaken => undef,
+ Type => undef,
+ OldValue => undef,
+ NewValue => undef,
+ OldReference => undef,
+ NewReference => undef,
+ ReferenceType => undef,
+ Data => undef,
+ Field => undef,
+ MIMEObj => undef,
+ ActivateScrips => 1,
+ CommitScrips => 1,
+ @_
+ );
+
+ my $old_ref = $args{'OldReference'};
+ my $new_ref = $args{'NewReference'};
+ my $ref_type = $args{'ReferenceType'};
+ if ($old_ref or $new_ref) {
+ $ref_type ||= ref($old_ref) || ref($new_ref);
+ if (!$ref_type) {
+ $RT::Logger->error("Reference type not specified for transaction");
+ return;
+ }
+ $old_ref = $old_ref->Id if ref($old_ref);
+ $new_ref = $new_ref->Id if ref($new_ref);
+ }
+
+ require RT::Transaction;
+ my $trans = new RT::Transaction( $self->CurrentUser );
+ my ( $transaction, $msg ) = $trans->Create(
+ ObjectId => $self->Id,
+ ObjectType => ref($self),
+ TimeTaken => $args{'TimeTaken'},
+ Type => $args{'Type'},
+ Data => $args{'Data'},
+ Field => $args{'Field'},
+ NewValue => $args{'NewValue'},
+ OldValue => $args{'OldValue'},
+ NewReference => $new_ref,
+ OldReference => $old_ref,
+ ReferenceType => $ref_type,
+ MIMEObj => $args{'MIMEObj'},
+ ActivateScrips => $args{'ActivateScrips'},
+ CommitScrips => $args{'CommitScrips'},
+ );
+
+ # Rationalize the object since we may have done things to it during the caching.
+ $self->Load($self->Id);
+
+ $RT::Logger->warning($msg) unless $transaction;
+
+ $self->_SetLastUpdated;
+
+ if ( defined $args{'TimeTaken'} ) {
+ $self->_UpdateTimeTaken( $args{'TimeTaken'} );
+ }
+ if ( $RT::UseTransactionBatch and $transaction ) {
+ push @{$self->{_TransactionBatch}}, $trans;
+ }
+ return ( $transaction, $msg, $trans );
+}
+
+# }}}
+
+# {{{ sub Transactions
+
+=head2 Transactions
+
+ Returns an RT::Transactions object of all transactions on this ticket
+
+=cut
+
+sub Transactions {
+ my $self = shift;
+
+ use RT::Transactions;
+ my $transactions = RT::Transactions->new( $self->CurrentUser );
+
+ #If the user has no rights, return an empty object
+ $transactions->Limit(
+ FIELD => 'ObjectId',
+ VALUE => $self->id,
+ );
+ $transactions->Limit(
+ FIELD => 'ObjectType',
+ VALUE => ref($self),
+ );
+
+ return ($transactions);
+}
+
+# }}}
+
+# {{{ Routines dealing with custom fields
+
+sub CustomFields {
+ my $self = shift;
+ my $cfs = RT::CustomFields->new( $self->CurrentUser );
+ $cfs->UnLimit;
+
+ # XXX handle multiple types properly
+ foreach my $lookup ($self->_LookupTypes) {
+ $cfs->LimitToLookupType($lookup);
+ $cfs->LimitToGlobalOrObjectId($self->_LookupId($lookup));
+ }
+
+ return $cfs;
+}
+
+sub _LookupId {
+ my $self = shift;
+ my $lookup = shift;
+ my @classes = ($lookup =~ /RT::(\w+)-/g);
+
+ foreach my $class (reverse @classes) {
+ my $method = "${class}Obj";
+ $self = $self->$method;
+ }
+
+ return $self->Id;
+}
+
+sub _LookupTypes { ref($_[0]) }
+
+# {{{ AddCustomFieldValue
+
+=item AddCustomFieldValue { Field => FIELD, Value => VALUE }
+
+VALUE should be a string.
+FIELD can be a CustomField object OR a CustomField ID.
+
+
+Adds VALUE as a value of CustomField FIELD. If this is a single-value custom field,
+deletes the old value.
+If VALUE isn't a valid value for the custom field, returns
+(0, 'Error message' ) otherwise, returns (1, 'Success Message')
+
+=cut
+
+sub AddCustomFieldValue {
+ my $self = shift;
+# unless ( $self->CurrentUserHasRight('ModifyTicket') ) {
+# return ( 0, $self->loc("Permission Denied") );
+# }
+ $self->_AddCustomFieldValue(@_);
+}
+
+sub _AddCustomFieldValue {
+ my $self = shift;
+ my %args = (
+ Field => undef,
+ Value => undef,
+ RecordTransaction => 1,
+ @_
+ );
+
+ my $cf = RT::CustomField->new( $self->CurrentUser );
+ if ( UNIVERSAL::isa( $args{'Field'}, "RT::CustomField" ) ) {
+ $cf->Load( $args{'Field'}->id );
+ }
+ else {
+ $cf->Load( $args{'Field'} );
+ }
+
+ unless ( $cf->Id ) {
+ return ( 0, $self->loc("Custom field [_1] not found", $args{'Field'}) );
+ }
+
+ my $OCFs = $self->CustomFields;
+ $OCFs->Limit( FIELD => 'id', VALUE => $cf->Id );
+ unless ($OCFs->Count) {
+ return ( 0, $self->loc("Custom field [_1] does not apply to this object", $args{'Field'}) );
+ }
+
+ # Load up a ObjectCustomFieldValues object for this custom field and this ticket
+ my $values = $cf->ValuesForObject( $self );
+
+ unless ( $cf->ValidateValue( $args{'Value'} ) ) {
+ return ( 0, $self->loc("Invalid value for custom field") );
+ }
+
+ # If the custom field only accepts a single value, delete the existing
+ # value and record a "changed from foo to bar" transaction
+ if ( $cf->SingleValue ) {
+
+ # We need to whack any old values here. In most cases, the custom field should
+ # only have one value to delete. In the pathalogical case, this custom field
+ # used to be a multiple and we have many values to whack....
+ my $cf_values = $values->Count;
+
+ if ( $cf_values > 1 ) {
+ my $i = 0; #We want to delete all but the last one, so we can then
+ # execute the same code to "change" the value from old to new
+ while ( my $value = $values->Next ) {
+ $i++;
+ if ( $i < $cf_values ) {
+ my ($val, $msg) = $cf->DeleteValueForObject(Object => $self, Content => $value->Content);
+ unless ($val) {
+ return (0,$msg);
+ }
+ my ( $TransactionId, $Msg, $TransactionObj ) =
+ $self->_NewTransaction(
+ Type => 'CustomField',
+ Field => $cf->Id,
+ OldReference => $value,
+ );
+ }
+ }
+ }
+
+ my ($old_value, $old_content);
+ if ($old_value = $cf->ValuesForObject( $self )->First) {
+ $old_content = $old_value->Content();
+ return (1) if $old_content eq $args{'Value'};
+ }
+
+ my ( $new_value_id, $value_msg ) = $cf->AddValueForObject(
+ Object => $self,
+ Content => $args{'Value'},
+ LargeContent => $args{'LargeContent'},
+ ContentType => $args{'ContentType'},
+ );
+
+ unless ($new_value_id) {
+ return ( 0,
+ $self->loc("Could not add new custom field value for ticket. [_1] ",
+ ,$value_msg) );
+ }
+
+ my $new_value = RT::ObjectCustomFieldValue->new( $self->CurrentUser );
+ $new_value->Load($new_value_id);
+
+ # now that adding the new value was successful, delete the old one
+ if ($old_value) {
+ my ($val, $msg) = $cf->DeleteValueForObject(Object => $self, Content => $old_content);
+ unless ($val) {
+ return (0,$msg);
+ }
+ }
+
+ if ($args{'RecordTransaction'}) {
+ my ( $TransactionId, $Msg, $TransactionObj ) = $self->_NewTransaction(
+ Type => 'CustomField',
+ Field => $cf->Id,
+ OldReference => $old_value,
+ NewReference => $new_value,
+ );
+ }
+
+ if ( $old_value eq '' ) {
+ return ( 1, $self->loc("[_1] [_2] added", $cf->Name, $new_value->Content) );
+ }
+ elsif ( $new_value->Content eq '' ) {
+ return ( 1, $self->loc("[_1] [_2] deleted", $cf->Name, $old_content) );
+ }
+ else {
+ return ( 1, $self->loc("[_1] [_2] changed to [_3]", $cf->Name, $old_content, $new_value->Content ) );
+ }
+
+ }
+
+ # otherwise, just add a new value and record "new value added"
+ else {
+ my ( $new_value_id ) = $cf->AddValueForObject(
+ Object => $self,
+ Content => $args{'Value'},
+ LargeContent => $args{'LargeContent'},
+ ContentType => $args{'ContentType'},
+ );
+
+ unless ($new_value_id) {
+ return ( 0,
+ $self->loc("Could not add new custom field value for ticket. "));
+ }
+ if ( $args{'RecordTransaction'} ) {
+ my ( $TransactionId, $Msg, $TransactionObj ) = $self->_NewTransaction(
+ Type => 'CustomField',
+ Field => $cf->Id,
+ NewReference => $new_value_id,
+ ReferenceType => 'RT::ObjectCustomFieldValue',
+ );
+ unless ($TransactionId) {
+ return ( 0,
+ $self->loc( "Couldn't create a transaction: [_1]", $Msg ) );
+ }
+ }
+ return ( 1, $self->loc("[_1] added as a value for [_2]",$args{'Value'}, $cf->Name));
+ }
+
+}
+
+# }}}
+
+# {{{ DeleteCustomFieldValue
+
+=item DeleteCustomFieldValue { Field => FIELD, Value => VALUE }
+
+Deletes VALUE as a value of CustomField FIELD.
+
+VALUE can be a string, a CustomFieldValue or a ObjectCustomFieldValue.
+
+If VALUE isn't a valid value for the custom field, returns
+(0, 'Error message' ) otherwise, returns (1, 'Success Message')
+
+=cut
+
+sub DeleteCustomFieldValue {
+ my $self = shift;
+ my %args = (
+ Field => undef,
+ Value => undef,
+ ValueId => undef,
+ @_);
+
+# XXX - normalise CF related ACLs... ask obra!
+# unless ( $self->CurrentUserHasRight('ModifyTicket') ) {
+# return ( 0, $self->loc("Permission Denied") );
+# }
+ my $cf = RT::CustomField->new( $self->CurrentUser );
+ if ( UNIVERSAL::isa( $args{'Field'}, "RT::CustomField" ) ) {
+ $cf->LoadById( $args{'Field'}->id );
+ }
+ else {
+ $cf->LoadById( $args{'Field'} );
+ }
+
+ unless ( $cf->Id ) {
+ return ( 0, $self->loc("Custom field not found") );
+ }
+
+
+ my ($val, $msg) = $cf->DeleteValueForObject(
+ Object => $self,
+ Id => $args{'ValueId'},
+ Content => $args{'Value'},
+ );
+ unless ($val) {
+ return (0,$msg);
+ }
+ my ( $TransactionId, $Msg, $TransactionObj ) = $self->_NewTransaction(
+ Type => 'CustomField',
+ Field => $cf->Id,
+ OldReference => $val,
+ ReferenceType => 'RT::ObjectCustomFieldValue',
+ );
+ unless($TransactionId) {
+ return(0, $self->loc("Couldn't create a transaction: [_1]", $Msg));
+ }
+
+ return($TransactionId, $self->loc("[_1] is no longer a value for custom field [_2]", $TransactionObj->OldValue, $cf->Name));
+}
+
+# }}}
+
+# {{{ FirstCustomFieldValue
+
+=item FirstCustomFieldValue FIELD
+
+Return the content of the first value of CustomField FIELD for this ticket
+Takes a field id or name
+
+=cut
+
+sub FirstCustomFieldValue {
+ my $self = shift;
+ my $field = shift;
+ my $values = $self->CustomFieldValues($field);
+ if ($values->First) {
+ return $values->First->Content;
+ } else {
+ return undef;
+ }
+
+}
+
+
+
+# {{{ CustomFieldValues
+
+=item CustomFieldValues FIELD
+
+Return a ObjectCustomFieldValues object of all values of CustomField FIELD for this ticket.
+Takes a field id.
+
+
+=cut
+
+sub CustomFieldValues {
+ my $self = shift;
+ my $field = shift;
+
+ my $cf_values = RT::ObjectCustomFieldValues->new( $self->CurrentUser );
+ $cf_values->LimitToObject($self);
+ $cf_values->OrderBy( FIELD => 'id' );
+
+ if (length $field) {
+ $field =~ /^\d+$/ or die "LoadByNameAndQueue impossible for Record.pm";
+ my $cf = RT::CustomField->new($self->CurrentUser);
+ $cf->LoadById($field);
+ $cf_values->LimitToCustomField($cf->id);
+ }
+
+ # @values is a CustomFieldValues object;
+ return ($cf_values);
+}
+
+# }}}
+
+# }}}
+
+sub BasicColumns {
+}
+
eval "require RT::Record_Vendor";
die $@ if ($@ && $@ !~ qr{^Can't locate RT/Record_Vendor.pm});
eval "require RT::Record_Local";
Modified: rt/branches/rt-3.1/lib/RT/SearchBuilder.pm
==============================================================================
--- rt/branches/rt-3.1/lib/RT/SearchBuilder.pm (original)
+++ rt/branches/rt-3.1/lib/RT/SearchBuilder.pm Sat Jul 10 02:05:15 2004
@@ -109,14 +109,42 @@
Takes NAME, OPERATOR and VALUE to find records that has the
matching Attribute.
+If EMPTY is set, also select rows with an empty string as
+Attribute's Content.
+
+If NULL is set, also select rows without the named Attribute.
+
=cut
+my %Negate = qw(
+ = !=
+ != =
+ > <=
+ < >=
+ >= <
+ <= >
+ LIKE NOT LIKE
+ NOT LIKE LIKE
+ IS IS NOT
+ IS NOT IS
+);
+
sub LimitAttribute {
my ($self, %args) = @_;
+ my $clause = 'ALIAS';
+ my $operator = ($args{OPERATOR} || '=');
+
+ if ($args{NULL} and exists $args{VALUE}) {
+ $clause = 'LEFTJOIN';
+ $operator = $Negate{$operator};
+ }
+ elsif ($args{NEGATE}) {
+ $operator = $Negate{$operator};
+ }
my $alias = $self->Join(
TYPE => 'left',
- ALIAS1 => 'main',
+ ALIAS1 => $args{ALIAS} || 'main',
FIELD1 => 'id',
TABLE2 => 'Attributes',
FIELD2 => 'ObjectId'
@@ -126,13 +154,13 @@
$type =~ s/(?:s|Collection)$//; # XXX - Hack!
$self->Limit(
- ALIAS => $alias,
+ $clause => $alias,
FIELD => 'ObjectType',
OPERATOR => '=',
VALUE => $type,
);
$self->Limit(
- ALIAS => $alias,
+ $clause => $alias,
FIELD => 'Name',
OPERATOR => '=',
VALUE => $args{NAME},
@@ -141,27 +169,91 @@
return unless exists $args{VALUE};
$self->Limit(
- ALIAS => $alias,
+ $clause => $alias,
FIELD => 'Content',
- OPERATOR => ($args{OPERATOR} || '='),
+ OPERATOR => $operator,
VALUE => $args{VALUE},
- ENTRYAGGREGATOR => 'OR',
);
- if ($args{EMPTY}) {
- # Capture rows without the attribute defined by testing IS NULL.
- $self->Limit(
- ALIAS => $alias,
- FIELD => $_,
- OPERATOR => 'IS',
- VALUE => 'NULL',
- ENTRYAGGREGATOR => 'OR',
- ) for qw( ObjectType Name Content );
- }
+ # Capture rows with the attribute defined as an empty string.
+ $self->Limit(
+ $clause => $alias,
+ FIELD => 'Content',
+ OPERATOR => '=',
+ VALUE => '',
+ ENTRYAGGREGATOR => $args{NULL} ? 'AND' : 'OR',
+ ) if $args{EMPTY};
+
+ # Capture rows without the attribute defined
+ $self->Limit(
+ %args,
+ ALIAS => $alias,
+ FIELD => 'id',
+ OPERATOR => ($args{NEGATE} ? 'IS NOT' : 'IS'),
+ VALUE => 'NULL',
+ ) if $args{NULL};
}
# }}}
-1;
+# {{{ sub LimitCustomField
+
+=head2 LimitCustomField
+
+Takes a paramhash of key/value pairs with the following keys:
+
+=over 4
+
+=item CUSTOMFIELD - CustomField name or id. If a name is passed, an additional
+parameter QUEUE may also be passed to distinguish the custom field.
+
+=item OPERATOR - The usual Limit operators
+
+=item VALUE - The value to compare against
+
+=back
+
+=cut
+
+sub _SingularClass {
+ my $self = shift;
+ my $class = ref($self);
+ $class =~ s/s$// or die "Cannot deduce SingularClass for $class";
+ return $class;
+}
+
+sub LimitCustomField {
+ my $self = shift;
+ my %args = ( VALUE => undef,
+ CUSTOMFIELD => undef,
+ OPERATOR => '=',
+ @_ );
+
+ my $alias = $self->Join(
+ TYPE => 'left',
+ ALIAS1 => 'main',
+ FIELD1 => 'id',
+ TABLE2 => 'ObjectCustomFieldValues',
+ FIELD2 => 'ObjectId'
+ );
+ $self->Limit(
+ ALIAS => $alias,
+ FIELD => 'CustomField',
+ OPERATOR => '=',
+ VALUE => $args{'CUSTOMFIELD'},
+ );
+ $self->Limit(
+ ALIAS => $alias,
+ FIELD => 'ObjectType',
+ OPERATOR => '=',
+ VALUE => $self->_SingularClass,
+ );
+ $self->Limit(
+ ALIAS => $alias,
+ FIELD => 'Content',
+ OPERATOR => $args{'OPERATOR'},
+ VALUE => $args{'VALUE'},
+ );
+}
# {{{ sub FindAllRows
Modified: rt/branches/rt-3.1/lib/RT/StyleGuide.pod
==============================================================================
--- rt/branches/rt-3.1/lib/RT/StyleGuide.pod (original)
+++ rt/branches/rt-3.1/lib/RT/StyleGuide.pod Sat Jul 10 02:05:15 2004
@@ -857,7 +857,28 @@
Send patches to rt-<major-version>-bugs at fsck.com, too. Use C<diff
-u> for patches.
+=head1 SCHEMA DESIGN
+RT uses a convention to denote the foreign key status in its tables.
+The rule of thumb is:
+
+=over 4
+
+=item When it references to another table, always use the table name
+
+For example, the C<Template> field in the C<Scrips> table refers to
+the C<Id> of the same-named C<Template> table.
+
+=item Otherwise, always use the C<Id> suffix
+
+For example, the C<ObjectId> field in the C<ACL> table can refer
+to any object, so it has the C<Id> suffix.
+
+=back
+
+There are some legacy fields that did not follow this rule, namely
+C<ACL.PrincipalId>, C<GroupMembers.GroupId> and C<Attachments.TransactionId>,
+but new tables are expected to be consistent.
=head1 TO DO
Modified: rt/branches/rt-3.1/lib/RT/System.pm
==============================================================================
--- rt/branches/rt-3.1/lib/RT/System.pm (original)
+++ rt/branches/rt-3.1/lib/RT/System.pm Sat Jul 10 02:05:15 2004
@@ -96,12 +96,14 @@
my $queue = RT::Queue->new($RT::SystemUser);
my $group = RT::Group->new($RT::SystemUser);
+ my $cf = RT::CustomField->new($RT::SystemUser);
my $qr =$queue->AvailableRights();
my $gr = $group->AvailableRights();
+ my $cr = $cf->AvailableRights();
# Build a merged list of all system wide rights, queue rights and group rights.
- my %rights = (%{$RIGHTS}, %{$gr}, %{$qr});
+ my %rights = (%{$RIGHTS}, %{$gr}, %{$qr}, %{$cr});
return(\%rights);
}
Modified: rt/branches/rt-3.1/lib/RT/Template_Overlay.pm
==============================================================================
--- rt/branches/rt-3.1/lib/RT/Template_Overlay.pm (original)
+++ rt/branches/rt-3.1/lib/RT/Template_Overlay.pm Sat Jul 10 02:05:15 2004
@@ -381,7 +381,15 @@
SOURCE => $content
);
- my $retval = $template->fill_in( PACKAGE => 'T' );
+ my $is_broken = 0;
+ my $retval = $template->fill_in( PACKAGE => 'T', BROKEN => sub {
+ my (%args) = @_;
+ $RT::Logger->error("Template parsing error: $args{error}")
+ unless $args{error} =~ /^Died at /; # ignore intentional die()
+ $is_broken++;
+ return undef;
+ } );
+ return undef if $is_broken;
# MIME::Parser has problems dealing with high-bit utf8 data.
Encode::_utf8_off($retval);
Modified: rt/branches/rt-3.1/lib/RT/Ticket_Overlay.pm
==============================================================================
--- rt/branches/rt-3.1/lib/RT/Ticket_Overlay.pm (original)
+++ rt/branches/rt-3.1/lib/RT/Ticket_Overlay.pm Sat Jul 10 02:05:15 2004
@@ -85,8 +85,8 @@
ok(my $t2 = RT::Ticket->new($RT::SystemUser));
ok($t2->Load($id));
-ok($t2->Subject eq 'Testing');
-ok($t2->QueueObj->Id eq $testqueue->id);
+is($t2->Subject, 'Testing');
+is($t2->QueueObj->Id, $testqueue->id);
ok($t2->OwnerObj->Id == $u->Id);
my $t3 = RT::Ticket->new($RT::SystemUser);
@@ -120,7 +120,6 @@
use RT::Links;
use RT::Date;
use RT::CustomFields;
-use RT::TicketCustomFieldValues;
use RT::Tickets;
use RT::URI::fsck_com_rt;
use RT::URI;
@@ -459,7 +458,7 @@
}
#If we've been handed something else, try to load the user.
- elsif ( $args{'Owner'} ) {
+ elsif ( defined $args{'Owner'} ) {
$Owner = RT::User->new( $self->CurrentUser );
$Owner->Load( $args{'Owner'} );
@@ -2679,6 +2678,7 @@
# {{{ sub MergeInto
=head2 MergeInto
+
MergeInto take the id of the ticket to merge this ticket into.
=cut
@@ -2877,9 +2877,9 @@
my $t = RT::Ticket->new($RT::SystemUser);
$t->Load(1);
$t->SetOwner('root');
-ok ($t->OwnerObj->Name eq 'root' , "Root owns the ticket");
+is ($t->OwnerObj->Name, 'root' , "Root owns the ticket");
$t->Steal();
-ok ($t->OwnerObj->id eq $RT::SystemUser->id , "SystemUser owns the ticket");
+is ($t->OwnerObj->id, $RT::SystemUser->id , "SystemUser owns the ticket");
my $txns = RT::Transactions->new($RT::SystemUser);
$txns->OrderBy(FIELD => 'id', ORDER => 'DESC');
$txns->Limit(FIELD => 'Ticket', VALUE => '1');
@@ -3109,14 +3109,14 @@
my ($id, $tid, $msg)= $tt->Create(Queue => 'general',
Subject => 'test');
ok($id, $msg);
-ok($tt->Status eq 'new', "New ticket is created as new");
+is($tt->Status, 'new', "New ticket is created as new");
($id, $msg) = $tt->SetStatus('open');
ok($id, $msg);
-ok ($msg =~ /open/i, "Status message is correct");
+like($msg, qr/open/i, "Status message is correct");
($id, $msg) = $tt->SetStatus('resolved');
ok($id, $msg);
-ok ($msg =~ /resolved/i, "Status message is correct");
+like($msg, qr/resolved/i, "Status message is correct");
($id, $msg) = $tt->SetStatus('resolved');
ok(!$id,$msg);
@@ -3268,282 +3268,6 @@
# }}}
-# {{{ Routines dealing with custom fields
-
-
-# {{{ FirstCustomFieldValue
-
-=item FirstCustomFieldValue FIELD
-
-Return the content of the first value of CustomField FIELD for this ticket
-Takes a field id or name
-
-=cut
-
-sub FirstCustomFieldValue {
- my $self = shift;
- my $field = shift;
- my $values = $self->CustomFieldValues($field);
- if ($values->First) {
- return $values->First->Content;
- } else {
- return undef;
- }
-
-}
-
-
-
-# {{{ CustomFieldValues
-
-=item CustomFieldValues FIELD
-
-Return a TicketCustomFieldValues object of all values of CustomField FIELD for this ticket.
-Takes a field id or name.
-
-
-=cut
-
-sub CustomFieldValues {
- my $self = shift;
- my $field = shift;
-
- my $cf = RT::CustomField->new($self->CurrentUser);
-
- if ($field =~ /^\d+$/) {
- $cf->LoadById($field);
- } else {
- $cf->LoadByNameAndQueue(Name => $field, Queue => $self->QueueObj->Id);
- unless( $cf->id ) {
- $cf->LoadByNameAndQueue(Name => $field, Queue => '0');
- }
- }
- my $cf_values = RT::TicketCustomFieldValues->new( $self->CurrentUser );
- $cf_values->LimitToCustomField($cf->id);
- $cf_values->LimitToTicket($self->Id());
- $cf_values->OrderBy( FIELD => 'id' );
-
- # @values is a CustomFieldValues object;
- return ($cf_values);
-}
-
-# }}}
-
-# {{{ AddCustomFieldValue
-
-=item AddCustomFieldValue { Field => FIELD, Value => VALUE }
-
-VALUE should be a string.
-FIELD can be a CustomField object OR a CustomField ID.
-
-
-Adds VALUE as a value of CustomField FIELD. If this is a single-value custom field,
-deletes the old value.
-If VALUE isn't a valid value for the custom field, returns
-(0, 'Error message' ) otherwise, returns (1, 'Success Message')
-
-=cut
-
-sub AddCustomFieldValue {
- my $self = shift;
- unless ( $self->CurrentUserHasRight('ModifyTicket') ) {
- return ( 0, $self->loc("Permission Denied") );
- }
- $self->_AddCustomFieldValue(@_);
-}
-
-sub _AddCustomFieldValue {
- my $self = shift;
- my %args = (
- Field => undef,
- Value => undef,
- RecordTransaction => 1,
- @_
- );
-
- my $cf = RT::CustomField->new( $self->CurrentUser );
- if ( UNIVERSAL::isa( $args{'Field'}, "RT::CustomField" ) ) {
- $cf->Load( $args{'Field'}->id );
- }
- else {
- $cf->Load( $args{'Field'} );
- }
-
- unless ( $cf->Id ) {
- return ( 0, $self->loc("Custom field [_1] not found", $args{'Field'}) );
- }
-
- # Load up a TicketCustomFieldValues object for this custom field and this ticket
- my $values = $cf->ValuesForTicket( $self->id );
-
- unless ( $cf->ValidateValue( $args{'Value'} ) ) {
- return ( 0, $self->loc("Invalid value for custom field") );
- }
-
- # If the custom field only accepts a single value, delete the existing
- # value and record a "changed from foo to bar" transaction
- if ( $cf->SingleValue ) {
-
- # We need to whack any old values here. In most cases, the custom field should
- # only have one value to delete. In the pathalogical case, this custom field
- # used to be a multiple and we have many values to whack....
- my $cf_values = $values->Count;
-
- if ( $cf_values > 1 ) {
- my $i = 0; #We want to delete all but the last one, so we can then
- # execute the same code to "change" the value from old to new
- while ( my $value = $values->Next ) {
- $i++;
- if ( $i < $cf_values ) {
- my $old_value = $value->Content;
- my ($val, $msg) = $cf->DeleteValueForTicket(Ticket => $self->Id, Content => $value->Content);
- unless ($val) {
- return (0,$msg);
- }
- my ( $TransactionId, $Msg, $TransactionObj ) =
- $self->_NewTransaction(
- Type => 'CustomField',
- Field => $cf->Id,
- OldValue => $old_value
- );
- }
- }
- }
-
- my $old_value;
- if (my $value = $cf->ValuesForTicket( $self->Id )->First) {
- $old_value = $value->Content();
- return (1) if $old_value eq $args{'Value'};
- }
-
- my ( $new_value_id, $value_msg ) = $cf->AddValueForTicket(
- Ticket => $self->Id,
- Content => $args{'Value'}
- );
-
- unless ($new_value_id) {
- return ( 0,
- $self->loc("Could not add new custom field value for ticket. [_1] ",
- ,$value_msg) );
- }
-
- my $new_value = RT::TicketCustomFieldValue->new( $self->CurrentUser );
- $new_value->Load($new_value_id);
-
- # now that adding the new value was successful, delete the old one
- if ($old_value) {
- my ($val, $msg) = $cf->DeleteValueForTicket(Ticket => $self->Id, Content => $old_value);
- unless ($val) {
- return (0,$msg);
- }
- }
-
- if ($args{'RecordTransaction'}) {
- my ( $TransactionId, $Msg, $TransactionObj ) = $self->_NewTransaction(
- Type => 'CustomField',
- Field => $cf->Id,
- OldValue => $old_value,
- NewValue => $new_value->Content
- );
- }
-
- if ( $old_value eq '' ) {
- return ( 1, $self->loc("[_1] [_2] added", $cf->Name, $new_value->Content) );
- }
- elsif ( $new_value->Content eq '' ) {
- return ( 1, $self->loc("[_1] [_2] deleted", $cf->Name, $old_value) );
- }
- else {
- return ( 1, $self->loc("[_1] [_2] changed to [_3]", $cf->Name, $old_value, $new_value->Content ) );
- }
-
- }
-
- # otherwise, just add a new value and record "new value added"
- else {
- my ( $new_value_id ) = $cf->AddValueForTicket(
- Ticket => $self->Id,
- Content => $args{'Value'}
- );
-
- unless ($new_value_id) {
- return ( 0,
- $self->loc("Could not add new custom field value for ticket. "));
- }
- if ( $args{'RecordTransaction'} ) {
- my ( $TransactionId, $Msg, $TransactionObj ) = $self->_NewTransaction(
- Type => 'CustomField',
- Field => $cf->Id,
- NewValue => $args{'Value'}
- );
- unless ($TransactionId) {
- return ( 0,
- $self->loc( "Couldn't create a transaction: [_1]", $Msg ) );
- }
- }
- return ( 1, $self->loc("[_1] added as a value for [_2]",$args{'Value'}, $cf->Name));
- }
-
-}
-
-# }}}
-
-# {{{ DeleteCustomFieldValue
-
-=item DeleteCustomFieldValue { Field => FIELD, Value => VALUE }
-
-Deletes VALUE as a value of CustomField FIELD.
-
-VALUE can be a string, a CustomFieldValue or a TicketCustomFieldValue.
-
-If VALUE isn't a valid value for the custom field, returns
-(0, 'Error message' ) otherwise, returns (1, 'Success Message')
-
-=cut
-
-sub DeleteCustomFieldValue {
- my $self = shift;
- my %args = (
- Field => undef,
- Value => undef,
- @_);
-
- unless ( $self->CurrentUserHasRight('ModifyTicket') ) {
- return ( 0, $self->loc("Permission Denied") );
- }
- my $cf = RT::CustomField->new( $self->CurrentUser );
- if ( UNIVERSAL::isa( $args{'Field'}, "RT::CustomField" ) ) {
- $cf->LoadById( $args{'Field'}->id );
- }
- else {
- $cf->LoadById( $args{'Field'} );
- }
-
- unless ( $cf->Id ) {
- return ( 0, $self->loc("Custom field not found") );
- }
-
-
- my ($val, $msg) = $cf->DeleteValueForTicket(Ticket => $self->Id, Content => $args{'Value'});
- unless ($val) {
- return (0,$msg);
- }
- my ( $TransactionId, $Msg, $TransactionObj ) = $self->_NewTransaction(
- Type => 'CustomField',
- Field => $cf->Id,
- OldValue => $args{'Value'}
- );
- unless($TransactionId) {
- return(0, $self->loc("Couldn't create a transaction: [_1]", $Msg));
- }
-
- return($TransactionId, $self->loc("[_1] is no longer a value for custom field [_2]", $args{'Value'}, $cf->Name));
-}
-
-# }}}
-
-# }}}
-
# {{{ Actions + Routines dealing with transactions
# {{{ sub SetTold and _SetTold
@@ -3598,113 +3322,6 @@
# }}}
-# {{{ sub Transactions
-
-=head2 Transactions
-
- Returns an RT::Transactions object of all transactions on this ticket
-
-=cut
-
-sub Transactions {
- my $self = shift;
-
- use RT::Transactions;
- my $transactions = RT::Transactions->new( $self->CurrentUser );
-
- #If the user has no rights, return an empty object
- if ( $self->CurrentUserHasRight('ShowTicket') ) {
- my $tickets = $transactions->NewAlias('Tickets');
- $transactions->Join(
- ALIAS1 => 'main',
- FIELD1 => 'Ticket',
- ALIAS2 => $tickets,
- FIELD2 => 'id'
- );
- $transactions->Limit(
- ALIAS => $tickets,
- FIELD => 'EffectiveId',
- VALUE => $self->id()
- );
-
- # if the user may not see comments do not return them
- unless ( $self->CurrentUserHasRight('ShowTicketComments') ) {
- $transactions->Limit(
- FIELD => 'Type',
- OPERATOR => '!=',
- VALUE => "Comment",
- ENTRYAGGREGATOR => 'AND'
- );
- $transactions->Limit(
- FIELD => 'Type',
- OPERATOR => '!=',
- VALUE => "CommentEmailRecord",
- ENTRYAGGREGATOR => 'AND'
- );
- }
- }
-
- return ($transactions);
-}
-
-# }}}
-
-# {{{ sub _NewTransaction
-
-=head2 _NewTransaction PARAMHASH
-
-Private function to create a new RT::Transaction object for this ticket update
-
-=cut
-
-sub _NewTransaction {
- my $self = shift;
- my %args = (
- TimeTaken => 0,
- Type => undef,
- OldValue => undef,
- NewValue => undef,
- Data => undef,
- Field => undef,
- MIMEObj => undef,
- ActivateScrips => 1,
- CommitScrips => 1,
- @_
- );
-
- require RT::Transaction;
- my $trans = new RT::Transaction( $self->CurrentUser );
- my ( $transaction, $msg ) = $trans->Create(
- Ticket => $self->Id,
- TimeTaken => $args{'TimeTaken'},
- Type => $args{'Type'},
- Data => $args{'Data'},
- Field => $args{'Field'},
- NewValue => $args{'NewValue'},
- OldValue => $args{'OldValue'},
- MIMEObj => $args{'MIMEObj'},
- ActivateScrips => $args{'ActivateScrips'},
- CommitScrips => $args{'CommitScrips'},
- );
-
- # Rationalize the object since we may have done things to it during the caching.
- $self->Load($self->Id);
-
- $RT::Logger->warning($msg) unless $transaction;
-
- $self->_SetLastUpdated;
-
- if ( defined $args{'TimeTaken'} ) {
- $self->_UpdateTimeTaken( $args{'TimeTaken'} );
- }
- if ( $RT::UseTransactionBatch and $transaction ) {
- push @{$self->{_TransactionBatch}}, $trans;
- }
- return ( $transaction, $msg, $trans );
-}
-
-# }}}
-
=head2 TransactionBatch
Returns an array reference of all transactions created on this ticket during
@@ -3957,6 +3574,86 @@
# }}}
+# {{{ sub Transactions
+
+=head2 Transactions
+
+ Returns an RT::Transactions object of all transactions on this ticket
+
+=cut
+
+sub Transactions {
+ my $self = shift;
+
+ use RT::Transactions;
+ my $transactions = RT::Transactions->new( $self->CurrentUser );
+
+ #If the user has no rights, return an empty object
+ if ( $self->CurrentUserHasRight('ShowTicket') ) {
+ my $tickets = $transactions->NewAlias('Tickets');
+ $transactions->Join(
+ ALIAS1 => 'main',
+ FIELD1 => 'ObjectId',
+ ALIAS2 => $tickets,
+ FIELD2 => 'id'
+ );
+ $transactions->Limit(
+ ALIAS => $tickets,
+ FIELD => 'EffectiveId',
+ VALUE => $self->id()
+ );
+ $transactions->Limit(
+ FIELD => 'ObjectType',
+ VALUE => ref($self),
+ );
+
+ # if the user may not see comments do not return them
+ unless ( $self->CurrentUserHasRight('ShowTicketComments') ) {
+ $transactions->Limit(
+ FIELD => 'Type',
+ OPERATOR => '!=',
+ VALUE => "Comment"
+ );
+ $transactions->Limit(
+ FIELD => 'Type',
+ OPERATOR => '!=',
+ VALUE => "CommentEmailRecord",
+ ENTRYAGGREGATOR => 'AND'
+ );
+
+ }
+ }
+
+ return ($transactions);
+}
+
+# }}}
+
+sub TransactionCustomFields {
+ my $self = shift;
+ return $self->QueueObj->TicketTransactionCustomFields;
+}
+
+# Do name => id mapping (if needed) before falling back to
+# RT::Record's CustomFieldValues
+sub CustomFieldValues {
+ my $self = shift;
+ my $field = shift;
+ unless ($field =~ /^\d+$/) {
+ my $cf = RT::CustomField->new($self->CurrentUser);
+ $cf->LoadByNameAndQueue(Name => $field, Queue => $self->QueueObj->Id);
+ unless( $cf->id ) {
+ $cf->LoadByNameAndQueue(Name => $field, Queue => '0');
+ }
+ $field = $cf->id;
+ }
+ return $self->SUPER::CustomFieldValues($field);
+}
+
+sub _LookupTypes {
+ "RT::Queue-RT::Ticket";
+}
+
1;
=head1 AUTHOR
Modified: rt/branches/rt-3.1/lib/RT/Tickets_Overlay.pm
==============================================================================
--- rt/branches/rt-3.1/lib/RT/Tickets_Overlay.pm (original)
+++ rt/branches/rt-3.1/lib/RT/Tickets_Overlay.pm Sat Jul 10 02:05:15 2004
@@ -108,6 +108,10 @@
LinkedTo => ['LINKFIELD',],
CustomFieldValue =>['CUSTOMFIELD',],
CF => ['CUSTOMFIELD',],
+ RequestorGroup => ['MEMBERSHIPFIELD' => 'Requestor',],
+ CCGroup => ['MEMBERSHIPFIELD' => 'Cc',],
+ AdminCCGroup => ['MEMBERSHIPFIELD' => 'AdminCc',],
+ WatcherGroup => ['MEMBERSHIPFIELD',],
);
# Mapping of Field Type to Function
@@ -120,8 +124,9 @@
TRANSFIELD => \&_TransLimit,
TRANSDATE => \&_TransDateLimit,
WATCHERFIELD => \&_WatcherLimit,
+ MEMBERSHIPFIELD => \&_WatcherMembershipLimit,
LINKFIELD => \&_LinkFieldLimit,
- CUSTOMFIELD => \&_CustomFieldLimit,
+ CUSTOMFIELD => \&_CustomFieldLimit,
);
my %can_bundle =
( WATCHERFIELD => "yeps",
@@ -242,7 +247,7 @@
$o->Load( $value );
$value = $o->Id;
}
- $sb->_SQLLimit( FIELD => $field,,
+ $sb->_SQLLimit( FIELD => $field,
VALUE => $value,
OPERATOR => $op,
@rest,
@@ -538,6 +543,14 @@
$sb->_OpenParen;
+ # Join Transactions To Attachments
+ $sb->_SQLJoin( ALIAS1 => $sb->{_sql_trattachalias}, FIELD1 => 'TransactionId',
+ ALIAS2 => $sb->{_sql_transalias}, FIELD2 => 'id');
+
+ # Join Transactions to Tickets
+ $sb->_SQLJoin( ALIAS1 => 'main', FIELD1 => $sb->{'primary_key'}, # UGH!
+ ALIAS2 => $sb->{_sql_transalias}, FIELD2 => 'Ticket');
+
#Search for the right field
$sb->_SQLLimit(ALIAS => $sb->{_sql_trattachalias},
FIELD => $field,
@@ -547,14 +560,6 @@
@rest
);
- # Join Transactions To Attachments
- $sb->_SQLJoin( ALIAS1 => $sb->{_sql_trattachalias}, FIELD1 => 'TransactionId',
- ALIAS2 => $sb->{_sql_transalias}, FIELD2 => 'id');
-
- # Join Transactions to Tickets
- $sb->_SQLJoin( ALIAS1 => 'main', FIELD1 => $sb->{'primary_key'}, # UGH!
- ALIAS2 => $sb->{_sql_transalias}, FIELD2 => 'Ticket');
-
$sb->_CloseParen;
}
@@ -642,6 +647,112 @@
}
+=head2 _WatcherMembershipLimit
+
+Handle watcher membership limits, i.e. whether the watcher belongs to a
+specific group or not.
+
+Meta Data:
+ 1: Field to query on
+
+SELECT DISTINCT main.*
+FROM
+ Tickets main,
+ Groups Groups_1,
+ CachedGroupMembers CachedGroupMembers_2,
+ Users Users_3
+WHERE (
+ (main.EffectiveId = main.id)
+) AND (
+ (main.Status != 'deleted')
+) AND (
+ (main.Type = 'ticket')
+) AND (
+ (
+ (Users_3.EmailAddress = '22')
+ AND
+ (Groups_1.Domain = 'RT::Ticket-Role')
+ AND
+ (Groups_1.Type = 'RequestorGroup')
+ )
+) AND
+ Groups_1.Instance = main.id
+AND
+ Groups_1.id = CachedGroupMembers_2.GroupId
+AND
+ CachedGroupMembers_2.MemberId = Users_3.id
+ORDER BY main.id ASC
+LIMIT 25
+=cut
+
+sub _WatcherMembershipLimit {
+ my ($self,$field,$op,$value, at rest) = @_;
+ my %rest = @rest;
+
+ $self->_OpenParen;
+
+ my $groups = $self->NewAlias('Groups');
+ my $groupmembers = $self->NewAlias('CachedGroupMembers');
+ my $users = $self->NewAlias('Users');
+ my $memberships = $self->NewAlias('CachedGroupMembers');
+
+ if (ref $field) { # gross hack
+ my @bundle = @$field;
+ $self->_OpenParen;
+ for my $chunk (@bundle) {
+ ($field,$op,$value, at rest) = @$chunk;
+ $self->_SQLLimit(ALIAS => $memberships,
+ FIELD => 'GroupId',
+ VALUE => $value,
+ OPERATOR => $op,
+ @rest,
+ );
+ }
+ $self->_CloseParen;
+ } else {
+ $self->_SQLLimit(ALIAS => $memberships,
+ FIELD => 'GroupId',
+ VALUE => $value,
+ OPERATOR => $op,
+ @rest,
+ );
+ }
+
+ # {{{ Tie to groups for tickets we care about
+ $self->_SQLLimit(ALIAS => $groups,
+ FIELD => 'Domain',
+ VALUE => 'RT::Ticket-Role',
+ ENTRYAGGREGATOR => 'AND');
+
+ $self->Join(ALIAS1 => $groups, FIELD1 => 'Instance',
+ ALIAS2 => 'main', FIELD2 => 'id');
+ # }}}
+
+ # If we care about which sort of watcher
+ my $meta = $FIELDS{$field};
+ my $type = ( defined $meta->[1] ? $meta->[1] : undef );
+
+ if ( $type ) {
+ $self->_SQLLimit(ALIAS => $groups,
+ FIELD => 'Type',
+ VALUE => $type,
+ ENTRYAGGREGATOR => 'AND');
+ }
+
+ $self->Join (ALIAS1 => $groups, FIELD1 => 'id',
+ ALIAS2 => $groupmembers, FIELD2 => 'GroupId');
+
+ $self->Join( ALIAS1 => $groupmembers, FIELD1 => 'MemberId',
+ ALIAS2 => $users, FIELD2 => 'id');
+
+ $self->Join( ALIAS1 => $memberships, FIELD1 => 'MemberId',
+ ALIAS2 => $users, FIELD2 => 'id');
+
+ $self->_CloseParen;
+
+}
+
+
sub _LinkFieldLimit {
my $restriction;
my $self;
@@ -710,93 +821,102 @@
=cut
sub _CustomFieldLimit {
- my ($self,$_field,$op,$value, at rest) = @_;
-
- my %rest = @rest;
- my $field = $rest{SUBKEY} || die "No field specified";
-
- # For our sanity, we can only limit on one queue at a time
- my $queue = 0;
+ my ( $self, $_field, $op, $value, @rest ) = @_;
+ my %rest = @rest;
+ my $field = $rest{SUBKEY} || die "No field specified";
- if ($field =~ /^(.+?)\.{(.+)}$/) {
- $queue = $1;
- $field = $2;
- }
- $field = $1 if $field =~ /^{(.+)}$/; # trim { }
+ # For our sanity, we can only limit on one queue at a time
+ my $queue = 0;
- my $q = RT::Queue->new($self->CurrentUser);
- $q->Load($queue) if ($queue);
-
- my $cf;
- if ($q->id) {
- $cf = $q->CustomField($field);
- }
- else {
- $cf = RT::CustomField->new($self->CurrentUser);
- $cf->LoadByNameAndQueue(Queue => '0', Name => $field);
+ if ( $field =~ /^(.+?)\.{(.+)}$/ ) {
+ $queue = $1;
+ $field = $2;
}
+ $field = $1 if $field =~ /^{(.+)}$/; # trim { }
+# If we're trying to find custom fields that don't match something, we want tickets
+# where the custom field has no value at all
-
- my $cfid = $cf->id;
-
- die "No custom field named $field found\n" unless $cfid;
-
+ my $null_columns_ok;
+ if ( ( $op =~ /^IS$/i ) or ( $op =~ /^NOT LIKE$/i ) or ( $op eq '!=' ) ) {
+ $null_columns_ok = 1;
+ }
- my $null_columns_ok;
- my $TicketCFs;
- # Perform one Join per CustomField
- if ($self->{_sql_keywordalias}{$cfid}) {
- $TicketCFs = $self->{_sql_keywordalias}{$cfid};
- } else {
- $TicketCFs = $self->{_sql_keywordalias}{$cfid} =
- $self->_SQLJoin( TYPE => 'left',
- ALIAS1 => 'main',
- FIELD1 => 'id',
- TABLE2 => 'TicketCustomFieldValues',
- FIELD2 => 'Ticket' );
- }
+ my $q = RT::Queue->new( $self->CurrentUser );
+ $q->Load($queue) if ($queue);
- $self->_OpenParen;
+ my $cf;
+ if ( $q->id ) {
+ $cf = $q->CustomField($field);
+ }
+ else {
+ $cf = RT::CustomField->new( $self->CurrentUser );
+ $cf->LoadByNameAndQueue( Queue => '0', Name => $field );
+ }
- $self->_SQLLimit( ALIAS => $TicketCFs,
- FIELD => 'Content',
- OPERATOR => $op,
- VALUE => $value,
- QUOTEVALUE => 1,
- @rest );
+ my $cfid = $cf->id;
+ die "No custom field named $field found\n" unless $cfid;
- # If we're trying to find custom fields that don't match something, we want tickets
- # where the custom field has no value at all
- if ( ($op =~ /^IS$/i) or ($op =~ /^NOT LIKE$/i) or ( $op eq '!=' ) ) {
- $null_columns_ok = 1;
- }
-
+ my $TicketCFs;
- if ( $null_columns_ok) {
- $self->_SQLLimit( ALIAS => $TicketCFs,
- FIELD => 'Content',
- OPERATOR => 'IS',
- VALUE => 'NULL',
- QUOTEVALUE => 0,
- ENTRYAGGREGATOR => 'OR', );
- }
+ # Perform one Join per CustomField
+ if ( $self->{_sql_keywordalias}{$cfid} ) {
+ $TicketCFs = $self->{_sql_keywordalias}{$cfid};
+ }
+ else {
+ $TicketCFs = $self->{_sql_keywordalias}{$cfid} = $self->_SQLJoin(
+ TYPE => 'left',
+ ALIAS1 => 'main',
+ FIELD1 => 'id',
+ TABLE2 => 'ObjectCustomFieldValues',
+ FIELD2 => 'ObjectId'
+ );
+
+ $self->_SQLLimit(
+ LEFTJOIN => $TicketCFs,
+ FIELD => 'ObjectType',
+ VALUE => ref($self->NewItem), # we want a single item, not a collection
+ ENTRYAGGREGATOR => 'AND'
+ );
+
+ $self->_SQLLimit(
+ LEFTJOIN => $TicketCFs,
+ FIELD => 'CustomField',
+ VALUE => $cfid,
+ ENTRYAGGREGATOR => 'AND'
+ );
- $self->_SQLLimit( LEFTJOIN => $TicketCFs,
- FIELD => 'CustomField',
- VALUE => $cfid,
- ENTRYAGGREGATOR => 'OR' );
+ }
+ $self->_OpenParen;
+ $self->_SQLLimit(
+ ALIAS => $TicketCFs,
+ FIELD => 'Content',
+ OPERATOR => $op,
+ VALUE => $value,
+ QUOTEVALUE => 1,
+ @rest
+ );
+ if ($null_columns_ok) {
+ $self->_SQLLimit(
+ ALIAS => $TicketCFs,
+ FIELD => 'Content',
+ OPERATOR => 'IS',
+ VALUE => 'NULL',
+ QUOTEVALUE => 0,
+ ENTRYAGGREGATOR => 'OR',
+ );
+ }
- $self->_CloseParen;
+ $self->_CloseParen;
}
@@ -870,8 +990,13 @@
sub FreezeLimits {
my $self = shift;
- require FreezeThaw;
- return (FreezeThaw::freeze(@{$self}{$self->_FreezeThawKeys}));
+ require Storable;
+ require MIME::Base64;
+ MIME::Base64::base64_encode(
+ Storable::freeze(
+ \@{$self}{$self->_FreezeThawKeys}
+ )
+ );
}
# }}}
@@ -893,13 +1018,14 @@
$self->{'RecalcTicketLimits'} = 1;
- require FreezeThaw;
-
+ require Storable;
+ require MIME::Base64;
+
#We don't need to die if the thaw fails.
-
- eval {
- @{$self}{$self->_FreezeThawKeys} = FreezeThaw::thaw($in);
+ @{$self}{$self->_FreezeThawKeys} = eval {
+ @{Storable::thaw( MIME::Base64::base64_decode($in) )};
};
+
$RT::Logger->error( $@ ) if $@;
}
@@ -1972,9 +2098,9 @@
}
# Two special case
- # CustomFields have a different real field
- if ($field =~ /^CF\./) {
- $realfield = "CF"
+ # Handle subkey fields with a different real field
+ if ($field =~ /^(\w+)\./) {
+ $realfield = $1;
}
die "I don't know about $field yet"
Modified: rt/branches/rt-3.1/lib/RT/Tickets_Overlay_SQL.pm
==============================================================================
--- rt/branches/rt-3.1/lib/RT/Tickets_Overlay_SQL.pm (original)
+++ rt/branches/rt-3.1/lib/RT/Tickets_Overlay_SQL.pm Sat Jul 10 02:05:15 2004
@@ -129,9 +129,14 @@
use constant OP => 4;
use constant PAREN => 8;
use constant KEYWORD => 16;
-my @tokens = qw[VALUE AGGREG OP PAREN KEYWORD];
+use constant SELECT => 32;
+use constant WHERE => 64;
+use constant COLUMN => 128;
+my @tokens = qw[VALUE AGGREG OP PAREN KEYWORD SELECT WHERE COLUMN];
my $re_aggreg = qr[(?i:AND|OR)];
+my $re_select = qr[(?i:SELECT)];
+my $re_where = qr[(?i:WHERE)];
my $re_value = qr[$RE{delimited}{-delim=>qq{\'\"}}|\d+];
my $re_keyword = qr[$RE{delimited}{-delim=>qq{\'\"}}|(?:\{|\}|\w|\.)+];
my $re_op = qr[=|!=|>=|<=|>|<|(?i:IS NOT)|(?i:IS)|(?i:NOT LIKE)|(?i:LIKE)]; # long to short
@@ -171,7 +176,7 @@
sub _parser {
my ($self,$string) = @_;
- my $want = KEYWORD | PAREN;
+ my $want = SELECT | KEYWORD | PAREN;
my $last = undef;
my $depth = 0;
@@ -188,7 +193,9 @@
while ($string =~ /(
- $re_aggreg
+ $re_select
+ |$re_where
+ |$re_aggreg
|$re_op
|$re_keyword
|$re_value
@@ -203,6 +210,9 @@
$current = KEYWORD if _match($re_keyword,$val) && ($want & KEYWORD);
$current = AGGREG if _match($re_aggreg,$val);
$current = PAREN if _match($re_paren,$val);
+ $current = COLUMN if _match($re_keyword,$val) && ($want & COLUMN);
+ $current = WHERE if _match($re_where,$val) && ($want & WHERE);
+ $current = SELECT if _match($re_select,$val);
unless ($current && $want & $current) {
@@ -230,7 +240,26 @@
$want = KEYWORD | PAREN | AGGREG;
}
+ elsif ($current & SELECT ) {
+ $want = COLUMN | WHERE;
+ }
+
+ elsif ($current & COLUMN ) {
+ if ($val =~ /$RE{delimited}{-delim=>qq{\'\"}}/) {
+ substr($val,0,1) = "";
+ substr($val,-1,1) = "";
+ }
+ # Unescape escaped characters
+ $val =~ s!\\(.)!$1!g;
+ $self->_DisplayColumn($val);
+
+ $want = COLUMN | WHERE;
+ }
+ elsif ($current & WHERE ) {
+ $want = KEYWORD | PAREN;
+
+ }
elsif ( $current & AGGREG ) {
$ea = $val;
$want = KEYWORD | PAREN;
@@ -376,63 +405,60 @@
use RT::Tickets;
-
+my $query = "SELECT id WHERE Status = 'open'";
my $tix = RT::Tickets->new($RT::SystemUser);
-my $query = "Status = 'open'";
my ($id, $msg) = $tix->FromSQL($query);
ok ($id, $msg);
+my @cols = $tix->DisplayColumns;
+
+ok ($cols[0]->{'attribute'} == 'id', "We're displaying the ticket id");
+ok ($cols[1] == undef, "We're displaying the ticket id");
-my (@ids, @expectedids);
-my $t = RT::Ticket->new($RT::SystemUser);
+my $query = "SELECT id, Status WHERE Status = 'open'";
-my $string = 'subject/content SQL test';
-ok( $t->Create(Queue => 'General', Subject => $string), "Ticket Created");
+my $tix = RT::Tickets->new($RT::SystemUser);
-push @ids, $t->Id;
+my ($id, $msg) = $tix->FromSQL($query);
-my $Message = MIME::Entity->build(
- Subject => 'this is my subject',
- From => 'jesse at example.com',
- Data => [ $string ],
- );
+ok ($id, $msg);
-ok( $t->Create(Queue => 'General', Subject => 'another ticket', MIMEObj => $Message, MemberOf => $ids[0]), "Ticket Created");
+my @cols = $tix->DisplayColumns;
-push @ids, $t->Id;
+ok ($cols[0]->{'attribute'} == 'id', "We're only displaying the ticket id");
+ok ($cols[1]->{'attribute'} == 'Status', "We're only displaying the ticket id");
-$query = ("Subject LIKE '$string' OR Content LIKE '$string'");
+my $query = qq[SELECT id, Status, '<A href="/Ticket/Display.html?id=##id##">Subject, this: ##Subject##</a>' WHERE Status = 'open'];
-my ($id, $msg) = $tix->FromSQL($query);
+my $tix = RT::Tickets->new($RT::SystemUser);
+
+my ($id, $msg) = $tix->FromSQL($query);
ok ($id, $msg);
-is ($tix->Count, scalar @ids, "number of returned tickets same as entered");
+my @cols = $tix->DisplayColumns;
-while (my $tick = $tix->Next) {
- push @expectedids, $tick->Id;
-}
+ok ($cols[0]->{'attribute'} == 'id', "We're only displaying the ticket id");
+ok ($cols[1]->{'attribute'} == 'Status', "We're only displaying the ticket id");
-ok (eq_array(\@ids, \@expectedids), "returned expected tickets");
-$query = ("id = $ids[0] OR MemberOf = $ids[0]");
-my ($id, $msg) = $tix->FromSQL($query);
+$query = "Status = 'open'";
+my ($id, $msg) = $tix->FromSQL($query);
ok ($id, $msg);
-is ($tix->Count, scalar @ids, "number of returned tickets same as entered");
+my @cols = $tix->DisplayColumns;
+
+ok ($cols[0] == undef, "We haven't explicitly asked to display anything");
+
+
- at expectedids = ();
-while (my $tick = $tix->Next) {
- push @expectedids, $tick->Id;
-}
-ok (eq_array(\@ids, \@expectedids), "returned expected tickets");
=end testing
@@ -499,6 +525,22 @@
Returns the query that this object was initialized with
+=begin testing
+
+my $query = "SELECT id, Status WHERE Status = 'open'";
+
+my $tix = RT::Tickets->new($RT::SystemUser);
+
+my ($id, $msg) = $tix->FromSQL($query);
+
+ok ($id, $msg);
+
+my $newq = $tix->Query();
+
+is ($query, $newq);
+
+=end testing
+
=cut
sub Query {
@@ -507,6 +549,71 @@
}
+=head2 _DisplayColumn COL
+
+Add COL to this search's list of "Columns to display"
+
+COL can either be a
+
+LiteralColumnName
+"QuotedString" (Containing ##LiteralColumnName## to embed the colum name inside it)
+
+What else?
+
+
+
+=cut
+
+sub _DisplayColumn {
+ my $self = shift;
+ my $col = shift;
+
+ my $colref;
+ if ( $col =~ s/\/STYLE:(.*?)$//io ) {
+ $colref->{'style'} = $1;
+ }
+ if ( $col =~ s/\/CLASS:(.*?)$//io ) {
+ $colref->{'class'} = $1;
+ }
+ if ( $col =~ s/\/TITLE:(.*?)$//io ) {
+ $colref->{'title'} = $1;
+ }
+ if ( $col =~ /__(.*?)__/gio ) {
+ my @subcols;
+ while ( $col =~ s/^(.*?)__(.*?)__//o ) {
+ push ( @subcols, $1 ) if ($1);
+ push ( @subcols, "__$2__" );
+ $colref->{'attribute'} = $2;
+ }
+ push ( @subcols, $col );
+ @{ $colref->{'output'} } = @subcols;
+ }
+ else {
+ @{ $colref->{'output'} } = ( "__" . $col . "__" );
+ $colref->{'attribute'} = $col;
+ }
+
+ if ( !$colref->{'title'} && grep { /^__(.*?)__$/io }
+ @{ $colref->{'output'} } )
+ {
+ $colref->{'title'} = $1;
+ $colref->{'attribute'} = $1;
+ }
+ push @{ $self->{'_sql_columns_to_display'} }, $colref;
+
+}
+
+=head2 DisplayColumns
+
+Returns an array of the columns to show in the printed results of this object
+
+=cut
+
+sub DisplayColumns {
+ my $self = shift;
+ return (@{$self->{'_sql_columns_to_display'}});
+}
+
1;
Modified: rt/branches/rt-3.1/lib/RT/Transaction.pm
==============================================================================
--- rt/branches/rt-3.1/lib/RT/Transaction.pm (original)
+++ rt/branches/rt-3.1/lib/RT/Transaction.pm Sat Jul 10 02:05:15 2004
@@ -46,7 +46,6 @@
package RT::Transaction;
use RT::Record;
-use RT::Ticket;
use vars qw( @ISA );
@@ -67,13 +66,16 @@
Create takes a hash of values and creates a row in the database:
- int(11) 'EffectiveTicket'.
- int(11) 'Ticket'.
+ varchar(64) 'ObjectType'.
+ int(11) 'ObjectId'.
int(11) 'TimeTaken'.
varchar(20) 'Type'.
varchar(40) 'Field'.
varchar(255) 'OldValue'.
varchar(255) 'NewValue'.
+ varchar(255) 'ReferenceType'.
+ int(11) 'OldReference'.
+ int(11) 'NewReference'.
varchar(255) 'Data'.
=cut
@@ -84,24 +86,30 @@
sub Create {
my $self = shift;
my %args = (
- EffectiveTicket => '0',
- Ticket => '0',
+ ObjectType => '',
+ ObjectId => '0',
TimeTaken => '0',
Type => '',
Field => '',
OldValue => '',
NewValue => '',
+ ReferenceType => '',
+ OldReference => '',
+ NewReference => '',
Data => '',
@_);
$self->SUPER::Create(
- EffectiveTicket => $args{'EffectiveTicket'},
- Ticket => $args{'Ticket'},
+ ObjectType => $args{'ObjectType'},
+ ObjectId => $args{'ObjectId'},
TimeTaken => $args{'TimeTaken'},
Type => $args{'Type'},
Field => $args{'Field'},
OldValue => $args{'OldValue'},
NewValue => $args{'NewValue'},
+ ReferenceType => $args{'ReferenceType'},
+ OldReference => $args{'OldReference'},
+ NewReference => $args{'NewReference'},
Data => $args{'Data'},
);
@@ -118,56 +126,42 @@
=cut
-=head2 EffectiveTicket
+=head2 ObjectType
-Returns the current value of EffectiveTicket.
-(In the database, EffectiveTicket is stored as int(11).)
+Returns the current value of ObjectType.
+(In the database, ObjectType is stored as varchar(64).)
-=head2 SetEffectiveTicket VALUE
+=head2 SetObjectType VALUE
-Set EffectiveTicket to VALUE.
+Set ObjectType to VALUE.
Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
-(In the database, EffectiveTicket will be stored as a int(11).)
+(In the database, ObjectType will be stored as a varchar(64).)
=cut
-=head2 Ticket
+=head2 ObjectId
-Returns the current value of Ticket.
-(In the database, Ticket is stored as int(11).)
+Returns the current value of ObjectId.
+(In the database, ObjectId is stored as int(11).)
-=head2 SetTicket VALUE
+=head2 SetObjectId VALUE
-Set Ticket to VALUE.
+Set ObjectId to VALUE.
Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
-(In the database, Ticket will be stored as a int(11).)
+(In the database, ObjectId will be stored as a int(11).)
=cut
-=head2 TicketObj
-
-Returns the Ticket Object which has the id returned by Ticket
-
-
-=cut
-
-sub TicketObj {
- my $self = shift;
- my $Ticket = RT::Ticket->new($self->CurrentUser);
- $Ticket->Load($self->__Value('Ticket'));
- return($Ticket);
-}
-
=head2 TimeTaken
Returns the current value of TimeTaken.
@@ -258,6 +252,60 @@
=cut
+=head2 ReferenceType
+
+Returns the current value of ReferenceType.
+(In the database, ReferenceType is stored as varchar(255).)
+
+
+
+=head2 SetReferenceType VALUE
+
+
+Set ReferenceType to VALUE.
+Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
+(In the database, ReferenceType will be stored as a varchar(255).)
+
+
+=cut
+
+
+=head2 OldReference
+
+Returns the current value of OldReference.
+(In the database, OldReference is stored as int(11).)
+
+
+
+=head2 SetOldReference VALUE
+
+
+Set OldReference to VALUE.
+Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
+(In the database, OldReference will be stored as a int(11).)
+
+
+=cut
+
+
+=head2 NewReference
+
+Returns the current value of NewReference.
+(In the database, NewReference is stored as int(11).)
+
+
+
+=head2 SetNewReference VALUE
+
+
+Set NewReference to VALUE.
+Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
+(In the database, NewReference will be stored as a int(11).)
+
+
+=cut
+
+
=head2 Data
Returns the current value of Data.
@@ -300,9 +348,9 @@
id =>
{read => 1, type => 'int(11)', default => ''},
- EffectiveTicket =>
- {read => 1, write => 1, type => 'int(11)', default => '0'},
- Ticket =>
+ ObjectType =>
+ {read => 1, write => 1, type => 'varchar(64)', default => ''},
+ ObjectId =>
{read => 1, write => 1, type => 'int(11)', default => '0'},
TimeTaken =>
{read => 1, write => 1, type => 'int(11)', default => '0'},
@@ -314,6 +362,12 @@
{read => 1, write => 1, type => 'varchar(255)', default => ''},
NewValue =>
{read => 1, write => 1, type => 'varchar(255)', default => ''},
+ ReferenceType =>
+ {read => 1, write => 1, type => 'varchar(255)', default => ''},
+ OldReference =>
+ {read => 1, write => 1, type => 'int(11)', default => ''},
+ NewReference =>
+ {read => 1, write => 1, type => 'int(11)', default => ''},
Data =>
{read => 1, write => 1, type => 'varchar(255)', default => ''},
Creator =>
Modified: rt/branches/rt-3.1/lib/RT/Transaction_Overlay.pm
==============================================================================
--- rt/branches/rt-3.1/lib/RT/Transaction_Overlay.pm (original)
+++ rt/branches/rt-3.1/lib/RT/Transaction_Overlay.pm Sat Jul 10 02:05:15 2004
@@ -75,7 +75,6 @@
my %args = (
id => undef,
TimeTaken => 0,
- Ticket => 0,
Type => 'undefined',
Data => '',
Field => undef,
@@ -84,24 +83,36 @@
MIMEObj => undef,
ActivateScrips => 1,
CommitScrips => 1,
+ ObjectType => 'RT::Ticket',
+ ObjectId => 0,
+ ReferenceType => undef,
+ OldReference => undef,
+ NewReference => undef,
@_
);
+ $args{ObjectId} ||= $args{Ticket};
+
#if we didn't specify a ticket, we need to bail
- unless ( $args{'Ticket'} ) {
- return ( 0, $self->loc( "Transaction->Create couldn't, as you didn't specify a ticket id"));
+ unless ( $args{'ObjectId'} && $args{'ObjectType'}) {
+ return ( 0, $self->loc( "Transaction->Create couldn't, as you didn't specify an object type and id"));
}
#lets create our transaction
- my %params = (Ticket => $args{'Ticket'},
+ my %params = (
Type => $args{'Type'},
Data => $args{'Data'},
Field => $args{'Field'},
OldValue => $args{'OldValue'},
NewValue => $args{'NewValue'},
- Created => $args{'Created'}
+ Created => $args{'Created'},
+ ObjectType => $args{'ObjectType'},
+ ObjectId => $args{'ObjectId'},
+ ReferenceType => $args{'ReferenceType'},
+ OldReference => $args{'OldReference'},
+ NewReference => $args{'NewReference'},
);
# Parameters passed in during an import that we probably don't want to touch, otherwise
@@ -116,7 +127,7 @@
#Provide a way to turn off scrips if we need to
$RT::Logger->debug('About to think about scrips for transaction' .$self->Id);
- if ( $args{'ActivateScrips'} ) {
+ if ( $args{'ActivateScrips'} and $args{'ObjectType'} eq 'RT::Ticket' ) {
$self->{'scrips'} = RT::Scrips->new($RT::SystemUser);
$RT::Logger->debug('About to prepare scrips for transaction' .$self->Id);
@@ -124,7 +135,7 @@
$self->{'scrips'}->Prepare(
Stage => 'TransactionCreate',
Type => $args{'Type'},
- Ticket => $args{'Ticket'},
+ Ticket => $args{'ObjectId'},
Transaction => $self->id,
);
if ($args{'CommitScrips'} ) {
@@ -493,13 +504,15 @@
return $self->loc("No transaction type specified");
}
+ my $obj_type = $self->FriendlyObjectType;
+
if ( $type eq 'Create' ) {
- return ($self->loc("Ticket created"));
+ return ($self->loc("[_1] created", $obj_type));
}
elsif ( $type =~ /Status/ ) {
if ( $self->Field eq 'Status' ) {
if ( $self->NewValue eq 'deleted' ) {
- return ($self->loc("Ticket deleted"));
+ return ($self->loc("[_1] deleted", $obj_type));
}
else {
return ( $self->loc("Status changed from [_1] to [_2]", $self->loc($self->OldValue), $self->loc($self->NewValue) ));
@@ -721,6 +734,7 @@
sub IsInbound {
my $self = shift;
+ $self->ObjectType eq 'RT::Ticket' or return undef;
return ( $self->TicketObj->IsRequestor( $self->CreatorObj->PrincipalId ) );
}
@@ -837,6 +851,77 @@
# }}}
+sub Ticket {
+ my $self = shift;
+ return $self->ObjectId;
+}
+
+sub TicketObj {
+ my $self = shift;
+ return $self->Object;
+}
+
+sub OldValue {
+ my $self = shift;
+ if (my $type = $self->__Value('ReferenceType')) {
+ my $Object = $type->new($self->CurrentUser);
+ $Object->Load($self->__Value('OldReference'));
+ return $Object->Content;
+ }
+ else {
+ return $self->__Value('OldValue');
+ }
+}
+
+sub NewValue {
+ my $self = shift;
+ if (my $type = $self->__Value('ReferenceType')) {
+ my $Object = $type->new($self->CurrentUser);
+ $Object->Load($self->__Value('NewReference'));
+ return $Object->Content;
+ }
+ else {
+ return $self->__Value('NewValue');
+ }
+}
+
+sub Object {
+ my $self = shift;
+ my $Object = $self->__Value('ObjectType')->new($self->CurrentUser);
+ $Object->Load($self->__Value('ObjectId'));
+ return($Object);
+}
+
+sub FriendlyObjectType {
+ my $self = shift;
+ my $type = $self->ObjectType or return undef;
+ $type =~ s/^RT:://;
+ return $self->loc($type);
+}
+
+sub UpdateCustomFields {
+ my ($self, %args) = @_;
+ my $args_ref = $args{ARGSRef} or return;
+
+ foreach my $arg ( keys %$args_ref ) {
+ $arg =~ /^(?:Transaction)?CustomField-(\d+).*?(?<!-Magic)$/ or next;
+ my $cfid = $1;
+ my $values = $args_ref->{$arg};
+ foreach my $value ( UNIVERSAL::isa($values, 'ARRAY') ? @$values : $values ) {
+ next unless length($value);
+ $self->_AddCustomFieldValue(
+ Field => $cfid,
+ Value => $value,
+ RecordTransaction => 0,
+ );
+ }
+ }
+}
+
+sub _LookupTypes {
+ "RT::Queue-RT::Ticket-RT::Transaction";
+}
+
# Transactions don't change. by adding this cache congif directiove, we don't lose pathalogically on long tickets.
sub _CacheConfig {
{
Modified: rt/branches/rt-3.1/lib/RT/Transactions_Overlay.pm
==============================================================================
--- rt/branches/rt-3.1/lib/RT/Transactions_Overlay.pm (original)
+++ rt/branches/rt-3.1/lib/RT/Transactions_Overlay.pm Sat Jul 10 02:05:15 2004
@@ -63,6 +63,30 @@
}
# }}}
+=head2 Limit
+
+A wrapper around SUPER::Limit to catch migration issues
+
+=cut
+
+sub Limit {
+ my $self = shift;
+ my %args = (@_);
+
+ if ($args{'FIELD'} eq 'Ticket') {
+ Carp::cluck("Historical code calling RT::Transactions::Limit with a 'Ticket'. This deprecated API will be deleted in 3.6");
+ $self->SUPER::Limit(FIELD => 'ObjectType', OPERATOR => '=', VALUE =>'RT::Ticket');
+ $args{'FIELD'} = 'ObjectId';
+ $self->SUPER::Limit(%args);
+
+ } else {
+
+ $self->SUPER::Limit(%args);
+ }
+
+
+}
+
# {{{ sub Next
sub Next {
my $self = shift;
Modified: rt/branches/rt-3.1/lib/RT/User_Overlay.pm
==============================================================================
--- rt/branches/rt-3.1/lib/RT/User_Overlay.pm (original)
+++ rt/branches/rt-3.1/lib/RT/User_Overlay.pm Sat Jul 10 02:05:15 2004
@@ -149,9 +149,13 @@
Privileged => 0,
Disabled => 0,
EmailAddress => '',
+ _RecordTransaction => 1,
@_ # get the real argumentlist
);
+ # remove the value so it does not cripple SUPER::Create
+ my $record_transaction = delete $args{'_RecordTransaction'};
+
#Check the ACL
unless ( $self->CurrentUser->HasRight(Right => 'AdminUsers', Object => $RT::System) ) {
return ( 0, $self->loc('No permission to create users') );
@@ -292,7 +296,12 @@
}
+ if ( $record_transaction ) {
+ $self->_NewTransaction( Type => "Create" );
+ }
+
$RT::Handle->Commit;
+
return ( $id, $self->loc('User created') );
}
@@ -1002,7 +1011,7 @@
=head2 _GeneratePassword PASSWORD
-returns an MD5 hash of the password passed in, in base64 encoding.
+returns an MD5 hash of the password passed in, in hexadecimal encoding.
=cut
@@ -1012,6 +1021,23 @@
my $md5 = Digest::MD5->new();
$md5->add($password);
+ return ($md5->hexdigest);
+
+}
+
+=head2 _GeneratePasswordBase64 PASSWORD
+
+returns an MD5 hash of the password passed in, in base64 encoding
+(obsoleted now).
+
+=cut
+
+sub _GeneratePasswordBase64 {
+ my $self = shift;
+ my $password = shift;
+
+ my $md5 = Digest::MD5->new();
+ $md5->add($password);
return ($md5->b64digest);
}
@@ -1055,9 +1081,12 @@
}
# if it's a historical password we say ok.
-
- if ( $self->__Value('Password') eq crypt( $value, $self->__Value('Password') ) ) {
- return (1);
+ if ($self->__Value('Password') eq crypt($value, $self->__Value('Password'))
+ or $self->_GeneratePasswordBase64($value) eq $self->__Value('Password'))
+ {
+ # ...but upgrade the legacy password inplace.
+ $self->SUPER::SetPassword( $self->_GeneratePassword($value) );
+ return(1);
}
# no password check has succeeded. get out
@@ -1109,7 +1138,7 @@
ok(my $u = RT::User->new($RT::SystemUser));
ok($u->Load(1), "Loaded the first user");
ok($u->PrincipalObj->ObjectId == 1, "user 1 is the first principal");
-ok($u->PrincipalObj->PrincipalType eq 'User' , "Principal 1 is a user, not a group");
+is($u->PrincipalObj->PrincipalType, 'User' , "Principal 1 is a user, not a group");
=end testing
@@ -1273,7 +1302,7 @@
my $new_tick2 = RT::Ticket->new($RT::SystemUser);
my ($tick2id, $tickmsg) = $new_tick2->Create(Subject=> 'ACL Test 2', Queue =>$q_as_system->Id);
ok($tick2id, "Created ticket: $tick2id");
-ok($new_tick2->QueueObj->id eq $q_as_system->Id, "Created a new ticket in queue 1");
+is($new_tick2->QueueObj->id, $q_as_system->Id, "Created a new ticket in queue 1");
# make sure that the user can't do this without subgroup membership
@@ -1523,6 +1552,8 @@
my %args = (
Field => undef,
Value => undef,
+ TransactionType => 'Set',
+ RecordTransaction => 1,
@_
);
@@ -1536,13 +1567,29 @@
return ( 0, $self->loc("Permission Denied") );
}
- #Set the new value
- my ( $ret, $msg ) = $self->SUPER::_Set(
- Field => $args{'Field'},
- Value => $args{'Value'}
- );
-
- return ( $ret, $msg );
+ my $Old = $self->SUPER::_Value("$args{'Field'}");
+
+ my ($ret, $msg) = $self->SUPER::_Set( Field => $args{'Field'},
+ Value => $args{'Value'} );
+
+ #If we can't actually set the field to the value, don't record
+ # a transaction. instead, get out of here.
+ if ( $ret == 0 ) { return ( 0, $msg ); }
+
+ if ( $args{'RecordTransaction'} == 1 ) {
+
+ my ( $Trans, $Msg, $TransObj ) = $self->_NewTransaction(
+ Type => $args{'TransactionType'},
+ Field => $args{'Field'},
+ NewValue => $args{'Value'},
+ OldValue => $Old,
+ TimeTaken => $args{'TimeTaken'},
+ );
+ return ( $Trans, scalar $TransObj->Description );
+ }
+ else {
+ return ( $ret, $msg );
+ }
}
# }}}
@@ -1592,6 +1639,14 @@
# }}}
+sub BasicColumns {
+ (
+ [ Name => 'User Id' ],
+ [ EmailAddress => 'Email' ],
+ [ RealName => 'Name' ],
+ [ Organization => 'Organization' ],
+ );
+}
1;
Modified: rt/branches/rt-3.1/releng.cnf
==============================================================================
--- rt/branches/rt-3.1/releng.cnf (original)
+++ rt/branches/rt-3.1/releng.cnf Sat Jul 10 02:05:15 2004
@@ -1,7 +1,7 @@
PRODUCT = rt
-TAG = 3.2.0
+TAG = 3.3.4
CANONICAL_REPO = svn+ssh://svn.bestpractical.com/svn/bps-public/rt/
TAGS = tags/
-TRUNK = branches/rt-3.1/
+TRUNK = branches/rt-3.3/
TMP_DIR = /tmp
RELEASE_DIR = /home/ftp/pub/rt/devel
Modified: rt/branches/rt-3.1/sbin/extract-message-catalog
==============================================================================
--- rt/branches/rt-3.1/sbin/extract-message-catalog (original)
+++ rt/branches/rt-3.1/sbin/extract-message-catalog Sat Jul 10 02:05:15 2004
@@ -174,6 +174,7 @@
while (@lines) {
my $msghdr = "";
$msghdr .= shift @lines while ( $lines[0] && $lines[0] !~ /^msgid/ );
+
my $msgid = shift @lines;
my $msgstr = "";
$msgstr .= shift @lines while ( $lines[0] && $lines[0] =~ /^(msgstr|")/ );
@@ -182,8 +183,8 @@
chomp $msgid;
chomp $msgstr;
- $msgid =~ s/^msgid "(.*)"$/$1/ or warn $msgid;
- $msgstr =~ s/^msgstr "(.*)"$/$1/ms or warn $msgstr;
+ $msgid =~ s/^msgid "(.*)"\s*?$/$1/ms or warn "$msgid in $file";
+ $msgstr =~ s/^msgstr "(.*)"\s*?$/$1/ms or warn "$msgstr in $file";
$Lexicon{$msgid} = $msgstr;
$Header{$msgid} = $msghdr;
@@ -208,6 +209,10 @@
my %seen;
$out .= $Header{$_} if exists $Header{$_};
+
+
+
+ next if (!$f && $_ && !$Lexicon{$_});
if ( $f && $f !~ /^\s+$/ ) {
$out .= "#: $f\n";
Added: rt/branches/rt-3.1/sbin/rt-dump-database.in
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.1/sbin/rt-dump-database.in Sat Jul 10 02:05:15 2004
@@ -0,0 +1,102 @@
+#!@PERL@ -w
+
+use strict;
+use lib "@RT_LIB_PATH@";
+use RT;
+
+RT::LoadConfig();
+RT::Init();
+
+my $LocalOnly = shift || 1;
+
+my %RV;
+my %Ignore = (
+ All => [qw(
+ id Created Creator LastUpdated LastUpdatedBy
+ )],
+ Templates => [qw(
+ TranslationOf
+ )],
+);
+
+my $SystemUserId = $RT::SystemUser->Id;
+my @classes = qw(
+ Users Groups Queues ScripActions ScripConditions
+ Templates Scrips ACL CustomFields
+);
+foreach my $class (@classes) {
+ require "RT/$class.pm";
+ my $objects = "RT::$class"->new($RT::SystemUser);
+ $objects->{find_disabled_rows} = 1;
+ $objects->UnLimit;
+ $objects->OrderBy( FIELD => 'Id' );
+
+ if ($LocalOnly) {
+ $objects->Limit( FIELD => 'LastUpdatedBy', OPERATOR => '!=', VALUE => $SystemUserId )
+ unless $class eq 'Groups';
+ $objects->Limit( FIELD => 'Id', OPERATOR => '!=', VALUE => $SystemUserId )
+ if $class eq 'Users';
+ }
+
+ my %fields;
+ while (my $obj = $objects->Next) {
+ next if $obj->can('LastUpdatedBy') and $obj->LastUpdatedBy == $SystemUserId;
+
+ if (!%fields) {
+ %fields = map { $_ => 1 } keys %{$obj->_ClassAccessible};
+ delete @fields{
+ @{$Ignore{$class}||=[]},
+ @{$Ignore{All}||=[]},
+ };
+ }
+
+ my $rv;
+ # next if $obj-> # skip default names
+ foreach my $field (sort keys %fields) {
+ my $value = $obj->__Value($field);
+ $rv->{$field} = $value if length($value);
+ }
+ delete $rv->{Disabled} unless $rv->{Disabled};
+
+ foreach my $record (map { /ACL/ ? 'ACE' : substr($_, 0, -1) } @classes) {
+ foreach my $key (map "$record$_", ('', 'Id')) {
+ next unless exists $rv->{$key};
+ my $id = $rv->{$key} or next;
+ my $obj = "RT::$record"->new($RT::SystemUser);
+ $obj->LoadByCols( Id => $id ) or next;
+ $rv->{$key} = $obj->__Value('Name') || 0;
+ }
+ }
+
+ if ($class eq 'Users') {
+ $rv->{Privileged} = int($obj->Privileged);
+ }
+ elsif ($class eq 'CustomFields') {
+ my $values = $obj->Values;
+ while (my $value = $values->Next) {
+ push @{$rv->{Values}}, {
+ map { ($_ => $value->__Value($_)) } qw(
+ Name Description SortOrder
+ ),
+ };
+ }
+ }
+
+ if (eval { require RT::Attributes; 1 }) {
+ my $attributes = $obj->Attributes;
+ while (my $attribute = $attributes->Next) {
+ my $content = $attribute->Content;
+ $rv->{Attributes}{$attribute->Name} = $content if length($content);
+ }
+ }
+
+ push @{$RV{$class}}, $rv;
+ }
+}
+
+use Data::Dumper;
+print Data::Dumper->Dump(
+ [map { $RV{$_} || [] } @classes],
+ [map { "*$_" } @classes],
+);
+
Added: rt/branches/rt-3.1/spec/schema.txt
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.1/spec/schema.txt Sat Jul 10 02:05:15 2004
@@ -0,0 +1,51 @@
+CF Schema redesign V5.
+======================
+
+TABLE CustomFields (
+ id INTEGER NOT NULL AUTO_INCREMENT,
+ Name varchar(200) NULL ,
+ Type varchar(200) NULL , # Changed -- 'Single' and 'Multiple' is moved out
+ MaxValues integer, # New -- was 'Single'(1) and 'Multiple'(0)
+ Pattern varchar(255) NULL , # New -- Must validate against this
+ LookupType varchar(255) NOT NULL, # Lookup paths like "RT::Queue-RT::Ticket"
+ Description varchar(255) NULL ,
+ SortOrder integer NOT NULL DEFAULT 0 , # not used!
+)
+
+TABLE ObjectCustomFields (
+ id INTEGER NOT NULL AUTO_INCREMENT,
+ CustomField int NOT NULL , # CustomField ID
+ ObjectId integer NOT NULL, # Final id of toplevel parent, or the
+ # object itself if ParentType is empty;
+ # 0 means global as usual.
+ SortOrder integer NOT NULL DEFAULT 0 ,
+);
+
+TABLE ObjectCustomFieldValues ( # New -- Replaces TicketCustomFieldValues
+ id INTEGER NOT NULL AUTO_INCREMENT,
+ CustomField int NOT NULL ,
+ ObjectType varchar(255) NOT NULL, # Final target of the Object
+ ObjectId int NOT NULL , # New -- Replaces Ticket
+ SortOrder integer NOT NULL DEFAULT 0 ,
+
+ Current BOOL DEFAULT '1', # New -- whether the value was current
+ Content varchar(255) NULL ,
+ LargeContent LONGTEXT NULL, # New -- to hold 255+ strings
+ ContentType varchar(80) NULL, # New -- only text/* gets searched
+ ContentEncoding varchar(80) NULL , # New -- for binary Content
+)
+
+TABLE Transactions (
+ id INTEGER NOT NULL AUTO_INCREMENT,
+ ObjectType varchar(255) NULL, # Final target of the Object
+ ObjectId integer NOT NULL DEFAULT 0 , # Changed -- was Ticket
+ TimeTaken integer NOT NULL DEFAULT 0 ,
+ Type varchar(20) NULL ,
+ Field varchar(40) NULL ,
+ OldValue varchar(255) NULL ,
+ NewValue varchar(255) NULL ,
+ ReferenceType varchar(255) NULL, # Currently "RT::OCFV" only
+ OldReference integer NULL , # New -- Id of ReferenceType
+ NewReference integer NULL , # New -- Id of ReferenceType
+ Data varchar(255) NULL ,
+)
More information about the Rt-commit
mailing list