'FREESIDE_1_5_BRANCH'.
# BEGIN LICENSE BLOCK
#
-# Copyright (c) 1996-2002 Jesse Vincent <jesse@bestpractical.com>
+# Copyright (c) 1996-2003 Jesse Vincent <jesse@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
+# 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
#
#
# END LICENSE BLOCK
-
-
#
# DO NOT HAND-EDIT the file named 'Makefile'. This file is autogenerated.
# Have a look at "configure" and "Makefile.in" instead
RT_VERSION_MAJOR = 3
RT_VERSION_MINOR = 0
-RT_VERSION_PATCH = 4
+RT_VERSION_PATCH = 9
RT_VERSION = $(RT_VERSION_MAJOR).$(RT_VERSION_MINOR).$(RT_VERSION_PATCH)
TAG = rt-$(RT_VERSION_MAJOR)-$(RT_VERSION_MINOR)-$(RT_VERSION_PATCH)
RT_FASTCGI_HANDLER = $(RT_BIN_PATH)/mason_handler.fcgi
# RT_WIN32_FASTCGI_HANDLER is the mason handler script for FastCGI
RT_WIN32_FASTCGI_HANDLER = $(RT_BIN_PATH)/mason_handler.svc
-# RT's admin CLI
-RT_CLI_ADMIN_BIN = $(RT_BIN_PATH)/rtadmin
+# RT's CLI
+RT_CLI_BIN = $(RT_BIN_PATH)/rt
# RT's mail gateway
RT_MAILGATE_BIN = $(RT_BIN_PATH)/rt-mailgate
# RT's cron tool
BINARIES = $(DESTDIR)/$(RT_MODPERL_HANDLER) \
$(DESTDIR)/$(RT_MAILGATE_BIN) \
+ $(DESTDIR)/$(RT_CLI_BIN) \
$(DESTDIR)/$(RT_CRON_BIN) \
$(SETGID_BINARIES)
SYSTEM_BINARIES = $(DESTDIR)/$(RT_SBIN_PATH)/
# DB_TYPE defines what sort of database RT trys to talk to
# "mysql" is known to work.
# "Pg" is known to work
+# "Informix" is known to work
DB_TYPE = mysql
# For mysql, you probably want 'root'
# For Pg, you probably want 'postgres'
-# For oracle, you want 'system'
+# For Oracle, you want 'system'
+# For Informix, you want 'informix'
DB_DBA = root
@echo " $(RT_SBIN_PATH)/rt-setup-database --action insert --datafile etc/upgrade/<version>"
-upgrade: dirs upgrade-noclobber upgrade-instruct
+upgrade: config-install dirs files-install fixperms upgrade-instruct
upgrade-noclobber: config-install libs-install html-install bin-install local-install doc-install fixperms
test:
$(PERL) -Ilib lib/t/00smoke.t
-regression-nosetgid-quiet: config-install dirs files-install libs-install sbin-install bin-install regression-instruct regression-reset-db testify-pods fixperms-nosetgid apachectl
+regression-install: config-install
+ $(PERL) -pi -e 's/Set\(\$$DatabaseName.*\);/Set\(\$$DatabaseName, "rt3regression"\);/' $(DESTDIR)/$(CONFIG_FILE)
+
+regression-nosetgid-quiet: regression-install dirs files-install libs-install sbin-install bin-install regression-instruct regression-reset-db testify-pods fixperms-nosetgid apachectl
$(PERL) sbin/regression_harness
-regression-nosetgid: config-install dirs files-install libs-install sbin-install bin-install regression-instruct regression-reset-db testify-pods fixperms-nosetgid apachectl
+regression-nosetgid: regression-install dirs files-install libs-install sbin-install bin-install regression-instruct regression-reset-db testify-pods fixperms-nosetgid apachectl
$(PERL) lib/t/02regression.t
-regression: config-install dirs files-install libs-install sbin-install bin-install regression-instruct regression-reset-db testify-pods apachectl
+regression: regression-install dirs files-install libs-install sbin-install bin-install regression-instruct regression-reset-db testify-pods fixperms apachectl
$(PERL) lib/t/02regression.t
regression-quiet:
-cp -rp \
bin/rt-mailgate \
bin/mason_handler.fcgi \
+ bin/mason_handler.scgi \
bin/mason_handler.svc \
+ bin/rt \
bin/webmux.pl \
bin/rt-crontool \
$(DESTDIR)/$(RT_BIN_PATH)
-# BEGIN LICENSE BLOCK
-#
-# Copyright (c) 1996-2003 Jesse Vincent <jesse@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
-RT is an enterprise-grade issue tracking system. It allows
-organizations to keep track of their to-do lists, who is working
-on which tasks, what's already been done, and when tasks were
-completed. It is available under the terms of version 2 of the GNU
-General Public License (GPL), so it doesn't cost anything to set
-up and use.
+RT is an enterprise-grade issue tracking system. It allows organizations
+to keep track of what needs to get done, who is working on which tasks,
+what's already been done, and when tasks were (or weren't) completed.
+RT doesn't cost anything to use, no matter how much you use it; it
+is freely available under the terms of Version 2 of the GNU General
+Public License.
+
+RT is commercially-supported software. To purchase support, training,
+custom development, or professional services, please get in touch with
+us at sales@bestpractical.com.
+
+ Jesse Vincent
+ Best Practical Solutions, LLC
+ March, 2005
- Jesse Vincent
- Best Practical Solutions, LLC
- March 2003
REQUIRED PACKAGES:
------------------
-o Perl 5.8.0 or later (http://www.perl.com).
+o Perl 5.8.3 or later (http://www.perl.com).
- (If you intend to use the FastCGI or SpeedyCGI support, you
- need to make sure that perl has been built with support for
- setgid perl scripts.)`
+ Perl versions prior to 5.8.3 contain bugs that could result
+ in data corruption. We recommend strongly that you use 5.8.3
+ or newer.
- Perl 5.6.1 is currently deprecated and will be officially desupported
- in a future release
+o A supported SQL database
-o A DB backend; MySQL is recommended ( http://www.mysql.com )
- Currently supported: Mysql 4.0.13 or later.
+ Currently supported: Mysql 4.0.13 or later with InnoDB support.
Postgres 7.2 or later.
-
- Mysql 3.23.46 or newer with support for InnoDB
- is currently deprecated and will be officially
- desupported in a future release.
+ Oracle 9iR2 or later.
+ SQLite 3.0. (Not recommended for production)
o Apache version 1.3.x or 2.x (http://httpd.apache.org)
- with mod_perl -- (http://perl.apache.org )
- or a webserver with FastCGI support (www.fastcgi.com)
-
- mod_perl 2.0 isn't quite ready for prime_time just yet;
- Best Practical Solutions strongly recommends that sites use
- Apache 1.3 or FastCGI.
+ with mod_perl -- (http://perl.apache.org )
+ or a webserver with FastCGI support (www.fastcgi.com)
Compiling mod_perl on Apache 1.3.x as a DSO has been known
- to have massive stability problems and is not recommended.
-
- mod_perl 1.x must be build with EVERYTHING=1
-
- RT's FastCGI handler runs setgid to the 'rt' group to
- protect RT's database password. You may need to install
- a special "suidperl" package or reconfigure your perl
- setup to support "setuid scripts" if you intend to use RT
- with FastCGI.
-
- Debian GNU/* 3.0+: the package which installs suidperl is
- called perl-suid, and should work without any tweaking.
-
- FreeBSD 4.2+: the package is called sperl, and should
- install a suidperl that just works
-
- Conectiva Linux 6.0+: suidperl is installed by default when
- perl is installed, but the program /bin/suidperl is not setuid.
- You must use chmod to make it setuid.
+ to have massive stability problems and is not recommended.
+ mod_perl 1.x must be built with EVERYTHING=1
+ RT's FastCGI handler needs to access RT's configuration file.
o Various and sundry perl modules
A tool included with RT takes care of the installation of
The tool supplied with RT uses Perl's CPAN system
(http://www.cpan.org) to install modules. Some operating
- systems package all or some of the modules required and
+ systems package all or some of the modules required, and
you may be better off installing the modules that way.
GENERAL INSTALLATION
--------------------
-This is a rough guide to installing RT. For more detail, you'll want
-to read 'Chapter 2: Installing' in RT's manual, available at
-http://www.bestpractical.com/rt
+This is a rough guide to installing RT. For more detail, you'll
+want to read a more comprehensive installation guide at:
+
+ http://wiki.bestpractical.com/index.cgi?InstallationGuides
-1 Unpack this distribution SOMWHERE OTHER THAN where you want to install RT
+1 Unpack this distribution other than where you want to install RT
- Granted, you've already got it open. To do this cleanly:
+ To do this cleanly, run the following command:
- tar xzvf rt.tar.gz -C /tmp
+ tar xzvf rt.tar.gz -C /tmp
2 Run the "configure" script.
- ./configure --help to see the list of options
- ./configure (with the flags you want)
+ ./configure --help to see the list of options
+ ./configure (with the flags you want)
+
+ RT defaults to installing in /opt/rt3 with MySQL as its database. It
+ tries to guess which of www-data, www, apache or nobody your webserver
+ will run as, but you can override that behavior.
+
+3 Make sure that RT has everything it needs to run.
+
+ Check for missing dependencies by running:
+
+ make testdeps
-3 Satisfy RT's myriad dependencies.
+4 If the script reports any missing dependencies, install them by hand
+ or run the following command as a user who has permission to install perl
+ modules on your system:
-3.1 Check for compliance:
-
- perl sbin/rt-test-dependencies \
- --with-<databasename> --with-<web-environment>
+ make fixdeps
- databasename is one of: mysql, postgres
- web-environment is one of: fastcgi, modperl1, modperl2
+5 Check to make sure everything was installed properly.
+
+ make testdeps
-3.2 If there are unsatisfied dependencies, install them by hand or run:
+ It might sometimes be necessary to run "make fixdeps" several times
+ to install all necessary perl modules.
- perl sbin/rt-test-dependencies \
- --with-<databasename> --with-<web-environment> --install
-
+6 If this is a new installation:
+
+ As a user with permission to install RT in your chosen directory, type:
-3.3 Check to make sure everything was installed properly:
+ make install
+
+ Set up etc/RT_SiteConfig.pm in your RT installation directory.
+ You'll need to add any values you need to change from the defaults
+ in etc/RT_Config.pm
- perl sbin/rt-test-dependencies \
- --with-<databasename> --with-<web-environment>
+ As a user with permission to read RT's configuration file, type:
+
+ make initialize-database
-4 Create a group called 'rt'
+ If the make fails, type:
+
+ make dropdb
-5a FOR A NEW INSTALLATION:
-
- As root, type:
- make install (replace "make" with the local name for
- Make, if you need to)
+ and start over from step 6
-
- make initialize-database
+7 If you're upgrading from RT 3.0 or newer:
+ Read through the UPGRADING document included in this distribution.
+
+ It includes special upgrade instructions that will help you get this
+ new version of RT up and running smoothly.
- If the make fails, type:
- make dropdb
- and start over from step 5a
+ As a user with permission to install RT in your chosen installation
+ directory, type:
-5b FOR UPGRADING: (Within the RT 3.0.x series)
+ make upgrade
- As root, type:
- make upgrade (replace "make" with the local name for
- Make, if you need to)
+ This will install new binaries, config files and libraries without
+ overwriting your RT database.
- This will build new binaries, config files and libraries without
- overwriting your RT database.
-
- It may then instruct you to update your RT system database objects
+ Update etc/RT_SiteConfig.pm in your RT installation directory.
+ You'll need to add any new values you need to change from the defaults
+ in etc/RT_Config.pm
-6 Edit etc/RT_SiteConfig.pm in your RT installation directory, by specifying
- any values you need to change from the defaults in etc/RT_Config.pm
+ You may also need to update RT's database. To find out, type:
-7 Configure the email and web gateways, as described below.
+ ls etc/upgrade
-8 Stop and start your webserver, so it picks up your configuration changes.
+ For each item in that directory whose name is greater than
+ your previously installed RT version, run:
+
+ /opt/rt3/sbin/rt-setup-database --action schema \
+ --datadir etc/upgrade/<version>
+ /opt/rt3/sbin/rt-setup-database --action acl \
+ --datadir etc/upgrade/<version>
+ /opt/rt3/sbin/rt-setup-database --action insert \
+ --datadir etc/upgrade/<version>
+
+8 If you're upgrading from RT 2.0:
+
+ Please upgrade from RT 2.0 to RT 3.2 and then follow the instructions
+ for section 7.
+
+9 Configure the email and web gateways, as described below.
NOTE: root's password for the web interface is "password"
- (without the quotes.) Not changing this is a SECURITY risk
+ (without the quotes). Not changing this is a SECURITY risk!
-9 Configure RT per the instructions in RT's manual.
+10 Set up users, groups, queues, scrips and access control.
Until you do this, RT will not be able to send or receive email,
nor will it be more than marginally functional. This is not an
optional step.
-THE WEB INTERFACE
------------------
+SETTING UP THE WEB INTERFACE
+----------------------------
+
+RT's web interface is based around HTML::Mason, which works well with
+the mod_perl perl interpreter within Apache httpd and FastCGI
-RT's web interface is based around HTML::Mason, which works best with the mod_perl
-perl interpreter within Apache httpd. Alternatively, support for the FastCGI
-(and plain CGI) interface is also provided as 'bin/mason_handler.fcgi'.
+mod_perl
+--------
-Apache
- You'll need to add a few lines to your httpd.conf telling it about RT:
+To install RT with mod_perl, you'll need to install the
+apache database connection cache. To make sure it's installed, run
+the following command:
+
+ perl -MCPAN -e'install Apache::DBI'
+
+Next, add a few lines to your Apache configuration file, so that
+it knows where to find RT:
<VirtualHost your.ip.address>
ServerName your.rt.server.hostname
DocumentRoot /opt/rt3/share/html
AddDefaultCharset UTF-8
- # this line applies to Apache2+mod_perl2 only
- PerlModule Apache2 Apache::compat
-
PerlModule Apache::DBI
PerlRequire /opt/rt3/bin/webmux.pl
- # this section applies to Apache 1 only
<Location />
- SetHandler perl-script
- PerlHandler RT::Mason
+ SetHandler perl-script
+ PerlHandler RT::Mason
</Location>
+</VirtualHost>
+
+FastCGI
+-------
+
+Installation with FastCGI is a little bit more complex and is documented
+in detail at http://wiki.bestpractical.com/index.cgi?FastCGIConfiguration
+
+In the most basic configuration, you can set up your webserver to run
+as a user who is a member of the "rt" unix group so that the FastCGI script
+can read RT's configuration file. It's important to understand the security
+implications of this configuration, which are discussed in the document
+mentioned above.
+
+To install RT with FastCGI, you'll need to add a few lines to your
+Apache configuration file telling it about RT:
+
+<VirtualHost rt.example.com>
+
+ # Pass through requests to display images
+ Alias /NoAuth/images/ /opt/rt3/share/html/NoAuth/images/
+
+ # Tell FastCGI to put its temporary files somewhere sane.
+ FastCgiIpcDir /tmp
+
+ FastCgiServer /opt/rt3/bin/mason_handler.fcgi -idle-timeout 120
- # this section applies to Apache2+mod_perl2 only
- <FilesMatch "\.html$">
- SetHandler perl-script
- PerlHandler RT::Mason
- </FilesMatch>
- <LocationMatch "/Attachment/">
- SetHandler perl-script
- PerlHandler RT::Mason
- </LocationMatch>
- <LocationMatch "/REST/">
- SetHandler perl-script
- PerlHandler RT::Mason
- </LocationMatch>
+ AddHandler fastcgi-script fcgi
+ ScriptAlias / /opt/rt3/bin/mason_handler.fcgi/
+
</VirtualHost>
SETTING UP THE MAIL GATEWAY
---------------------------
-An alias for the initial queue will need to be made in either your
-global mail aliases file (if you are using NIS) or locally on your
-machine.
-
-Add the following lines to /etc/aliases (or your local equivalent) :
+To let email flow to your RT server, you need to add a few lines of
+configuration to your mail server's "aliases" file. These lines "pipe"
+incoming email messages from your mail server to RT.
-rt: "|/opt/rt3/bin/rt-mailgate --queue general --action correspond --url http://localhost/"
-rt-comment: "|/opt/rt3/bin/rt-mailgate --queue general --action comment --url http://localhost/"
- | | |
- <queue-name>----/ | |
- | |
- <correspond or comment depending on whether | |
- the mail should be resent to the requestor>---/ |
- |
- <URL for RT's web interface>---/
+Add the following lines to /etc/aliases (or your local equivalent) on your mail server:
+rt: "|/opt/rt3/bin/rt-mailgate --queue general --action correspond --url http://rt.example.com/"
+rt-comment: "|/opt/rt3/bin/rt-mailgate --queue general --action comment --url http://rt.example.com/"
+
+You'll need to add similar lines for each queue you want to be able
+to send email to. To find out more about how to configure RT's email
+gateway, type:
+
+ perldoc /opt/rt3/bin/rt-mailgate
-BUGS
-----
-To report a bug, send email to rt-3.0-bugs@fsck.com.
GETTING HELP
------------
If RT is mission-critical for you or if you use it heavily, we recommend that
you purchase a commercial support contract. Details on support contracts
-are available at http://www.bestpractical.com.
+are available at http://www.bestpractical.com or by writing to
+<sales@bestpractical.com>.
If you're interested in having RT extended or customized or would like more
information about commercial support options, please send email to
<sales@bestpractical.com> to discuss rates and availability.
-RT-USERS MAILINGLIST
+
+RT WEBSITE
+----------
+
+For current information about RT, check out the RT website at
+ http://www.bestpractical.com/
+
+You'll find screenshots, a pointer to the current version of RT, contributed
+patches, and lots of other great stuff.
+
+
+
+RT-USERS MAILING LIST
--------------------
To keep up to date on the latest RT tips, techniques and extensions,
you probably want to join the rt-users mailing list. Send a message to:
- rt-users-request@lists.fsck.com
+ rt-users-request@lists.bestpractical.com
-With the body of the message consisting of only the word:
+with the body of the message consisting of only the word:
- subscribe
+ subscribe
If you're interested in hacking on RT, you'll want to subscribe to
-rt-devel@lists.fsck.com. Subscribe to it with instructions similar to
-those above.
+rt-devel@lists.bestpractical.com. Subscribe to it with instructions
+similar to those above.
Address questions about the stable release to the rt-users list, and
questions about the development version to the rt-devel list. If you feel
<jesse@bestpractical.com>.
-RT WEBSITE
-----------
-
-For current information about RT, check out the RT website at
- http://www.bestpractical.com/
-
-You'll find screenshots, a pointer to the current version of RT, contributed
-patches, and lots of other great stuff.
+BUGS
+----
-TROUBLESHOOTING
----------------
+RT's a pretty complex application, and as you get up to speed, you might
+run into some trouble. Generally, it's best to ask about things you
+run into on the rt-users mailinglist (or pick up a commercial support
+contract from Best Practical). But, sometimes people do run into bugs. In
+the exceedingly unlikely event that you hit a bug in RT, please report
+it! We'd love to hear about problems you have with RT, so we can fix them.
+To report a bug, send email to rt-bugs@fsck.com.
-If the solution to the problem you're running into isn't obvious and you've
-checked the FAQ, feel free to send mail to rt-users@fsck.com (for released
-versions of RT) or rt-devel@fsck.com (for development versions).
-Thanks!
+# BEGIN BPS TAGGED BLOCK {{{
+#
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# <jesse@bestpractical.com>
+#
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
+#
+# 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.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
+#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
+#
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
+#
+# END BPS TAGGED BLOCK }}}
use File::Basename;
require ('/opt/rt3/bin/webmux.pl');
-my $h = &RT::Interface::Web::NewCGIHandler();
+my $h = &RT::Interface::Web::NewCGIHandler(@RT::MasonParameters);
# Enter CGI::Fast mode, which should also work as a vanilla CGI script.
require CGI::Fast;
$ENV{'ENV'} = '' if defined $ENV{'ENV'};
$ENV{'IFS'} = '' if defined $ENV{'IFS'};
- unless ($h->interp->comp_exists($cgi->path_info)) {
- $cgi->path_info($cgi->path_info . "/index.html");
+ RT::ConnectToDatabase();
+
+ if ( ( !$h->interp->comp_exists( $cgi->path_info ) )
+ && ( $h->interp->comp_exists( $cgi->path_info . "/index.html" ) ) ) {
+ $cgi->path_info( $cgi->path_info . "/index.html" );
+ }
+
+ eval { $h->handle_cgi_object($cgi); };
+ if ($@) {
+ $RT::Logger->crit($@);
+ }
+
+
+ if ($RT::Handle->TransactionDepth) {
+ $RT::Handle->ForceRollback;
+ $RT::Logger->crit("Transaction not committed. Usually indicates a software fault. Data loss may have occurred") ;
}
- $h->handle_cgi_object($cgi);
- # _should_ always be tied
+
+
}
1;
use strict;
require ('/opt/rt3/bin/webmux.pl');
-my $h = &RT::Interface::Web::NewCGIHandler();
+my $h = &RT::Interface::Web::NewCGIHandler(@RT::MasonParameters);
require CGI;
RT::Init();
my $cgi = CGI->new;
-unless ($h->interp->comp_exists($cgi->path_info)) {
- $cgi->path_info($cgi->path_info . "/index.html");
+if ( ( !$h->interp->comp_exists( $cgi->path_info ) )
+ && ( $h->interp->comp_exists( $cgi->path_info . "/index.html" ) ) ) {
+ $cgi->path_info( $cgi->path_info . "/index.html" );
}
+
$h->handle_cgi_object($cgi);
1;
#!/usr/bin/perl -w
# BEGIN LICENSE BLOCK
-#
+#
# Copyright (c) 1996-2003 Jesse Vincent <jesse@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
=head1 NAME
use RT::I18N;
+# Make sure that when we call the mailgate wrong, it tempfails
+
+ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://bad.address"), "Opened the mailgate - The error below is expected - $@");
+print MAIL <<EOF;
+From: root\@localhost
+To: rt\@example.com
+Subject: This is a test of new ticket creation
+
+Foob!
+EOF
+close (MAIL);
+
+# Check the return value
+is ( $? >> 8, 75, "The error message above is expected The mail gateway exited with a failure. yay");
+
# {{{ Test new ticket creation by root who is privileged and superuser
-ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost/ --queue general --action correspond"), "Opened the mailgate - $@");
+ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost".$RT::WebPath."/ --queue general --action correspond"), "Opened the mailgate - $@");
print MAIL <<EOF;
From: root\@localhost
To: rt\@example.com
EOF
close (MAIL);
+#Check the return value
+is ($? >> 8, 0, "The mail gateway exited normally. yay");
+
use RT::Tickets;
my $tickets = RT::Tickets->new($RT::SystemUser);
$tickets->OrderBy(FIELD => 'id', ORDER => 'DESC');
# {{{This is a test of new ticket creation as an unknown user
-ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost/ --queue general --action correspond"), "Opened the mailgate - $@");
+ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost".$RT::WebPath."/ --queue general --action correspond"), "Opened the mailgate - $@");
print MAIL <<EOF;
From: doesnotexist\@example.com
To: rt\@example.com
Foob!
EOF
close (MAIL);
+#Check the return value
+is ($? >> 8, 0, "The mail gateway exited normally. yay");
$tickets = RT::Tickets->new($RT::SystemUser);
$tickets->OrderBy(FIELD => 'id', ORDER => 'DESC');
sleep(60); # gotta sleep so the remote process' ACL cache times out
-ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost/ --queue general --action correspond"), "Opened the mailgate - $@");
+ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost".$RT::WebPath."/ --queue general --action correspond"), "Opened the mailgate - $@");
print MAIL <<EOF;
From: doesnotexist\@example.com
To: rt\@example.com
Foob!
EOF
close (MAIL);
+#Check the return value
+is ($? >> 8, 0, "The mail gateway exited normally. yay");
$tickets = RT::Tickets->new($RT::SystemUser);
#ok ($val, "Granted everybody the right to create tickets - $msg");
#sleep(60); # gotta sleep so the remote process' ACL cache times out
-ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost/ --queue general --action correspond"), "Opened the mailgate - $@");
+ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost".$RT::WebPath."/ --queue general --action correspond"), "Opened the mailgate - $@");
print MAIL <<EOF;
From: doesnotexist-2\@example.com
To: rt\@example.com
Foob!
EOF
close (MAIL);
+#Check the return value
+is ($? >> 8, 0, "The mail gateway exited normally. yay");
$u = RT::User->new($RT::SystemUser);
$u->Load('doesnotexist-2@example.com');
ok ($val, "Granted everybody the right to reply to tickets - $msg");
sleep(60); # gotta sleep so the remote process' ACL cache times out
-ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost/ --queue general --action correspond"), "Opened the mailgate - $@");
+ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost".$RT::WebPath."/ --queue general --action correspond"), "Opened the mailgate - $@");
print MAIL <<EOF;
From: doesnotexist-2\@example.com
To: rt\@example.com
Foob!
EOF
close (MAIL);
+#Check the return value
+is ($? >> 8, 0, "The mail gateway exited normally. yay");
$u = RT::User->new($RT::SystemUser);
#ok ($val, "Granted everybody the right to create tickets - $msg");
#sleep(60); # gotta sleep so the remote process' ACL cache times out
-ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost/ --queue general --action comment"), "Opened the mailgate - $@");
+ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost".$RT::WebPath."/ --queue general --action comment"), "Opened the mailgate - $@");
print MAIL <<EOF;
From: doesnotexist-3\@example.com
To: rt\@example.com
EOF
close (MAIL);
+#Check the return value
+is ($? >> 8, 0, "The mail gateway exited normally. yay");
+
$u = RT::User->new($RT::SystemUser);
$u->Load('doesnotexist-3@example.com');
ok( $u->Id == 0, " user does not exist and was not created by ticket comment submission");
ok ($val, "Granted everybody the right to reply to tickets - $msg");
sleep(60); # gotta sleep so the remote process' ACL cache times out
-ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost/ --queue general --action comment"), "Opened the mailgate - $@");
+ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost".$RT::WebPath."/ --queue general --action comment"), "Opened the mailgate - $@");
print MAIL <<EOF;
From: doesnotexist-3\@example.com
To: rt\@example.com
EOF
close (MAIL);
+#Check the return value
+is ($? >> 8, 0, "The mail gateway exited normally. yay");
$u = RT::User->new($RT::SystemUser);
$u->Load('doesnotexist-3@example.com');
Data => ['This is a test of a binary attachment']);
# currently in lib/t/autogen
-$entity->attach(Path => '../../../html/NoAuth/images/spacer.gif',
+$entity->attach(Path => '/opt/rt3/share/html/NoAuth/images/spacer.gif',
Type => 'image/gif',
Encoding => 'base64');
# Create a ticket with a binary attachment
-ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost/ --queue general --action correspond"), "Opened the mailgate - $@");
+ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost".$RT::WebPath."/ --queue general --action correspond"), "Opened the mailgate - $@");
$entity->print(\*MAIL);
close (MAIL);
+#Check the return value
+is ($? >> 8, 0, "The mail gateway exited normally. yay");
+
my $tickets = RT::Tickets->new($RT::SystemUser);
$tickets->OrderBy(FIELD => 'id', ORDER => 'DESC');
$tickets->Limit(FIELD => 'id', OPERATOR => '>', VALUE => '0');
# Grab the binary attachment via the web ui
my $ua = LWP::UserAgent->new();
-my $full_url = "http://localhost/Ticket/Attachment/".$attachment->TransactionId."/".$attachment->id."/spacer.gif?&user=root&pass=password";
+my $full_url = "http://localhost".$RT::WebPath."/Ticket/Attachment/".$attachment->TransactionId."/".$attachment->id."/spacer.gif?&user=root&pass=password";
my $r = $ua->get( $full_url);
# {{{ Simple I18N testing
-ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost/ --queue general --action correspond"), "Opened the mailgate - $@");
+ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost".$RT::WebPath."/ --queue general --action correspond"), "Opened the mailgate - $@");
print MAIL <<EOF;
From: root\@localhost
EOF
close (MAIL);
+#Check the return value
+is ($? >> 8, 0, "The mail gateway exited normally. yay");
+
my $unitickets = RT::Tickets->new($RT::SystemUser);
$unitickets->OrderBy(FIELD => 'id', ORDER => 'DESC');
$unitickets->Limit(FIELD => 'id', OPERATOR => '>', VALUE => '0');
ok($unitick->Transactions->First->Attachments->First->Content =~ /$unistring/i, $unitick->Id." appears to be unicode ". $unitick->Transactions->First->Attachments->First->Id);
# supposedly I18N fails on the second message sent in.
-ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost/ --queue general --action correspond"), "Opened the mailgate - $@");
+ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost".$RT::WebPath."/ --queue general --action correspond"), "Opened the mailgate - $@");
print MAIL <<EOF;
From: root\@localhost
EOF
close (MAIL);
+#Check the return value
+is ($? >> 8, 0, "The mail gateway exited normally. yay");
+
my $tickets2 = RT::Tickets->new($RT::SystemUser);
$tickets2->OrderBy(FIELD => 'id', ORDER => 'DESC');
$tickets2->Limit(FIELD => 'id', OPERATOR => '>', VALUE => '0');
use constant EX_TEMPFAIL => 75;
my %opts;
-GetOptions( \%opts, "queue=s", "action=s", "url=s", "jar=s", "help", "debug", "extension=s" );
+GetOptions( \%opts, "queue=s", "action=s", "url=s", "jar=s", "help", "debug", "extension=s", "timeout=i" );
if ( $opts{help} ) {
require Pod::Usage;
}
undef $/;
-my $message = <>;
my $ua = LWP::UserAgent->new();
$ua->cookie_jar( { file => $opts{jar} } );
my %args = (
queue => $opts{queue},
action => $opts{action},
- message => $message,
SessionType => 'REST', # Surpress login box
);
+# Read the message in from STDIN
+$args{'message'} = <>;
+
if ($opts{'extension'}) {
$args{$opts{'extension'}} = $ENV{'EXTENSION'};
+$ua->timeout(exists($opts{'timeout'}) ? $opts{'timeout'} : 180);
my $r = $ua->post( $full_url, {%args} );
check_failure($r);
# It's not the server's fault if the mail is bogus. We just want to know that
# *something* came out of the server.
- die <<EOF
+ warn <<EOF;
RT server error.
The RT server which handled your email did not behave as expected. It
$content
EOF
+exit EX_TEMPFAIL;
+
}
+exit;
+
+
sub check_failure {
my $r = shift;
return if $r->is_success();
rt-mailgate --action (correspond|comment) --queue queuename
--url http://your.rt.server/
- [ --extension (queue|action|ticket)
+ [ --debug ]
+ [ --extension (queue|action|ticket) ]
+ [ --timeout seconds ]
+
+
See C<man rt-mailgate> for more.
is related to. "action" will allow the user to specify either "comment" or
"correspond" in the address extension.
+=item C<--debug> OPTIONAL
+
+Print debugging output to standard error
+
+
+=item C<--timeout> OPTIONAL
+
+Configure the timeout for posting the message to the web server. The
+default timeout is 3 minutes (180 seconds).
+
=head1 DESCRIPTION
$ENV{'SHELL'} = '/bin/sh' if defined $ENV{'SHELL'};
$ENV{'ENV'} = '' if defined $ENV{'ENV'};
$ENV{'IFS'} = '' if defined $ENV{'IFS'};
+
}
use lib ("/opt/rt3/local/lib", "/opt/rt3/lib");
#set private_tempfiles
BEGIN {
+ if ($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 ($CGI::MOD_PERL) {
require HTML::Mason::ApacheHandler;
}
unless ( ( -d _ ) and ( -r _ ) and ( -w _ ) );
}
-my $ah = &RT::Interface::Web::NewApacheHandler() if $CGI::MOD_PERL;
+my $ah = &RT::Interface::Web::NewApacheHandler(@RT::MasonParameters) if $CGI::MOD_PERL;
sub handler {
($r) = @_;
+ local $SIG{__WARN__};
+ local $SIG{__DIE__};
+
RT::Init();
# We don't need to handle non-text items
return -1 if defined( $r->content_type ) && $r->content_type !~ m|^text/|io;
my %session;
- my $status = $ah->handle_request($r);
+ my $status;
+ eval { $status = $ah->handle_request($r) };
+ if ($@) {
+ $RT::Logger->crit($@);
+ }
+
undef (%session);
- $RT::Logger->crit("Transaction not committed. Usually indicates a software fault. Data loss may have occurred") if $RT::Handle->TransactionDepth;
+ if ($RT::Handle->TransactionDepth) {
+ $RT::Handle->ForceRollback;
+ $RT::Logger->crit("Transaction not committed. Usually indicates a software fault. Data loss may have occurred") ;
+ }
return $status;
}
sub acl {
return (
-"CREATE USER ${RT::DatabaseUser} identified by ${RT::DatabasePassword}".
-"temporary tablespace TEMP" .
-"default tablespace USERS" .
-"quota unlimited on USERS;" ,
-"grant connect, resource to ${RT::DatabaseUser};",
-"exit;");
+"CREATE USER ${RT::DatabaseUser} identified by ${RT::DatabasePassword} ".
+"default tablespace USERS " .
+"temporary tablespace TEMP " .
+"quota unlimited on USERS" ,
+"grant connect, resource to ${RT::DatabaseUser}"
+);
}
1;
attachments_id_seq
Attachments
+ 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
sub acl {
+return () if !$RT::DatabaseUser or $RT::DatabaseUser eq 'root';
return (
"USE mysql;",
"DELETE FROM user WHERE user = '${RT::DatabaseUser}';",
"DELETE FROM db where db = '${RT::DatabaseName}';",
-"GRANT SELECT,INSERT,CREATE,INDEX,UPDATE,DELETE ON ${RT::DatabaseName}.* TO ${RT::DatabaseUser}\@${RT::DatabaseRTHost} IDENTIFIED BY '${RT::DatabasePassword}';");
+"GRANT SELECT,INSERT,CREATE,INDEX,UPDATE,DELETE ON ${RT::DatabaseName}.* TO ${RT::DatabaseUser}\@'${RT::DatabaseRTHost}' IDENTIFIED BY '${RT::DatabasePassword}';");
}
1;
--
------------------------------------------------------------------
-BEGIN;
-
-
--
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)
);
);
CREATE UNIQUE INDEX Links1 ON Links (Base, Target, Type) ;
+CREATE INDEX Links4 ON Links(Type,LocalBase);
-- }}}
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)
);
Description varchar(255) NULL ,
Domain varchar(64),
Type varchar(64),
- Instance varchar(64),
+ Instance integer,
PRIMARY KEY (id)
);
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 ,
- Data varchar(100) NULL ,
+ ReferenceType varchar(255) NULL,
+ OldReference integer NULL ,
+ NewReference integer NULL ,
+ Data varchar(255) NULL ,
Creator integer NOT NULL DEFAULT 0 ,
Created TIMESTAMP NULL ,
PRIMARY KEY (id)
);
-CREATE INDEX Transactions1 ON Transactions (Ticket);
-CREATE INDEX Transactions2 ON Transactions (EffectiveTicket);
+CREATE INDEX Transactions1 ON Transactions (ObjectType, ObjectId);
-- }}}
MemberId int,
Via int,
ImmediateParentId int,
- Disabled int2 NOT NULL DEFAULT 0 ,
+ Disabled integer NOT NULL DEFAULT 0 ,
PRIMARY KEY (id)
);
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)
);
-- }}}
--- {{{ TicketCustomFieldValues
+-- {{{ ObjectCustomFieldValues
-- 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 ,
+ SortOrder integer NOT NULL DEFAULT 0 ,
+
Content varchar(255) NULL ,
+ LargeContent text NULL,
+ ContentType varchar(80) NULL,
+ ContentEncoding varchar(80) NULL ,
Creator integer NOT NULL DEFAULT 0 ,
Created TIMESTAMP NULL ,
LastUpdatedBy integer NOT NULL DEFAULT 0 ,
LastUpdated TIMESTAMP NULL ,
+ Disabled integer NOT NULL DEFAULT 0 ,
PRIMARY KEY (id)
);
+CREATE INDEX ObjectCustomFieldValues1 ON ObjectCustomFieldValues (CustomField,ObjectType,ObjectId,Content);
+CREATE INDEX ObjectCustomFieldValues2 ON ObjectCustomFieldValues (CustomField,ObjectType,ObjectId);
+
-- }}}
-- {{{ CustomFields
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 ,
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)
);
);
+CREATE INDEX CustomFieldValues1 ON CustomFieldValues (CustomField);
+
+-- }}}
+
+
+-- {{{ Attributes
+
+CREATE SEQUENCE attributes_id_seq;
+
+CREATE TABLE Attributes (
+ id INTEGER DEFAULT nextval('attributes_id_seq'),
+ Name varchar(255) NOT NULL ,
+ Description varchar(255) NULL ,
+ Content text,
+ ContentType varchar(16),
+ ObjectType varchar(64),
+ ObjectId integer,
+ Creator integer NOT NULL DEFAULT 0 ,
+ Created TIMESTAMP NULL ,
+ LastUpdatedBy integer NOT NULL DEFAULT 0 ,
+ LastUpdated TIMESTAMP NULL ,
+ PRIMARY KEY (id)
+
+);
+
+CREATE INDEX Attributes1 on Attributes(Name);
+CREATE INDEX Attributes2 on Attributes(ObjectType, ObjectId);
+
-- }}}
-- {{{ Sessions
-- }}}
-
-
-COMMIT;
PRIMARY KEY (id)
) TYPE=InnoDB;
-CREATE INDEX Attachments1 ON Attachments (Parent) ;
CREATE INDEX Attachments2 ON Attachments (TransactionId) ;
CREATE INDEX Attachments3 ON Attachments (Parent, TransactionId) ;
# }}}
CREATE UNIQUE INDEX Links1 ON Links (Base, Target, Type) ;
CREATE INDEX Links2 ON Links (Base, Type) ;
CREATE INDEX Links3 ON Links (Target, Type) ;
+CREATE INDEX Links4 ON Links (Type,LocalBase);
# }}}
Description varchar(255) NULL ,
Domain varchar(64),
Type varchar(64),
- Instance varchar(64),
+ Instance integer,
PRIMARY KEY (id)
) TYPE=InnoDB;
CREATE INDEX Groups1 ON Groups (Domain,Instance,Type,id);
-CREATE INDEX Groups2 On Groups (Type, Instance, Domain);
+CREATE INDEX Groups2 On Groups (Type, Instance);
# }}}
# {{{ 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 ,
- Data varchar(100) 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);
# }}}
) TYPE=InnoDB;
CREATE INDEX DisGrouMem on CachedGroupMembers (GroupId,MemberId,Disabled);
-CREATE INDEX GrouMem on CachedGroupMembers (GroupId,MemberId);
# }}}
CREATE UNIQUE INDEX Users1 ON Users (Name) ;
-CREATE INDEX Users2 ON Users (Name);
-CREATE INDEX Users3 ON Users (id, EmailAddress);
CREATE INDEX Users4 ON Users (EmailAddress);
CREATE INDEX Tickets1 ON Tickets (Queue, Status) ;
CREATE INDEX Tickets2 ON Tickets (Owner) ;
-CREATE INDEX Tickets3 ON Tickets (EffectiveId) ;
-CREATE INDEX Tickets4 ON Tickets (id, Status) ;
-CREATE INDEX Tickets5 ON Tickets (id, EffectiveId) ;
CREATE INDEX Tickets6 ON Tickets (EffectiveId, Type) ;
# }}}
# }}}
-# {{{ 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
+ SortOrder integer NOT NULL DEFAULT 0 , # New -- ordering for multiple values
+
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 ,
LastUpdatedBy integer NOT NULL DEFAULT 0 ,
LastUpdated DATETIME NULL ,
+ Disabled int2 NOT NULL DEFAULT 0 , # New -- whether the value was current
PRIMARY KEY (id)
) TYPE=InnoDB;
+CREATE INDEX ObjectCustomFieldValues1 ON ObjectCustomFieldValues (Content);
+CREATE INDEX ObjectCustomFieldValues2 ON ObjectCustomFieldValues (CustomField,ObjectType,ObjectId);
+
# }}}
# {{{ CustomFields
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 ,
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;
# }}}
PRIMARY KEY (id)
) TYPE=InnoDB;
+CREATE INDEX CustomFieldValues1 ON CustomFieldValues (CustomField);
+
+# }}}
+
+
+# {{{ Attributes
+
+CREATE TABLE Attributes (
+ id INTEGER NOT NULL AUTO_INCREMENT,
+ Name varchar(255) NULL ,
+ Description varchar(255) NULL ,
+ Content text,
+ ContentType varchar(16),
+ ObjectType varchar(64),
+ ObjectId integer, # foreign key to anything
+ Creator integer NOT NULL DEFAULT 0 ,
+ Created DATETIME NULL ,
+ LastUpdatedBy integer NOT NULL DEFAULT 0 ,
+ LastUpdated DATETIME NULL ,
+ PRIMARY KEY (id)
+) TYPE=InnoDB;
+
+CREATE INDEX Attributes1 on Attributes(Name);
+CREATE INDEX Attributes2 on Attributes(ObjectType, ObjectId);
+
# }}}
# {{{ Sessions
$MasonSessionDir
);
-$VERSION = '3.0.4';
+$VERSION = '3.0.9';
$CORE_CONFIG_FILE = "/opt/rt3/etc/RT_Config.pm";
$SITE_CONFIG_FILE = "/opt/rt3/etc/RT_SiteConfig.pm";
=cut
sub Init {
- require RT::Handle;
+
#Get a database connection
- unless ($Handle && $Handle->dbh->ping) {
- $Handle = RT::Handle->new();
- }
- $Handle->Connect();
-
+ ConnectToDatabase();
+
#RT's system user is a genuine database user. its id lives here
$SystemUser = new RT::CurrentUser();
$SystemUser->LoadByName('RT_System');
InitLogging();
}
+
+=head2 ConnectToDatabase
+
+Get a database connection
+
+=cut
+
+sub ConnectToDatabase {
+ require RT::Handle;
+ unless ($Handle && $Handle->dbh && $Handle->dbh->ping) {
+ $Handle = RT::Handle->new();
+ }
+ $Handle->Connect();
+}
+
=head2 InitLogging
Create the RT::Logger object.
=head1 BUGS
+Please report them to rt-3.0-bugs@fsck.com, if you know what's broken and have at least some idea of what needs to be fixed.
+If you're not sure what's going on, report them rt-devel@lists.fsck.com.
+
=head1 SEE ALSO
+L<RT::StyleGuide>
+L<DBIx::SearchBuilder>
+
+
=begin testing
-# BEGIN LICENSE BLOCK
+# BEGIN BPS TAGGED BLOCK {{{
#
-# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# <jesse@bestpractical.com>
#
-# (Except where explictly superceded by other copyright notices)
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
#
# 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
# 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.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
+#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
#
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
#
-# END LICENSE BLOCK
+# END BPS TAGGED BLOCK }}}
# Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>)
# WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST.
#
-=item Create PARAMHASH
+=head2 Create PARAMHASH
Create takes a hash of values and creates a row in the database:
-=item id
+=head2 id
Returns the current value of id.
(In the database, id is stored as int(11).)
=cut
-=item PrincipalType
+=head2 PrincipalType
Returns the current value of PrincipalType.
(In the database, PrincipalType is stored as varchar(25).)
-=item SetPrincipalType VALUE
+=head2 SetPrincipalType VALUE
Set PrincipalType to VALUE.
=cut
-=item PrincipalId
+=head2 PrincipalId
Returns the current value of PrincipalId.
(In the database, PrincipalId is stored as int(11).)
-=item SetPrincipalId VALUE
+=head2 SetPrincipalId VALUE
Set PrincipalId to VALUE.
=cut
-=item RightName
+=head2 RightName
Returns the current value of RightName.
(In the database, RightName is stored as varchar(25).)
-=item SetRightName VALUE
+=head2 SetRightName VALUE
Set RightName to VALUE.
=cut
-=item ObjectType
+=head2 ObjectType
Returns the current value of ObjectType.
(In the database, ObjectType is stored as varchar(25).)
-=item SetObjectType VALUE
+=head2 SetObjectType VALUE
Set ObjectType to VALUE.
=cut
-=item ObjectId
+=head2 ObjectId
Returns the current value of ObjectId.
(In the database, ObjectId is stored as int(11).)
-=item SetObjectId VALUE
+=head2 SetObjectId VALUE
Set ObjectId to VALUE.
=cut
-=item DelegatedBy
+=head2 DelegatedBy
Returns the current value of DelegatedBy.
(In the database, DelegatedBy is stored as int(11).)
-=item SetDelegatedBy VALUE
+=head2 SetDelegatedBy VALUE
Set DelegatedBy to VALUE.
=cut
-=item DelegatedFrom
+=head2 DelegatedFrom
Returns the current value of DelegatedFrom.
(In the database, DelegatedFrom is stored as int(11).)
-=item SetDelegatedFrom VALUE
+=head2 SetDelegatedFrom VALUE
Set DelegatedFrom to VALUE.
-sub _ClassAccessible {
+sub _CoreAccessible {
{
id =>
- {read => 1, type => 'int(11)', default => ''},
+ {read => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => ''},
PrincipalType =>
- {read => 1, write => 1, type => 'varchar(25)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 25, is_blob => 0, is_numeric => 0, type => 'varchar(25)', default => ''},
PrincipalId =>
- {read => 1, write => 1, type => 'int(11)', default => '0'},
+ {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
RightName =>
- {read => 1, write => 1, type => 'varchar(25)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 25, is_blob => 0, is_numeric => 0, type => 'varchar(25)', default => ''},
ObjectType =>
- {read => 1, write => 1, type => 'varchar(25)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 25, is_blob => 0, is_numeric => 0, type => 'varchar(25)', default => ''},
ObjectId =>
- {read => 1, write => 1, type => 'int(11)', default => '0'},
+ {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
DelegatedBy =>
- {read => 1, write => 1, type => 'int(11)', default => '0'},
+ {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
DelegatedFrom =>
- {read => 1, write => 1, type => 'int(11)', default => '0'},
+ {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
}
};
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
+Each of these files should begin with the line
no warnings qw(redefine);
-# BEGIN LICENSE BLOCK
+# BEGIN BPS TAGGED BLOCK {{{
#
-# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# <jesse@bestpractical.com>
#
-# (Except where explictly superceded by other copyright notices)
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
#
# 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
# 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.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
+#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
#
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
#
-# END LICENSE BLOCK
+# END BPS TAGGED BLOCK }}}
# Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>)
# WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST.
#
}
-=item NewItem
+=head2 NewItem
Returns an empty new RT::ACE item
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
+Each of these files should begin with the line
no warnings qw(redefine);
-# BEGIN LICENSE BLOCK
+# BEGIN BPS TAGGED BLOCK {{{
#
-# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# <jesse@bestpractical.com>
#
-# (Except where explictly superceded by other copyright notices)
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
#
# 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
# 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.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
#
+# CONTRIBUTION SUBMISSION POLICY:
#
-# END LICENSE BLOCK
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
+#
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
+#
+# END BPS TAGGED BLOCK }}}
package RT::Action::Autoreply;
require RT::Action::SendEmail;
use vars qw/@ISA/;
@ISA = qw(RT::Action::SendEmail);
+=head2 Prepare
+
+Set up the relevant recipients, then call our parent.
+
+=cut
+
+
+sub Prepare {
+ my $self = shift;
+ $self->SetRecipients();
+ $self->SUPER::Prepare();
+}
# {{{ sub SetRecipients
}
unless ($self->TemplateObj->MIMEObj->head->get('From')) {
- my $friendly_name = $self->TicketObj->QueueObj->Description ||
- $self->TicketObj->QueueObj->Name;
- $friendly_name =~ s/"/\\"/g;
- $self->SetHeader('From', "\"$friendly_name\" <$replyto>");
+ if ($RT::UseFriendlyFromLine) {
+ my $friendly_name = $self->TicketObj->QueueObj->Description ||
+ $self->TicketObj->QueueObj->Name;
+ $friendly_name =~ s/"/\\"/g;
+ $self->SetHeader( 'From',
+ sprintf($RT::FriendlyFromLineFormat,
+ $self->MIMEEncodeString( $friendly_name, $RT::EmailOutputEncoding ), $replyto),
+ );
+ }
+ else {
+ $self->SetHeader( 'From', $replyto );
+ }
}
unless ($self->TemplateObj->MIMEObj->head->get('Reply-To')) {
-# BEGIN LICENSE BLOCK
+# BEGIN BPS TAGGED BLOCK {{{
#
-# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# <jesse@bestpractical.com>
#
-# (Except where explictly superceded by other copyright notices)
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
#
# 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
# 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.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
#
-# END LICENSE BLOCK
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
+#
+# END BPS TAGGED BLOCK }}}
+
=head1 NAME
RT::Action::Generic - a generic baseclass for RT Actions
package RT::Action::Generic;
use strict;
+use Scalar::Util;
+
+use base qw/RT::Base/;
# {{{ sub new
sub new {
}
# }}}
-# {{{ sub new
-sub loc {
- my $self = shift;
- return $self->{'ScripObj'}->loc(@_);
-}
-# }}}
-
# {{{ sub _Init
sub _Init {
my $self = shift;
- my %args = ( TransactionObj => undef,
- TicketObj => undef,
- ScripObj => undef,
- TemplateObj => undef,
- Argument => undef,
- Type => undef,
- @_ );
-
-
+ my %args = ( Argument => undef,
+ CurrentUser => undef,
+ ScripActionObj => undef,
+ ScripObj => undef,
+ TemplateObj => undef,
+ TicketObj => undef,
+ TransactionObj => undef,
+ Type => undef,
+
+ @_ );
+
$self->{'Argument'} = $args{'Argument'};
+ $self->CurrentUser( $args{'CurrentUser'});
+ $self->{'ScripActionObj'} = $args{'ScripActionObj'};
$self->{'ScripObj'} = $args{'ScripObj'};
+ $self->{'TemplateObj'} = $args{'TemplateObj'};
$self->{'TicketObj'} = $args{'TicketObj'};
$self->{'TransactionObj'} = $args{'TransactionObj'};
- $self->{'TemplateObj'} = $args{'TemplateObj'};
$self->{'Type'} = $args{'Type'};
+
+ Scalar::Util::weaken($self->{'ScripActionObj'});
+ Scalar::Util::weaken($self->{'ScripObj'});
+ Scalar::Util::weaken($self->{'TemplateObj'});
+ Scalar::Util::weaken($self->{'TicketObj'});
+ Scalar::Util::weaken($self->{'TransactionObj'});
+
}
# }}}
}
# }}}
+# {{{ sub ScripActionObj
+sub ScripActionObj {
+ my $self = shift;
+ return($self->{'ScripActionObj'});
+}
+# }}}
+
# {{{ sub Type
sub Type {
my $self = shift;
# We need to clean up all the references that might maybe get
# oddly circular
+ $self->{'ScripActionObj'} = undef;
+ $self->{'ScripObj'} = undef;
$self->{'TemplateObj'} =undef
$self->{'TicketObj'} = undef;
$self->{'TransactionObj'} = undef;
- $self->{'ScripObj'} = undef;
-
-
-
}
# }}}
-# BEGIN LICENSE BLOCK
+# BEGIN BPS TAGGED BLOCK {{{
#
-# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# <jesse@bestpractical.com>
#
-# (Except where explictly superceded by other copyright notices)
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
#
# 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
# 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.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
+#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
#
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
#
-# END LICENSE BLOCK
+# END BPS TAGGED BLOCK }}}
+#
package RT::Action::Notify;
require RT::Action::SendEmail;
-
+use Mail::Address;
use strict;
use vars qw/@ISA/;
@ISA = qw(RT::Action::SendEmail);
+
+=head2 Prepare
+
+Set up the relevant recipients, then call our parent.
+
+=cut
+
+
+sub Prepare {
+ my $self = shift;
+ $self->SetRecipients();
+ $self->SUPER::Prepare();
+}
+
# {{{ sub SetRecipients
=head2 SetRecipients
my ( @To, @PseudoTo, @Cc, @Bcc );
- if ($arg =~ /\bOtherRecipients\b/) {
- if ($self->TransactionObj->Attachments->First) {
- push (@Cc, $self->TransactionObj->Attachments->First->GetHeader('RT-Send-Cc'));
- push (@Bcc, $self->TransactionObj->Attachments->First->GetHeader('RT-Send-Bcc'));
+ if ( $arg =~ /\bOtherRecipients\b/ ) {
+ if ( $self->TransactionObj->Attachments->First ) {
+ my @cc_addresses = Mail::Address->parse($self->TransactionObj->Attachments->First->GetHeader('RT-Send-Cc'));
+ foreach my $addr (@cc_addresses) {
+ push @Cc, $addr->address;
+ }
+ my @bcc_addresses = Mail::Address->parse($self->TransactionObj->Attachments->First->GetHeader('RT-Send-Bcc'));
+
+ foreach my $addr (@bcc_addresses) {
+ push @Bcc, $addr->address;
+ }
+
}
}
@{ $self->{'Bcc'} } = @Bcc;
}
else {
- @{ $self->{'To'} } = grep ( !/^$creator$/, @To );
- @{ $self->{'Cc'} } = grep ( !/^$creator$/, @Cc );
- @{ $self->{'Bcc'} } = grep ( !/^$creator$/, @Bcc );
+ @{ $self->{'To'} } = grep ( lc $_ ne lc $creator, @To );
+ @{ $self->{'Cc'} } = grep ( lc $_ ne lc $creator, @Cc );
+ @{ $self->{'Bcc'} } = grep ( lc $_ ne lc $creator, @Bcc );
}
@{ $self->{'PseudoTo'} } = @PseudoTo;
- return (1);
+
}
-# BEGIN LICENSE BLOCK
+# BEGIN BPS TAGGED BLOCK {{{
#
-# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# <jesse@bestpractical.com>
#
-# (Except where explictly superceded by other copyright notices)
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
#
# 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
# 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.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
+#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
#
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
#
-# END LICENSE BLOCK
+# END BPS TAGGED BLOCK }}}
package RT::Action::NotifyAsComment;
require RT::Action::Notify;
-# BEGIN LICENSE BLOCK
+# BEGIN BPS TAGGED BLOCK {{{
#
-# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# <jesse@bestpractical.com>
#
-# (Except where explictly superceded by other copyright notices)
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
#
# 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
# 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.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
+#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
#
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
#
-# END LICENSE BLOCK
+# END BPS TAGGED BLOCK }}}
# This Action will resolve all members of a resolved group ticket
package RT::Action::ResolveMembers;
-# BEGIN LICENSE BLOCK
+# BEGIN BPS TAGGED BLOCK {{{
#
-# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# <jesse@bestpractical.com>
#
-# (Except where explictly superceded by other copyright notices)
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
#
# 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
# 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.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
#
-# END LICENSE BLOCK
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
+#
+# END BPS TAGGED BLOCK }}}
# Portions Copyright 2000 Tobias Brox <tobix@cpan.org>
package RT::Action::SendEmail;
use MIME::Words qw(encode_mimeword);
use RT::EmailParser;
+use Mail::Address;
=head1 NAME
Basically, you create another module RT::Action::YourAction which ISA
RT::Action::SendEmail.
-If you want to set the recipients of the mail to something other than
-the addresses mentioned in the To, Cc, Bcc and headers in
-the template, you should subclass RT::Action::SendEmail and override
-either the SetRecipients method or the SetTo, SetCc, etc methods (see
-the comments for the SetRecipients sub).
-
-
=begin testing
ok (require RT::Action::SendEmail);
# {{{ Scrip methods (_Init, Commit, Prepare, IsApplicable)
-# {{{ sub _Init
-# We use _Init from RT::Action
-# }}}
# {{{ sub Commit
-#Do what we need to do and send it out.
+
sub Commit {
my $self = shift;
- my $MIMEObj = $self->TemplateObj->MIMEObj;
- my $msgid = $MIMEObj->head->get('Message-Id');
- chomp $msgid;
- $RT::Logger->info($msgid." #".$self->TicketObj->id."/".$self->TransactionObj->id." - Scrip ". $self->ScripObj->id ." ".$self->ScripObj->Description);
- #send the email
+ return($self->SendMessage($self->TemplateObj->MIMEObj));
+}
- # Weed out any RT addresses. We really don't want to talk to ourselves!
- @{$self->{'To'}} = RT::EmailParser::CullRTAddresses("", @{$self->{'To'}});
- @{$self->{'Cc'}} = RT::EmailParser::CullRTAddresses("", @{$self->{'Cc'}});
- @{$self->{'Bcc'}} = RT::EmailParser::CullRTAddresses("", @{$self->{'Bcc'}});
- # If there are no recipients, don't try to send the message.
- # If the transaction has content and has the header RT-Squelch-Replies-To
+# }}}
- if ( defined $self->TransactionObj->Attachments->First() ) {
+# {{{ sub Prepare
- my $squelch = $self->TransactionObj->Attachments->First->GetHeader( 'RT-Squelch-Replies-To');
+sub Prepare {
+ my $self = shift;
- if ($squelch) {
- my @blacklist = split ( /,/, $squelch );
-
- # Cycle through the people we're sending to and pull out anyone on the
- # system blacklist
-
- foreach my $person_to_yank (@blacklist) {
- $person_to_yank =~ s/\s//g;
- @{ $self->{'To'} } =
- grep ( !/^$person_to_yank$/, @{ $self->{'To'} } );
- @{ $self->{'Cc'} } =
- grep ( !/^$person_to_yank$/, @{ $self->{'Cc'} } );
- @{ $self->{'Bcc'} } =
- grep ( !/^$person_to_yank$/, @{ $self->{'Bcc'} } );
- }
- }
+ my ( $result, $message ) = $self->TemplateObj->Parse(
+ Argument => $self->Argument,
+ TicketObj => $self->TicketObj,
+ TransactionObj => $self->TransactionObj
+ );
+ if ( !$result ) {
+ return (undef);
}
+ my $MIMEObj = $self->TemplateObj->MIMEObj;
+
+ # Header
+ $self->SetRTSpecialHeaders();
+
+ $self->RemoveInappropriateRecipients();
+
# Go add all the Tos, Ccs and Bccs that we need to to the message to
# make it happy, but only if we actually have values in those arrays.
- $self->SetHeader( 'To', join ( ',', @{ $self->{'To'} } ) )
- if ( $self->{'To'} && @{ $self->{'To'} } );
- $self->SetHeader( 'Cc', join ( ',', @{ $self->{'Cc'} } ) )
- if ( $self->{'Cc'} && @{ $self->{'Cc'} } );
- $self->SetHeader( 'Bcc', join ( ',', @{ $self->{'Bcc'} } ) )
- if ( $self->{'Cc'} && @{ $self->{'Bcc'} } );
+ # TODO: We should be pulling the recipients out of the template and shove them into To, Cc and Bcc
+
+ $self->SetHeader( 'To', join ( ', ', @{ $self->{'To'} } ) )
+ if ( ! $MIMEObj->head->get('To') && $self->{'To'} && @{ $self->{'To'} } );
+ $self->SetHeader( 'Cc', join ( ', ', @{ $self->{'Cc'} } ) )
+ if ( !$MIMEObj->head->get('Cc') && $self->{'Cc'} && @{ $self->{'Cc'} } );
+ $self->SetHeader( 'Bcc', join ( ', ', @{ $self->{'Bcc'} } ) )
+ if ( !$MIMEObj->head->get('Bcc') && $self->{'Bcc'} && @{ $self->{'Bcc'} } );
+ # PseudoTo (fake to headers) shouldn't get matched for message recipients.
+ # If we don't have any 'To' header (but do have other recipients), drop in
+ # the pseudo-to header.
+ $self->SetHeader( 'To', join ( ', ', @{ $self->{'PseudoTo'} } ) )
+ if ( $self->{'PseudoTo'} && ( @{ $self->{'PseudoTo'} } )
+ and ( !$MIMEObj->head->get('To') ) ) and ( $MIMEObj->head->get('Cc') or $MIMEObj->head->get('Bcc'));
- $self->SetHeader('MIME-Version', '1.0');
+ # We should never have to set the MIME-Version header
+ $self->SetHeader( 'MIME-Version', '1.0' );
# try to convert message body from utf-8 to $RT::EmailOutputEncoding
$self->SetHeader( 'Content-Type', 'text/plain; charset="utf-8"' );
- RT::I18N::SetMIMEEntityToEncoding( $MIMEObj, $RT::EmailOutputEncoding, 'mime_words_ok' );
- $self->SetHeader( 'Content-Type', 'text/plain; charset="' . $RT::EmailOutputEncoding . '"' );
+ # fsck.com #5959: Since RT sends 8bit mail, we should say so.
+ $self->SetHeader( 'Content-Transfer-Encoding','8bit');
- # Build up a MIME::Entity that looks like the original message.
-
- my $do_attach = $self->TemplateObj->MIMEObj->head->get('RT-Attach-Message');
+ RT::I18N::SetMIMEEntityToEncoding( $MIMEObj, $RT::EmailOutputEncoding,
+ 'mime_words_ok' );
+ $self->SetHeader( 'Content-Type', 'text/plain; charset="' . $RT::EmailOutputEncoding . '"' );
- if ($do_attach) {
- $self->TemplateObj->MIMEObj->head->delete('RT-Attach-Message');
+ # Build up a MIME::Entity that looks like the original message.
+ $self->AddAttachments() if ( $MIMEObj->head->get('RT-Attach-Message') );
- my $attachments = RT::Attachments->new($RT::SystemUser);
- $attachments->Limit( FIELD => 'TransactionId',
- VALUE => $self->TransactionObj->Id );
- $attachments->OrderBy('id');
+ return $result;
- my $transaction_content_obj = $self->TransactionObj->ContentObj;
+}
- # attach any of this transaction's attachments
- while ( my $attach = $attachments->Next ) {
+# }}}
- # Don't attach anything blank
- next unless ( $attach->ContentLength );
+# }}}
- # We want to make sure that we don't include the attachment that's being sued as the "Content" of this message"
- next
- if ( $transaction_content_obj
- && $transaction_content_obj->Id == $attach->Id
- && $transaction_content_obj->ContentType =~ qr{text/plain}i
- );
- $MIMEObj->make_multipart('mixed');
- $MIMEObj->attach( Type => $attach->ContentType,
- Charset => $attach->OriginalEncoding,
- Data => $attach->OriginalContent,
- Filename => $self->MIMEEncodeString( $attach->Filename, $RT::EmailOutputEncoding ),
- Encoding => '-SUGGEST');
- }
- }
+=head2 To
- my $retval = $self->SendMessage($MIMEObj);
+Returns an array of Mail::Address objects containing all the To: recipients for this notification
+=cut
- return ($retval);
+sub To {
+ my $self = shift;
+ return ($self->_AddressesFromHeader('To'));
}
-# }}}
+=head2 Cc
-# {{{ sub Prepare
+Returns an array of Mail::Address objects containing all the Cc: recipients for this notification
-sub Prepare {
- my $self = shift;
+=cut
- # This actually populates the MIME::Entity fields in the Template Object
+sub Cc {
+ my $self = shift;
+ return ($self->_AddressesFromHeader('Cc'));
+}
- unless ( $self->TemplateObj ) {
- $RT::Logger->warning("No template object handed to $self\n");
- }
+=head2 Bcc
- unless ( $self->TransactionObj ) {
- $RT::Logger->warning("No transaction object handed to $self\n");
+Returns an array of Mail::Address objects containing all the Bcc: recipients for this notification
- }
+=cut
- unless ( $self->TicketObj ) {
- $RT::Logger->warning("No ticket object handed to $self\n");
- }
+sub Bcc {
+ my $self = shift;
+ return ($self->_AddressesFromHeader('Bcc'));
- my ( $result, $message ) = $self->TemplateObj->Parse(
- Argument => $self->Argument,
- TicketObj => $self->TicketObj,
- TransactionObj => $self->TransactionObj
- );
- if ($result) {
-
- # Header
- $self->SetSubject();
- $self->SetSubjectToken();
- $self->SetRecipients();
- $self->SetReturnAddress();
- $self->SetRTSpecialHeaders();
- if ($RT::EmailOutputEncoding) {
-
- # l10n related header
- $self->SetHeaderAsEncoding( 'Subject', $RT::EmailOutputEncoding );
- }
- }
+}
- return $result;
+sub _AddressesFromHeader {
+ my $self = shift;
+ my $field = shift;
+ my $header = $self->TemplateObj->MIMEObj->head->get($field);
+ my @addresses = Mail::Address->parse($header);
+ return (@addresses);
}
-# }}}
-
-# }}}
# {{{ SendMessage
+
=head2 SendMessage MIMEObj
sends the message using RT's preferred API.
-TODO: Break this out to a seperate module
+TODO: Break this out to a separate module
=cut
sub SendMessage {
- my $self = shift;
+ my $self = shift;
my $MIMEObj = shift;
- my $msgid = $MIMEObj->head->get('Message-Id');
+ my $msgid = $MIMEObj->head->get('Message-ID');
+ chomp $msgid;
+ $self->ScripActionObj->{_Message_ID}++;
+
+ $RT::Logger->info( $msgid . " #"
+ . $self->TicketObj->id . "/"
+ . $self->TransactionObj->id
+ . " - Scrip "
+ . $self->ScripObj->id . " "
+ . $self->ScripObj->Description );
#If we don't have any recipients to send to, don't send a message;
- unless ( $MIMEObj->head->get('To')
- || $MIMEObj->head->get('Cc')
- || $MIMEObj->head->get('Bcc') ) {
- $RT::Logger->info($msgid. " No recipients found. Not sending.\n");
+ unless ( $MIMEObj->head->get('To')
+ || $MIMEObj->head->get('Cc')
+ || $MIMEObj->head->get('Bcc') )
+ {
+ $RT::Logger->info( $msgid . " No recipients found. Not sending.\n" );
return (1);
}
- # PseudoTo (fake to headers) shouldn't get matched for message recipients.
- # If we don't have any 'To' header, drop in the pseudo-to header.
- $self->SetHeader( 'To', join ( ',', @{ $self->{'PseudoTo'} } ) )
- if ( $self->{'PseudoTo'} && ( @{ $self->{'PseudoTo'} } )
- and ( !$MIMEObj->head->get('To') ) );
if ( $RT::MailCommand eq 'sendmailpipe' ) {
eval {
- open( MAIL, "|$RT::SendmailPath $RT::SendmailArguments" );
+ open( MAIL, "|$RT::SendmailPath $RT::SendmailArguments" ) || die $!;
print MAIL $MIMEObj->as_string;
close(MAIL);
- };
- if ($@) {
- $RT::Logger->crit($msgid. "Could not send mail. -".$@ );
+ };
+ if ($@) {
+ $RT::Logger->crit( $msgid . "Could not send mail. -" . $@ );
}
}
else {
- my @mailer_args = ($RT::MailCommand);
- local $ENV{MAILADDRESS};
+ my @mailer_args = ($RT::MailCommand);
+
+ local $ENV{MAILADDRESS};
if ( $RT::MailCommand eq 'sendmail' ) {
- push @mailer_args, $RT::SendmailArguments;
+ push @mailer_args, split(/\s+/, $RT::SendmailArguments);
}
elsif ( $RT::MailCommand eq 'smtp' ) {
- $ENV{MAILADDRESS} = $RT::SMTPFrom || $MIMEObj->head->get('From');
- push @mailer_args, (Server => $RT::SMTPServer);
- push @mailer_args, (Debug => $RT::SMTPDebug);
+ $ENV{MAILADDRESS} = $RT::SMTPFrom || $MIMEObj->head->get('From');
+ push @mailer_args, ( Server => $RT::SMTPServer );
+ push @mailer_args, ( Debug => $RT::SMTPDebug );
+ }
+ else {
+ push @mailer_args, $RT::MailParams;
}
- else {
- push @mailer_args, $RT::MailParams;
- }
- unless ( $MIMEObj->send( @mailer_args ) ) {
- $RT::Logger->crit($msgid. "Could not send mail." );
+ unless ( $MIMEObj->send(@mailer_args) ) {
+ $RT::Logger->crit( $msgid . "Could not send mail." );
return (0);
}
}
-
- my $success = ($msgid. " sent To: ".$MIMEObj->head->get('To') . " Cc: ".$MIMEObj->head->get('Cc') . " Bcc: ".$MIMEObj->head->get('Bcc'));
+ my $success =
+ ( $msgid
+ . " sent To: "
+ . $MIMEObj->head->get('To') . " Cc: "
+ . $MIMEObj->head->get('Cc') . " Bcc: "
+ . $MIMEObj->head->get('Bcc') );
$success =~ s/\n//gi;
+
+ $self->RecordOutgoingMailTransaction($MIMEObj) if ($RT::RecordOutgoingEmail);
+
$RT::Logger->info($success);
return (1);
# }}}
-# {{{ Deal with message headers (Set* subs, designed for easy overriding)
+# {{{ AddAttachments
+
+=head2 AddAttachments
+
+Takes any attachments to this transaction and attaches them to the message
+we're building.
+
+=cut
+
+
+sub AddAttachments {
+ my $self = shift;
+
+ my $MIMEObj = $self->TemplateObj->MIMEObj;
+
+ $MIMEObj->head->delete('RT-Attach-Message');
+
+ my $attachments = RT::Attachments->new($RT::SystemUser);
+ $attachments->Limit(
+ FIELD => 'TransactionId',
+ VALUE => $self->TransactionObj->Id
+ );
+ $attachments->OrderBy('id');
+
+ my $transaction_content_obj = $self->TransactionObj->ContentObj;
+
+ # attach any of this transaction's attachments
+ while ( my $attach = $attachments->Next ) {
+
+ # Don't attach anything blank
+ next unless ( $attach->ContentLength );
+
+# We want to make sure that we don't include the attachment that's being sued as the "Content" of this message"
+ next
+ if ( $transaction_content_obj
+ && $transaction_content_obj->Id == $attach->Id
+ && $transaction_content_obj->ContentType =~ qr{text/plain}i );
+ $MIMEObj->make_multipart('mixed');
+ $MIMEObj->attach(
+ Type => $attach->ContentType,
+ Charset => $attach->OriginalEncoding,
+ Data => $attach->OriginalContent,
+ Filename => $self->MIMEEncodeString( $attach->Filename,
+ $RT::EmailOutputEncoding ),
+ 'RT-Attachment:' => $self->TicketObj->Id."/".$self->TransactionObj->Id."/".$attach->id,
+ Encoding => '-SUGGEST'
+ );
+ }
+
+}
+
+# }}}
+
+# {{{ RecordOutgoingMailTransaction
+
+=head2 RecordOutgoingMailTransaction MIMEObj
+
+Record a transaction in RT with this outgoing message for future record-keeping purposes
+
+=cut
+
+
+
+sub RecordOutgoingMailTransaction {
+ my $self = shift;
+ my $MIMEObj = shift;
+
+
+ my @parts = $MIMEObj->parts;
+ my @attachments;
+ my @keep;
+ foreach my $part (@parts) {
+ my $attach = $part->head->get('RT-Attachment');
+ if ($attach) {
+ $RT::Logger->debug("We found an attachment. we want to not record it.");
+ push @attachments, $attach;
+ } else {
+ $RT::Logger->debug("We found a part. we want to record it.");
+ push @keep, $part;
+ }
+ }
+ $MIMEObj->parts(\@keep);
+ foreach my $attachment (@attachments) {
+ $MIMEObj->head->add('RT-Attachment', $attachment);
+ }
+
+ RT::I18N::SetMIMEEntityToEncoding( $MIMEObj, 'utf-8', 'mime_words_ok' );
+
+ my $transaction = RT::Transaction->new($self->TransactionObj->CurrentUser);
+
+ # XXX: TODO -> Record attachments as references to things in the attachments table, maybe.
+
+ my $type;
+ if ($self->TransactionObj->Type eq 'Comment') {
+ $type = 'CommentEmailRecord';
+ } else {
+ $type = 'EmailRecord';
+ }
+
+ my $msgid = $MIMEObj->head->get('Message-ID');
+ chomp $msgid;
+
+ my ( $id, $msg ) = $transaction->Create(
+ Ticket => $self->TicketObj->Id,
+ Type => $type,
+ Data => $msgid,
+ MIMEObj => $MIMEObj,
+ ActivateScrips => 0
+ );
+
+
+}
+
+# }}}
+#
# {{{ sub SetRTSpecialHeaders
sub SetRTSpecialHeaders {
my $self = shift;
- $self->SetReferences();
-
- $self->SetMessageID();
+ $self->SetSubject();
+ $self->SetSubjectToken();
+ $self->SetHeaderAsEncoding( 'Subject', $RT::EmailOutputEncoding )
+ if ($RT::EmailOutputEncoding);
+ $self->SetReturnAddress();
+ $self->SetReferencesHeaders();
+
+ unless ($self->TemplateObj->MIMEObj->head->get('Message-ID')) {
+ # Get Message-ID for this txn
+ my $msgid = "";
+ $msgid = $self->TransactionObj->Message->First->GetHeader("RT-Message-ID")
+ || $self->TransactionObj->Message->First->GetHeader("Message-ID")
+ if $self->TransactionObj->Message && $self->TransactionObj->Message->First;
+
+ # If there is one, and we can parse it, then base our Message-ID on it
+ if ($msgid
+ and $msgid =~ s/<(rt-.*?-\d+-\d+)\.(\d+-0-0)\@$RT::Organization>$/
+ "<$1." . $self->TicketObj->id
+ . "-" . $self->ScripObj->id
+ . "-" . $self->ScripActionObj->{_Message_ID}
+ . "@" . $RT::Organization . ">"/eg
+ and $2 == $self->TicketObj->id) {
+ $self->SetHeader( "Message-ID" => $msgid );
+ } else {
+ $self->SetHeader( 'Message-ID',
+ "<rt-"
+ . $RT::VERSION . "-"
+ . $$ . "-"
+ . CORE::time() . "-"
+ . int(rand(2000)) . '.'
+ . $self->TicketObj->id . "-"
+ . $self->ScripObj->id . "-" # Scrip
+ . $self->ScripActionObj->{_Message_ID} . "@" # Email sent
+ . $RT::Organization
+ . ">" );
+ }
+ }
- $self->SetPrecedence();
+ $self->SetHeader( 'Precedence', "bulk" )
+ unless ( $self->TemplateObj->MIMEObj->head->get("Precedence") );
$self->SetHeader( 'X-RT-Loop-Prevention', $RT::rtname );
$self->SetHeader( 'RT-Ticket',
- $RT::rtname . " #" . $self->TicketObj->id() );
+ $RT::rtname . " #" . $self->TicketObj->id() );
$self->SetHeader( 'Managed-by',
- "RT $RT::VERSION (http://www.bestpractical.com/rt/)" );
+ "RT $RT::VERSION (http://www.bestpractical.com/rt/)" );
$self->SetHeader( 'RT-Originator',
- $self->TransactionObj->CreatorObj->EmailAddress );
- return ();
+ $self->TransactionObj->CreatorObj->EmailAddress );
}
-# {{{ sub SetReferences
+# }}}
+
-=head2 SetReferences
-
- # This routine will set the References: and In-Reply-To headers,
-# autopopulating it with all the correspondence on this ticket so
-# far. This should make RT responses threadable.
+# }}}
+
+# {{{ RemoveInappropriateRecipients
+
+=head2 RemoveInappropriateRecipients
+
+Remove addresses that are RT addresses or that are on this transaction's blacklist
=cut
-sub SetReferences {
+sub RemoveInappropriateRecipients {
my $self = shift;
- # TODO: this one is broken. What is this email really a reply to?
- # If it's a reply to an incoming message, we'll need to use the
- # actual message-id from the appropriate Attachment object. For
- # incoming mails, we would like to preserve the In-Reply-To and/or
- # References.
+ my @blacklist;
- $self->SetHeader( 'In-Reply-To',
- "<rt-" . $self->TicketObj->id() . "\@" . $RT::rtname . ">" );
+ my @types = qw/To Cc Bcc/;
- # TODO We should always add References headers for all message-ids
- # of previous messages related to this ticket.
-}
+ # Weed out any RT addresses. We really don't want to talk to ourselves!
+ foreach my $type (@types) {
+ @{ $self->{$type} } =
+ RT::EmailParser::CullRTAddresses( "", @{ $self->{$type} } );
+ }
-# }}}
+ # If there are no recipients, don't try to send the message.
+ # If the transaction has content and has the header RT-Squelch-Replies-To
-# {{{ sub SetMessageID
+ if ( $self->TransactionObj->Attachments->First() ) {
+ if (
+ $self->TransactionObj->Attachments->First->GetHeader(
+ 'RT-DetectedAutoGenerated')
+ )
+ {
-=head2 SetMessageID
+ # What do we want to do with this? It's probably (?) a bounce
+ # caused by one of the watcher addresses being broken.
+ # Default ("true") is to redistribute, for historical reasons.
-Without this one, threading won't work very nice in email agents.
-Anyway, I'm not really sure it's that healthy if we need to send
-several separate/different emails about the same transaction.
+ if ( !$RT::RedistributeAutoGeneratedMessages ) {
-=cut
+ # Don't send to any watchers.
+ @{ $self->{'To'} } = ();
+ @{ $self->{'Cc'} } = ();
+ @{ $self->{'Bcc'} } = ();
-sub SetMessageID {
- my $self = shift;
+ }
+ elsif ( $RT::RedistributeAutoGeneratedMessages eq 'privileged' ) {
- # TODO this one might be sort of broken. If we have several scrips +++
- # sending several emails to several different persons, we need to
- # pull out different message-ids. I'd suggest message ids like
- # "rt-ticket#-transaction#-scrip#-receipient#"
-
- $self->SetHeader( 'Message-ID',
- "<rt-"
- . $RT::VERSION ."-"
- . $self->TicketObj->id() . "-"
- . $self->TransactionObj->id() . "."
- . rand(20) . "\@"
- . $RT::Organization . ">" )
- unless $self->TemplateObj->MIMEObj->head->get('Message-ID');
-}
+ # Only send to "privileged" watchers.
+ #
-# }}}
+ foreach my $type (@types) {
-# }}}
+ foreach my $addr ( @{ $self->{$type} } ) {
+ my $user = RT::User->new($RT::SystemUser);
+ $user->LoadByEmail($addr);
+ @{ $self->{$type} } =
+ grep ( !/^\Q$addr\E$/, @{ $self->{$type} } )
+ if ( !$user->Privileged );
+
+ }
+ }
+
+ }
+
+ }
+
+ my $squelch =
+ $self->TransactionObj->Attachments->First->GetHeader(
+ 'RT-Squelch-Replies-To');
+
+ if ($squelch) {
+ @blacklist = split( /,/, $squelch );
+ }
+ }
+ # Let's grab the SquelchMailTo attribue and push those entries into the @blacklist
+ my @non_recipients = $self->TicketObj->SquelchMailTo;
+ foreach my $attribute (@non_recipients) {
+ push @blacklist, $attribute->Content;
+ }
+
+ # Cycle through the people we're sending to and pull out anyone on the
+ # system blacklist
+
+ foreach my $person_to_yank (@blacklist) {
+ $person_to_yank =~ s/\s//g;
+ foreach my $type (@types) {
+ @{ $self->{$type} } =
+ grep ( !/^\Q$person_to_yank\E$/, @{ $self->{$type} } );
+ }
+ }
+}
+
+# }}}
# {{{ sub SetReturnAddress
=head2 SetReturnAddress is_comment => BOOLEAN
sub SetReturnAddress {
my $self = shift;
- my %args = ( is_comment => 0,
- @_ );
+ my %args = (
+ is_comment => 0,
+ @_
+ );
# From and Reply-To
# $args{is_comment} should be set if the comment address is to be used.
}
unless ( $self->TemplateObj->MIMEObj->head->get('From') ) {
- if ($RT::UseFriendlyFromLine) {
- my $friendly_name = $self->TransactionObj->CreatorObj->RealName;
- if ( $friendly_name =~ /^"(.*)"$/ ) { # a quoted string
- $friendly_name = $1;
- }
-
- $friendly_name =~ s/"/\\"/g;
- $self->SetHeader( 'From',
- sprintf($RT::FriendlyFromLineFormat,
- $self->MIMEEncodeString( $friendly_name, $RT::EmailOutputEncoding ), $replyto),
- );
- }
- else {
- $self->SetHeader( 'From', $replyto );
- }
+ if ($RT::UseFriendlyFromLine) {
+ my $friendly_name = $self->TransactionObj->CreatorObj->RealName;
+ if ( $friendly_name =~ /^"(.*)"$/ ) { # a quoted string
+ $friendly_name = $1;
+ }
+
+ $friendly_name =~ s/"/\\"/g;
+ $self->SetHeader(
+ 'From',
+ sprintf(
+ $RT::FriendlyFromLineFormat,
+ $self->MIMEEncodeString( $friendly_name,
+ $RT::EmailOutputEncoding ),
+ $replyto
+ ),
+ );
+ }
+ else {
+ $self->SetHeader( 'From', $replyto );
+ }
}
unless ( $self->TemplateObj->MIMEObj->head->get('Reply-To') ) {
# }}}
-# {{{ sub SetRecipients
-
-=head2 SetRecipients
-
-Dummy method to be overriden by subclasses which want to set the recipients.
-
-=cut
-
-sub SetRecipients {
- my $self = shift;
- return ();
-}
-
-# }}}
-
-# {{{ sub SetTo
-
-=head2 SetTo
-
-Takes a string that is the addresses you want to send mail to
-
-=cut
-
-sub SetTo {
- my $self = shift;
- my $addresses = shift;
- return $self->SetHeader( 'To', $addresses );
-}
-
-# }}}
-
-# {{{ sub SetCc
-
-=head2 SetCc
-
-Takes a string that is the addresses you want to Cc
-
-=cut
-
-sub SetCc {
- my $self = shift;
- my $addresses = shift;
-
- return $self->SetHeader( 'Cc', $addresses );
-}
-
-# }}}
-
-# {{{ sub SetBcc
-
-=head2 SetBcc
-
-Takes a string that is the addresses you want to Bcc
-
-=cut
-
-sub SetBcc {
- my $self = shift;
- my $addresses = shift;
-
- return $self->SetHeader( 'Bcc', $addresses );
-}
-
-# }}}
-
-# {{{ sub SetPrecedence
-
-sub SetPrecedence {
- my $self = shift;
-
- unless ( $self->TemplateObj->MIMEObj->head->get("Precedence") ) {
- $self->SetHeader( 'Precedence', "bulk" );
- }
-}
-
-# }}}
# {{{ sub SetSubject
my $self = shift;
my $subject;
- unless ( $self->TemplateObj->MIMEObj->head->get('Subject') ) {
- my $message = $self->TransactionObj->Attachments;
- my $ticket = $self->TicketObj->Id;
-
- if ( $self->{'Subject'} ) {
- $subject = $self->{'Subject'};
- }
- elsif ( ( $message->First() )
- && ( $message->First->Headers ) ) {
- my $header = $message->First->Headers();
- $header =~ s/\n\s+/ /g;
- if ( $header =~ /^Subject: (.*?)$/m ) {
- $subject = $1;
- }
- else {
- $subject = $self->TicketObj->Subject();
- }
-
+ my $message = $self->TransactionObj->Attachments;
+ if ( $self->TemplateObj->MIMEObj->head->get('Subject') ) {
+ return ();
+ }
+ if ( $self->{'Subject'} ) {
+ $subject = $self->{'Subject'};
+ }
+ elsif ( ( $message->First() ) && ( $message->First->Headers ) ) {
+ my $header = $message->First->Headers();
+ $header =~ s/\n\s+/ /g;
+ if ( $header =~ /^Subject: (.*?)$/m ) {
+ $subject = $1;
}
else {
$subject = $self->TicketObj->Subject();
}
- $subject =~ s/(\r\n|\n|\s)/ /gi;
+ }
+ else {
+ $subject = $self->TicketObj->Subject();
+ }
+
+ $subject =~ s/(\r\n|\n|\s)/ /gi;
- chomp $subject;
- $self->SetHeader( 'Subject', $subject );
+ chomp $subject;
+ $self->SetHeader( 'Subject', $subject );
- }
- return ($subject);
}
# }}}
# }}}
+=head2 SetReferencesHeaders
+
+Set References and In-Reply-To headers for this message.
+
+=cut
+
+sub SetReferencesHeaders {
+
+ my $self = shift;
+ my ( @in_reply_to, @references, @msgid );
+
+ my $attachments = $self->TransactionObj->Message;
+
+ if ( my $top = $attachments->First() ) {
+ @in_reply_to = split(/\s+/m, $top->GetHeader('In-Reply-To') || '');
+ @references = split(/\s+/m, $top->GetHeader('References') || '' );
+ @msgid = split(/\s+/m, $top->GetHeader('Message-ID') || '');
+ }
+ else {
+ return (undef);
+ }
+
+ # There are two main cases -- this transaction was created with
+ # the RT Web UI, and hence we want to *not* append its Message-ID
+ # to the References and In-Reply-To. OR it came from an outside
+ # source, and we should treat it as per the RFC
+ if ( "@msgid" =~ /<(rt-.*?-\d+-\d+)\.(\d+-0-0)\@$RT::Organization>/) {
+
+ # Make all references which are internal be to version which we
+ # have sent out
+ for (@references, @in_reply_to) {
+ s/<(rt-.*?-\d+-\d+)\.(\d+-0-0)\@$RT::Organization>$/
+ "<$1." . $self->TicketObj->id .
+ "-" . $self->ScripObj->id .
+ "-" . $self->ScripActionObj->{_Message_ID} .
+ "@" . $RT::Organization . ">"/eg
+ }
+
+ # In reply to whatever the internal message was in reply to
+ $self->SetHeader( 'In-Reply-To', join( " ", ( @in_reply_to )));
+
+ # Default the references to whatever we're in reply to
+ @references = @in_reply_to unless @references;
+
+ # References are unchanged from internal
+ } else {
+ # In reply to that message
+ $self->SetHeader( 'In-Reply-To', join( " ", ( @msgid )));
+
+ # Default the references to whatever we're in reply to
+ @references = @in_reply_to unless @references;
+
+ # Push that message onto the end of the references
+ push @references, @msgid;
+ }
+
+ # Push pseudo-ref to the front
+ my $pseudo_ref = $self->PseudoReference;
+ @references = ($pseudo_ref, grep { $_ ne $pseudo_ref } @references);
+
+ # If there are more than 10 references headers, remove all but the
+ # first four and the last six (Gotta keep this from growing
+ # forever)
+ splice(@references, 4, -6) if ($#references >= 10);
+
+ # Add on the references
+ $self->SetHeader( 'References', join( " ", @references) );
+ $self->TemplateObj->MIMEObj->head->fold_length( 'References', 80 );
+
+}
+
# }}}
-# {{{
+=head2 PseudoReference
+
+Returns a fake Message-ID: header for the ticket to allow a base level of threading
+
+=cut
+
+sub PseudoReference {
+
+ my $self = shift;
+ my $pseudo_ref = '<RT-Ticket-'.$self->TicketObj->id .'@'.$RT::Organization .'>';
+ return $pseudo_ref;
+}
+
+
+# {{{ SetHeadingAsEncoding
=head2 SetHeaderAsEncoding($field_name, $charset_encoding)
}
# }}}
-# {{{ MIMENcodeString
+# {{{ MIMEEncodeString
=head2 MIMEEncodeString STRING ENCODING
sub MIMEEncodeString {
my $self = shift;
my $value = shift;
- my $enc = shift;
+ # using RFC2047 notation, sec 2.
+ # encoded-word = "=?" charset "?" encoding "?" encoded-text "?="
+ my $charset = shift;
+ my $encoding = 'B';
+ # An 'encoded-word' may not be more than 75 characters long
+ #
+ # MIME encoding increases 4/3*(number of bytes), and always in multiples
+ # of 4. Thus we have to find the best available value of bytes available
+ # for each chunk.
+ #
+ # First we get the integer max which max*4/3 would fit on space.
+ # Then we find the greater multiple of 3 lower or equal than $max.
+ my $max = int(((75-length('=?'.$charset.'?'.$encoding.'?'.'?='))*3)/4);
+ $max = int($max/3)*3;
chomp $value;
return ($value) unless $value =~ /[^\x20-\x7e]/;
$value =~ s/\s*$//;
Encode::_utf8_off($value);
- my $res = Encode::from_to( $value, "utf-8", $enc );
- $value = encode_mimeword( $value, 'B', $enc );
+ my $res = Encode::from_to( $value, "utf-8", $charset );
+
+ if ($max > 0) {
+ # copy value and split in chuncks
+ my $str=$value;
+ my @chunks = unpack("a$max" x int(length($str)/$max
+ + ((length($str) % $max) ? 1:0)), $str);
+ # encode an join chuncks
+ $value = join " ",
+ map encode_mimeword( $_, $encoding, $charset ), @chunks ;
+ return($value);
+ } else {
+ # gives an error...
+ $RT::Logger->crit("Can't encode! Charset or encoding too big.\n");
+ }
}
# }}}
-# BEGIN LICENSE BLOCK
+# BEGIN BPS TAGGED BLOCK {{{
#
-# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# <jesse@bestpractical.com>
#
-# (Except where explictly superceded by other copyright notices)
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
#
# 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
# 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.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
+#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
#
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
#
-# END LICENSE BLOCK
+# END BPS TAGGED BLOCK }}}
# Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>)
# WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST.
#
-=item Create PARAMHASH
+=head2 Create PARAMHASH
Create takes a hash of values and creates a row in the database:
-=item id
+=head2 id
Returns the current value of id.
(In the database, id is stored as int(11).)
=cut
-=item TransactionId
+=head2 TransactionId
Returns the current value of TransactionId.
(In the database, TransactionId is stored as int(11).)
-=item SetTransactionId VALUE
+=head2 SetTransactionId VALUE
Set TransactionId to VALUE.
=cut
-=item Parent
+=head2 Parent
Returns the current value of Parent.
(In the database, Parent is stored as int(11).)
-=item SetParent VALUE
+=head2 SetParent VALUE
Set Parent to VALUE.
=cut
-=item MessageId
+=head2 MessageId
Returns the current value of MessageId.
(In the database, MessageId is stored as varchar(160).)
-=item SetMessageId VALUE
+=head2 SetMessageId VALUE
Set MessageId to VALUE.
=cut
-=item Subject
+=head2 Subject
Returns the current value of Subject.
(In the database, Subject is stored as varchar(255).)
-=item SetSubject VALUE
+=head2 SetSubject VALUE
Set Subject to VALUE.
=cut
-=item Filename
+=head2 Filename
Returns the current value of Filename.
(In the database, Filename is stored as varchar(255).)
-=item SetFilename VALUE
+=head2 SetFilename VALUE
Set Filename to VALUE.
=cut
-=item ContentType
+=head2 ContentType
Returns the current value of ContentType.
(In the database, ContentType is stored as varchar(80).)
-=item SetContentType VALUE
+=head2 SetContentType VALUE
Set ContentType to VALUE.
=cut
-=item ContentEncoding
+=head2 ContentEncoding
Returns the current value of ContentEncoding.
(In the database, ContentEncoding is stored as varchar(80).)
-=item SetContentEncoding VALUE
+=head2 SetContentEncoding VALUE
Set ContentEncoding to VALUE.
=cut
-=item Content
+=head2 Content
Returns the current value of Content.
(In the database, Content is stored as longtext.)
-=item SetContent VALUE
+=head2 SetContent VALUE
Set Content to VALUE.
=cut
-=item Headers
+=head2 Headers
Returns the current value of Headers.
(In the database, Headers is stored as longtext.)
-=item SetHeaders VALUE
+=head2 SetHeaders VALUE
Set Headers to VALUE.
=cut
-=item Creator
+=head2 Creator
Returns the current value of Creator.
(In the database, Creator is stored as int(11).)
=cut
-=item Created
+=head2 Created
Returns the current value of Created.
(In the database, Created is stored as datetime.)
-sub _ClassAccessible {
+sub _CoreAccessible {
{
id =>
- {read => 1, type => 'int(11)', default => ''},
+ {read => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => ''},
TransactionId =>
- {read => 1, write => 1, type => 'int(11)', default => '0'},
+ {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
Parent =>
- {read => 1, write => 1, type => 'int(11)', default => '0'},
+ {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
MessageId =>
- {read => 1, write => 1, type => 'varchar(160)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 160, is_blob => 0, is_numeric => 0, type => 'varchar(160)', default => ''},
Subject =>
- {read => 1, write => 1, type => 'varchar(255)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 255, is_blob => 0, is_numeric => 0, type => 'varchar(255)', default => ''},
Filename =>
- {read => 1, write => 1, type => 'varchar(255)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 255, is_blob => 0, is_numeric => 0, type => 'varchar(255)', default => ''},
ContentType =>
- {read => 1, write => 1, type => 'varchar(80)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 80, is_blob => 0, is_numeric => 0, type => 'varchar(80)', default => ''},
ContentEncoding =>
- {read => 1, write => 1, type => 'varchar(80)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 80, is_blob => 0, is_numeric => 0, type => 'varchar(80)', default => ''},
Content =>
- {read => 1, write => 1, type => 'longtext', default => ''},
+ {read => 1, write => 1, sql_type => -4, length => 0, is_blob => 1, is_numeric => 0, type => 'longtext', default => ''},
Headers =>
- {read => 1, write => 1, type => 'longtext', default => ''},
+ {read => 1, write => 1, sql_type => -4, length => 0, is_blob => 1, is_numeric => 0, type => 'longtext', default => ''},
Creator =>
- {read => 1, auto => 1, type => 'int(11)', default => '0'},
+ {read => 1, auto => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
Created =>
- {read => 1, auto => 1, type => 'datetime', default => ''},
+ {read => 1, auto => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''},
}
};
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
+Each of these files should begin with the line
no warnings qw(redefine);
-# BEGIN LICENSE BLOCK
+# BEGIN BPS TAGGED BLOCK {{{
#
-# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# <jesse@bestpractical.com>
#
-# (Except where explictly superceded by other copyright notices)
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
#
# 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
# 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.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
+#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
#
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
#
-# END LICENSE BLOCK
+# END BPS TAGGED BLOCK }}}
# Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>)
# WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST.
#
}
-=item NewItem
+=head2 NewItem
Returns an empty new RT::Attachment item
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
+Each of these files should begin with the line
no warnings qw(redefine);
-# BEGIN LICENSE BLOCK
+# BEGIN BPS TAGGED BLOCK {{{
#
-# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# <jesse@bestpractical.com>
#
-# (Except where explictly superceded by other copyright notices)
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
#
# 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
# 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.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
+#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
#
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
#
-# END LICENSE BLOCK
+# END BPS TAGGED BLOCK }}}
package RT::Condition::AnyTransaction;
-# BEGIN LICENSE BLOCK
+# BEGIN BPS TAGGED BLOCK {{{
#
-# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# <jesse@bestpractical.com>
#
-# (Except where explictly superceded by other copyright notices)
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
#
# 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
# 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.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
#
+# CONTRIBUTION SUBMISSION POLICY:
#
-# END LICENSE BLOCK
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
+#
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
+#
+# END BPS TAGGED BLOCK }}}
+
=head1 NAME
RT::Condition::Generic - ;
package RT::Condition::Generic;
-use RT::Base;
use strict;
-use vars qw/@ISA/;
-@ISA = qw(RT::Base);
+use base qw/RT::Base/;
# {{{ sub new
sub new {
TemplateObj => undef,
Argument => undef,
ApplicableTransTypes => undef,
+ CurrentUser => undef,
@_ );
$self->{'Argument'} = $args{'Argument'};
$self->{'TicketObj'} = $args{'TicketObj'};
$self->{'TransactionObj'} = $args{'TransactionObj'};
$self->{'ApplicableTransTypes'} = $args{'ApplicableTransTypes'};
+ $self->CurrentUser($args{'CurrentUser'});
}
# }}}
-# BEGIN LICENSE BLOCK
+# BEGIN BPS TAGGED BLOCK {{{
#
-# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# <jesse@bestpractical.com>
#
-# (Except where explictly superceded by other copyright notices)
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
#
# 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
# 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.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
+#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
#
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
#
-# END LICENSE BLOCK
+# END BPS TAGGED BLOCK }}}
-# BEGIN LICENSE BLOCK
+# BEGIN BPS TAGGED BLOCK {{{
#
-# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# <jesse@bestpractical.com>
#
-# (Except where explictly superceded by other copyright notices)
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
#
# 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
# 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.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
#
-# END LICENSE BLOCK
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
+#
+# END BPS TAGGED BLOCK }}}
+
=head1 NAME
RT::CurrentUser - an RT object representing the current user
use RT::I18N;
use strict;
-use vars qw/@ISA/;
-@ISA= qw(RT::Record);
+use base qw/RT::Record/;
# {{{ sub _Init
# to be a CurrentUser object. but that's hard to do when we're trying to load
# the CurrentUser object
-sub _Init {
- my $self = shift;
- my $Name = shift;
+sub _Init {
+ my $self = shift;
+ my $User = shift;
- $self->{'table'} = "Users";
+ $self->{'table'} = "Users";
- if (defined($Name)) {
- $self->Load($Name);
- }
-
- $self->CurrentUser($self);
+ if ( defined($User) ) {
+
+ if ( UNIVERSAL::isa( $User, 'RT::User' )
+ || UNIVERSAL::isa( $User, 'RT::CurrentUser' ) )
+ {
+ $self->Load( $User->id );
+
+ }
+ elsif ( ref($User) ) {
+ $RT::Logger->crit(
+ "RT::CurrentUser->new() called with a bogus argument: $User");
+ }
+ else {
+ $self->Load($User);
+ }
+ }
+
+ $self->_BuildTableAttributes();
}
# }}}
sub UserObj {
my $self = shift;
- unless ($self->{'UserObj'}) {
use RT::User;
- $self->{'UserObj'} = RT::User->new($self);
- unless ($self->{'UserObj'}->Load($self->Id)) {
+ my $user = RT::User->new($self);
+
+ unless ($user->Load($self->Id)) {
$RT::Logger->err($self->loc("Couldn't load [_1] from the users database.\n", $self->Id));
}
-
- }
- return ($self->{'UserObj'});
+ return ($user);
}
# }}}
# {{{ sub _Accessible
-sub _Accessible {
- my $self = shift;
- my %Cols = (
- Name => 'read',
- Gecos => 'read',
- RealName => 'read',
- Password => 'neither',
- EmailAddress => 'read',
- Privileged => 'read',
- IsAdministrator => 'read'
- );
- return($self->SUPER::_Accessible(@_, %Cols));
+
+
+ sub _CoreAccessible {
+ {
+ Name => { 'read' => 1 },
+ Gecos => { 'read' => 1 },
+ RealName => { 'read' => 1 },
+ Lang => { 'read' => 1 },
+ Password => { 'read' => 0, 'write' => 0 },
+ EmailAddress => { 'read' => 1, 'write' => 0 }
+ };
+
}
# }}}
Loads a User into this CurrentUser object.
Takes a Name.
+
=cut
sub LoadByName {
if ($identifier !~ /\D/) {
$self->SUPER::LoadById($identifier);
}
+
+ elsif (UNIVERSAL::isa($identifier,"RT::User")) {
+ # DWIM if they pass a user in
+ $self->SUPER::LoadById($identifier->Id);
+ }
else {
# This is a bit dangerous, we might get false authen if somebody
# uses ambigous userids or real names:
=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
sub LanguageHandle {
my $self = shift;
- if ((!defined $self->{'LangHandle'}) ||
- (!UNIVERSAL::can($self->{'LangHandle'}, 'maketext')) ||
- (@_)) {
+ if ( ( !defined $self->{'LangHandle'} )
+ || ( !UNIVERSAL::can( $self->{'LangHandle'}, 'maketext' ) )
+ || (@_) ) {
+ if ( !$RT::SystemUser or ($self->id || 0) == $RT::SystemUser->id() ) {
+ @_ = qw(en-US);
+ }
+
+ elsif ( $self->Lang ) {
+ push @_, $self->Lang;
+ }
$self->{'LangHandle'} = RT::I18N->get_handle(@_);
}
+
# Fall back to english.
- unless ($self->{'LangHandle'}) {
+ unless ( $self->{'LangHandle'} ) {
die "We couldn't get a dictionary. Nye mogu naidti slovar. No puedo encontrar dictionario.";
}
- return ($self->{'LangHandle'});
+ return ( $self->{'LangHandle'} );
}
sub loc {
sub loc_fuzzy {
my $self = shift;
- return '' if $_[0] eq '';
+ return '' if (!$_[0] || $_[0] eq '');
# XXX: work around perl's deficiency when matching utf8 data
return $_[0] if Encode::is_utf8($_[0]);
}
# }}}
+
+=head2 CurrentUser
+
+Return the current currentuser object
+
+=cut
+
+sub CurrentUser {
+ my $self = shift;
+ return($self);
+
+}
+
+=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});
eval "require RT::CurrentUser_Local";
-# BEGIN LICENSE BLOCK
+# BEGIN BPS TAGGED BLOCK {{{
#
-# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# <jesse@bestpractical.com>
#
-# (Except where explictly superceded by other copyright notices)
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
#
# 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
# 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.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
+#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
#
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
#
-# END LICENSE BLOCK
+# END BPS TAGGED BLOCK }}}
+
=head1 NAME
RT::Date - a simple Object Oriented date.
$s = int( $duration / $YEAR );
$time_unit = $self->loc("years");
}
- if (0) { # For now, never display the "AGO" # $negative) {
+
+ if ($negative) {
return $self->loc( "[_1] [_2] ago", $s, $time_unit );
}
else {
# }}}
# {{{ GetWeekday
+
=head2 GetWeekday DAY
Takes an integer day of week and returns a localized string for that day of week
# }}}
# {{{ GetMonth
+
=head2 GetMonth DAY
Takes an integer month and returns a localized string for that month
# }}}
+# {{{ sub W3CDTF
+
+=head2 W3CDTF
+
+Takes nothing
+
+Returns the object's date in W3C DTF format
+
+=cut
+
+sub W3CDTF {
+ my $self = shift;
+ my $date = $self->ISO . 'Z';
+ $date =~ s/ /T/;
+ return $date;
+};
+
+# }}}
# {{{ sub LocalTimezone
+
=head2 LocalTimezone
Returns the current timezone. For now, draws off a system timezone, RT::Timezone. Eventually, this may
-# BEGIN LICENSE BLOCK
+# BEGIN BPS TAGGED BLOCK {{{
#
-# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# <jesse@bestpractical.com>
#
-# (Except where explictly superceded by other copyright notices)
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
#
# 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
# 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.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
+#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
#
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
#
-# END LICENSE BLOCK
+# END BPS TAGGED BLOCK }}}
# Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>)
# WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST.
#
-=item Create PARAMHASH
+=head2 Create PARAMHASH
Create takes a hash of values and creates a row in the database:
varchar(255) 'Description'.
varchar(64) 'Domain'.
varchar(64) 'Type'.
- varchar(64) 'Instance'.
+ int(11) 'Instance'.
=cut
-=item id
+=head2 id
Returns the current value of id.
(In the database, id is stored as int(11).)
=cut
-=item Name
+=head2 Name
Returns the current value of Name.
(In the database, Name is stored as varchar(200).)
-=item SetName VALUE
+=head2 SetName VALUE
Set Name to VALUE.
=cut
-=item Description
+=head2 Description
Returns the current value of Description.
(In the database, Description is stored as varchar(255).)
-=item SetDescription VALUE
+=head2 SetDescription VALUE
Set Description to VALUE.
=cut
-=item Domain
+=head2 Domain
Returns the current value of Domain.
(In the database, Domain is stored as varchar(64).)
-=item SetDomain VALUE
+=head2 SetDomain VALUE
Set Domain to VALUE.
=cut
-=item Type
+=head2 Type
Returns the current value of Type.
(In the database, Type is stored as varchar(64).)
-=item SetType VALUE
+=head2 SetType VALUE
Set Type to VALUE.
=cut
-=item Instance
+=head2 Instance
Returns the current value of Instance.
-(In the database, Instance is stored as varchar(64).)
+(In the database, Instance is stored as int(11).)
-=item SetInstance VALUE
+=head2 SetInstance VALUE
Set Instance to VALUE.
Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
-(In the database, Instance will be stored as a varchar(64).)
+(In the database, Instance will be stored as a int(11).)
=cut
-sub _ClassAccessible {
+sub _CoreAccessible {
{
id =>
- {read => 1, type => 'int(11)', default => ''},
+ {read => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => ''},
Name =>
- {read => 1, write => 1, type => 'varchar(200)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 200, is_blob => 0, is_numeric => 0, type => 'varchar(200)', default => ''},
Description =>
- {read => 1, write => 1, type => 'varchar(255)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 255, is_blob => 0, is_numeric => 0, type => 'varchar(255)', default => ''},
Domain =>
- {read => 1, write => 1, type => 'varchar(64)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 64, is_blob => 0, is_numeric => 0, type => 'varchar(64)', default => ''},
Type =>
- {read => 1, write => 1, type => 'varchar(64)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 64, is_blob => 0, is_numeric => 0, type => 'varchar(64)', default => ''},
Instance =>
- {read => 1, write => 1, type => 'varchar(64)', default => ''},
+ {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => ''},
}
};
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
+Each of these files should begin with the line
no warnings qw(redefine);
-# BEGIN LICENSE BLOCK
+# BEGIN BPS TAGGED BLOCK {{{
#
-# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# <jesse@bestpractical.com>
#
-# (Except where explictly superceded by other copyright notices)
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
#
# 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
# 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.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
+#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
#
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
#
-# END LICENSE BLOCK
+# END BPS TAGGED BLOCK }}}
# Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>)
# WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST.
#
-=item Create PARAMHASH
+=head2 Create PARAMHASH
Create takes a hash of values and creates a row in the database:
-=item id
+=head2 id
Returns the current value of id.
(In the database, id is stored as int(11).)
=cut
-=item GroupId
+=head2 GroupId
Returns the current value of GroupId.
(In the database, GroupId is stored as int(11).)
-=item SetGroupId VALUE
+=head2 SetGroupId VALUE
Set GroupId to VALUE.
=cut
-=item MemberId
+=head2 MemberId
Returns the current value of MemberId.
(In the database, MemberId is stored as int(11).)
-=item SetMemberId VALUE
+=head2 SetMemberId VALUE
Set MemberId to VALUE.
-sub _ClassAccessible {
+sub _CoreAccessible {
{
id =>
- {read => 1, type => 'int(11)', default => ''},
+ {read => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => ''},
GroupId =>
- {read => 1, write => 1, type => 'int(11)', default => '0'},
+ {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
MemberId =>
- {read => 1, write => 1, type => 'int(11)', default => '0'},
+ {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
}
};
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
+Each of these files should begin with the line
no warnings qw(redefine);
-# BEGIN LICENSE BLOCK
+# BEGIN BPS TAGGED BLOCK {{{
#
-# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# <jesse@bestpractical.com>
#
-# (Except where explictly superceded by other copyright notices)
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
#
# 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
# 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.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
+#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
#
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
#
-# END LICENSE BLOCK
+# END BPS TAGGED BLOCK }}}
# Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>)
# WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST.
#
}
-=item NewItem
+=head2 NewItem
Returns an empty new RT::GroupMember item
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
+Each of these files should begin with the line
no warnings qw(redefine);
-# BEGIN LICENSE BLOCK
+# BEGIN BPS TAGGED BLOCK {{{
#
-# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# <jesse@bestpractical.com>
#
-# (Except where explictly superceded by other copyright notices)
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
#
# 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
# 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.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
+#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
#
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
#
-# END LICENSE BLOCK
+# END BPS TAGGED BLOCK }}}
# Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>)
# WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST.
#
}
-=item NewItem
+=head2 NewItem
Returns an empty new RT::Group item
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
+Each of these files should begin with the line
no warnings qw(redefine);
-# BEGIN LICENSE BLOCK
+# BEGIN BPS TAGGED BLOCK {{{
#
-# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# <jesse@bestpractical.com>
#
-# (Except where explictly superceded by other copyright notices)
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
#
# 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
# 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.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
#
-# END LICENSE BLOCK
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
+#
+# END BPS TAGGED BLOCK }}}
+
=head1 NAME
RT::Handle - RT's database handle
eval "use DBIx::SearchBuilder::Handle::$RT::DatabaseType;
\@ISA= qw(DBIx::SearchBuilder::Handle::$RT::DatabaseType);";
-#TODO check for errors here.
+
+if ($@) {
+ die "Unable to load DBIx::SearchBuilder database handle for '$RT::DatabaseType'.".
+ "\n".
+ "Perhaps you've picked an invalid database type or spelled it incorrectly.".
+ "\n". $@;
+}
=head2 Connect
=cut
sub Connect {
-my $self=shift;
+ my $self = shift;
-# Unless the database port is a positive integer, we really don't want to pass it.
+ if ($RT::DatabaseType eq 'Oracle') {
+ $ENV{'NLS_LANG'} = "AMERICAN_AMERICA.AL32UTF8";
+ $ENV{'NLS_NCHAR'} = "AL32UTF8";
+
+ }
-$self->SUPER::Connect(
+ $self->SUPER::Connect(
User => $RT::DatabaseUser,
Password => $RT::DatabasePassword,
);
+
+ $self->dbh->{LongReadLen} = $RT::MaxAttachmentSize;
}
-=item BuildDSN
+=head2 BuildDSN
Build the DSN for the RT database. doesn't take any parameters, draws all that
from the config file.
=cut
+use File::Spec;
sub BuildDSN {
my $self = shift;
+# Unless the database port is a positive integer, we really don't want to pass it.
$RT::DatabasePort = undef unless (defined $RT::DatabasePort && $RT::DatabasePort =~ /^(\d+)$/);
$RT::DatabaseHost = undef unless (defined $RT::DatabaseHost && $RT::DatabaseHost ne '');
+$RT::DatabaseName = File::Spec->catfile($RT::VarPath, $RT::DatabaseName)
+ if ($RT::DatabaseType eq 'SQLite') and
+ not File::Spec->file_name_is_absolute($RT::DatabaseName);
+
$self->SUPER::BuildDSN(Host => $RT::DatabaseHost,
Database => $RT::DatabaseName,
-# BEGIN LICENSE BLOCK
+# BEGIN BPS TAGGED BLOCK {{{
#
-# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# <jesse@bestpractical.com>
#
-# (Except where explictly superceded by other copyright notices)
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
#
# 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
# 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.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
+#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
#
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
#
-# END LICENSE BLOCK
+# END BPS TAGGED BLOCK }}}
use strict;
use RT;
use vars qw ($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
# set the version for version checking
- $VERSION = do { my @r = (q$Revision: 1.2 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; # must be all one line, for MakeMaker
+ $VERSION = do { my @r = (q$Revision: 1.1.1.3 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; # must be all one line, for MakeMaker
@ISA = qw(Exporter);
-# BEGIN LICENSE BLOCK
+# BEGIN BPS TAGGED BLOCK {{{
#
-# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# <jesse@bestpractical.com>
#
-# (Except where explictly superceded by other copyright notices)
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
#
# 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
# 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.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
#
-# END LICENSE BLOCK
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
+#
+# END BPS TAGGED BLOCK }}}
package RT::Interface::Email;
use strict;
use Mail::Address;
use MIME::Entity;
use RT::EmailParser;
-
+use File::Temp;
BEGIN {
use Exporter ();
use vars qw ($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
# set the version for version checking
- $VERSION = do { my @r = (q$Revision: 1.2 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; # must be all one line, for MakeMaker
+ $VERSION = do { my @r = (q$Revision: 1.1.1.5 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; # must be all one line, for MakeMaker
@ISA = qw(Exporter);
# as well as any optionally exported functions
@EXPORT_OK = qw(
&CreateUser
- &GetMessageContent
- &CheckForLoops
- &CheckForSuspiciousSender
- &CheckForAutoGenerated
- &MailError
- &ParseCcAddressesFromHead
- &ParseSenderAddressFromHead
- &ParseErrorsToAddressFromHead
- &ParseAddressFromHeader
+ &GetMessageContent
+ &CheckForLoops
+ &CheckForSuspiciousSender
+ &CheckForAutoGenerated
+ &MailError
+ &ParseCcAddressesFromHead
+ &ParseSenderAddressFromHead
+ &ParseErrorsToAddressFromHead
+ &ParseAddressFromHeader
&Gateway);
}
=head1 NAME
- RT::Interface::CLI - helper functions for creating a commandline RT interface
+ RT::Interface::Email - helper functions for parsing email sent to RT
=head1 SYNOPSIS
my ($From, $junk) = ParseSenderAddressFromHead($head);
- if (($From =~ /^mailer-daemon/i) or
- ($From =~ /^postmaster/i)){
+ if (($From =~ /^mailer-daemon\@/i) or
+ ($From =~ /^postmaster\@/i)){
return (1);
}
if ($Precedence =~ /^(bulk|junk)/i) {
return (1);
}
- else {
- return (0);
+
+ # First Class mailer uses this as a clue.
+ my $FCJunk = $head->get("X-FC-Machinegenerated") || "";
+ if ($FCJunk =~ /^true/i) {
+ return (1);
}
+
+ return (0);
}
# }}}
+# {{{ IsRTAddress
+
+=head2 IsRTAddress ADDRESS
+
+Takes a single parameter, an email address.
+Returns true if that address matches the $RTAddressRegexp.
+Returns false, otherwise.
+
+=cut
+
+sub IsRTAddress {
+ my $address = shift || '';
+
+ # Example: the following rule would tell RT not to Cc
+ # "tickets@noc.example.com"
+ if ( defined($RT::RTAddressRegexp) &&
+ $address =~ /$RT::RTAddressRegexp/ ) {
+ return(1);
+ } else {
+ return (undef);
+ }
+}
+
+# }}}
+
+# {{{ CullRTAddresses
+
+=head2 CullRTAddresses ARRAY
+
+Takes a single argument, an array of email addresses.
+Returns the same array with any IsRTAddress()es weeded out.
+
+=cut
+
+sub CullRTAddresses {
+ return (grep { IsRTAddress($_) } @_);
+}
+
+# }}}
# {{{ sub MailError
sub MailError {
Subject => 'There has been an error',
Explanation => 'Unexplained error',
MIMEObj => undef,
+ Attach => undef,
LogLevel => 'crit',
@_);
Bcc => $args{'Bcc'},
To => $args{'To'},
Subject => $args{'Subject'},
+ Precedence => 'bulk',
'X-RT-Loop-Prevention' => $RT::rtname,
);
$mimeobj->sync_headers();
$entity->add_part($mimeobj);
}
-
+
+ if ($args{'Attach'}) {
+ $entity->attach(Data => $args{'Attach'}, Type => 'message/rfc822');
+
+ }
+
if ($RT::MailCommand eq 'sendmailpipe') {
open (MAIL, "|$RT::SendmailPath $RT::SendmailArguments") || return(0);
print MAIL $entity->as_string;
close(MAIL);
}
else {
- $entity->send($RT::MailCommand, $RT::MailParams);
+ $entity->send($RT::MailCommand, $RT::MailParams);
}
}
my ($Username, $Address, $Name, $ErrorsTo, $entity) = @_;
my $NewUser = RT::User->new($RT::SystemUser);
- # This data is tainted by some Very Broken mailers.
- # (Sometimes they send raw ISO 8859-1 data here. fear that.
- require Encode;
- $Username = Encode::encode(utf8 => $Username, Encode::FB_PERLQQ()) if defined $Username;
- $Name = Encode::encode(utf8 => $Name, Encode::FB_PERLQQ()) if defined $Name;
-
my ($Val, $Message) =
$NewUser->Create(Name => ($Username || $Address),
EmailAddress => $Address,
return $CurrentUser;
}
-# }}}
+# }}}
+
# {{{ ParseCcAddressesFromHead
=head2 ParseCcAddressesFromHead HASHREF
foreach my $AddrObj (@ToObjs, @CcObjs) {
my $Address = $AddrObj->address;
$Address = $args{'CurrentUser'}->UserObj->CanonicalizeEmailAddress($Address);
- next if ($args{'CurrentUser'}->EmailAddress =~ /^$Address$/i);
- next if ($args{'QueueObj'}->CorrespondAddress =~ /^$Address$/i);
- next if ($args{'QueueObj'}->CommentAddress =~ /^$Address$/i);
- next if (RT::EmailParser::IsRTAddress(undef, $Address));
+ next if ($args{'CurrentUser'}->EmailAddress =~ /^\Q$Address\E$/i);
+ next if ($args{'QueueObj'}->CorrespondAddress =~ /^\Q$Address\E$/i);
+ next if ($args{'QueueObj'}->CommentAddress =~ /^\Q$Address\E$/i);
+ next if (RT::EmailParser->IsRTAddress($Address));
push (@Addresses, $Address);
}
sub ParseAddressFromHeader{
my $Addr = shift;
+ # Perl 5.8.0 breaks when doing regex matches on utf8
+ Encode::_utf8_off($Addr) if $] == 5.008;
my @Addresses = Mail::Address->parse($Addr);
my $AddrObj = $Addresses[0];
}
# }}}
+# {{{ sub ParseTicketId
+
+
+sub ParseTicketId {
+ my $Subject = shift;
+ my $id;
+
+ my $test_name = $RT::EmailSubjectTagRegex || qr/\Q$RT::rtname\E/;
+
+ if ( $Subject =~ s/\[$test_name\s+\#(\d+)\s*\]//i ) {
+ my $id = $1;
+ $RT::Logger->debug("Found a ticket ID. It's $id");
+ return ($id);
+ }
+ else {
+ return (undef);
+ }
+}
+
+# }}}
+
+
+=head2 Gateway ARGSREF
-=head2 Gateway
+Takes parameters:
+
+ action
+ queue
+ message
+
This performs all the "guts" of the mail rt-mailgate program, and is
designed to be called from the web interface with a message, user
object, and so on.
+Can also take an optional 'ticket' parameter; this ticket id overrides
+any ticket id found in the subject.
+
+Returns:
+
+ An array of:
+
+ (status code, message, optional ticket object)
+
+ status code is a numeric value.
+
+ for temporary failures, the status code should be -75
+
+ for permanent failures which are handled by RT, the status code
+ should be 0
+
+ for succces, the status code should be 1
+
+
+
=cut
sub Gateway {
- my %args = ( message => undef,
- queue => 1,
- action => 'correspond',
- ticket => undef,
- @_ );
+ my $argsref = shift;
+
+ my %args = %$argsref;
+
+ # Set some reasonable defaults
+ $args{'action'} ||= 'correspond';
+ $args{'queue'} ||= '1';
# Validate the action
- unless ( $args{'action'} =~ /^(comment|correspond|action)$/ ) {
+ my ($status, @actions) = IsCorrectAction( $args{'action'} );
+ unless ( $status ) {
# Can't safely loc this. What object do we loc around?
- return ( 0, "Invalid 'action' parameter", undef );
+ $RT::Logger->crit("Mail gateway called with an invalid action paramenter '".$actions[0]."' for queue '".$args{'queue'}."'");
+
+ return ( -75, "Invalid 'action' parameter", undef );
}
my $parser = RT::EmailParser->new();
- $parser->ParseMIMEEntityFromScalar( $args{'message'} );
+
+ $parser->SmartParseMIMEEntityFromScalar( Message => $args{'message'});
+
+ if (!$parser->Entity()) {
+ MailError(
+ To => $RT::OwnerEmail,
+ Subject => "RT Bounce: Unparseable message",
+ Explanation => "RT couldn't process the message below",
+ Attach => $args{'message'}
+ );
+
+ return(0,"Failed to parse this message. Something is likely badly wrong with the message");
+ }
my $Message = $parser->Entity();
- my $head = $Message->head;
+ my $head = $Message->head;
+
+ my ( $CurrentUser, $AuthStat, $error );
- my ( $CurrentUser, $AuthStat, $status, $error );
+ # Initalize AuthStat so comparisons work correctly
+ $AuthStat = -9999999;
my $ErrorsTo = ParseErrorsToAddressFromHead($head);
- my $MessageId = $head->get('Message-Id')
+ my $MessageId = $head->get('Message-ID')
|| "<no-message-id-" . time . rand(2000) . "\@.$RT::Organization>";
#Pull apart the subject line
my $Subject = $head->get('Subject') || '';
chomp $Subject;
-
- $args{'ticket'} ||= $parser->ParseTicketId($Subject);
+ $args{'ticket'} ||= ParseTicketId($Subject);
my $SystemTicket;
- if ($args{'ticket'} ) {
+ my $Right = 'CreateTicket';
+ if ( $args{'ticket'} ) {
$SystemTicket = RT::Ticket->new($RT::SystemUser);
- $SystemTicket->Load($args{'ticket'});
+ $SystemTicket->Load( $args{'ticket'} );
+ # if there's an existing ticket, this must be a reply
+ $Right = 'ReplyToTicket';
}
#Set up a queue object
my $SystemQueueObj = RT::Queue->new($RT::SystemUser);
$SystemQueueObj->Load( $args{'queue'} );
-
# We can safely have no queue of we have a known-good ticket
unless ( $args{'ticket'} || $SystemQueueObj->id ) {
- MailError(
- To => $RT::OwnerEmail,
- Subject => "RT Bounce: $Subject",
- Explanation => "RT couldn't find the queue: " . $args{'queue'},
- MIMEObj => $Message );
- return ( 0, "RT couldn't find the queue: " . $args{'queue'}, undef );
+ return ( -75, "RT couldn't find the queue: " . $args{'queue'}, undef );
}
# Authentication Level
- # -1 - Get out. this user has been explicitly declined
+ # -1 - Get out. this user has been explicitly declined
# 0 - User may not do anything (Not used at the moment)
# 1 - Normal user
# 2 - User is allowed to specify status updates etc. a la enhanced-mailgate
- push @RT::MailPlugins, "Auth::MailFrom" unless @RT::MailPlugins;
+ push @RT::MailPlugins, "Auth::MailFrom" unless @RT::MailPlugins;
+
# Since this needs loading, no matter what
- for (@RT::MailPlugins) {
+ foreach (@RT::MailPlugins) {
my $Code;
my $NewAuthStat;
if ( ref($_) eq "CODE" ) {
$Code = $_;
}
else {
- $_ = "RT::Interface::Email::$_" unless /^RT::Interface::Email::/;
+ $_ = "RT::Interface::Email::".$_ unless $_ =~ /^RT::Interface::Email::/;
eval "require $_;";
if ($@) {
- die ("Couldn't load module $_: $@");
+ $RT::Logger->crit("Couldn't load module '$_': $@");
next;
}
no strict 'refs';
if ( !defined( $Code = *{ $_ . "::GetCurrentUser" }{CODE} ) ) {
- die ("No GetCurrentUser code found in $_ module");
+ $RT::Logger->crit("No GetCurrentUser code found in $_ module");
next;
}
}
- ( $CurrentUser, $NewAuthStat ) = $Code->( Message => $Message,
- CurrentUser => $CurrentUser,
- AuthLevel => $AuthStat,
- Action => $args{'action'},
- Ticket => $SystemTicket,
- Queue => $SystemQueueObj );
+ foreach my $action ( @actions ) {
+
+ ( $CurrentUser, $NewAuthStat ) = $Code->(
+ Message => $Message,
+ RawMessageRef => \$args{'message'},
+ CurrentUser => $CurrentUser,
+ AuthLevel => $AuthStat,
+ Action => $action,
+ Ticket => $SystemTicket,
+ Queue => $SystemQueueObj
+ );
+
+
+ # If a module returns a "-1" then we discard the ticket, so.
+ $AuthStat = -1 if $NewAuthStat == -1;
+
+ # You get the highest level of authentication you were assigned.
+ $AuthStat = $NewAuthStat if $NewAuthStat > $AuthStat;
+
+ last if $AuthStat == -1;
+ }
- # You get the highest level of authentication you were assigned.
last if $AuthStat == -1;
- $AuthStat = $NewAuthStat if $NewAuthStat > $AuthStat;
}
# {{{ If authentication fails and no new user was created, get out.
if ( !$CurrentUser or !$CurrentUser->Id or $AuthStat == -1 ) {
# If the plugins refused to create one, they lose.
- MailError(
- Subject => "Could not load a valid user",
- Explanation => <<EOT,
+ unless ( $AuthStat == -1 ) {
+
+ # Notify the RT Admin of the failure.
+ # XXX Should this be configurable?
+ MailError(
+ To => $RT::OwnerEmail,
+ Subject => "Could not load a valid user",
+ Explanation => <<EOT,
RT could not load a valid user, and RT's configuration does not allow
-for the creation of a new user for your email.
+for the creation of a new user for this email ($ErrorsTo).
-Your RT administrator needs to grant 'Everyone' the right 'CreateTicket'
-for this queue.
+You might need to grant 'Everyone' the right '$Right' for the
+queue @{[$args{'queue'}]}.
EOT
- MIMEObj => $Message,
- LogLevel => 'error' )
- unless $AuthStat == -1;
+ MIMEObj => $Message,
+ LogLevel => 'error'
+ );
+
+ # Also notify the requestor that his request has been dropped.
+ MailError(
+ To => $ErrorsTo,
+ Subject => "Could not load a valid user",
+ Explanation => <<EOT,
+RT could not load a valid user, and RT's configuration does not allow
+for the creation of a new user for your email.
+
+EOT
+ MIMEObj => $Message,
+ LogLevel => 'error'
+ );
+ }
return ( 0, "Could not load a valid user", undef );
}
# {{{ Drop it if it's disallowed
if ( $AuthStat == 0 ) {
MailError(
- To => $ErrorsTo,
- Subject => "Permission Denied",
- Explanation => "You do not have permission to communicate with RT",
- MIMEObj => $Message );
+ To => $ErrorsTo,
+ Subject => "Permission Denied",
+ Explanation => "You do not have permission to communicate with RT",
+ MIMEObj => $Message
+ );
}
# }}}
#Should we mail it to RTOwner?
if ($RT::LoopsToRTOwner) {
- MailError( To => $RT::OwnerEmail,
- Subject => "RT Bounce: $Subject",
- Explanation => "RT thinks this message may be a bounce",
- MIMEObj => $Message );
-
- #Do we actually want to store it?
- return ( 0, "Message Bounced", undef ) unless ($RT::StoreLoops);
+ MailError(
+ To => $RT::OwnerEmail,
+ Subject => "RT Bounce: $Subject",
+ Explanation => "RT thinks this message may be a bounce",
+ MIMEObj => $Message
+ );
}
+
+ #Do we actually want to store it?
+ return ( 0, "Message Bounced", undef ) unless ($RT::StoreLoops);
}
# }}}
# {{{ Squelch replies if necessary
# Don't let the user stuff the RT-Squelch-Replies-To header.
if ( $head->get('RT-Squelch-Replies-To') ) {
- $head->add( 'RT-Relocated-Squelch-Replies-To',
- $head->get('RT-Squelch-Replies-To') );
+ $head->add(
+ 'RT-Relocated-Squelch-Replies-To',
+ $head->get('RT-Squelch-Replies-To')
+ );
$head->delete('RT-Squelch-Replies-To');
}
if ($SquelchReplies) {
- ## TODO: This is a hack. It should be some other way to
- ## indicate that the transaction should be "silent".
+ # Squelch replies to the sender, and also leave a clue to
+ # allow us to squelch ALL outbound messages. This way we
+ # can punt the logic of "what to do when we get a bounce"
+ # to the scrip. We might want to notify nobody. Or just
+ # the RT Owner. Or maybe all Privileged watchers.
my ( $Sender, $junk ) = ParseSenderAddressFromHead($head);
$head->add( 'RT-Squelch-Replies-To', $Sender );
+ $head->add( 'RT-DetectedAutoGenerated', 'true' );
}
# }}}
my $Ticket = RT::Ticket->new($CurrentUser);
# {{{ If we don't have a ticket Id, we're creating a new ticket
- if ( !$args{'ticket'} ) {
+ if ( (!$SystemTicket || !$SystemTicket->Id) &&
+ grep /^(comment|correspond)$/, @actions ) {
# {{{ Create a new ticket
my @Requestors = ( $CurrentUser->id );
if ($RT::ParseNewMessageForTicketCcs) {
- @Cc = ParseCcAddressesFromHead( Head => $head,
- CurrentUser => $CurrentUser,
- QueueObj => $SystemQueueObj );
+ @Cc = ParseCcAddressesFromHead(
+ Head => $head,
+ CurrentUser => $CurrentUser,
+ QueueObj => $SystemQueueObj
+ );
}
my ( $id, $Transaction, $ErrStr ) = $Ticket->Create(
- Queue => $SystemQueueObj->Id,
- Subject => $Subject,
- Requestor => \@Requestors,
- Cc => \@Cc,
- MIMEObj => $Message );
+ Queue => $SystemQueueObj->Id,
+ Subject => $Subject,
+ Requestor => \@Requestors,
+ Cc => \@Cc,
+ MIMEObj => $Message
+ );
if ( $id == 0 ) {
- MailError( To => $ErrorsTo,
- Subject => "Ticket creation failed",
- Explanation => $ErrStr,
- MIMEObj => $Message );
+ MailError(
+ To => $ErrorsTo,
+ Subject => "Ticket creation failed",
+ Explanation => $ErrStr,
+ MIMEObj => $Message
+ );
$RT::Logger->error("Create failed: $id / $Transaction / $ErrStr ");
return ( 0, "Ticket creation failed", $Ticket );
}
+ # strip comments&corresponds from the actions we don't need record twice
+ @actions = grep !/^(comment|correspond)$/, @actions;
+ $args{'ticket'} = $id;
# }}}
}
- # }}}
+ $Ticket->Load( $args{'ticket'} );
+ unless ( $Ticket->Id ) {
+ my $message = "Could not find a ticket with id " . $args{'ticket'};
+ MailError(
+ To => $ErrorsTo,
+ Subject => "Message not recorded",
+ Explanation => $message,
+ MIMEObj => $Message
+ );
+
+ return ( 0, $message );
+ }
- # If the action is comment, add a comment.
- elsif ( $args{'action'} =~ /^(comment|correspond)$/i ) {
- $Ticket->Load($args{'ticket'});
- unless ( $Ticket->Id ) {
- my $message = "Could not find a ticket with id ".$args{'ticket'};
- MailError( To => $ErrorsTo,
- Subject => "Message not recorded",
- Explanation => $message,
- MIMEObj => $Message );
-
- return ( 0, $message);
+ # }}}
+ foreach my $action( @actions ) {
+ # If the action is comment, add a comment.
+ if ( $action =~ /^(comment|correspond)$/i ) {
+ my ( $status, $msg );
+ if ( $action =~ /^correspond$/i ) {
+ ( $status, $msg ) = $Ticket->Correspond( MIMEObj => $Message );
+ }
+ else {
+ ( $status, $msg ) = $Ticket->Comment( MIMEObj => $Message );
+ }
+ unless ($status) {
+
+ #Warn the sender that we couldn't actually submit the comment.
+ MailError(
+ To => $ErrorsTo,
+ Subject => "Message not recorded",
+ Explanation => $msg,
+ MIMEObj => $Message
+ );
+ return ( 0, "Message not recorded", $Ticket );
+ }
}
-
- my ( $status, $msg );
- if ( $args{'action'} =~ /^correspond$/ ) {
- ( $status, $msg ) = $Ticket->Correspond( MIMEObj => $Message );
+ elsif ($RT::UnsafeEmailCommands && $action =~ /^take$/i ) {
+ my ( $status, $msg ) = $Ticket->SetOwner( $CurrentUser->id );
+ unless ($status) {
+
+ #Warn the sender that we couldn't actually submit the comment.
+ MailError(
+ To => $ErrorsTo,
+ Subject => "Ticket not taken",
+ Explanation => $msg,
+ MIMEObj => $Message
+ );
+ return ( 0, "Ticket not taken", $Ticket );
+ }
}
- else {
- ( $status, $msg ) = $Ticket->Comment( MIMEObj => $Message );
+ elsif ( $RT::UnsafeEmailCommands && $action =~ /^resolve$/i ) {
+ my ( $status, $msg ) = $Ticket->SetStatus( 'resolved' );
+ unless ($status) {
+ #Warn the sender that we couldn't actually submit the comment.
+ MailError(
+ To => $ErrorsTo,
+ Subject => "Ticket not resolved",
+ Explanation => $msg,
+ MIMEObj => $Message
+ );
+ return ( 0, "Ticket not resolved", $Ticket );
+ }
}
- unless ($status) {
-
- #Warn the sender that we couldn't actually submit the comment.
- MailError( To => $ErrorsTo,
- Subject => "Message not recorded",
- Explanation => $msg,
- MIMEObj => $Message );
- return ( 0, "Message not recorded", $Ticket );
+
+ else {
+
+ #Return mail to the sender with an error
+ MailError(
+ To => $ErrorsTo,
+ Subject => "RT Configuration error",
+ Explanation => "'"
+ . $args{'action'}
+ . "' not a recognized action."
+ . " Your RT administrator has misconfigured "
+ . "the mail aliases which invoke RT",
+ MIMEObj => $Message
+ );
+ $RT::Logger->crit( $args{'action'} . " type unknown for $MessageId" );
+ return (
+ -75,
+ "Configuration error: "
+ . $args{'action'}
+ . " not a recognized action",
+ $Ticket
+ );
+
}
}
- else {
-
- #Return mail to the sender with an error
- MailError( To => $ErrorsTo,
- Subject => "RT Configuration error",
- Explanation => "'"
- . $args{'action'}
- . "' not a recognized action."
- . " Your RT administrator has misconfigured "
- . "the mail aliases which invoke RT",
- MIMEObj => $Message );
- $RT::Logger->crit( $args{'action'} . " type unknown for $MessageId" );
- return ( 0, "Configuration error: " . $args{'action'} . " not a recognized action", $Ticket );
-
- }
-
+ return ( 1, "Success", $Ticket );
+}
-return ( 1, "Success", $Ticket );
+sub IsCorrectAction
+{
+ my $action = shift;
+ my @actions = split /-/, $action;
+ foreach ( @actions ) {
+ return (0, $_) unless /^(?:comment|correspond|take|resolve)$/;
+ }
+ return (1, @actions);
}
+
eval "require RT::Interface::Email_Vendor";
die $@ if ($@ && $@ !~ qr{^Can't locate RT/Interface/Email_Vendor.pm});
eval "require RT::Interface::Email_Local";
-# BEGIN LICENSE BLOCK
+# BEGIN BPS TAGGED BLOCK {{{
#
-# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# <jesse@bestpractical.com>
#
-# (Except where explictly superceded by other copyright notices)
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
#
# 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
# 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.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
#
-# END LICENSE BLOCK
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
+#
+# END BPS TAGGED BLOCK }}}
## Portions Copyright 2000 Tobias Brox <tobix@fsck.com>
## This is a library of static subs to be used by the Mason web
+# {{{ EscapeUTF8
+=head2 EscapeUTF8 SCALARREF
-# {{{ sub NewApacheHandler
-
-=head2 NewApacheHandler
-
- Takes extra options to pass to HTML::Mason::ApacheHandler->new
- Returns a new Mason::ApacheHandler object
+does a css-busting but minimalist escaping of whatever html you're passing in.
=cut
-sub NewApacheHandler {
- require HTML::Mason::ApacheHandler;
- my $ah = new HTML::Mason::ApacheHandler(
-
- comp_root => [
- [ local => $RT::MasonLocalComponentRoot ],
- [ standard => $RT::MasonComponentRoot ]
- ],
- args_method => "CGI",
- default_escape_flags => 'h',
- allow_globals => [qw(%session)],
- data_dir => "$RT::MasonDataDir",
- @_
- );
+sub EscapeUTF8 {
+ my $ref = shift;
+ return unless defined $$ref;
+ my $val = $$ref;
+ use bytes;
+ $val =~ s/&/&/g;
+ $val =~ s/</</g;
+ $val =~ s/>/>/g;
+ $val =~ s/\(/(/g;
+ $val =~ s/\)/)/g;
+ $val =~ s/"/"/g;
+ $val =~ s/'/'/g;
+ $$ref = $val;
+ Encode::_utf8_on($$ref);
+
- $ah->interp->set_escape( h => \&RT::Interface::Web::EscapeUTF8 );
-
- return ($ah);
}
# }}}
-# {{{ sub NewCGIHandler
+# {{{ EscapeURI
-=head2 NewCGIHandler
+=head2 EscapeURI SCALARREF
- Returns a new Mason::CGIHandler object
+Escapes URI component according to RFC2396
=cut
-sub NewCGIHandler {
- my %args = (
- @_
- );
+use Encode qw();
+sub EscapeURI {
+ my $ref = shift;
+ $$ref = Encode::encode_utf8( $$ref );
+ $$ref =~ s/([^a-zA-Z0-9_.!~*'()-])/uc sprintf("%%%02X", ord($1))/eg;
+ Encode::_utf8_on( $$ref );
+}
- my $handler = HTML::Mason::CGIHandler->new(
- comp_root => [
- [ local => $RT::MasonLocalComponentRoot ],
- [ standard => $RT::MasonComponentRoot ]
- ],
- data_dir => "$RT::MasonDataDir",
- default_escape_flags => 'h',
- allow_globals => [qw(%session)]
- );
-
+# }}}
+
+# {{{ WebCanonicalizeInfo
- $handler->interp->set_escape( h => \&RT::Interface::Web::EscapeUTF8 );
+=head2 WebCanonicalizeInfo();
+Different web servers set different environmental varibles. This
+function must return something suitable for REMOTE_USER. By default,
+just downcase $ENV{'REMOTE_USER'}
+
+=cut
- return ($handler);
+sub WebCanonicalizeInfo {
+ my $user;
+ if ( defined $ENV{'REMOTE_USER'} ) {
+ $user = lc ( $ENV{'REMOTE_USER'} ) if( length($ENV{'REMOTE_USER'}) );
+ }
+
+ return $user;
}
+
# }}}
+# {{{ WebExternalAutoInfo
-# {{{ EscapeUTF8
+=head2 WebExternalAutoInfo($user);
-=head2 EscapeUTF8 SCALARREF
-
-does a css-busting but minimalist escaping of whatever html you're passing in.
+Returns a hash of user attributes, used when WebExternalAuto is set.
=cut
-sub EscapeUTF8 {
- my $ref = shift;
- my $val = $$ref;
- use bytes;
- $val =~ s/&/&/g;
- $val =~ s/</</g;
- $val =~ s/>/>/g;
- $val =~ s/\(/(/g;
- $val =~ s/\)/)/g;
- $val =~ s/"/"/g;
- $val =~ s/'/'/g;
- $$ref = $val;
- Encode::_utf8_on($$ref);
+sub WebExternalAutoInfo {
+ my $user = shift;
+
+ my %user_info;
+ $user_info{'Privileged'} = 1;
+
+ if ($^O !~ /^(?:riscos|MacOS|MSWin32|dos|os2)$/) {
+ # Populate fields with information from Unix /etc/passwd
+
+ my ($comments, $realname) = (getpwnam($user))[5, 6];
+ $user_info{'Comments'} = $comments if defined $comments;
+ $user_info{'RealName'} = $realname if defined $realname;
+ }
+ elsif ($^O eq 'MSWin32' and eval 'use Net::AdminMisc; 1') {
+ # Populate fields with information from NT domain controller
+ }
+
+ # and return the wad of stuff
+ return {%user_info};
}
# }}}
UNIVERSAL::can($session{'CurrentUser'}, 'loc')){
return($session{'CurrentUser'}->loc(@_));
}
- else {
- my $u = RT::CurrentUser->new($RT::SystemUser);
+ elsif ( my $u = eval { RT::CurrentUser->new($RT::SystemUser->Id) } ) {
return ($u->loc(@_));
}
+ else {
+ # pathetic case -- SystemUser is gone.
+ return $_[0];
+ }
}
# }}}
return($session{'CurrentUser'}->loc_fuzzy($msg));
}
else {
- my $u = RT::CurrentUser->new($RT::SystemUser);
+ my $u = RT::CurrentUser->new($RT::SystemUser->Id);
return ($u->loc_fuzzy($msg));
}
}
}
my %create_args = (
+ Type => $ARGS{'Type'} || 'ticket',
Queue => $ARGS{'Queue'},
Owner => $ARGS{'Owner'},
InitialPriority => $ARGS{'InitialPriority'},
Starts => $starts->ISO,
MIMEObj => $MIMEObj
);
- foreach my $arg (%ARGS) {
- if ($arg =~ /^CustomField-(\d+)(.*?)$/) {
+ foreach my $arg (keys %ARGS) {
+ my $cfid = $1;
+
next if ($arg =~ /-Magic$/);
- $create_args{"CustomField-".$1} = $ARGS{"$arg"};
+ #Object-RT::Ticket--CustomField-3-Values
+ if ($arg =~ /^Object-RT::Transaction--CustomField-/) {
+ $create_args{$arg} = $ARGS{$arg};
+ }
+ elsif ($arg =~ /^Object-RT::Ticket--CustomField-(\d+)(.*?)$/) {
+ my $cfid = $1;
+ my $cf = RT::CustomField->new( $session{'CurrentUser'});
+ $cf->Load($cfid);
+
+ if ( $cf->Type eq 'Freeform' && ! $cf->SingleValue) {
+ $ARGS{$arg} =~ s/\r\n/\n/g;
+ $ARGS{$arg} = [split('\n', $ARGS{$arg})];
+ }
+
+ if ( $cf->Type =~ /text/i) { # Catch both Text and Wikitext
+ $ARGS{$arg} =~ s/\r//g;
+ }
+
+ if ( $arg =~ /-Upload$/ ) {
+ $create_args{"CustomField-".$cfid} = _UploadedFile($arg);
+ }
+ else {
+ $create_args{"CustomField-".$cfid} = $ARGS{"$arg"};
+ }
}
}
- my ( $id, $Trans, $ErrMsg ) = $Ticket->Create(%create_args);
- unless ( $id && $Trans ) {
- Abort($ErrMsg);
+
+
+ # XXX TODO This code should be about six lines. and badly needs refactoring.
+
+ # {{{ turn new link lists into arrays, and pass in the proper arguments
+ my (@dependson, @dependedonby, @parents, @children, @refersto, @referredtoby);
+
+ foreach my $luri ( split ( / /, $ARGS{"new-DependsOn"} ) ) {
+ $luri =~ s/\s*$//; # Strip trailing whitespace
+ push @dependson, $luri;
}
- my @linktypes = qw( DependsOn MemberOf RefersTo );
+ $create_args{'DependsOn'} = \@dependson;
- foreach my $linktype (@linktypes) {
- foreach my $luri ( split ( / /, $ARGS{"new-$linktype"} ) ) {
- $luri =~ s/\s*$//; # Strip trailing whitespace
- my ( $val, $msg ) = $Ticket->AddLink(
- Target => $luri,
- Type => $linktype
- );
- push ( @Actions, $msg ) unless ($val);
- }
+ foreach my $luri ( split ( / /, $ARGS{"DependsOn-new"} ) ) {
+ push @dependedonby, $luri;
+ }
+ $create_args{'DependedOnBy'} = \@dependedonby;
- foreach my $luri ( split ( / /, $ARGS{"$linktype-new"} ) ) {
- my ( $val, $msg ) = $Ticket->AddLink(
- Base => $luri,
- Type => $linktype
- );
+ foreach my $luri ( split ( / /, $ARGS{"new-MemberOf"} ) ) {
+ $luri =~ s/\s*$//; # Strip trailing whitespace
+ push @parents, $luri;
+ }
+ $create_args{'Parents'} = \@parents;
- push ( @Actions, $msg ) unless ($val);
- }
+ foreach my $luri ( split ( / /, $ARGS{"MemberOf-new"} ) ) {
+ push @children, $luri;
+ }
+ $create_args{'Children'} = \@children;
+
+ foreach my $luri ( split ( / /, $ARGS{"new-RefersTo"} ) ) {
+ $luri =~ s/\s*$//; # Strip trailing whitespace
+ push @refersto, $luri;
+ }
+ $create_args{'RefersTo'} = \@refersto;
+
+ foreach my $luri ( split ( / /, $ARGS{"RefersTo-new"} ) ) {
+ push @referredtoby, $luri;
+ }
+ $create_args{'ReferredToBy'} = \@referredtoby;
+ # }}}
+
+
+ my ( $id, $Trans, $ErrMsg ) = $Ticket->Create(%create_args);
+ unless ( $id && $Trans ) {
+ Abort($ErrMsg);
}
push ( @Actions, split("\n", $ErrMsg) );
);
#Make the update content have no 'weird' newlines in it
- if ( $args{ARGSRef}->{'UpdateContent'} ) {
+ if ( $args{ARGSRef}->{'UpdateTimeWorked'}
+ || $args{ARGSRef}->{'UpdateContent'}
+ || $args{ARGSRef}->{'UpdateAttachments'} )
+ {
if (
$args{ARGSRef}->{'UpdateSubject'} eq $args{'TicketObj'}->Subject() )
}
my $Message = MakeMIMEEntity(
- Subject => $args{ARGSRef}->{'UpdateSubject'},
- Body => $args{ARGSRef}->{'UpdateContent'},
+ Subject => $args{ARGSRef}->{'UpdateSubject'},
+ Body => $args{ARGSRef}->{'UpdateContent'},
);
- if ($args{ARGSRef}->{'UpdateAttachments'}) {
- $Message->make_multipart;
- $Message->add_part($_) foreach values %{$args{ARGSRef}->{'UpdateAttachments'}};
- }
-
- ## TODO: Implement public comments
- if ( $args{ARGSRef}->{'UpdateType'} =~ /^(private|public)$/ ) {
- my ( $Transaction, $Description ) = $args{TicketObj}->Comment(
- CcMessageTo => $args{ARGSRef}->{'UpdateCc'},
- BccMessageTo => $args{ARGSRef}->{'UpdateBcc'},
- MIMEObj => $Message,
- TimeTaken => $args{ARGSRef}->{'UpdateTimeWorked'}
- );
- push ( @{ $args{Actions} }, $Description );
- }
- elsif ( $args{ARGSRef}->{'UpdateType'} eq 'response' ) {
- my ( $Transaction, $Description ) = $args{TicketObj}->Correspond(
- CcMessageTo => $args{ARGSRef}->{'UpdateCc'},
- BccMessageTo => $args{ARGSRef}->{'UpdateBcc'},
- MIMEObj => $Message,
- TimeTaken => $args{ARGSRef}->{'UpdateTimeWorked'}
- );
- push ( @{ $args{Actions} }, $Description );
+ $Message->head->add( 'Message-ID' =>
+ "<rt-"
+ . $RT::VERSION . "-"
+ . $$ . "-"
+ . CORE::time() . "-"
+ . int(rand(2000)) . "."
+ . $args{'TicketObj'}->id . "-"
+ . "0" . "-" # Scrip
+ . "0" . "@" # Email sent
+ . $RT::Organization
+ . ">" );
+ my $old_txn = RT::Transaction->new( $session{'CurrentUser'} );
+ if ( $args{ARGSRef}->{'QuoteTransaction'} ) {
+ $old_txn->Load( $args{ARGSRef}->{'QuoteTransaction'} );
}
else {
- push ( @{ $args{'Actions'} },
- loc("Update type was neither correspondence nor comment.").
- " ".
- loc("Update not recorded.")
- );
+ $old_txn = $args{TicketObj}->Transactions->First();
}
+
+ if ( $old_txn->Message && $old_txn->Message->First ) {
+ my @in_reply_to = split(/\s+/m, $old_txn->Message->First->GetHeader('In-Reply-To') || '');
+ my @references = split(/\s+/m, $old_txn->Message->First->GetHeader('References') || '' );
+ my @msgid = split(/\s+/m,$old_txn->Message->First->GetHeader('Message-ID') || '');
+ my @rtmsgid = split(/\s+/m,$old_txn->Message->First->GetHeader('RT-Message-ID') || '');
+
+ $Message->head->replace( 'In-Reply-To', join (' ', @rtmsgid ? @rtmsgid : @msgid));
+ $Message->head->replace( 'References', join(' ', @references, @msgid, @rtmsgid));
+ }
+
+ if ( $args{ARGSRef}->{'UpdateAttachments'} ) {
+ $Message->make_multipart;
+ $Message->add_part($_)
+ foreach values %{ $args{ARGSRef}->{'UpdateAttachments'} };
+ }
+
+ ## TODO: Implement public comments
+ if ( $args{ARGSRef}->{'UpdateType'} =~ /^(private|public)$/ ) {
+ my ( $Transaction, $Description, $Object ) = $args{TicketObj}->Comment(
+ CcMessageTo => $args{ARGSRef}->{'UpdateCc'},
+ BccMessageTo => $args{ARGSRef}->{'UpdateBcc'},
+ MIMEObj => $Message,
+ 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(
+ CcMessageTo => $args{ARGSRef}->{'UpdateCc'},
+ BccMessageTo => $args{ARGSRef}->{'UpdateBcc'},
+ MIMEObj => $Message,
+ TimeTaken => $args{ARGSRef}->{'UpdateTimeWorked'}
+ );
+ push( @{ $args{Actions} }, $Description );
+ $Object->UpdateCustomFields( ARGSRef => $args{ARGSRef} ) if $Object;
+ }
+ else {
+ push(
+ @{ $args{'Actions'} },
+ loc("Update type was neither correspondence nor comment.") . " "
+ . loc("Update not recorded.")
+ );
}
}
+}
# }}}
Cc => undef,
Body => undef,
AttachmentFieldName => undef,
- map Encode::encode_utf8($_), @_,
+# map Encode::encode_utf8($_), @_,
+ @_,
);
#Make the update content have no 'weird' newlines in it
Subject => $args{'Subject'} || "",
From => $args{'From'},
Cc => $args{'Cc'},
+ Charset => 'utf8',
Data => [ $args{'Body'} ]
);
}
#foreach my $filehandle (@filenames) {
- my ( $fh, $temp_file ) = tempfile();
+ my ( $fh, $temp_file );
+ for ( 1 .. 10 ) {
+ # on NFS and NTFS, it is possible that tempfile() conflicts
+ # with other processes, causing a race condition. we try to
+ # accommodate this by pausing and retrying.
+ last if ($fh, $temp_file) = eval { tempfile( UNLINK => 1) };
+ sleep 1;
+ }
binmode $fh; #thank you, windows
my ($buffer);
$Message->attach(
Path => $temp_file,
- Filename => $filename,
+ Filename => Encode::decode_utf8($filename),
Type => $uploadinfo->{'Content-Type'},
);
close($fh);
# }}}
# {{{ Limit requestor email
+ if ( $args{ARGS}->{'ValueOfWatcherRole'} ne '' ) {
+ $session{'tickets'}->LimitWatcher(
+ TYPE => $args{ARGS}->{'WatcherRole'},
+ VALUE => $args{ARGS}->{'ValueOfWatcherRole'},
+ OPERATOR => $args{ARGS}->{'WatcherRoleOp'},
- if ( $args{ARGS}->{'ValueOfRequestor'} ne '' ) {
- my $alias = $session{'tickets'}->LimitRequestor(
- VALUE => $args{ARGS}->{'ValueOfRequestor'},
- OPERATOR => $args{ARGS}->{'RequestorOp'},
);
-
}
# }}}
# }}}
-# {{{ sub Config
-# TODO: This might eventually read the cookies, user configuration
-# information from the DB, queue configuration information from the
-# DB, etc.
-
-sub Config {
- my $args = shift;
- my $key = shift;
- return $args->{$key} || $RT::WebOptions{$key};
-}
-
-# }}}
-
# {{{ sub ProcessACLChanges
sub ProcessACLChanges {
my $obj;
- if ($object_type eq 'RT::Queue') {
- $obj = RT::Queue->new($session{'CurrentUser'});
- $obj->Load($object_id);
- } elsif ($object_type eq 'RT::Group') {
- $obj = RT::Group->new($session{'CurrentUser'});
- $obj->Load($object_id);
-
- } elsif ($object_type eq 'RT::System') {
+ if ($object_type eq 'RT::System') {
$obj = $RT::System;
+ } elsif ($RT::ACE::OBJECT_TYPES{$object_type}) {
+ $obj = $object_type->new($session{'CurrentUser'});
+ $obj->Load($object_id);
} else {
- push (@results, loc("System Error").
+ push (@results, loc("System Error"). ': '.
loc("Rights could not be granted for [_1]", $object_type));
next;
}
next unless ($right);
my $obj;
- if ($object_type eq 'RT::Queue') {
- $obj = RT::Queue->new($session{'CurrentUser'});
- $obj->Load($object_id);
- } elsif ($object_type eq 'RT::Group') {
- $obj = RT::Group->new($session{'CurrentUser'});
- $obj->Load($object_id);
-
- } elsif ($object_type eq 'RT::System') {
+ if ($object_type eq 'RT::System') {
$obj = $RT::System;
+ } elsif ($RT::ACE::OBJECT_TYPES{$object_type}) {
+ $obj = $object_type->new($session{'CurrentUser'});
+ $obj->Load($object_id);
} else {
- push (@results, loc("System Error").
+ push (@results, loc("System Error"). ': '.
loc("Rights could not be revoked for [_1]", $object_type));
next;
}
@_
);
- my (@results);
-
- my $object = $args{'Object'};
- my $attributes = $args{'AttributesRef'};
- my $ARGSRef = $args{'ARGSRef'};
- foreach my $attribute (@$attributes) {
- my $value;
- if ( defined $ARGSRef->{$attribute} ) {
- $value = $ARGSRef->{$attribute};
- }
- elsif (
- defined( $args{'AttributePrefix'} )
- && defined(
- $ARGSRef->{ $args{'AttributePrefix'} . "-" . $attribute }
- )
- ) {
- $value = $ARGSRef->{ $args{'AttributePrefix'} . "-" . $attribute };
-
- } else {
- next;
- }
+ my $Object = $args{'Object'};
+ my @results = $Object->Update(AttributesRef => $args{'AttributesRef'},
+ ARGSRef => $args{'ARGSRef'},
+ AttributePrefix => $args{'AttributePrefix'}
+ );
- $value =~ s/\r\n/\n/gs;
-
- if ($value ne $object->$attribute()){
-
- my $method = "Set$attribute";
- my ( $code, $msg ) = $object->$method($value);
-
- push @results, loc($attribute) . ': ' . loc_fuzzy($msg);
-=for loc
- "[_1] could not be set to [_2].", # loc
- "That is already the current value", # loc
- "No value sent to _Set!\n", # loc
- "Illegal value for [_1]", # loc
- "The new value has been set.", # loc
- "No column specified", # loc
- "Immutable field", # loc
- "Nonexistant field?", # loc
- "Invalid data", # loc
- "Couldn't find row", # loc
- "Missing a primary key?: [_1]", # loc
- "Found Object", # loc
-=cut
- };
- }
return (@results);
}
my ( $err, $msg ) = $Object->DeleteValue($id);
push ( @results, $msg );
}
+
+ my $vals = $Object->Values();
+ while (my $cfv = $vals->Next()) {
+ if (my $so = $ARGSRef->{ 'CustomField-' . $Object->Id . '-SortOrder' . $cfv->Id }) {
+ if ($cfv->SortOrder != $so) {
+ my ( $err, $msg ) = $cfv->SetSortOrder($so);
+ push ( @results, $msg );
+ }
+ }
+ }
+
return (@results);
}
TimeEstimated
TimeWorked
TimeLeft
+ Type
Status
Queue
);
}
}
+
+ # Status isn't a field that can be set to a null value.
+ # RT core complains if you try
+ delete $ARGSRef->{'Status'} unless ($ARGSRef->{'Status'});
+
my @results = UpdateRecordObject(
AttributesRef => \@attribs,
Object => $TicketObj,
# }}}
-# {{{ 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 = RT::Ticket->new( $session{'CurrentUser'} );
- $Ticket->Load($tick);
-
- # For each custom field
- foreach my $cf ( keys %{ $custom_fields_to_mod{$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{$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} }
- : ( $ARGSRef->{$arg} );
- if ( ( $arg =~ /-AddValue$/ ) || ( $arg =~ /-Value$/ ) ) {
- foreach my $value (@values) {
- next unless ($value);
- my ( $val, $msg ) = $Ticket->AddCustomFieldValue(
- Field => $cf,
- Value => $value
- );
- push ( @results, $msg );
- }
- }
- elsif ( $arg =~ /-DeleteValues$/ ) {
- foreach my $value (@values) {
- next unless ($value);
- my ( $val, $msg ) = $Ticket->DeleteCustomFieldValue(
+ foreach my $arg ( keys %{$ARGSRef} ) {
+ # Only interested in args for the current CF:
+ next unless ( $arg =~ /^Object-$class-(?:$id)?-CustomField-$cf-/ );
+
+ # 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 ($ARGSRef->{$1.'-Value'} || $ARGSRef->{$1.'-Values'}) ;
+
+ # "Empty" values does not mean anything for Image and Binary fields
+ next if $CustomFieldObj->Type =~ /^(?:Image|Binary)$/;
+
+ $arg = $1."-Values";
+ $ARGSRef->{$1."-Values"} = undef;
+
+ }
+ my @values = ();
+ if (ref( $ARGSRef->{$arg} ) eq 'ARRAY' ) {
+ @values = @{ $ARGSRef->{$arg} };
+ } elsif ($CustomFieldObj->Type =~ /text/i) { # Both Text and Wikitext
+ @values = ($ARGSRef->{$arg});
+ } else {
+ @values = split /\n/, $ARGSRef->{$arg};
+ }
+
+ if ( ($CustomFieldObj->Type eq 'Freeform'
+ && ! $CustomFieldObj->SingleValue) ||
+ $CustomFieldObj->Type =~ /text/i) {
+ foreach my $val (@values) {
+ $val =~ s/\r//g;
+ }
+ }
+
+ 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 $value_hash = _UploadedFile($arg) or next;
+
+ my ( $val, $msg ) = $Object->AddCustomFieldValue(
+ %$value_hash,
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 ($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);
+ );
+ 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;
# 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 );
foreach my $key ( keys %$ARGSRef ) {
# {{{ Delete deletable watchers
- if ( ( $key =~ /^Ticket-DelWatcher-Type-(.*)-Principal-(\d+)$/ ) ) {
+ if ( ( $key =~ /^Ticket-DeleteWatcher-Type-(.*)-Principal-(\d+)$/ ) ) {
my ( $code, $msg ) =
$Ticket->DeleteWatcher(PrincipalId => $2,
Type => $1);
}
# Delete watchers in the simple style demanded by the bulk manipulator
- elsif ( $key =~ /^Delete(Requestor|Cc|AdminCc)$/ ) {
- my ( $code, $msg ) = $Ticket->DeleteWatcher( Type => $ARGSRef->{$key}, PrincipalId => $1 );
+ elsif ( $key =~ /^Delete(Requestor|Cc|AdminCc)$/ ) {
+ my ( $code, $msg ) = $Ticket->DeleteWatcher( Email => $ARGSRef->{$key}, Type => $1 );
push @results, $msg;
}
my $Ticket = $args{'TicketObj'};
my $ARGSRef = $args{'ARGSRef'};
+
+ my (@results) = ProcessRecordLinks(RecordObj => $Ticket,
+ ARGSRef => $ARGSRef);
+
+ #Merge if we need to
+ if ( $ARGSRef->{ $Ticket->Id . "-MergeInto" } ) {
+ my ( $val, $msg ) =
+ $Ticket->MergeInto( $ARGSRef->{ $Ticket->Id . "-MergeInto" } );
+ push @results, $msg;
+ }
+
+ return (@results);
+}
+
+# }}}
+
+sub ProcessRecordLinks {
+ my %args = ( RecordObj => undef,
+ ARGSRef => undef,
+ @_ );
+
+ my $Record = $args{'RecordObj'};
+ my $ARGSRef = $args{'ARGSRef'};
+
my (@results);
# Delete links that are gone gone gone.
push @results,
"Trying to delete: Base: $base Target: $target Type $type";
- my ( $val, $msg ) = $Ticket->DeleteLink( Base => $base,
+ my ( $val, $msg ) = $Record->DeleteLink( Base => $base,
Type => $type,
Target => $target );
my @linktypes = qw( DependsOn MemberOf RefersTo );
foreach my $linktype (@linktypes) {
- if ( $ARGSRef->{ $Ticket->Id . "-$linktype" } ) {
- for my $luri ( split ( / /, $ARGSRef->{ $Ticket->Id . "-$linktype" } ) ) {
+ if ( $ARGSRef->{ $Record->Id . "-$linktype" } ) {
+ for my $luri ( split ( / /, $ARGSRef->{ $Record->Id . "-$linktype" } ) ) {
$luri =~ s/\s*$//; # Strip trailing whitespace
- my ( $val, $msg ) = $Ticket->AddLink( Target => $luri,
+ my ( $val, $msg ) = $Record->AddLink( Target => $luri,
Type => $linktype );
push @results, $msg;
}
}
- if ( $ARGSRef->{ "$linktype-" . $Ticket->Id } ) {
+ if ( $ARGSRef->{ "$linktype-" . $Record->Id } ) {
- for my $luri ( split ( / /, $ARGSRef->{ "$linktype-" . $Ticket->Id } ) ) {
- my ( $val, $msg ) = $Ticket->AddLink( Base => $luri,
+ for my $luri ( split ( / /, $ARGSRef->{ "$linktype-" . $Record->Id } ) ) {
+ my ( $val, $msg ) = $Record->AddLink( Base => $luri,
Type => $linktype );
push @results, $msg;
}
}
- #Merge if we need to
- if ( $ARGSRef->{ $Ticket->Id . "-MergeInto" } ) {
- my ( $val, $msg ) =
- $Ticket->MergeInto( $ARGSRef->{ $Ticket->Id . "-MergeInto" } );
- push @results, $msg;
- }
-
return (@results);
}
-# }}}
+
+=head2 _UploadedFile ( $arg );
+
+Takes a CGI parameter name; if a file is uploaded under that name,
+return a hash reference suitable for AddCustomFieldValue's use:
+C<( Value => $filename, LargeContent => $content, ContentType => $type )>.
+
+Returns C<undef> if no files were uploaded in the C<$arg> field.
+
+=cut
+
+sub _UploadedFile {
+ my $arg = shift;
+ my $cgi_object = $m->cgi_object;
+ my $fh = $cgi_object->upload($arg) or return undef;
+ my $upload_info = $cgi_object->uploadInfo($fh);
+
+ my $filename = "$fh";
+ $filename =~ s#^.*[\\/]##;
+ binmode($fh);
+
+ return {
+ Value => $filename,
+ LargeContent => do { local $/; scalar <$fh> },
+ ContentType => $upload_info->{'Content-Type'},
+ };
+}
eval "require RT::Interface::Web_Vendor";
die $@ if ($@ && $@ !~ qr{^Can't locate RT/Interface/Web_Vendor.pm});
-# BEGIN LICENSE BLOCK
+# BEGIN BPS TAGGED BLOCK {{{
#
-# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# <jesse@bestpractical.com>
#
-# (Except where explictly superceded by other copyright notices)
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
#
# 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
# 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.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
+#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
#
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
#
-# END LICENSE BLOCK
+# END BPS TAGGED BLOCK }}}
# Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>)
# WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST.
#
-=item Create PARAMHASH
+=head2 Create PARAMHASH
Create takes a hash of values and creates a row in the database:
-=item id
+=head2 id
Returns the current value of id.
(In the database, id is stored as int(11).)
=cut
-=item Base
+=head2 Base
Returns the current value of Base.
(In the database, Base is stored as varchar(240).)
-=item SetBase VALUE
+=head2 SetBase VALUE
Set Base to VALUE.
=cut
-=item Target
+=head2 Target
Returns the current value of Target.
(In the database, Target is stored as varchar(240).)
-=item SetTarget VALUE
+=head2 SetTarget VALUE
Set Target to VALUE.
=cut
-=item Type
+=head2 Type
Returns the current value of Type.
(In the database, Type is stored as varchar(20).)
-=item SetType VALUE
+=head2 SetType VALUE
Set Type to VALUE.
=cut
-=item LocalTarget
+=head2 LocalTarget
Returns the current value of LocalTarget.
(In the database, LocalTarget is stored as int(11).)
-=item SetLocalTarget VALUE
+=head2 SetLocalTarget VALUE
Set LocalTarget to VALUE.
=cut
-=item LocalBase
+=head2 LocalBase
Returns the current value of LocalBase.
(In the database, LocalBase is stored as int(11).)
-=item SetLocalBase VALUE
+=head2 SetLocalBase VALUE
Set LocalBase to VALUE.
=cut
-=item LastUpdatedBy
+=head2 LastUpdatedBy
Returns the current value of LastUpdatedBy.
(In the database, LastUpdatedBy is stored as int(11).)
=cut
-=item LastUpdated
+=head2 LastUpdated
Returns the current value of LastUpdated.
(In the database, LastUpdated is stored as datetime.)
=cut
-=item Creator
+=head2 Creator
Returns the current value of Creator.
(In the database, Creator is stored as int(11).)
=cut
-=item Created
+=head2 Created
Returns the current value of Created.
(In the database, Created is stored as datetime.)
-sub _ClassAccessible {
+sub _CoreAccessible {
{
id =>
- {read => 1, type => 'int(11)', default => ''},
+ {read => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => ''},
Base =>
- {read => 1, write => 1, type => 'varchar(240)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 240, is_blob => 0, is_numeric => 0, type => 'varchar(240)', default => ''},
Target =>
- {read => 1, write => 1, type => 'varchar(240)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 240, is_blob => 0, is_numeric => 0, type => 'varchar(240)', default => ''},
Type =>
- {read => 1, write => 1, type => 'varchar(20)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 20, is_blob => 0, is_numeric => 0, type => 'varchar(20)', default => ''},
LocalTarget =>
- {read => 1, write => 1, type => 'int(11)', default => '0'},
+ {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
LocalBase =>
- {read => 1, write => 1, type => 'int(11)', default => '0'},
+ {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
LastUpdatedBy =>
- {read => 1, auto => 1, type => 'int(11)', default => '0'},
+ {read => 1, auto => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
LastUpdated =>
- {read => 1, auto => 1, type => 'datetime', default => ''},
+ {read => 1, auto => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''},
Creator =>
- {read => 1, auto => 1, type => 'int(11)', default => '0'},
+ {read => 1, auto => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
Created =>
- {read => 1, auto => 1, type => 'datetime', default => ''},
+ {read => 1, auto => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''},
}
};
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
+Each of these files should begin with the line
no warnings qw(redefine);
-# BEGIN LICENSE BLOCK
+# BEGIN BPS TAGGED BLOCK {{{
#
-# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# <jesse@bestpractical.com>
#
-# (Except where explictly superceded by other copyright notices)
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
#
# 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
# 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.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
+#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
#
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
#
-# END LICENSE BLOCK
+# END BPS TAGGED BLOCK }}}
# Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>)
# WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST.
#
}
-=item NewItem
+=head2 NewItem
Returns an empty new RT::Link item
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
+Each of these files should begin with the line
no warnings qw(redefine);
-# BEGIN LICENSE BLOCK
+# BEGIN BPS TAGGED BLOCK {{{
#
-# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# <jesse@bestpractical.com>
#
-# (Except where explictly superceded by other copyright notices)
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
#
# 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
# 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.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
+#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
#
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
#
-# END LICENSE BLOCK
+# END BPS TAGGED BLOCK }}}
# Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>)
# WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST.
#
-=item Create PARAMHASH
+=head2 Create PARAMHASH
Create takes a hash of values and creates a row in the database:
-=item id
+=head2 id
Returns the current value of id.
(In the database, id is stored as int(11).)
=cut
-=item Name
+=head2 Name
Returns the current value of Name.
(In the database, Name is stored as varchar(200).)
-=item SetName VALUE
+=head2 SetName VALUE
Set Name to VALUE.
=cut
-=item Description
+=head2 Description
Returns the current value of Description.
(In the database, Description is stored as varchar(255).)
-=item SetDescription VALUE
+=head2 SetDescription VALUE
Set Description to VALUE.
=cut
-=item CorrespondAddress
+=head2 CorrespondAddress
Returns the current value of CorrespondAddress.
(In the database, CorrespondAddress is stored as varchar(120).)
-=item SetCorrespondAddress VALUE
+=head2 SetCorrespondAddress VALUE
Set CorrespondAddress to VALUE.
=cut
-=item CommentAddress
+=head2 CommentAddress
Returns the current value of CommentAddress.
(In the database, CommentAddress is stored as varchar(120).)
-=item SetCommentAddress VALUE
+=head2 SetCommentAddress VALUE
Set CommentAddress to VALUE.
=cut
-=item InitialPriority
+=head2 InitialPriority
Returns the current value of InitialPriority.
(In the database, InitialPriority is stored as int(11).)
-=item SetInitialPriority VALUE
+=head2 SetInitialPriority VALUE
Set InitialPriority to VALUE.
=cut
-=item FinalPriority
+=head2 FinalPriority
Returns the current value of FinalPriority.
(In the database, FinalPriority is stored as int(11).)
-=item SetFinalPriority VALUE
+=head2 SetFinalPriority VALUE
Set FinalPriority to VALUE.
=cut
-=item DefaultDueIn
+=head2 DefaultDueIn
Returns the current value of DefaultDueIn.
(In the database, DefaultDueIn is stored as int(11).)
-=item SetDefaultDueIn VALUE
+=head2 SetDefaultDueIn VALUE
Set DefaultDueIn to VALUE.
=cut
-=item Creator
+=head2 Creator
Returns the current value of Creator.
(In the database, Creator is stored as int(11).)
=cut
-=item Created
+=head2 Created
Returns the current value of Created.
(In the database, Created is stored as datetime.)
=cut
-=item LastUpdatedBy
+=head2 LastUpdatedBy
Returns the current value of LastUpdatedBy.
(In the database, LastUpdatedBy is stored as int(11).)
=cut
-=item LastUpdated
+=head2 LastUpdated
Returns the current value of LastUpdated.
(In the database, LastUpdated is stored as datetime.)
=cut
-=item Disabled
+=head2 Disabled
Returns the current value of Disabled.
(In the database, Disabled is stored as smallint(6).)
-=item SetDisabled VALUE
+=head2 SetDisabled VALUE
Set Disabled to VALUE.
-sub _ClassAccessible {
+sub _CoreAccessible {
{
id =>
- {read => 1, type => 'int(11)', default => ''},
+ {read => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => ''},
Name =>
- {read => 1, write => 1, type => 'varchar(200)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 200, is_blob => 0, is_numeric => 0, type => 'varchar(200)', default => ''},
Description =>
- {read => 1, write => 1, type => 'varchar(255)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 255, is_blob => 0, is_numeric => 0, type => 'varchar(255)', default => ''},
CorrespondAddress =>
- {read => 1, write => 1, type => 'varchar(120)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 120, is_blob => 0, is_numeric => 0, type => 'varchar(120)', default => ''},
CommentAddress =>
- {read => 1, write => 1, type => 'varchar(120)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 120, is_blob => 0, is_numeric => 0, type => 'varchar(120)', default => ''},
InitialPriority =>
- {read => 1, write => 1, type => 'int(11)', default => '0'},
+ {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
FinalPriority =>
- {read => 1, write => 1, type => 'int(11)', default => '0'},
+ {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
DefaultDueIn =>
- {read => 1, write => 1, type => 'int(11)', default => '0'},
+ {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
Creator =>
- {read => 1, auto => 1, type => 'int(11)', default => '0'},
+ {read => 1, auto => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
Created =>
- {read => 1, auto => 1, type => 'datetime', default => ''},
+ {read => 1, auto => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''},
LastUpdatedBy =>
- {read => 1, auto => 1, type => 'int(11)', default => '0'},
+ {read => 1, auto => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
LastUpdated =>
- {read => 1, auto => 1, type => 'datetime', default => ''},
+ {read => 1, auto => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''},
Disabled =>
- {read => 1, write => 1, type => 'smallint(6)', default => '0'},
+ {read => 1, write => 1, sql_type => 5, length => 6, is_blob => 0, is_numeric => 1, type => 'smallint(6)', default => '0'},
}
};
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
+Each of these files should begin with the line
no warnings qw(redefine);
-# BEGIN LICENSE BLOCK
+# BEGIN BPS TAGGED BLOCK {{{
#
-# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# <jesse@bestpractical.com>
#
-# (Except where explictly superceded by other copyright notices)
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
#
# 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
# 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.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
+#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
#
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
#
-# END LICENSE BLOCK
+# END BPS TAGGED BLOCK }}}
# Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>)
# WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST.
#
}
-=item NewItem
+=head2 NewItem
Returns an empty new RT::Queue item
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
+Each of these files should begin with the line
no warnings qw(redefine);
-# BEGIN LICENSE BLOCK
+# BEGIN BPS TAGGED BLOCK {{{
#
-# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# <jesse@bestpractical.com>
#
-# (Except where explictly superceded by other copyright notices)
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
#
# 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
# 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.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
#
-# END LICENSE BLOCK
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
+#
+# END BPS TAGGED BLOCK }}}
+
=head1 NAME
RT::Record - Base class for RT record objects
package RT::Record;
use RT::Date;
use RT::User;
-
+use RT::Attributes;
use RT::Base;
use DBIx::SearchBuilder::Record::Cachable;
use strict;
-use vars qw/@ISA/;
+use vars qw/@ISA $_TABLE_ATTR/;
@ISA = qw(RT::Base);
sub _Init {
my $self = shift;
+ $self->_BuildTableAttributes unless ($_TABLE_ATTR->{ref($self)});
$self->CurrentUser(@_);
-
}
# }}}
# }}}
+=head2 Delete
+
+Delete this record object from the database.
+
+=cut
+
+sub Delete {
+ my $self = shift;
+ my ($rv) = $self->SUPER::Delete;
+ if ($rv) {
+ return ($rv, $self->loc("Object deleted"));
+ } else {
+
+ return(0, $self->loc("Object could not be deleted"))
+ }
+}
+
+=head2 ObjectTypeStr
+
+Returns a string which is this object's type. The type is the class,
+without the "RT::" prefix.
+
+=begin testing
+
+my $ticket = RT::Ticket->new($RT::SystemUser);
+my $group = RT::Group->new($RT::SystemUser);
+is($ticket->ObjectTypeStr, 'Ticket', "Ticket returns correct typestring");
+is($group->ObjectTypeStr, 'Group', "Group returns correct typestring");
+
+=end testing
+
+=cut
+
+sub ObjectTypeStr {
+ my $self = shift;
+ if (ref($self) =~ /^.*::(\w+)$/) {
+ return $self->loc($1);
+ } else {
+ return $self->loc(ref($self));
+ }
+}
+
+=head2 Attributes
+
+Return this object's attributes as an RT::Attributes object
+
+=cut
+
+sub Attributes {
+ my $self = shift;
+
+ unless ($self->{'attributes'}) {
+ $self->{'attributes'} = RT::Attributes->new($self->CurrentUser);
+ $self->{'attributes'}->LimitToObject($self);
+ }
+ return ($self->{'attributes'});
+
+}
+
+
+=head2 AddAttribute { Name, Description, Content }
+
+Adds a new attribute for this object.
+
+=cut
+
+sub AddAttribute {
+ my $self = shift;
+ my %args = ( Name => undef,
+ Description => undef,
+ Content => undef,
+ @_ );
+
+ my $attr = RT::Attribute->new( $self->CurrentUser );
+ my ( $id, $msg ) = $attr->Create(
+ Object => $self,
+ Name => $args{'Name'},
+ Description => $args{'Description'},
+ Content => $args{'Content'} );
+
+
+ # XXX TODO: Why won't RedoSearch work here?
+ $self->Attributes->_DoSearch;
+
+ return ($id, $msg);
+}
+
+
+=head2 SetAttribute { Name, Description, Content }
+
+Like AddAttribute, but replaces all existing attributes with the same Name.
+
+=cut
+
+sub SetAttribute {
+ my $self = shift;
+ my %args = ( Name => undef,
+ Description => undef,
+ Content => undef,
+ @_ );
+
+ my @AttributeObjs = $self->Attributes->Named( $args{'Name'} )
+ or return $self->AddAttribute( %args );
+
+ my $AttributeObj = pop( @AttributeObjs );
+ $_->Delete foreach @AttributeObjs;
+
+ $AttributeObj->SetDescription( $args{'Description'} );
+ $AttributeObj->SetContent( $args{'Content'} );
+
+ $self->Attributes->RedoSearch;
+ return 1;
+}
+
+=head2 DeleteAttribute NAME
+
+Deletes all attributes with the matching name for this object.
+
+=cut
+
+sub DeleteAttribute {
+ my $self = shift;
+ my $name = shift;
+ return $self->Attributes->DeleteEntry( Name => $name );
+}
+
+=head2 FirstAttribute NAME
+
+Returns the value of the first attribute with the matching name
+for this object, or C<undef> if no such attributes exist.
+
+=cut
+
+sub FirstAttribute {
+ my $self = shift;
+ my $name = shift;
+ return ($self->Attributes->Named( $name ))[0];
+}
+
+
# {{{ sub _Handle
sub _Handle {
my $self = shift;
# {{{ sub Create
-=item Create PARAMHASH
+=head2 Create PARAMHASH
Takes a PARAMHASH of Column -> Value pairs.
If any Column has a Validate$PARAMNAME subroutine defined and the
my $self = shift;
my %hash = (@_);
+ # We don't want to hang onto this
+ delete $self->{'attributes'};
+
# If this database is case sensitive we need to uncase objects for
# explicit loading
if ( $self->_Handle->CaseSensitive ) {
$newhash{$key} = $hash{$key};
}
else {
- $newhash{ "lower(" . $key . ")" } = lc( $hash{$key} );
+ my ($op, $val, $func);
+ ($key, $op, $val, $func) = $self->_Handle->_MakeClauseCaseInsensitive($key, '=', $hash{$key});
+ $newhash{$key}->{operator} = $op;
+ $newhash{$key}->{value} = $val;
+ $newhash{$key}->{function} = $func;
}
}
# }}} Datehandling
# {{{ sub _Set
+#
sub _Set {
my $self = shift;
$args{'Value'} = 0;
}
- $self->_SetLastUpdated();
- my ( $val, $msg ) = $self->SUPER::_Set(
+ my $old_val = $self->__Value($args{'Field'});
+ $self->_SetLastUpdated();
+ my $ret = $self->SUPER::_Set(
Field => $args{'Field'},
Value => $args{'Value'},
IsSQL => $args{'IsSQL'}
);
+ my ($status, $msg) = $ret->as_array();
+
+ # @values has two values, a status code and a message.
+
+ # $ret is a Class::ReturnValue object. as such, in a boolean context, it's a bool
+ # we want to change the standard "success" message
+ if ($status) {
+ $msg =
+ $self->loc(
+ "[_1] changed from [_2] to [_3]",
+ $args{'Field'},
+ ( $old_val ? "'$old_val'" : $self->loc("(no value)") ),
+ '"' . $self->__Value( $args{'Field'}) . '"'
+ );
+ } else {
+
+ $msg = $self->CurrentUser->loc_fuzzy($msg);
+ }
+ return wantarray ? ($status, $msg) : $ret;
+
}
# }}}
# }}}
+# {{{ sub URI
+
+=head2 URI
+
+Returns this record's URI
+
+=cut
+
+sub URI {
+ my $self = shift;
+ my $uri = RT::URI::fsck_com_rt->new($self->CurrentUser);
+ return($uri->URIForObject($self));
+}
+
+# }}}
+
+=head2 ValidateName NAME
+
+Validate the name of the record we're creating. Mostly, just make sure it's not a numeric ID, which is invalid for Name
+
+=cut
+
+sub ValidateName {
+ my $self = shift;
+ my $value = shift;
+ if ($value && $value=~ /^\d+$/) {
+ return(0);
+ } else {
+ return (1);
+ }
+}
+
+
+
+=head2 SQLType attribute
+
+return the SQL type for the attribute 'attribute' as stored in _ClassAccessible
+
+=cut
+
+sub SQLType {
+ my $self = shift;
+ my $field = shift;
+
+ return ($self->_Accessible($field, 'type'));
+
+
+}
require Encode::compat if $] < 5.007001;
require Encode;
+
+
+
sub __Value {
my $self = shift;
my $field = shift;
sub _CacheConfig {
{
'cache_p' => 1,
- 'fast_update_p' => 1,
'cache_for_sec' => 30,
}
}
-=head2 _DecodeUTF8
- When passed a string will "decode" it int a proper UTF-8 string
+
+sub _BuildTableAttributes {
+ my $self = shift;
+
+ my $attributes;
+ if ( UNIVERSAL::can( $self, '_CoreAccessible' ) ) {
+ $attributes = $self->_CoreAccessible();
+ } elsif ( UNIVERSAL::can( $self, '_ClassAccessible' ) ) {
+ $attributes = $self->_ClassAccessible();
+
+ }
+
+ foreach my $column (%$attributes) {
+ foreach my $attr ( %{ $attributes->{$column} } ) {
+ $_TABLE_ATTR->{ref($self)}->{$column}->{$attr} = $attributes->{$column}->{$attr};
+ }
+ }
+ if ( UNIVERSAL::can( $self, '_OverlayAccessible' ) ) {
+ $attributes = $self->_OverlayAccessible();
+
+ foreach my $column (%$attributes) {
+ foreach my $attr ( %{ $attributes->{$column} } ) {
+ $_TABLE_ATTR->{ref($self)}->{$column}->{$attr} = $attributes->{$column}->{$attr};
+ }
+ }
+ }
+ if ( UNIVERSAL::can( $self, '_VendorAccessible' ) ) {
+ $attributes = $self->_VendorAccessible();
+
+ foreach my $column (%$attributes) {
+ foreach my $attr ( %{ $attributes->{$column} } ) {
+ $_TABLE_ATTR->{ref($self)}->{$column}->{$attr} = $attributes->{$column}->{$attr};
+ }
+ }
+ }
+ if ( UNIVERSAL::can( $self, '_LocalAccessible' ) ) {
+ $attributes = $self->_LocalAccessible();
+
+ foreach my $column (%$attributes) {
+ foreach my $attr ( %{ $attributes->{$column} } ) {
+ $_TABLE_ATTR->{ref($self)}->{$column}->{$attr} = $attributes->{$column}->{$attr};
+ }
+ }
+ }
+
+}
+
+
+=head2 _ClassAccessible
+
+Overrides the "core" _ClassAccessible using $_TABLE_ATTR. Behaves identical to the version in
+DBIx::SearchBuilder::Record
+
+=cut
+
+sub _ClassAccessible {
+ my $self = shift;
+ return $_TABLE_ATTR->{ref($self)};
+}
+
+=head2 _Accessible COLUMN ATTRIBUTE
+
+returns the value of ATTRIBUTE for COLUMN
+
+
+=cut
+
+sub _Accessible {
+ my $self = shift;
+ my $column = shift;
+ my $attribute = lc(shift);
+ return 0 unless defined ($_TABLE_ATTR->{ref($self)}->{$column});
+ return $_TABLE_ATTR->{ref($self)}->{$column}->{$attribute} || 0;
+
+}
+
+=head2 _EncodeLOB BODY MIME_TYPE
+
+Takes a potentially large attachment. Returns (ContentEncoding, EncodedBody) based on system configuration and selected database
+
+=cut
+
+sub _EncodeLOB {
+ my $self = shift;
+ my $Body = shift;
+ my $MIMEType = shift;
+
+ my $ContentEncoding = 'none';
+
+ #get the max attachment length from RT
+ my $MaxSize = $RT::MaxAttachmentSize;
+
+ #if the current attachment contains nulls and the
+ #database doesn't support embedded nulls
+
+ if ( $RT::AlwaysUseBase64 or
+ ( !$RT::Handle->BinarySafeBLOBs ) && ( $Body =~ /\x00/ ) ) {
+
+ # set a flag telling us to mimencode the attachment
+ $ContentEncoding = 'base64';
+
+ #cut the max attchment size by 25% (for mime-encoding overhead.
+ $RT::Logger->debug("Max size is $MaxSize\n");
+ $MaxSize = $MaxSize * 3 / 4;
+ # Some databases (postgres) can't handle non-utf8 data
+ } elsif ( !$RT::Handle->BinarySafeBLOBs
+ && $MIMEType !~ /text\/plain/gi
+ && !Encode::is_utf8( $Body, 1 ) ) {
+ $ContentEncoding = 'quoted-printable';
+ }
+
+ #if the attachment is larger than the maximum size
+ if ( ($MaxSize) and ( $MaxSize < length($Body) ) ) {
+
+ # if we're supposed to truncate large attachments
+ if ($RT::TruncateLongAttachments) {
+
+ # truncate the attachment to that length.
+ $Body = substr( $Body, 0, $MaxSize );
+
+ }
+
+ # elsif we're supposed to drop large attachments on the floor,
+ elsif ($RT::DropLongAttachments) {
+
+ # drop the attachment on the floor
+ $RT::Logger->info( "$self: Dropped an attachment of size " . length($Body) . "\n" . "It started: " . substr( $Body, 0, 60 ) . "\n" );
+ return ("none", "Large attachment dropped" );
+ }
+ }
+
+ # if we need to mimencode the attachment
+ if ( $ContentEncoding eq 'base64' ) {
+
+ # base64 encode the attachment
+ Encode::_utf8_off($Body);
+ $Body = MIME::Base64::encode_base64($Body);
+
+ } elsif ($ContentEncoding eq 'quoted-printable') {
+ Encode::_utf8_off($Body);
+ $Body = MIME::QuotedPrint::encode($Body);
+ }
+
+
+ return ($ContentEncoding, $Body);
+
+}
+
+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' ) {
+ $Content = Encode::decode_utf8($Content) unless Encode::is_utf8($Content);
+ }
+ return ($Content);
+}
+
+# {{{ LINKDIRMAP
+# A helper table for links mapping to make it easier
+# to build and parse links between tickets
+
+use vars '%LINKDIRMAP';
+
+%LINKDIRMAP = (
+ MemberOf => { Base => 'MemberOf',
+ Target => 'HasMember', },
+ RefersTo => { Base => 'RefersTo',
+ Target => 'ReferredToBy', },
+ DependsOn => { Base => 'DependsOn',
+ Target => 'DependedOnBy', },
+ MergedInto => { Base => 'MergedInto',
+ Target => 'MergedInto', },
+
+);
+
+sub Update {
+ my $self = shift;
+
+ my %args = (
+ ARGSRef => undef,
+ AttributesRef => undef,
+ AttributePrefix => undef,
+ @_
+ );
+
+ my $attributes = $args{'AttributesRef'};
+ my $ARGSRef = $args{'ARGSRef'};
+ my @results;
+
+ foreach my $attribute (@$attributes) {
+ my $value;
+ if ( defined $ARGSRef->{$attribute} ) {
+ $value = $ARGSRef->{$attribute};
+ }
+ elsif (
+ defined( $args{'AttributePrefix'} )
+ && defined(
+ $ARGSRef->{ $args{'AttributePrefix'} . "-" . $attribute }
+ )
+ ) {
+ $value = $ARGSRef->{ $args{'AttributePrefix'} . "-" . $attribute };
+
+ }
+ else {
+ next;
+ }
+
+ $value =~ s/\r\n/\n/gs;
+
+
+ # If Queue is 'General', we want to resolve the queue name for
+ # the object.
+
+ # This is in an eval block because $object might not exist.
+ # and might not have a Name method. But "can" won't find autoloaded
+ # items. If it fails, we don't care
+ eval {
+ my $object = $attribute . "Obj";
+ next if ($self->$object->Name eq $value);
+ };
+ next if ( $value eq $self->$attribute() );
+ my $method = "Set$attribute";
+ my ( $code, $msg ) = $self->$method($value);
+ my ($prefix) = ref($self) =~ /RT::(\w+)/;
+
+ # Default to $id, but use name if we can get it.
+ my $label = $self->id;
+ $label = $self->Name if (UNIVERSAL::can($self,'Name'));
+ push @results, $self->loc( "$prefix [_1]", $label ) . ': '. $msg;
+
+=for loc
+
+ "[_1] could not be set to [_2].", # loc
+ "That is already the current value", # loc
+ "No value sent to _Set!\n", # loc
+ "Illegal value for [_1]", # loc
+ "The new value has been set.", # loc
+ "No column specified", # loc
+ "Immutable field", # loc
+ "Nonexistant field?", # loc
+ "Invalid data", # loc
+ "Couldn't find row", # loc
+ "Missing a primary key?: [_1]", # loc
+ "Found Object", # loc
+
+=cut
+
+ }
+
+ return @results;
+}
+
+# {{{ Routines dealing with Links
+
+# {{{ Link Collections
+
+# {{{ sub Members
+
+=head2 Members
+
+ This returns an RT::Links object which references all the tickets
+which are 'MembersOf' this ticket
+
+=cut
+
+sub Members {
+ my $self = shift;
+ return ( $self->_Links( 'Target', 'MemberOf' ) );
+}
+
+# }}}
+
+# {{{ sub MemberOf
+
+=head2 MemberOf
+
+ This returns an RT::Links object which references all the tickets that this
+ticket is a 'MemberOf'
+
+=cut
+
+sub MemberOf {
+ my $self = shift;
+ return ( $self->_Links( 'Base', 'MemberOf' ) );
+}
+
+# }}}
+
+# {{{ RefersTo
+
+=head2 RefersTo
+
+ This returns an RT::Links object which shows all references for which this ticket is a base
+
+=cut
+
+sub RefersTo {
+ my $self = shift;
+ return ( $self->_Links( 'Base', 'RefersTo' ) );
+}
+
+# }}}
+
+# {{{ ReferredToBy
+
+=head2 ReferredToBy
+
+ This returns an RT::Links object which shows all references for which this ticket is a target
+
+=cut
+
+sub ReferredToBy {
+ my $self = shift;
+ return ( $self->_Links( 'Target', 'RefersTo' ) );
+}
+
+# }}}
+
+# {{{ DependedOnBy
+
+=head2 DependedOnBy
+
+ This returns an RT::Links object which references all the tickets that depend on this one
=cut
+sub DependedOnBy {
+ my $self = shift;
+ return ( $self->_Links( 'Target', 'DependsOn' ) );
+}
+
+# }}}
+
+
+
+=head2 HasUnresolvedDependencies
+
+ Takes a paramhash of Type (default to '__any'). Returns true if
+$self->UnresolvedDependencies returns an object with one or more members
+of that type. Returns false otherwise
+
+
+=begin testing
+
+my $t1 = RT::Ticket->new($RT::SystemUser);
+my ($id, $trans, $msg) = $t1->Create(Subject => 'DepTest1', Queue => 'general');
+ok($id, "Created dep test 1 - $msg");
+
+my $t2 = RT::Ticket->new($RT::SystemUser);
+my ($id2, $trans, $msg2) = $t2->Create(Subject => 'DepTest2', Queue => 'general');
+ok($id2, "Created dep test 2 - $msg2");
+my $t3 = RT::Ticket->new($RT::SystemUser);
+my ($id3, $trans, $msg3) = $t3->Create(Subject => 'DepTest3', Queue => 'general', Type => 'approval');
+ok($id3, "Created dep test 3 - $msg3");
+my ($addid, $addmsg);
+ok (($addid, $addmsg) =$t1->AddLink( Type => 'DependsOn', Target => $t2->id));
+ok ($addid, $addmsg);
+ok (($addid, $addmsg) =$t1->AddLink( Type => 'DependsOn', Target => $t3->id));
+
+ok ($addid, $addmsg);
+my $link = RT::Link->new($RT::SystemUser);
+my ($rv, $msg) = $link->Load($addid);
+ok ($rv, $msg);
+ok ($link->LocalTarget == $t3->id, "Link LocalTarget is correct");
+ok ($link->LocalBase == $t1->id, "Link LocalBase is correct");
+
+ok ($t1->HasUnresolvedDependencies, "Ticket ".$t1->Id." has unresolved deps");
+ok (!$t1->HasUnresolvedDependencies( Type => 'blah' ), "Ticket ".$t1->Id." has no unresolved blahs");
+ok ($t1->HasUnresolvedDependencies( Type => 'approval' ), "Ticket ".$t1->Id." has unresolved approvals");
+ok (!$t2->HasUnresolvedDependencies, "Ticket ".$t2->Id." has no unresolved deps");
+;
+
+my ($rid, $rmsg)= $t1->Resolve();
+ok(!$rid, $rmsg);
+my ($rid2, $rmsg2) = $t2->Resolve();
+ok ($rid2, $rmsg2);
+($rid, $rmsg)= $t1->Resolve();
+ok(!$rid, $rmsg);
+my ($rid3,$rmsg3) = $t3->Resolve;
+ok ($rid3,$rmsg3);
+($rid, $rmsg)= $t1->Resolve();
+ok($rid, $rmsg);
+
+
+=end testing
+
+=cut
+
+sub HasUnresolvedDependencies {
+ my $self = shift;
+ my %args = (
+ Type => undef,
+ @_
+ );
+
+ my $deps = $self->UnresolvedDependencies;
+
+ if ($args{Type}) {
+ $deps->Limit( FIELD => 'Type',
+ OPERATOR => '=',
+ VALUE => $args{Type});
+ }
+ else {
+ $deps->IgnoreType;
+ }
+
+ if ($deps->Count > 0) {
+ return 1;
+ }
+ else {
+ return (undef);
+ }
+}
+
+
+# {{{ UnresolvedDependencies
+
+=head2 UnresolvedDependencies
+
+Returns an RT::Tickets object of tickets which this ticket depends on
+and which have a status of new, open or stalled. (That list comes from
+RT::Queue->ActiveStatusArray
+
+=cut
+
+
+sub UnresolvedDependencies {
+ my $self = shift;
+ my $deps = RT::Tickets->new($self->CurrentUser);
+
+ my @live_statuses = RT::Queue->ActiveStatusArray();
+ foreach my $status (@live_statuses) {
+ $deps->LimitStatus(VALUE => $status);
+ }
+ $deps->LimitDependedOnBy($self->Id);
+
+ return($deps);
+
+}
+
+# }}}
+
+# {{{ AllDependedOnBy
+
+=head2 AllDependedOnBy
+
+Returns an array of RT::Ticket objects which (directly or indirectly)
+depends on this ticket; takes an optional 'Type' argument in the param
+hash, which will limit returned tickets to that type, as well as cause
+tickets with that type to serve as 'leaf' nodes that stops the recursive
+dependency search.
+
+=cut
+
+sub AllDependedOnBy {
+ my $self = shift;
+ my $dep = $self->DependedOnBy;
+ my %args = (
+ Type => undef,
+ _found => {},
+ _top => 1,
+ @_
+ );
+
+ while (my $link = $dep->Next()) {
+ next unless ($link->BaseURI->IsLocal());
+ next if $args{_found}{$link->BaseObj->Id};
+
+ if (!$args{Type}) {
+ $args{_found}{$link->BaseObj->Id} = $link->BaseObj;
+ $link->BaseObj->AllDependedOnBy( %args, _top => 0 );
+ }
+ elsif ($link->BaseObj->Type eq $args{Type}) {
+ $args{_found}{$link->BaseObj->Id} = $link->BaseObj;
+ }
+ else {
+ $link->BaseObj->AllDependedOnBy( %args, _top => 0 );
+ }
+ }
+
+ if ($args{_top}) {
+ return map { $args{_found}{$_} } sort keys %{$args{_found}};
+ }
+ else {
+ return 1;
+ }
+}
+
+# }}}
+
+# {{{ DependsOn
+
+=head2 DependsOn
+
+ This returns an RT::Links object which references all the tickets that this ticket depends on
+
+=cut
+
+sub DependsOn {
+ my $self = shift;
+ return ( $self->_Links( 'Base', 'DependsOn' ) );
+}
+
+# }}}
+
+
+
+
+# {{{ sub _Links
+
+=head2 Links DIRECTION TYPE
+
+return links to/from this object.
+
+=cut
+
+*Links = \&_Links;
+
+sub _Links {
+ my $self = shift;
+
+ #TODO: Field isn't the right thing here. but I ahave no idea what mnemonic ---
+ #tobias meant by $f
+ my $field = shift;
+ my $type = shift || "";
+
+ unless ( $self->{"$field$type"} ) {
+ $self->{"$field$type"} = new RT::Links( $self->CurrentUser );
+ # at least to myself
+ $self->{"$field$type"}->Limit( FIELD => $field,
+ VALUE => $self->URI,
+ ENTRYAGGREGATOR => 'OR' );
+ $self->{"$field$type"}->Limit( FIELD => 'Type',
+ VALUE => $type )
+ if ($type);
+ }
+ return ( $self->{"$field$type"} );
+}
+
+# }}}
+
+# }}}
+
+# {{{ sub _AddLink
+
+=head2 _AddLink
+
+Takes a paramhash of Type and one of Base or Target. Adds that link to this ticket.
+
+
+=cut
+
+
+sub _AddLink {
+ my $self = shift;
+ my %args = ( Target => '',
+ Base => '',
+ Type => '',
+ Silent => undef,
+ @_ );
+
+
+ # Remote_link is the URI of the object that is not this ticket
+ my $remote_link;
+ my $direction;
+
+ if ( $args{'Base'} and $args{'Target'} ) {
+ $RT::Logger->debug( "$self tried to create a link. both base and target were specified\n" );
+ return ( 0, $self->loc("Can't specifiy both base and target") );
+ }
+ elsif ( $args{'Base'} ) {
+ $args{'Target'} = $self->URI();
+ my $class = ref($self);
+ $remote_link = $args{'Base'};
+ $direction = 'Target';
+ }
+ elsif ( $args{'Target'} ) {
+ $args{'Base'} = $self->URI();
+ my $class = ref($self);
+ $remote_link = $args{'Target'};
+ $direction = 'Base';
+ }
+ else {
+ return ( 0, $self->loc('Either base or target must be specified') );
+ }
+
+ # {{{ Check if the link already exists - we don't want duplicates
+ use RT::Link;
+ my $old_link = RT::Link->new( $self->CurrentUser );
+ $old_link->LoadByParams( Base => $args{'Base'},
+ Type => $args{'Type'},
+ Target => $args{'Target'} );
+ if ( $old_link->Id ) {
+ $RT::Logger->debug("$self Somebody tried to duplicate a link");
+ return ( $old_link->id, $self->loc("Link already exists"), 0 );
+ }
+
+ # }}}
+
+
+ # Storing the link in the DB.
+ my $link = RT::Link->new( $self->CurrentUser );
+ my ($linkid, $linkmsg) = $link->Create( Target => $args{Target},
+ Base => $args{Base},
+ Type => $args{Type} );
+
+ unless ($linkid) {
+ $RT::Logger->error("Link could not be created: ".$linkmsg);
+ return ( 0, $self->loc("Link could not be created") );
+ }
+
+ my $TransString =
+ "Record $args{'Base'} $args{Type} record $args{'Target'}.";
+
+ return ( $linkid, $self->loc( "Link created ([_1])", $TransString ) );
+}
+
+# }}}
+
+# {{{ sub _DeleteLink
+
+=head2 _DeleteLink
+
+Delete a link. takes a paramhash of Base, Target and Type.
+Either Base or Target must be null. The null value will
+be replaced with this ticket\'s id
+
+=cut
+
+sub _DeleteLink {
+ my $self = shift;
+ my %args = (
+ Base => undef,
+ Target => undef,
+ Type => undef,
+ @_
+ );
+
+ #we want one of base and target. we don't care which
+ #but we only want _one_
+
+ my $direction;
+ my $remote_link;
+
+ if ( $args{'Base'} and $args{'Target'} ) {
+ $RT::Logger->debug("$self ->_DeleteLink. got both Base and Target\n");
+ return ( 0, $self->loc("Can't specifiy both base and target") );
+ }
+ elsif ( $args{'Base'} ) {
+ $args{'Target'} = $self->URI();
+ $remote_link = $args{'Base'};
+ $direction = 'Target';
+ }
+ elsif ( $args{'Target'} ) {
+ $args{'Base'} = $self->URI();
+ $remote_link = $args{'Target'};
+ $direction='Base';
+ }
+ else {
+ $RT::Logger->debug("$self: Base or Target must be specified\n");
+ return ( 0, $self->loc('Either base or target must be specified') );
+ }
+
+ my $link = new RT::Link( $self->CurrentUser );
+ $RT::Logger->debug( "Trying to load link: " . $args{'Base'} . " " . $args{'Type'} . " " . $args{'Target'} . "\n" );
+
+
+ $link->LoadByParams( Base=> $args{'Base'}, Type=> $args{'Type'}, Target=> $args{'Target'} );
+ #it's a real link.
+ if ( $link->id ) {
+
+ my $linkid = $link->id;
+ $link->Delete();
+
+ my $TransString = "Record $args{'Base'} no longer $args{Type} record $args{'Target'}.";
+ return ( 1, $self->loc("Link deleted ([_1])", $TransString));
+ }
+
+ #if it's not a link we can find
+ else {
+ $RT::Logger->debug("Couldn't find that link\n");
+ return ( 0, $self->loc("Link not found") );
+ }
+}
+
+# }}}
+
+# }}}
+
+# {{{ Routines dealing with 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 => 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 record object
+
+=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 );
+
+ # XXX handle multiple types properly
+ $cfs->LimitToLookupType( $self->CustomFieldLookupType );
+ $cfs->LimitToGlobalOrObjectId(
+ $self->_LookupId( $self->CustomFieldLookupType ) );
+
+ return $cfs;
+}
+
+# TODO: This _only_ works for RT::Class classes. it doesn't work, for example, for RT::FM classes.
+
+sub _LookupId {
+ my $self = shift;
+ my $lookup = shift;
+ my @classes = ($lookup =~ /RT::(\w+)-/g);
+
+ my $object = $self;
+ foreach my $class (reverse @classes) {
+ my $method = "${class}Obj";
+ $object = $object->$method;
+ }
+
+ return $object->Id;
+}
+
+
+=head2 CustomFieldLookupType
+
+Returns the path RT uses to figure out which custom fields apply to this object.
+
+=cut
+
+sub CustomFieldLookupType {
+ my $self = shift;
+ return ref($self);
+}
+
+#TODO Deprecated API. Destroy in 3.6
+sub _LookupTypes {
+ my $self = shift;
+ $RT::Logger->warning("_LookupTypes call is deprecated. Replace with CustomFieldLookupType");
+ $RT::Logger->warning("Besides, it was a private API. Were you doing using it?");
+
+ return($self->CustomFieldLookupType);
+
+}
+
+# {{{ AddCustomFieldValue
+
+=head2 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 is not a valid value for the custom field, returns
+(0, 'Error message' ) otherwise, returns (1, 'Success Message')
+
+=cut
+
+sub AddCustomFieldValue {
+ my $self = shift;
+ $self->_AddCustomFieldValue(@_);
+}
+
+sub _AddCustomFieldValue {
+ my $self = shift;
+ my %args = (
+ Field => undef,
+ Value => undef,
+ RecordTransaction => 1,
+ @_
+ );
+
+ my $cf = $self->LoadCustomFieldByIdentifier($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 certain # of values, delete the existing
+ # value and record a "changed from foo to bar" transaction
+ unless ( $cf->UnlimitedValues) {
+
+ # 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 > $cf->MaxValues ) {
+ my $i = 0; #We want to delete all but the max we can currently have , 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'} && $old_value->LargeContent eq $args{'LargeContent'});;
+ }
+
+ 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. [_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 ) = $old_value->Delete();
+ 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_value->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. ") );
+ }
+ 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
+
+=head2 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 is not 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,
+ @_
+ );
+
+ my $cf = $self->LoadCustomFieldByIdentifier($args{'Field'});
+
+ unless ( $cf->Id ) {
+ return ( 0, $self->loc( "Custom field [_1] not found", $args{'Field'} ) );
+ }
+ 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
+
+=head2 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
+
+=head2 CustomFieldValues FIELD
+
+Return a ObjectCustomFieldValues object of all values of the CustomField whose
+id or Name is FIELD for this record.
+
+Returns an RT::ObjectCustomFieldValues object
+
+=cut
+
+sub CustomFieldValues {
+ my $self = shift;
+ my $field = shift;
+
+ if ($field) {
+ my $cf = $self->LoadCustomFieldByIdentifier($field);
+
+ # we were asked to search on a custom field we couldn't fine
+ unless ( $cf->id ) {
+ return RT::ObjectCustomFieldValues->new( $self->CurrentUser );
+ }
+ return ( $cf->ValuesForObject($self) );
+ }
+
+ # we're not limiting to a specific custom field;
+ my $ocfs = RT::ObjectCustomFieldValues->new( $self->CurrentUser );
+ $ocfs->LimitToObject($self);
+ return $ocfs;
+
+}
+
+=head2 CustomField IDENTIFER
+
+Find the custom field has id or name IDENTIFIER for this object.
+
+If no valid field is found, returns an empty RT::CustomField object.
+
+=cut
+
+sub LoadCustomFieldByIdentifier {
+ my $self = shift;
+ my $field = shift;
+
+ my $cf = RT::CustomField->new($self->CurrentUser);
+
+ if ( UNIVERSAL::isa( $field, "RT::CustomField" ) ) {
+ $cf->LoadById( $field->id );
+ }
+ elsif ($field =~ /^\d+$/) {
+ $cf = RT::CustomField->new($self->CurrentUser);
+ $cf->Load($field);
+ } else {
+
+ my $cfs = $self->CustomFields($self->CurrentUser);
+ $cfs->Limit(FIELD => 'Name', VALUE => $field);
+ $cf = $cfs->First || RT::CustomField->new($self->CurrentUser);
+ }
+ return $cf;
+}
+
+
+# }}}
+
+# }}}
+
+# }}}
+
+sub BasicColumns {
+}
+
eval "require RT::Record_Vendor";
die $@ if ($@ && $@ !~ qr{^Can't locate RT/Record_Vendor.pm});
eval "require RT::Record_Local";
-# BEGIN LICENSE BLOCK
+# BEGIN BPS TAGGED BLOCK {{{
#
-# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# <jesse@bestpractical.com>
#
-# (Except where explictly superceded by other copyright notices)
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
#
# 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
# 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.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
+#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
#
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
#
-# END LICENSE BLOCK
+# END BPS TAGGED BLOCK }}}
# Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>)
# WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST.
#
-=item Create PARAMHASH
+=head2 Create PARAMHASH
Create takes a hash of values and creates a row in the database:
-=item id
+=head2 id
Returns the current value of id.
(In the database, id is stored as int(11).)
=cut
-=item Description
+=head2 Description
Returns the current value of Description.
(In the database, Description is stored as varchar(255).)
-=item SetDescription VALUE
+=head2 SetDescription VALUE
Set Description to VALUE.
=cut
-=item ScripCondition
+=head2 ScripCondition
Returns the current value of ScripCondition.
(In the database, ScripCondition is stored as int(11).)
-=item SetScripCondition VALUE
+=head2 SetScripCondition VALUE
Set ScripCondition to VALUE.
=cut
-=item ScripConditionObj
+=head2 ScripConditionObj
Returns the ScripCondition Object which has the id returned by ScripCondition
return($ScripCondition);
}
-=item ScripAction
+=head2 ScripAction
Returns the current value of ScripAction.
(In the database, ScripAction is stored as int(11).)
-=item SetScripAction VALUE
+=head2 SetScripAction VALUE
Set ScripAction to VALUE.
=cut
-=item ScripActionObj
+=head2 ScripActionObj
Returns the ScripAction Object which has the id returned by ScripAction
return($ScripAction);
}
-=item ConditionRules
+=head2 ConditionRules
Returns the current value of ConditionRules.
(In the database, ConditionRules is stored as text.)
-=item SetConditionRules VALUE
+=head2 SetConditionRules VALUE
Set ConditionRules to VALUE.
=cut
-=item ActionRules
+=head2 ActionRules
Returns the current value of ActionRules.
(In the database, ActionRules is stored as text.)
-=item SetActionRules VALUE
+=head2 SetActionRules VALUE
Set ActionRules to VALUE.
=cut
-=item CustomIsApplicableCode
+=head2 CustomIsApplicableCode
Returns the current value of CustomIsApplicableCode.
(In the database, CustomIsApplicableCode is stored as text.)
-=item SetCustomIsApplicableCode VALUE
+=head2 SetCustomIsApplicableCode VALUE
Set CustomIsApplicableCode to VALUE.
=cut
-=item CustomPrepareCode
+=head2 CustomPrepareCode
Returns the current value of CustomPrepareCode.
(In the database, CustomPrepareCode is stored as text.)
-=item SetCustomPrepareCode VALUE
+=head2 SetCustomPrepareCode VALUE
Set CustomPrepareCode to VALUE.
=cut
-=item CustomCommitCode
+=head2 CustomCommitCode
Returns the current value of CustomCommitCode.
(In the database, CustomCommitCode is stored as text.)
-=item SetCustomCommitCode VALUE
+=head2 SetCustomCommitCode VALUE
Set CustomCommitCode to VALUE.
=cut
-=item Stage
+=head2 Stage
Returns the current value of Stage.
(In the database, Stage is stored as varchar(32).)
-=item SetStage VALUE
+=head2 SetStage VALUE
Set Stage to VALUE.
=cut
-=item Queue
+=head2 Queue
Returns the current value of Queue.
(In the database, Queue is stored as int(11).)
-=item SetQueue VALUE
+=head2 SetQueue VALUE
Set Queue to VALUE.
=cut
-=item QueueObj
+=head2 QueueObj
Returns the Queue Object which has the id returned by Queue
return($Queue);
}
-=item Template
+=head2 Template
Returns the current value of Template.
(In the database, Template is stored as int(11).)
-=item SetTemplate VALUE
+=head2 SetTemplate VALUE
Set Template to VALUE.
=cut
-=item TemplateObj
+=head2 TemplateObj
Returns the Template Object which has the id returned by Template
return($Template);
}
-=item Creator
+=head2 Creator
Returns the current value of Creator.
(In the database, Creator is stored as int(11).)
=cut
-=item Created
+=head2 Created
Returns the current value of Created.
(In the database, Created is stored as datetime.)
=cut
-=item LastUpdatedBy
+=head2 LastUpdatedBy
Returns the current value of LastUpdatedBy.
(In the database, LastUpdatedBy is stored as int(11).)
=cut
-=item LastUpdated
+=head2 LastUpdated
Returns the current value of LastUpdated.
(In the database, LastUpdated is stored as datetime.)
-sub _ClassAccessible {
+sub _CoreAccessible {
{
id =>
- {read => 1, type => 'int(11)', default => ''},
+ {read => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => ''},
Description =>
- {read => 1, write => 1, type => 'varchar(255)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 255, is_blob => 0, is_numeric => 0, type => 'varchar(255)', default => ''},
ScripCondition =>
- {read => 1, write => 1, type => 'int(11)', default => '0'},
+ {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
ScripAction =>
- {read => 1, write => 1, type => 'int(11)', default => '0'},
+ {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
ConditionRules =>
- {read => 1, write => 1, type => 'text', default => ''},
+ {read => 1, write => 1, sql_type => -4, length => 0, is_blob => 1, is_numeric => 0, type => 'text', default => ''},
ActionRules =>
- {read => 1, write => 1, type => 'text', default => ''},
+ {read => 1, write => 1, sql_type => -4, length => 0, is_blob => 1, is_numeric => 0, type => 'text', default => ''},
CustomIsApplicableCode =>
- {read => 1, write => 1, type => 'text', default => ''},
+ {read => 1, write => 1, sql_type => -4, length => 0, is_blob => 1, is_numeric => 0, type => 'text', default => ''},
CustomPrepareCode =>
- {read => 1, write => 1, type => 'text', default => ''},
+ {read => 1, write => 1, sql_type => -4, length => 0, is_blob => 1, is_numeric => 0, type => 'text', default => ''},
CustomCommitCode =>
- {read => 1, write => 1, type => 'text', default => ''},
+ {read => 1, write => 1, sql_type => -4, length => 0, is_blob => 1, is_numeric => 0, type => 'text', default => ''},
Stage =>
- {read => 1, write => 1, type => 'varchar(32)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 32, is_blob => 0, is_numeric => 0, type => 'varchar(32)', default => ''},
Queue =>
- {read => 1, write => 1, type => 'int(11)', default => '0'},
+ {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
Template =>
- {read => 1, write => 1, type => 'int(11)', default => '0'},
+ {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
Creator =>
- {read => 1, auto => 1, type => 'int(11)', default => '0'},
+ {read => 1, auto => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
Created =>
- {read => 1, auto => 1, type => 'datetime', default => ''},
+ {read => 1, auto => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''},
LastUpdatedBy =>
- {read => 1, auto => 1, type => 'int(11)', default => '0'},
+ {read => 1, auto => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
LastUpdated =>
- {read => 1, auto => 1, type => 'datetime', default => ''},
+ {read => 1, auto => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''},
}
};
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
+Each of these files should begin with the line
no warnings qw(redefine);
-# BEGIN LICENSE BLOCK
+# BEGIN BPS TAGGED BLOCK {{{
#
-# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# <jesse@bestpractical.com>
#
-# (Except where explictly superceded by other copyright notices)
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
#
# 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
# 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.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
+#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
#
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
#
-# END LICENSE BLOCK
+# END BPS TAGGED BLOCK }}}
# Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>)
# WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST.
#
-=item Create PARAMHASH
+=head2 Create PARAMHASH
Create takes a hash of values and creates a row in the database:
-=item id
+=head2 id
Returns the current value of id.
(In the database, id is stored as int(11).)
=cut
-=item Name
+=head2 Name
Returns the current value of Name.
(In the database, Name is stored as varchar(200).)
-=item SetName VALUE
+=head2 SetName VALUE
Set Name to VALUE.
=cut
-=item Description
+=head2 Description
Returns the current value of Description.
(In the database, Description is stored as varchar(255).)
-=item SetDescription VALUE
+=head2 SetDescription VALUE
Set Description to VALUE.
=cut
-=item ExecModule
+=head2 ExecModule
Returns the current value of ExecModule.
(In the database, ExecModule is stored as varchar(60).)
-=item SetExecModule VALUE
+=head2 SetExecModule VALUE
Set ExecModule to VALUE.
=cut
-=item Argument
+=head2 Argument
Returns the current value of Argument.
(In the database, Argument is stored as varchar(255).)
-=item SetArgument VALUE
+=head2 SetArgument VALUE
Set Argument to VALUE.
=cut
-=item Creator
+=head2 Creator
Returns the current value of Creator.
(In the database, Creator is stored as int(11).)
=cut
-=item Created
+=head2 Created
Returns the current value of Created.
(In the database, Created is stored as datetime.)
=cut
-=item LastUpdatedBy
+=head2 LastUpdatedBy
Returns the current value of LastUpdatedBy.
(In the database, LastUpdatedBy is stored as int(11).)
=cut
-=item LastUpdated
+=head2 LastUpdated
Returns the current value of LastUpdated.
(In the database, LastUpdated is stored as datetime.)
-sub _ClassAccessible {
+sub _CoreAccessible {
{
id =>
- {read => 1, type => 'int(11)', default => ''},
+ {read => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => ''},
Name =>
- {read => 1, write => 1, type => 'varchar(200)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 200, is_blob => 0, is_numeric => 0, type => 'varchar(200)', default => ''},
Description =>
- {read => 1, write => 1, type => 'varchar(255)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 255, is_blob => 0, is_numeric => 0, type => 'varchar(255)', default => ''},
ExecModule =>
- {read => 1, write => 1, type => 'varchar(60)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 60, is_blob => 0, is_numeric => 0, type => 'varchar(60)', default => ''},
Argument =>
- {read => 1, write => 1, type => 'varchar(255)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 255, is_blob => 0, is_numeric => 0, type => 'varchar(255)', default => ''},
Creator =>
- {read => 1, auto => 1, type => 'int(11)', default => '0'},
+ {read => 1, auto => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
Created =>
- {read => 1, auto => 1, type => 'datetime', default => ''},
+ {read => 1, auto => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''},
LastUpdatedBy =>
- {read => 1, auto => 1, type => 'int(11)', default => '0'},
+ {read => 1, auto => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
LastUpdated =>
- {read => 1, auto => 1, type => 'datetime', default => ''},
+ {read => 1, auto => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''},
}
};
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
+Each of these files should begin with the line
no warnings qw(redefine);
-# BEGIN LICENSE BLOCK
+# BEGIN BPS TAGGED BLOCK {{{
#
-# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# <jesse@bestpractical.com>
#
-# (Except where explictly superceded by other copyright notices)
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
#
# 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
# 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.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
+#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
#
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
#
-# END LICENSE BLOCK
+# END BPS TAGGED BLOCK }}}
# Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>)
# WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST.
#
}
-=item NewItem
+=head2 NewItem
Returns an empty new RT::ScripAction item
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
+Each of these files should begin with the line
no warnings qw(redefine);
-# BEGIN LICENSE BLOCK
+# BEGIN BPS TAGGED BLOCK {{{
#
-# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# <jesse@bestpractical.com>
#
-# (Except where explictly superceded by other copyright notices)
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
#
# 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
# 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.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
+#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
#
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
#
-# END LICENSE BLOCK
+# END BPS TAGGED BLOCK }}}
# Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>)
# WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST.
#
-=item Create PARAMHASH
+=head2 Create PARAMHASH
Create takes a hash of values and creates a row in the database:
-=item id
+=head2 id
Returns the current value of id.
(In the database, id is stored as int(11).)
=cut
-=item Name
+=head2 Name
Returns the current value of Name.
(In the database, Name is stored as varchar(200).)
-=item SetName VALUE
+=head2 SetName VALUE
Set Name to VALUE.
=cut
-=item Description
+=head2 Description
Returns the current value of Description.
(In the database, Description is stored as varchar(255).)
-=item SetDescription VALUE
+=head2 SetDescription VALUE
Set Description to VALUE.
=cut
-=item ExecModule
+=head2 ExecModule
Returns the current value of ExecModule.
(In the database, ExecModule is stored as varchar(60).)
-=item SetExecModule VALUE
+=head2 SetExecModule VALUE
Set ExecModule to VALUE.
=cut
-=item Argument
+=head2 Argument
Returns the current value of Argument.
(In the database, Argument is stored as varchar(255).)
-=item SetArgument VALUE
+=head2 SetArgument VALUE
Set Argument to VALUE.
=cut
-=item ApplicableTransTypes
+=head2 ApplicableTransTypes
Returns the current value of ApplicableTransTypes.
(In the database, ApplicableTransTypes is stored as varchar(60).)
-=item SetApplicableTransTypes VALUE
+=head2 SetApplicableTransTypes VALUE
Set ApplicableTransTypes to VALUE.
=cut
-=item Creator
+=head2 Creator
Returns the current value of Creator.
(In the database, Creator is stored as int(11).)
=cut
-=item Created
+=head2 Created
Returns the current value of Created.
(In the database, Created is stored as datetime.)
=cut
-=item LastUpdatedBy
+=head2 LastUpdatedBy
Returns the current value of LastUpdatedBy.
(In the database, LastUpdatedBy is stored as int(11).)
=cut
-=item LastUpdated
+=head2 LastUpdated
Returns the current value of LastUpdated.
(In the database, LastUpdated is stored as datetime.)
-sub _ClassAccessible {
+sub _CoreAccessible {
{
id =>
- {read => 1, type => 'int(11)', default => ''},
+ {read => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => ''},
Name =>
- {read => 1, write => 1, type => 'varchar(200)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 200, is_blob => 0, is_numeric => 0, type => 'varchar(200)', default => ''},
Description =>
- {read => 1, write => 1, type => 'varchar(255)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 255, is_blob => 0, is_numeric => 0, type => 'varchar(255)', default => ''},
ExecModule =>
- {read => 1, write => 1, type => 'varchar(60)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 60, is_blob => 0, is_numeric => 0, type => 'varchar(60)', default => ''},
Argument =>
- {read => 1, write => 1, type => 'varchar(255)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 255, is_blob => 0, is_numeric => 0, type => 'varchar(255)', default => ''},
ApplicableTransTypes =>
- {read => 1, write => 1, type => 'varchar(60)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 60, is_blob => 0, is_numeric => 0, type => 'varchar(60)', default => ''},
Creator =>
- {read => 1, auto => 1, type => 'int(11)', default => '0'},
+ {read => 1, auto => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
Created =>
- {read => 1, auto => 1, type => 'datetime', default => ''},
+ {read => 1, auto => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''},
LastUpdatedBy =>
- {read => 1, auto => 1, type => 'int(11)', default => '0'},
+ {read => 1, auto => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
LastUpdated =>
- {read => 1, auto => 1, type => 'datetime', default => ''},
+ {read => 1, auto => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''},
}
};
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
+Each of these files should begin with the line
no warnings qw(redefine);
-# BEGIN LICENSE BLOCK
+# BEGIN BPS TAGGED BLOCK {{{
#
-# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# <jesse@bestpractical.com>
#
-# (Except where explictly superceded by other copyright notices)
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
#
# 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
# 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.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
+#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
#
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
#
-# END LICENSE BLOCK
+# END BPS TAGGED BLOCK }}}
# Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>)
# WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST.
#
}
-=item NewItem
+=head2 NewItem
Returns an empty new RT::ScripCondition item
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
+Each of these files should begin with the line
no warnings qw(redefine);
-# BEGIN LICENSE BLOCK
+# BEGIN BPS TAGGED BLOCK {{{
#
-# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# <jesse@bestpractical.com>
#
-# (Except where explictly superceded by other copyright notices)
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
#
# 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
# 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.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
+#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
#
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
#
-# END LICENSE BLOCK
+# END BPS TAGGED BLOCK }}}
# Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>)
# WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST.
#
}
-=item NewItem
+=head2 NewItem
Returns an empty new RT::Scrip item
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
+Each of these files should begin with the line
no warnings qw(redefine);
-# BEGIN LICENSE BLOCK
+# BEGIN BPS TAGGED BLOCK {{{
#
-# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# <jesse@bestpractical.com>
#
-# (Except where explictly superceded by other copyright notices)
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
#
# 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
# 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.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
+#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
#
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
#
-# END LICENSE BLOCK
+# END BPS TAGGED BLOCK }}}
# Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>)
# WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST.
#
-=item Create PARAMHASH
+=head2 Create PARAMHASH
Create takes a hash of values and creates a row in the database:
-=item id
+=head2 id
Returns the current value of id.
(In the database, id is stored as int(11).)
=cut
-=item Queue
+=head2 Queue
Returns the current value of Queue.
(In the database, Queue is stored as int(11).)
-=item SetQueue VALUE
+=head2 SetQueue VALUE
Set Queue to VALUE.
=cut
-=item QueueObj
+=head2 QueueObj
Returns the Queue Object which has the id returned by Queue
return($Queue);
}
-=item Name
+=head2 Name
Returns the current value of Name.
(In the database, Name is stored as varchar(200).)
-=item SetName VALUE
+=head2 SetName VALUE
Set Name to VALUE.
=cut
-=item Description
+=head2 Description
Returns the current value of Description.
(In the database, Description is stored as varchar(255).)
-=item SetDescription VALUE
+=head2 SetDescription VALUE
Set Description to VALUE.
=cut
-=item Type
+=head2 Type
Returns the current value of Type.
(In the database, Type is stored as varchar(16).)
-=item SetType VALUE
+=head2 SetType VALUE
Set Type to VALUE.
=cut
-=item Language
+=head2 Language
Returns the current value of Language.
(In the database, Language is stored as varchar(16).)
-=item SetLanguage VALUE
+=head2 SetLanguage VALUE
Set Language to VALUE.
=cut
-=item TranslationOf
+=head2 TranslationOf
Returns the current value of TranslationOf.
(In the database, TranslationOf is stored as int(11).)
-=item SetTranslationOf VALUE
+=head2 SetTranslationOf VALUE
Set TranslationOf to VALUE.
=cut
-=item Content
+=head2 Content
Returns the current value of Content.
(In the database, Content is stored as blob.)
-=item SetContent VALUE
+=head2 SetContent VALUE
Set Content to VALUE.
=cut
-=item LastUpdated
+=head2 LastUpdated
Returns the current value of LastUpdated.
(In the database, LastUpdated is stored as datetime.)
=cut
-=item LastUpdatedBy
+=head2 LastUpdatedBy
Returns the current value of LastUpdatedBy.
(In the database, LastUpdatedBy is stored as int(11).)
=cut
-=item Creator
+=head2 Creator
Returns the current value of Creator.
(In the database, Creator is stored as int(11).)
=cut
-=item Created
+=head2 Created
Returns the current value of Created.
(In the database, Created is stored as datetime.)
-sub _ClassAccessible {
+sub _CoreAccessible {
{
id =>
- {read => 1, type => 'int(11)', default => ''},
+ {read => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => ''},
Queue =>
- {read => 1, write => 1, type => 'int(11)', default => '0'},
+ {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
Name =>
- {read => 1, write => 1, type => 'varchar(200)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 200, is_blob => 0, is_numeric => 0, type => 'varchar(200)', default => ''},
Description =>
- {read => 1, write => 1, type => 'varchar(255)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 255, is_blob => 0, is_numeric => 0, type => 'varchar(255)', default => ''},
Type =>
- {read => 1, write => 1, type => 'varchar(16)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 16, is_blob => 0, is_numeric => 0, type => 'varchar(16)', default => ''},
Language =>
- {read => 1, write => 1, type => 'varchar(16)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 16, is_blob => 0, is_numeric => 0, type => 'varchar(16)', default => ''},
TranslationOf =>
- {read => 1, write => 1, type => 'int(11)', default => '0'},
+ {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
Content =>
- {read => 1, write => 1, type => 'blob', default => ''},
+ {read => 1, write => 1, sql_type => -4, length => 0, is_blob => 1, is_numeric => 0, type => 'blob', default => ''},
LastUpdated =>
- {read => 1, auto => 1, type => 'datetime', default => ''},
+ {read => 1, auto => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''},
LastUpdatedBy =>
- {read => 1, auto => 1, type => 'int(11)', default => '0'},
+ {read => 1, auto => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
Creator =>
- {read => 1, auto => 1, type => 'int(11)', default => '0'},
+ {read => 1, auto => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
Created =>
- {read => 1, auto => 1, type => 'datetime', default => ''},
+ {read => 1, auto => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''},
}
};
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
+Each of these files should begin with the line
no warnings qw(redefine);
-# BEGIN LICENSE BLOCK
+# BEGIN BPS TAGGED BLOCK {{{
#
-# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# <jesse@bestpractical.com>
#
-# (Except where explictly superceded by other copyright notices)
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
#
# 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
# 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.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
+#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
#
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
#
-# END LICENSE BLOCK
+# END BPS TAGGED BLOCK }}}
# Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>)
# WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST.
#
}
-=item NewItem
+=head2 NewItem
Returns an empty new RT::Template item
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
+Each of these files should begin with the line
no warnings qw(redefine);
-# BEGIN LICENSE BLOCK
+# BEGIN BPS TAGGED BLOCK {{{
#
-# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# <jesse@bestpractical.com>
#
-# (Except where explictly superceded by other copyright notices)
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
#
# 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
# 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.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
+#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
#
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
#
-# END LICENSE BLOCK
+# END BPS TAGGED BLOCK }}}
# Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>)
# WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST.
#
-=item Create PARAMHASH
+=head2 Create PARAMHASH
Create takes a hash of values and creates a row in the database:
-=item id
+=head2 id
Returns the current value of id.
(In the database, id is stored as int(11).)
=cut
-=item EffectiveId
+=head2 EffectiveId
Returns the current value of EffectiveId.
(In the database, EffectiveId is stored as int(11).)
-=item SetEffectiveId VALUE
+=head2 SetEffectiveId VALUE
Set EffectiveId to VALUE.
=cut
-=item Queue
+=head2 Queue
Returns the current value of Queue.
(In the database, Queue is stored as int(11).)
-=item SetQueue VALUE
+=head2 SetQueue VALUE
Set Queue to VALUE.
=cut
-=item QueueObj
+=head2 QueueObj
Returns the Queue Object which has the id returned by Queue
return($Queue);
}
-=item Type
+=head2 Type
Returns the current value of Type.
(In the database, Type is stored as varchar(16).)
-=item SetType VALUE
+=head2 SetType VALUE
Set Type to VALUE.
=cut
-=item IssueStatement
+=head2 IssueStatement
Returns the current value of IssueStatement.
(In the database, IssueStatement is stored as int(11).)
-=item SetIssueStatement VALUE
+=head2 SetIssueStatement VALUE
Set IssueStatement to VALUE.
=cut
-=item Resolution
+=head2 Resolution
Returns the current value of Resolution.
(In the database, Resolution is stored as int(11).)
-=item SetResolution VALUE
+=head2 SetResolution VALUE
Set Resolution to VALUE.
=cut
-=item Owner
+=head2 Owner
Returns the current value of Owner.
(In the database, Owner is stored as int(11).)
-=item SetOwner VALUE
+=head2 SetOwner VALUE
Set Owner to VALUE.
=cut
-=item Subject
+=head2 Subject
Returns the current value of Subject.
(In the database, Subject is stored as varchar(200).)
-=item SetSubject VALUE
+=head2 SetSubject VALUE
Set Subject to VALUE.
=cut
-=item InitialPriority
+=head2 InitialPriority
Returns the current value of InitialPriority.
(In the database, InitialPriority is stored as int(11).)
-=item SetInitialPriority VALUE
+=head2 SetInitialPriority VALUE
Set InitialPriority to VALUE.
=cut
-=item FinalPriority
+=head2 FinalPriority
Returns the current value of FinalPriority.
(In the database, FinalPriority is stored as int(11).)
-=item SetFinalPriority VALUE
+=head2 SetFinalPriority VALUE
Set FinalPriority to VALUE.
=cut
-=item Priority
+=head2 Priority
Returns the current value of Priority.
(In the database, Priority is stored as int(11).)
-=item SetPriority VALUE
+=head2 SetPriority VALUE
Set Priority to VALUE.
=cut
-=item TimeEstimated
+=head2 TimeEstimated
Returns the current value of TimeEstimated.
(In the database, TimeEstimated is stored as int(11).)
-=item SetTimeEstimated VALUE
+=head2 SetTimeEstimated VALUE
Set TimeEstimated to VALUE.
=cut
-=item TimeWorked
+=head2 TimeWorked
Returns the current value of TimeWorked.
(In the database, TimeWorked is stored as int(11).)
-=item SetTimeWorked VALUE
+=head2 SetTimeWorked VALUE
Set TimeWorked to VALUE.
=cut
-=item Status
+=head2 Status
Returns the current value of Status.
(In the database, Status is stored as varchar(10).)
-=item SetStatus VALUE
+=head2 SetStatus VALUE
Set Status to VALUE.
=cut
-=item TimeLeft
+=head2 TimeLeft
Returns the current value of TimeLeft.
(In the database, TimeLeft is stored as int(11).)
-=item SetTimeLeft VALUE
+=head2 SetTimeLeft VALUE
Set TimeLeft to VALUE.
=cut
-=item Told
+=head2 Told
Returns the current value of Told.
(In the database, Told is stored as datetime.)
-=item SetTold VALUE
+=head2 SetTold VALUE
Set Told to VALUE.
=cut
-=item Starts
+=head2 Starts
Returns the current value of Starts.
(In the database, Starts is stored as datetime.)
-=item SetStarts VALUE
+=head2 SetStarts VALUE
Set Starts to VALUE.
=cut
-=item Started
+=head2 Started
Returns the current value of Started.
(In the database, Started is stored as datetime.)
-=item SetStarted VALUE
+=head2 SetStarted VALUE
Set Started to VALUE.
=cut
-=item Due
+=head2 Due
Returns the current value of Due.
(In the database, Due is stored as datetime.)
-=item SetDue VALUE
+=head2 SetDue VALUE
Set Due to VALUE.
=cut
-=item Resolved
+=head2 Resolved
Returns the current value of Resolved.
(In the database, Resolved is stored as datetime.)
-=item SetResolved VALUE
+=head2 SetResolved VALUE
Set Resolved to VALUE.
=cut
-=item LastUpdatedBy
+=head2 LastUpdatedBy
Returns the current value of LastUpdatedBy.
(In the database, LastUpdatedBy is stored as int(11).)
=cut
-=item LastUpdated
+=head2 LastUpdated
Returns the current value of LastUpdated.
(In the database, LastUpdated is stored as datetime.)
=cut
-=item Creator
+=head2 Creator
Returns the current value of Creator.
(In the database, Creator is stored as int(11).)
=cut
-=item Created
+=head2 Created
Returns the current value of Created.
(In the database, Created is stored as datetime.)
=cut
-=item Disabled
+=head2 Disabled
Returns the current value of Disabled.
(In the database, Disabled is stored as smallint(6).)
-=item SetDisabled VALUE
+=head2 SetDisabled VALUE
Set Disabled to VALUE.
-sub _ClassAccessible {
+sub _CoreAccessible {
{
id =>
- {read => 1, type => 'int(11)', default => ''},
+ {read => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => ''},
EffectiveId =>
- {read => 1, write => 1, type => 'int(11)', default => '0'},
+ {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
Queue =>
- {read => 1, write => 1, type => 'int(11)', default => '0'},
+ {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
Type =>
- {read => 1, write => 1, type => 'varchar(16)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 16, is_blob => 0, is_numeric => 0, type => 'varchar(16)', default => ''},
IssueStatement =>
- {read => 1, write => 1, type => 'int(11)', default => '0'},
+ {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
Resolution =>
- {read => 1, write => 1, type => 'int(11)', default => '0'},
+ {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
Owner =>
- {read => 1, write => 1, type => 'int(11)', default => '0'},
+ {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
Subject =>
- {read => 1, write => 1, type => 'varchar(200)', default => '[no subject]'},
+ {read => 1, write => 1, sql_type => 12, length => 200, is_blob => 0, is_numeric => 0, type => 'varchar(200)', default => '[no subject]'},
InitialPriority =>
- {read => 1, write => 1, type => 'int(11)', default => '0'},
+ {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
FinalPriority =>
- {read => 1, write => 1, type => 'int(11)', default => '0'},
+ {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
Priority =>
- {read => 1, write => 1, type => 'int(11)', default => '0'},
+ {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
TimeEstimated =>
- {read => 1, write => 1, type => 'int(11)', default => '0'},
+ {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
TimeWorked =>
- {read => 1, write => 1, type => 'int(11)', default => '0'},
+ {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
Status =>
- {read => 1, write => 1, type => 'varchar(10)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 10, is_blob => 0, is_numeric => 0, type => 'varchar(10)', default => ''},
TimeLeft =>
- {read => 1, write => 1, type => 'int(11)', default => '0'},
+ {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
Told =>
- {read => 1, write => 1, type => 'datetime', default => ''},
+ {read => 1, write => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''},
Starts =>
- {read => 1, write => 1, type => 'datetime', default => ''},
+ {read => 1, write => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''},
Started =>
- {read => 1, write => 1, type => 'datetime', default => ''},
+ {read => 1, write => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''},
Due =>
- {read => 1, write => 1, type => 'datetime', default => ''},
+ {read => 1, write => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''},
Resolved =>
- {read => 1, write => 1, type => 'datetime', default => ''},
+ {read => 1, write => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''},
LastUpdatedBy =>
- {read => 1, auto => 1, type => 'int(11)', default => '0'},
+ {read => 1, auto => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
LastUpdated =>
- {read => 1, auto => 1, type => 'datetime', default => ''},
+ {read => 1, auto => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''},
Creator =>
- {read => 1, auto => 1, type => 'int(11)', default => '0'},
+ {read => 1, auto => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
Created =>
- {read => 1, auto => 1, type => 'datetime', default => ''},
+ {read => 1, auto => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''},
Disabled =>
- {read => 1, write => 1, type => 'smallint(6)', default => '0'},
+ {read => 1, write => 1, sql_type => 5, length => 6, is_blob => 0, is_numeric => 1, type => 'smallint(6)', default => '0'},
}
};
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
+Each of these files should begin with the line
no warnings qw(redefine);
-# BEGIN LICENSE BLOCK
+# BEGIN BPS TAGGED BLOCK {{{
#
-# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# <jesse@bestpractical.com>
#
-# (Except where explictly superceded by other copyright notices)
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
#
# 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
# 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.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
+#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
#
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
#
-# END LICENSE BLOCK
+# END BPS TAGGED BLOCK }}}
# Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>)
# WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST.
#
}
-=item NewItem
+=head2 NewItem
Returns an empty new RT::Ticket item
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
+Each of these files should begin with the line
no warnings qw(redefine);
-# BEGIN LICENSE BLOCK
+# BEGIN BPS TAGGED BLOCK {{{
#
-# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# <jesse@bestpractical.com>
#
-# (Except where explictly superceded by other copyright notices)
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
#
# 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
# 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.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
#
+# CONTRIBUTION SUBMISSION POLICY:
#
-# END LICENSE BLOCK
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
+#
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
+#
+# END BPS TAGGED BLOCK }}}
# Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>)
# WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST.
#
package RT::Transaction;
use RT::Record;
-use RT::Ticket;
use vars qw( @ISA );
-=item Create PARAMHASH
+=head2 Create PARAMHASH
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(100) 'Data'.
+ varchar(255) 'ReferenceType'.
+ int(11) 'OldReference'.
+ int(11) 'NewReference'.
+ varchar(255) 'Data'.
=cut
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'},
);
-=item id
+=head2 id
Returns the current value of id.
(In the database, id is stored as int(11).)
=cut
-=item 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).)
-=item 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
-=item 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).)
-=item 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).)
-
-
-=cut
-
-
-=item TicketObj
-
-Returns the Ticket Object which has the id returned by Ticket
+(In the database, ObjectId will be stored as a int(11).)
=cut
-sub TicketObj {
- my $self = shift;
- my $Ticket = RT::Ticket->new($self->CurrentUser);
- $Ticket->Load($self->__Value('Ticket'));
- return($Ticket);
-}
-=item TimeTaken
+=head2 TimeTaken
Returns the current value of TimeTaken.
(In the database, TimeTaken is stored as int(11).)
-=item SetTimeTaken VALUE
+=head2 SetTimeTaken VALUE
Set TimeTaken to VALUE.
=cut
-=item Type
+=head2 Type
Returns the current value of Type.
(In the database, Type is stored as varchar(20).)
-=item SetType VALUE
+=head2 SetType VALUE
Set Type to VALUE.
=cut
-=item Field
+=head2 Field
Returns the current value of Field.
(In the database, Field is stored as varchar(40).)
-=item SetField VALUE
+=head2 SetField VALUE
Set Field to VALUE.
=cut
-=item OldValue
+=head2 OldValue
Returns the current value of OldValue.
(In the database, OldValue is stored as varchar(255).)
-=item SetOldValue VALUE
+=head2 SetOldValue VALUE
Set OldValue to VALUE.
=cut
-=item NewValue
+=head2 NewValue
Returns the current value of NewValue.
(In the database, NewValue is stored as varchar(255).)
-=item SetNewValue VALUE
+=head2 SetNewValue VALUE
Set NewValue to VALUE.
=cut
-=item Data
+=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.
-(In the database, Data is stored as varchar(100).)
+(In the database, Data is stored as varchar(255).)
-=item SetData VALUE
+=head2 SetData VALUE
Set Data to VALUE.
Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
-(In the database, Data will be stored as a varchar(100).)
+(In the database, Data will be stored as a varchar(255).)
=cut
-=item Creator
+=head2 Creator
Returns the current value of Creator.
(In the database, Creator is stored as int(11).)
=cut
-=item Created
+=head2 Created
Returns the current value of Created.
(In the database, Created is stored as datetime.)
-sub _ClassAccessible {
+sub _CoreAccessible {
{
id =>
- {read => 1, type => 'int(11)', default => ''},
- EffectiveTicket =>
- {read => 1, write => 1, type => 'int(11)', default => '0'},
- Ticket =>
- {read => 1, write => 1, type => 'int(11)', default => '0'},
+ {read => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => ''},
+ ObjectType =>
+ {read => 1, write => 1, sql_type => 12, length => 64, is_blob => 0, is_numeric => 0, type => 'varchar(64)', default => ''},
+ ObjectId =>
+ {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
TimeTaken =>
- {read => 1, write => 1, type => 'int(11)', default => '0'},
+ {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
Type =>
- {read => 1, write => 1, type => 'varchar(20)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 20, is_blob => 0, is_numeric => 0, type => 'varchar(20)', default => ''},
Field =>
- {read => 1, write => 1, type => 'varchar(40)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 40, is_blob => 0, is_numeric => 0, type => 'varchar(40)', default => ''},
OldValue =>
- {read => 1, write => 1, type => 'varchar(255)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 255, is_blob => 0, is_numeric => 0, type => 'varchar(255)', default => ''},
NewValue =>
- {read => 1, write => 1, type => 'varchar(255)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 255, is_blob => 0, is_numeric => 0, type => 'varchar(255)', default => ''},
+ ReferenceType =>
+ {read => 1, write => 1, sql_type => 12, length => 255, is_blob => 0, is_numeric => 0, type => 'varchar(255)', default => ''},
+ OldReference =>
+ {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => ''},
+ NewReference =>
+ {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => ''},
Data =>
- {read => 1, write => 1, type => 'varchar(100)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 255, is_blob => 0, is_numeric => 0, type => 'varchar(255)', default => ''},
Creator =>
- {read => 1, auto => 1, type => 'int(11)', default => '0'},
+ {read => 1, auto => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
Created =>
- {read => 1, auto => 1, type => 'datetime', default => ''},
+ {read => 1, auto => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''},
}
};
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
+Each of these files should begin with the line
no warnings qw(redefine);
-# BEGIN LICENSE BLOCK
+# BEGIN BPS TAGGED BLOCK {{{
#
-# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# <jesse@bestpractical.com>
#
-# (Except where explictly superceded by other copyright notices)
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
#
# 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
# 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.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
+#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
#
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
#
-# END LICENSE BLOCK
+# END BPS TAGGED BLOCK }}}
# Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>)
# WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST.
#
}
-=item NewItem
+=head2 NewItem
Returns an empty new RT::Transaction item
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
+Each of these files should begin with the line
no warnings qw(redefine);
-# BEGIN LICENSE BLOCK
+# BEGIN BPS TAGGED BLOCK {{{
#
-# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# <jesse@bestpractical.com>
#
-# (Except where explictly superceded by other copyright notices)
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
#
# 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
# 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.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
+#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
#
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
#
-# END LICENSE BLOCK
+# END BPS TAGGED BLOCK }}}
# Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>)
# WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST.
#
-=item Create PARAMHASH
+=head2 Create PARAMHASH
Create takes a hash of values and creates a row in the database:
-=item id
+=head2 id
Returns the current value of id.
(In the database, id is stored as int(11).)
=cut
-=item Name
+=head2 Name
Returns the current value of Name.
(In the database, Name is stored as varchar(200).)
-=item SetName VALUE
+=head2 SetName VALUE
Set Name to VALUE.
=cut
-=item Password
+=head2 Password
Returns the current value of Password.
(In the database, Password is stored as varchar(40).)
-=item SetPassword VALUE
+=head2 SetPassword VALUE
Set Password to VALUE.
=cut
-=item Comments
+=head2 Comments
Returns the current value of Comments.
(In the database, Comments is stored as blob.)
-=item SetComments VALUE
+=head2 SetComments VALUE
Set Comments to VALUE.
=cut
-=item Signature
+=head2 Signature
Returns the current value of Signature.
(In the database, Signature is stored as blob.)
-=item SetSignature VALUE
+=head2 SetSignature VALUE
Set Signature to VALUE.
=cut
-=item EmailAddress
+=head2 EmailAddress
Returns the current value of EmailAddress.
(In the database, EmailAddress is stored as varchar(120).)
-=item SetEmailAddress VALUE
+=head2 SetEmailAddress VALUE
Set EmailAddress to VALUE.
=cut
-=item FreeformContactInfo
+=head2 FreeformContactInfo
Returns the current value of FreeformContactInfo.
(In the database, FreeformContactInfo is stored as blob.)
-=item SetFreeformContactInfo VALUE
+=head2 SetFreeformContactInfo VALUE
Set FreeformContactInfo to VALUE.
=cut
-=item Organization
+=head2 Organization
Returns the current value of Organization.
(In the database, Organization is stored as varchar(200).)
-=item SetOrganization VALUE
+=head2 SetOrganization VALUE
Set Organization to VALUE.
=cut
-=item RealName
+=head2 RealName
Returns the current value of RealName.
(In the database, RealName is stored as varchar(120).)
-=item SetRealName VALUE
+=head2 SetRealName VALUE
Set RealName to VALUE.
=cut
-=item NickName
+=head2 NickName
Returns the current value of NickName.
(In the database, NickName is stored as varchar(16).)
-=item SetNickName VALUE
+=head2 SetNickName VALUE
Set NickName to VALUE.
=cut
-=item Lang
+=head2 Lang
Returns the current value of Lang.
(In the database, Lang is stored as varchar(16).)
-=item SetLang VALUE
+=head2 SetLang VALUE
Set Lang to VALUE.
=cut
-=item EmailEncoding
+=head2 EmailEncoding
Returns the current value of EmailEncoding.
(In the database, EmailEncoding is stored as varchar(16).)
-=item SetEmailEncoding VALUE
+=head2 SetEmailEncoding VALUE
Set EmailEncoding to VALUE.
=cut
-=item WebEncoding
+=head2 WebEncoding
Returns the current value of WebEncoding.
(In the database, WebEncoding is stored as varchar(16).)
-=item SetWebEncoding VALUE
+=head2 SetWebEncoding VALUE
Set WebEncoding to VALUE.
=cut
-=item ExternalContactInfoId
+=head2 ExternalContactInfoId
Returns the current value of ExternalContactInfoId.
(In the database, ExternalContactInfoId is stored as varchar(100).)
-=item SetExternalContactInfoId VALUE
+=head2 SetExternalContactInfoId VALUE
Set ExternalContactInfoId to VALUE.
=cut
-=item ContactInfoSystem
+=head2 ContactInfoSystem
Returns the current value of ContactInfoSystem.
(In the database, ContactInfoSystem is stored as varchar(30).)
-=item SetContactInfoSystem VALUE
+=head2 SetContactInfoSystem VALUE
Set ContactInfoSystem to VALUE.
=cut
-=item ExternalAuthId
+=head2 ExternalAuthId
Returns the current value of ExternalAuthId.
(In the database, ExternalAuthId is stored as varchar(100).)
-=item SetExternalAuthId VALUE
+=head2 SetExternalAuthId VALUE
Set ExternalAuthId to VALUE.
=cut
-=item AuthSystem
+=head2 AuthSystem
Returns the current value of AuthSystem.
(In the database, AuthSystem is stored as varchar(30).)
-=item SetAuthSystem VALUE
+=head2 SetAuthSystem VALUE
Set AuthSystem to VALUE.
=cut
-=item Gecos
+=head2 Gecos
Returns the current value of Gecos.
(In the database, Gecos is stored as varchar(16).)
-=item SetGecos VALUE
+=head2 SetGecos VALUE
Set Gecos to VALUE.
=cut
-=item HomePhone
+=head2 HomePhone
Returns the current value of HomePhone.
(In the database, HomePhone is stored as varchar(30).)
-=item SetHomePhone VALUE
+=head2 SetHomePhone VALUE
Set HomePhone to VALUE.
=cut
-=item WorkPhone
+=head2 WorkPhone
Returns the current value of WorkPhone.
(In the database, WorkPhone is stored as varchar(30).)
-=item SetWorkPhone VALUE
+=head2 SetWorkPhone VALUE
Set WorkPhone to VALUE.
=cut
-=item MobilePhone
+=head2 MobilePhone
Returns the current value of MobilePhone.
(In the database, MobilePhone is stored as varchar(30).)
-=item SetMobilePhone VALUE
+=head2 SetMobilePhone VALUE
Set MobilePhone to VALUE.
=cut
-=item PagerPhone
+=head2 PagerPhone
Returns the current value of PagerPhone.
(In the database, PagerPhone is stored as varchar(30).)
-=item SetPagerPhone VALUE
+=head2 SetPagerPhone VALUE
Set PagerPhone to VALUE.
=cut
-=item Address1
+=head2 Address1
Returns the current value of Address1.
(In the database, Address1 is stored as varchar(200).)
-=item SetAddress1 VALUE
+=head2 SetAddress1 VALUE
Set Address1 to VALUE.
=cut
-=item Address2
+=head2 Address2
Returns the current value of Address2.
(In the database, Address2 is stored as varchar(200).)
-=item SetAddress2 VALUE
+=head2 SetAddress2 VALUE
Set Address2 to VALUE.
=cut
-=item City
+=head2 City
Returns the current value of City.
(In the database, City is stored as varchar(100).)
-=item SetCity VALUE
+=head2 SetCity VALUE
Set City to VALUE.
=cut
-=item State
+=head2 State
Returns the current value of State.
(In the database, State is stored as varchar(100).)
-=item SetState VALUE
+=head2 SetState VALUE
Set State to VALUE.
=cut
-=item Zip
+=head2 Zip
Returns the current value of Zip.
(In the database, Zip is stored as varchar(16).)
-=item SetZip VALUE
+=head2 SetZip VALUE
Set Zip to VALUE.
=cut
-=item Country
+=head2 Country
Returns the current value of Country.
(In the database, Country is stored as varchar(50).)
-=item SetCountry VALUE
+=head2 SetCountry VALUE
Set Country to VALUE.
=cut
-=item Timezone
+=head2 Timezone
Returns the current value of Timezone.
(In the database, Timezone is stored as varchar(50).)
-=item SetTimezone VALUE
+=head2 SetTimezone VALUE
Set Timezone to VALUE.
=cut
-=item PGPKey
+=head2 PGPKey
Returns the current value of PGPKey.
(In the database, PGPKey is stored as text.)
-=item SetPGPKey VALUE
+=head2 SetPGPKey VALUE
Set PGPKey to VALUE.
=cut
-=item Creator
+=head2 Creator
Returns the current value of Creator.
(In the database, Creator is stored as int(11).)
=cut
-=item Created
+=head2 Created
Returns the current value of Created.
(In the database, Created is stored as datetime.)
=cut
-=item LastUpdatedBy
+=head2 LastUpdatedBy
Returns the current value of LastUpdatedBy.
(In the database, LastUpdatedBy is stored as int(11).)
=cut
-=item LastUpdated
+=head2 LastUpdated
Returns the current value of LastUpdated.
(In the database, LastUpdated is stored as datetime.)
-sub _ClassAccessible {
+sub _CoreAccessible {
{
id =>
- {read => 1, type => 'int(11)', default => ''},
+ {read => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => ''},
Name =>
- {read => 1, write => 1, type => 'varchar(200)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 200, is_blob => 0, is_numeric => 0, type => 'varchar(200)', default => ''},
Password =>
- {read => 1, write => 1, type => 'varchar(40)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 40, is_blob => 0, is_numeric => 0, type => 'varchar(40)', default => ''},
Comments =>
- {read => 1, write => 1, type => 'blob', default => ''},
+ {read => 1, write => 1, sql_type => -4, length => 0, is_blob => 1, is_numeric => 0, type => 'blob', default => ''},
Signature =>
- {read => 1, write => 1, type => 'blob', default => ''},
+ {read => 1, write => 1, sql_type => -4, length => 0, is_blob => 1, is_numeric => 0, type => 'blob', default => ''},
EmailAddress =>
- {read => 1, write => 1, type => 'varchar(120)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 120, is_blob => 0, is_numeric => 0, type => 'varchar(120)', default => ''},
FreeformContactInfo =>
- {read => 1, write => 1, type => 'blob', default => ''},
+ {read => 1, write => 1, sql_type => -4, length => 0, is_blob => 1, is_numeric => 0, type => 'blob', default => ''},
Organization =>
- {read => 1, write => 1, type => 'varchar(200)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 200, is_blob => 0, is_numeric => 0, type => 'varchar(200)', default => ''},
RealName =>
- {read => 1, write => 1, type => 'varchar(120)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 120, is_blob => 0, is_numeric => 0, type => 'varchar(120)', default => ''},
NickName =>
- {read => 1, write => 1, type => 'varchar(16)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 16, is_blob => 0, is_numeric => 0, type => 'varchar(16)', default => ''},
Lang =>
- {read => 1, write => 1, type => 'varchar(16)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 16, is_blob => 0, is_numeric => 0, type => 'varchar(16)', default => ''},
EmailEncoding =>
- {read => 1, write => 1, type => 'varchar(16)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 16, is_blob => 0, is_numeric => 0, type => 'varchar(16)', default => ''},
WebEncoding =>
- {read => 1, write => 1, type => 'varchar(16)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 16, is_blob => 0, is_numeric => 0, type => 'varchar(16)', default => ''},
ExternalContactInfoId =>
- {read => 1, write => 1, type => 'varchar(100)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 100, is_blob => 0, is_numeric => 0, type => 'varchar(100)', default => ''},
ContactInfoSystem =>
- {read => 1, write => 1, type => 'varchar(30)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 30, is_blob => 0, is_numeric => 0, type => 'varchar(30)', default => ''},
ExternalAuthId =>
- {read => 1, write => 1, type => 'varchar(100)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 100, is_blob => 0, is_numeric => 0, type => 'varchar(100)', default => ''},
AuthSystem =>
- {read => 1, write => 1, type => 'varchar(30)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 30, is_blob => 0, is_numeric => 0, type => 'varchar(30)', default => ''},
Gecos =>
- {read => 1, write => 1, type => 'varchar(16)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 16, is_blob => 0, is_numeric => 0, type => 'varchar(16)', default => ''},
HomePhone =>
- {read => 1, write => 1, type => 'varchar(30)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 30, is_blob => 0, is_numeric => 0, type => 'varchar(30)', default => ''},
WorkPhone =>
- {read => 1, write => 1, type => 'varchar(30)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 30, is_blob => 0, is_numeric => 0, type => 'varchar(30)', default => ''},
MobilePhone =>
- {read => 1, write => 1, type => 'varchar(30)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 30, is_blob => 0, is_numeric => 0, type => 'varchar(30)', default => ''},
PagerPhone =>
- {read => 1, write => 1, type => 'varchar(30)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 30, is_blob => 0, is_numeric => 0, type => 'varchar(30)', default => ''},
Address1 =>
- {read => 1, write => 1, type => 'varchar(200)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 200, is_blob => 0, is_numeric => 0, type => 'varchar(200)', default => ''},
Address2 =>
- {read => 1, write => 1, type => 'varchar(200)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 200, is_blob => 0, is_numeric => 0, type => 'varchar(200)', default => ''},
City =>
- {read => 1, write => 1, type => 'varchar(100)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 100, is_blob => 0, is_numeric => 0, type => 'varchar(100)', default => ''},
State =>
- {read => 1, write => 1, type => 'varchar(100)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 100, is_blob => 0, is_numeric => 0, type => 'varchar(100)', default => ''},
Zip =>
- {read => 1, write => 1, type => 'varchar(16)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 16, is_blob => 0, is_numeric => 0, type => 'varchar(16)', default => ''},
Country =>
- {read => 1, write => 1, type => 'varchar(50)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 50, is_blob => 0, is_numeric => 0, type => 'varchar(50)', default => ''},
Timezone =>
- {read => 1, write => 1, type => 'varchar(50)', default => ''},
+ {read => 1, write => 1, sql_type => 12, length => 50, is_blob => 0, is_numeric => 0, type => 'varchar(50)', default => ''},
PGPKey =>
- {read => 1, write => 1, type => 'text', default => ''},
+ {read => 1, write => 1, sql_type => -4, length => 0, is_blob => 1, is_numeric => 0, type => 'text', default => ''},
Creator =>
- {read => 1, auto => 1, type => 'int(11)', default => '0'},
+ {read => 1, auto => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
Created =>
- {read => 1, auto => 1, type => 'datetime', default => ''},
+ {read => 1, auto => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''},
LastUpdatedBy =>
- {read => 1, auto => 1, type => 'int(11)', default => '0'},
+ {read => 1, auto => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
LastUpdated =>
- {read => 1, auto => 1, type => 'datetime', default => ''},
+ {read => 1, auto => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''},
}
};
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
+Each of these files should begin with the line
no warnings qw(redefine);
-# BEGIN LICENSE BLOCK
+# BEGIN BPS TAGGED BLOCK {{{
#
-# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# <jesse@bestpractical.com>
#
-# (Except where explictly superceded by other copyright notices)
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
#
# 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
# 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.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
+#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
#
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
#
-# END LICENSE BLOCK
+# END BPS TAGGED BLOCK }}}
# Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>)
# WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST.
#
}
-=item NewItem
+=head2 NewItem
Returns an empty new RT::User item
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
+Each of these files should begin with the line
no warnings qw(redefine);