[rt-commit] [svn] r478 - in rt/branches: . autrijus-3.1/etc autrijus-3.1/html/Admin/CustomFields autrijus-3.1/html/Admin/Elements autrijus-3.1/html/Admin/Groups autrijus-3.1/html/Admin/Users autrijus-3.1/html/Elements autrijus-3.1/html/Elements/CustomField autrijus-3.1/lib/RT autrijus-3.1/lib/RT/Interface autrijus-3.1/spec

autrijus at fsck.com autrijus at fsck.com
Fri Mar 5 12:26:14 EST 2004


Author: autrijus
Date: Fri Mar  5 12:26:12 2004
New Revision: 478

Added:
   rt/branches/autrijus-3.1/html/Admin/Elements/PickCustomFields
   rt/branches/autrijus-3.1/html/Admin/Elements/SelectCustomFieldLookupType
   rt/branches/autrijus-3.1/html/Admin/Groups/CustomFields.html
   rt/branches/autrijus-3.1/html/Admin/Users/Memberships.html
   rt/branches/autrijus-3.1/html/Elements/CustomField/
   rt/branches/autrijus-3.1/html/Elements/CustomField/FreeformSingle
   rt/branches/autrijus-3.1/html/Elements/EditCustomField
Removed:
   rt/branches/autrijus-3.1/html/Admin/Elements/SelectCustomFieldObjectType
Modified:
   rt/branches/   (props changed)
   rt/branches/autrijus-3.1/etc/schema.mysql
   rt/branches/autrijus-3.1/html/Admin/CustomFields/Modify.html
   rt/branches/autrijus-3.1/html/Admin/Elements/EditCustomFields
   rt/branches/autrijus-3.1/html/Admin/Elements/UserTabs
   rt/branches/autrijus-3.1/html/Admin/Users/History.html
   rt/branches/autrijus-3.1/html/Admin/Users/Modify.html
   rt/branches/autrijus-3.1/lib/RT/CustomField.pm
   rt/branches/autrijus-3.1/lib/RT/CustomField_Overlay.pm
   rt/branches/autrijus-3.1/lib/RT/CustomFields_Overlay.pm
   rt/branches/autrijus-3.1/lib/RT/Interface/Web.pm
   rt/branches/autrijus-3.1/lib/RT/ObjectCustomField.pm
   rt/branches/autrijus-3.1/lib/RT/ObjectCustomFieldValue_Overlay.pm
   rt/branches/autrijus-3.1/lib/RT/ObjectCustomFieldValues_Overlay.pm
   rt/branches/autrijus-3.1/lib/RT/ObjectCustomFields_Overlay.pm
   rt/branches/autrijus-3.1/lib/RT/Queue_Overlay.pm
   rt/branches/autrijus-3.1/lib/RT/Record.pm
   rt/branches/autrijus-3.1/lib/RT/Ticket_Overlay.pm
   rt/branches/autrijus-3.1/lib/RT/User_Overlay.pm
   rt/branches/autrijus-3.1/spec/schema.txt
   rt/branches/autrijus-3.1/spec/spec.txt
Log:
* CF editing (at least for Freeform-1) for User/Group done.
* add new, dispatch-oriented customfield editing widgets
* refactor lookup paths to _CustomFieldComposites.
* warn on deprecated Queue->CustomFields per request from obra.
  (it should now be Queue->TicketCustomFields)
* re-rationalise lookup into "LookupType".


Modified: rt/branches/autrijus-3.1/etc/schema.mysql
==============================================================================
--- rt/branches/autrijus-3.1/etc/schema.mysql	(original)
+++ rt/branches/autrijus-3.1/etc/schema.mysql	Fri Mar  5 12:26:12 2004
@@ -383,10 +383,7 @@
   Repeated int2 NOT NULL DEFAULT 0 , # New -- repeated table entry
   Description varchar(255) NULL  ,
   SortOrder integer NOT NULL DEFAULT 0  ,
-
-  ObjectType varchar(255) NOT NULL,
-  IntermediateType varchar(255) NOT NULL,
-  ParentType varchar(255) NOT NULL,
+  LookupType varchar(255) NOT NULL,
 
   Creator integer NOT NULL DEFAULT 0  ,
   Created DATETIME NULL  ,
@@ -403,7 +400,7 @@
 CREATE TABLE ObjectCustomFields (
   id INTEGER NOT NULL  AUTO_INCREMENT,
   CustomField int NOT NULL  ,
-  ParentId integer NOT NULL,
+  ObjectId integer NOT NULL,
   SortOrder integer NOT NULL DEFAULT 0  ,
 
   Creator integer NOT NULL DEFAULT 0  ,

Modified: rt/branches/autrijus-3.1/html/Admin/CustomFields/Modify.html
==============================================================================
--- rt/branches/autrijus-3.1/html/Admin/CustomFields/Modify.html	(original)
+++ rt/branches/autrijus-3.1/html/Admin/CustomFields/Modify.html	Fri Mar  5 12:26:12 2004
@@ -25,9 +25,9 @@
 </tr>
 <tr>
 <td class="label"><&|/l&>Applies to</&></td>
-<td><& /Admin/Elements/SelectCustomFieldObjectType, 
-        Name => "ObjectTypeComposite", 
-        Default => $CustomFieldObj->ObjectTypeComposite, &>
+<td><& /Admin/Elements/SelectCustomFieldLookupType, 
+        Name => "LookupType", 
+        Default => $CustomFieldObj->LookupType, &>
 </td>
 </tr>
 <tr>
@@ -67,7 +67,7 @@
     if ( $id eq 'new' ) {
         my ( $val, $msg ) = $CustomFieldObj->Create(Name        => $Name,
                                                     TypeComposite => $TypeComposite,
-                                                    ObjectTypeComposite => $ObjectTypeComposite,
+                                                    LookupType => $LookupType,
                                                     Description => $Description,);
         $m->comp("/Elements/Error", Why =>  loc( "Could not create CustomField", $msg ) ) unless ($val);
         push @results, $msg;
@@ -77,7 +77,7 @@
         $CustomFieldObj->Load($id) || $m->comp("/Elements/Error", Why =>  loc('No CustomField') );
         $title = loc( 'Editing CustomField [_1]', $CustomFieldObj->Name() );
 
-        my @attribs = qw( Name TypeComposite ObjectTypeComposite Description);
+        my @attribs = qw( Name TypeComposite LookupType Description);
         my @aresults = UpdateRecordObject( AttributesRef => \@attribs,
                                            Object        => $CustomFieldObj,
                                            ARGSRef       => \%ARGS );
@@ -155,7 +155,7 @@
 <%ARGS>
 $id => undef
 $TypeComposite => undef
-$ObjectTypeComposite => undef
+$LookupType => undef
 $MaxValues => undef
 $SortOrder => undef
 $Description => undef

Modified: rt/branches/autrijus-3.1/html/Admin/Elements/EditCustomFields
==============================================================================
--- rt/branches/autrijus-3.1/html/Admin/Elements/EditCustomFields	(original)
+++ rt/branches/autrijus-3.1/html/Admin/Elements/EditCustomFields	Fri Mar  5 12:26:12 2004
@@ -60,9 +60,9 @@
 my (@GlobalCFs, @AssociatedCFs, @UnassociatedCFs);
 
 # XXX - exception: by "RT::Queue" fields on UI we really mean "RT::Ticket" fields.
-my $composite = "$ObjectType--";
-$composite = 'RT::Ticket--RT::Queue' if $composite eq 'RT::Queue--';
-$CustomFields->LimitToComposite($composite);
+my $lookup = $ObjectType;
+$lookup = 'RT::Queue-RT::Ticket' if $lookup eq 'RT::Queue';
+$CustomFields->LimitToLookupType($lookup);
 
 if ($FindDisabledCustomFields) {
     $caption = loc("All Custom Fields");
@@ -115,11 +115,13 @@
 my $id = $Object->Id;
 my ($GlobalCFs, $ObjectCFs);
 $ObjectCFs = RT::ObjectCustomFields->new($session{'CurrentUser'});
-$ObjectCFs->LimitToParentAndComposite(Parent => $Object, Composite => $composite);
+$ObjectCFs->LimitToObjectId($Object->Id);
+$ObjectCFs->LimitToLookupType($lookup);
 
 if ($id) {
     $GlobalCFs = RT::ObjectCustomFields->new($session{'CurrentUser'});
-    $GlobalCFs->LimitToParentAndComposite(ParentType => ref($Object), Composite => $composite);
+    $GlobalCFs->LimitToObjectId(0);
+    $GlobalCFs->LimitToLookupType($lookup);
 }
 
 while (my $cf = $CustomFields->Next) { 
@@ -137,7 +139,7 @@
 	if ($ARGS{$key}) {
 	    push @AssociatedCFs, $cf;
 	    if (!$ObjectCFs->HasEntryForCustomField($cf_id)) {
-		my ($val, $msg) = $cf->AddToParent($Object, $composite);
+		my ($val, $msg) = $cf->AddToObject($Object);
 		push (@results, $msg);
 	    }
 	    # my ($val, $msg) = $cf->SetSortOrderForObject(Object => $Object, SortOrder => $ARGS{"Object-$id-CF-$cf_id-SortOrder"});
@@ -145,7 +147,7 @@
 	else {
 	    push @UnassociatedCFs, $cf;
 	    if ($ObjectCFs->HasEntryForCustomField($cf_id)) {
-		my ($val, $msg) = $cf->RemoveFromParent($Object, $composite);
+		my ($val, $msg) = $cf->RemoveFromParent($Object);
 		push (@results, $msg);
 	    }
 	}

Added: rt/branches/autrijus-3.1/html/Admin/Elements/PickCustomFields
==============================================================================
--- (empty file)
+++ rt/branches/autrijus-3.1/html/Admin/Elements/PickCustomFields	Fri Mar  5 12:26:12 2004
@@ -0,0 +1,72 @@
+%# BEGIN LICENSE BLOCK
+%# 
+%# Copyright (c) 1996-2003 Jesse Vincent <jesse at bestpractical.com>
+%# 
+%# (Except where explictly superceded by other copyright notices)
+%# 
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%# 
+%# This work is distributed in the hope that it will be useful, but
+%# WITHOUT ANY WARRANTY; without even the implied warranty of
+%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+%# General Public License for more details.
+%# 
+%# Unless otherwise specified, all modifications, corrections or
+%# extensions to this work which alter its source code become the
+%# property of Best Practical Solutions, LLC when submitted for
+%# inclusion in the work.
+%# 
+%# 
+%# END LICENSE BLOCK
+% if (@CustomFields == 0) {
+<P><i><&|/l&>(No custom fields)</&></i></P>
+% } else {
+<TABLE cellspacing=0 cellpadding=2>
+% my $count;
+% foreach my $CustomFieldObj (@CustomFields) {
+<TR>
+  <TD valign="TOP">
+<input type="checkbox"
+name="Object-<%$id%>-CF-<%$CustomFieldObj->Id%>"
+value="1" 
+<% $Checked && 'CHECKED' %>
+>
+  </TD>
+  <TD valign="TOP">
+% if ($CustomFieldObj->Name) {
+    <A HREF="/Admin/CustomFields/Modify.html?id=<%$CustomFieldObj->id()%>"><b><%$CustomFieldObj->Name%></b></a><br>
+% } else {
+    <A HREF="/Admin/CustomFields/Modify.html?id=<%$CustomFieldObj->id()%>"><i>(<%loc("no name")%>)</i></a><br>
+% }
+    <%$CustomFieldObj->Description%>
+  </TD>
+  <TD valign="TOP">
+    <i><% $CustomFieldObj->FriendlyTypeComposite %></i>
+  </TD>
+%  # show 'move up' unless it's the first item
+%  if ($count++ and !$ReadOnly) {
+  <TD valign="TOP">
+    <a href="CustomFields.html?id=<%$id%>&CustomField=<%$CustomFieldObj->id%>&Move=-1"><&|/l&>Move up</&></a>
+%  } else {
+  <TD valign="TOP" ALIGN=RIGHT>
+%  }
+
+%  # show 'move down' unless it's the last item
+%  if ($count != @CustomFields and !$ReadOnly) {
+%  $m->print(' | ') if $count > 1;
+    <a href="CustomFields.html?id=<%$id%>&CustomField=<%$CustomFieldObj->id%>&Move=1"><&|/l&>Move down</&></a>
+%  }
+  </TD>
+</TR>
+% }
+</TABLE>
+% }
+<%ARGS>
+ at CustomFields
+$id
+$ReadOnly => 0
+$Checked => 0
+</%ARGS>

Added: rt/branches/autrijus-3.1/html/Admin/Elements/SelectCustomFieldLookupType
==============================================================================
--- (empty file)
+++ rt/branches/autrijus-3.1/html/Admin/Elements/SelectCustomFieldLookupType	Fri Mar  5 12:26:12 2004
@@ -0,0 +1,36 @@
+%# BEGIN LICENSE BLOCK
+%# 
+%# Copyright (c) 1996-2003 Jesse Vincent <jesse at bestpractical.com>
+%# 
+%# (Except where explictly superceded by other copyright notices)
+%# 
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%# 
+%# This work is distributed in the hope that it will be useful, but
+%# WITHOUT ANY WARRANTY; without even the implied warranty of
+%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+%# General Public License for more details.
+%# 
+%# Unless otherwise specified, all modifications, corrections or
+%# extensions to this work which alter its source code become the
+%# property of Best Practical Solutions, LLC when submitted for
+%# inclusion in the work.
+%# 
+%# 
+%# END LICENSE BLOCK
+<SELECT NAME ="<%$Name%>">
+%for my $option ($cf->LookupTypes) {
+<OPTION VALUE="<%$option%>" <%$option eq $Default && "SELECTED"%>><% $cf->FriendlyLookupType($option) %></OPTION>
+%}
+</SELECT>
+<%INIT>
+my $cf = RT::CustomField->new($session{'CurrentUser'});
+
+</%INIT>
+<%ARGS>
+$Default=>undef
+$Name => 'LookupType'
+</%ARGS>

Modified: rt/branches/autrijus-3.1/html/Admin/Elements/UserTabs
==============================================================================
--- rt/branches/autrijus-3.1/html/Admin/Elements/UserTabs	(original)
+++ rt/branches/autrijus-3.1/html/Admin/Elements/UserTabs	Fri Mar  5 12:26:12 2004
@@ -24,7 +24,7 @@
 <& /Admin/Elements/Tabs, 
     subtabs => $tabs,
     current_tab => 'Admin/Users/', 
-    current_subtab => $current_subtab, 
+    current_subtab => $current_tab, 
     Title => $Title &>
 <%INIT>
 my $tabs;
@@ -37,6 +37,9 @@
 	       Basics => { title => loc('Basics'),
 			   path => "Admin/Users/Modify.html?id=".$id
 			 },
+	       Memberships => { title => loc('Memberships'),
+			   path => "Admin/Users/Memberships.html?id=".$id
+			 },
 	       History => { title => loc('History'),
 			   path => "Admin/Users/History.html?id=".$id
 			 },
@@ -63,11 +66,19 @@
   # Now let callbacks add their extra tabs
   $m->comp('/Elements/Callback', tabs => $tabs, %ARGS);
                                                                                 
-foreach my $tab ( sort keys %{$tabs} ) {                                        
-    if ( $tabs->{$tab}->{'path'} eq $current_subtab ) {                         
-        $tabs->{$tab}->{"current_subtab"} = $current_subtab;                    
+#foreach my $tab ( sort keys %{$tabs} ) {                                        
+#    if ( $tabs->{$tab}->{'path'} eq $current_subtab ) {                         
+#        $tabs->{$tab}->{"current_subtab"} = $current_subtab;                    
+#    }                                                                           
+#}                                                                               
+foreach my $tab ( sort keys %{$tabs->{'this'}->{'subtabs'}} ) {  
+    if ( $tabs->{'this'}->{'subtabs'}->{$tab}->{'path'} eq $current_tab ) {
+        $tabs->{'this'}->{'subtabs'}->{$tab}->{"subtabs"}        = $subtabs; 
+        $tabs->{'this'}->{'subtabs'}->{$tab}->{"current_subtab"} = $current_subtab; 
     }                                                                           
-}                                                                               
+}   
+$tabs->{'this'}->{"current_subtab"} = $current_tab; 
+$current_tab = "Admin/Users/Modify.html?id=".$id if $id;
 </%INIT>
   
   

Added: rt/branches/autrijus-3.1/html/Admin/Groups/CustomFields.html
==============================================================================
--- (empty file)
+++ rt/branches/autrijus-3.1/html/Admin/Groups/CustomFields.html	Fri Mar  5 12:26:12 2004
@@ -0,0 +1,24 @@
+%# BEGIN LICENSE BLOCK
+%# 
+%# Copyright (c) 1996-2003 Jesse Vincent <jesse at bestpractical.com>
+%# 
+%# (Except where explictly superceded by other copyright notices)
+%# 
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%# 
+%# This work is distributed in the hope that it will be useful, but
+%# WITHOUT ANY WARRANTY; without even the implied warranty of
+%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+%# General Public License for more details.
+%# 
+%# Unless otherwise specified, all modifications, corrections or
+%# extensions to this work which alter its source code become the
+%# property of Best Practical Solutions, LLC when submitted for
+%# inclusion in the work.
+%# 
+%# 
+%# END LICENSE BLOCK
+<& /Admin/Elements/ObjectCustomFields, %ARGS, ObjectType => 'RT::Group' &>

Modified: rt/branches/autrijus-3.1/html/Admin/Users/History.html
==============================================================================
--- rt/branches/autrijus-3.1/html/Admin/Users/History.html	(original)
+++ rt/branches/autrijus-3.1/html/Admin/Users/History.html	Fri Mar  5 12:26:12 2004
@@ -25,7 +25,7 @@
 <& /Admin/Elements/UserTabs, 
     id => $id, 
     UserObj => $UserObj,
-    current_subtab => $current_tab, 
+    current_tab => $current_tab, 
     Title => $title &>
 
 <& /Ticket/Elements/ShowHistory,

Added: rt/branches/autrijus-3.1/html/Admin/Users/Memberships.html
==============================================================================
--- (empty file)
+++ rt/branches/autrijus-3.1/html/Admin/Users/Memberships.html	Fri Mar  5 12:26:12 2004
@@ -0,0 +1,78 @@
+%# BEGIN LICENSE BLOCK
+%# 
+%# Copyright (c) 1996-2003 Jesse Vincent <jesse at bestpractical.com>
+%# 
+%# (Except where explictly superceded by other copyright notices)
+%# 
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%# 
+%# This work is distributed in the hope that it will be useful, but
+%# WITHOUT ANY WARRANTY; without even the implied warranty of
+%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+%# General Public License for more details.
+%# 
+%# Unless otherwise specified, all modifications, corrections or
+%# extensions to this work which alter its source code become the
+%# property of Best Practical Solutions, LLC when submitted for
+%# inclusion in the work.
+%# 
+%# 
+%# END LICENSE BLOCK
+<& /Admin/Elements/Header, Title => $title  &>
+<& /Admin/Elements/UserTabs, 
+    id => $id, 
+    UserObj => $UserObj,
+    current_tab => $current_tab, 
+    Title => $title &>
+
+<h2><&|/l&>Groups</&></h2>
+
+<ul>
+% while ( my $GroupMember = $GroupMembers->Next ) {
+%    my $Group = RT::Group->new($session{'CurrentUser'});
+%    $Group->Load($GroupMember->GroupId) or next;
+%    if ($Group->Domain eq 'UserDefined') {
+<li><a href="/Admin/Groups/Modify.html?id=<% $Group->Id %>"><% $Group->Name %></a></li>
+%    } elsif ($Group->Domain eq 'SystemInternal') {
+<li><em><% loc($Group->Type) %></em></li>
+%    }
+% }
+</ul>
+
+<%INIT>
+my $current_tab = 'Admin/Users/Memberships.html?id='.$id;
+my $UserObj = new RT::User($session{'CurrentUser'});
+$UserObj->Load($id) || Abort("Couldn't load user '$id'");
+my $title = loc("Memberships of the user [_1]", $UserObj->Name);
+my $GroupMembers = RT::GroupMembers->new($session{'CurrentUser'});
+$GroupMembers->Limit( FIELD => 'MemberId', VALUE => $UserObj->Id );
+my $alias = $GroupMembers->Join(
+    TYPE       => 'left',
+    ALIAS1     => 'main',
+    FIELD1     => 'GroupId',
+    TABLE2     => 'Groups',
+    FIELD2     => 'id'
+);
+$GroupMembers->Limit(
+    ALIAS      => $alias,
+    FIELD      => 'Domain',
+    OPERATOR   => '=',
+    VALUE      => 'SystemInternal',
+);
+$GroupMembers->Limit(
+    ALIAS      => $alias,
+    FIELD      => 'Domain',
+    OPERATOR   => '=',
+    VALUE      => 'UserDefined',
+);
+$GroupMembers->OrderByCols(
+    { ALIAS => $alias, FIELD => 'Domain' },
+    { ALIAS => $alias, FIELD => 'Name' },
+);
+</%INIT>
+<%ARGS>
+$id => undef
+</%ARGS>

Modified: rt/branches/autrijus-3.1/html/Admin/Users/Modify.html
==============================================================================
--- rt/branches/autrijus-3.1/html/Admin/Users/Modify.html	(original)
+++ rt/branches/autrijus-3.1/html/Admin/Users/Modify.html	Fri Mar  5 12:26:12 2004
@@ -25,7 +25,7 @@
 <& /Admin/Elements/UserTabs, 
     id => $id, 
     UserObj => $UserObj,
-    current_subtab => $current_tab, 
+    current_tab => $current_tab, 
     Title => $title &>
 
 <& /Elements/ListActions, actions => \@results &>
@@ -179,14 +179,15 @@
 <TR>
 </TR>
 </TABLE>
+<BR>
 <& /Elements/TitleBoxStart, title => loc('Custom Fields') &>
 <TABLE>
 % my $CFs = $UserObj->CustomFields;
 % while (my $CF = $CFs->Next) {
 <TR><TD ALIGN="RIGHT">
-<% $CF->Name %>
+<% $CF->Name %>:
 </TD><TD>
-<& /Ticket/Elements/EditCustomField, CustomField => $CF &>
+<& /Elements/EditCustomField, %ARGS, Object => $UserObj, CustomField => $CF &>
 </TD></TR>
 % }
 <TR>
@@ -278,6 +279,7 @@
 					    Object => $UserObj,
 					    ARGSRef => \%ARGS );
     push (@results, at fieldresults);
+    push @results, ProcessObjectCustomFieldUpdates( ARGSRef => \%ARGS );
 
 
 # {{{ Deal with special fields: Privileged, Enabled and Password

Added: rt/branches/autrijus-3.1/html/Elements/CustomField/FreeformSingle
==============================================================================
--- (empty file)
+++ rt/branches/autrijus-3.1/html/Elements/CustomField/FreeformSingle	Fri Mar  5 12:26:12 2004
@@ -0,0 +1,31 @@
+%# BEGIN LICENSE BLOCK
+%# 
+%# Copyright (c) 1996-2003 Jesse Vincent <jesse at bestpractical.com>
+%# 
+%# (Except where explictly superceded by other copyright notices)
+%# 
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%# 
+%# This work is distributed in the hope that it will be useful, but
+%# WITHOUT ANY WARRANTY; without even the implied warranty of
+%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+%# General Public License for more details.
+%# 
+%# Unless otherwise specified, all modifications, corrections or
+%# extensions to this work which alter its source code become the
+%# property of Best Practical Solutions, LLC when submitted for
+%# inclusion in the work.
+%# 
+%# 
+%# END LICENSE BLOCK
+<input name="<%$NamePrefix%><%$CustomField->Id%>-Value" size="<%$Cols%>" value="<%$Default ? $Default : ''%>">
+<%ARGS>
+$Object => undef
+$CustomField => undef
+$NamePrefix => undef
+$Default => undef
+$Cols
+</%ARGS>

Added: rt/branches/autrijus-3.1/html/Elements/EditCustomField
==============================================================================
--- (empty file)
+++ rt/branches/autrijus-3.1/html/Elements/EditCustomField	Fri Mar  5 12:26:12 2004
@@ -0,0 +1,93 @@
+%# BEGIN LICENSE BLOCK
+%# 
+%# Copyright (c) 1996-2003 Jesse Vincent <jesse at bestpractical.com>
+%# 
+%# (Except where explictly superceded by other copyright notices)
+%# 
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%# 
+%# This work is distributed in the hope that it will be useful, but
+%# WITHOUT ANY WARRANTY; without even the implied warranty of
+%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+%# General Public License for more details.
+%# 
+%# Unless otherwise specified, all modifications, corrections or
+%# extensions to this work which alter its source code become the
+%# property of Best Practical Solutions, LLC when submitted for
+%# inclusion in the work.
+%# 
+%# 
+%# END LICENSE BLOCK
+% if ($CustomField->Type eq 'FreeformSingle') {
+      <input name="<%$NamePrefix%><%$CustomField->Id%>-Value"
+        size="<%$Cols%>"
+% if ($Object) {
+          value="<%$Values->Count ? $Values->First->Content : ''%>"
+% } elsif ($Default) {
+          value="<%$Default ? $Default : ''%>"
+% }
+>
+% } elsif ($CustomField->Type eq 'FreeformMultiple') {
+% my $content;
+% if ($Object) {
+%          while (my $value = $Values->Next ) {
+%                 $content .= $value->Content;
+%           }
+% } elsif ($Default) {
+          value="<%$Default ? $Default : ''%>"
+%  }
+<input type="hidden" name="<%$NamePrefix%><%$CustomField->Id%>-Values-Magic" value="1">
+<textarea cols=<%$Cols%> rows=<%$Rows%> name="<%$NamePrefix%><%$CustomField->Id%>-Values"><%$content%></textarea>
+% } elsif ($CustomField->Type =~ /^Select/) {
+      <input type="hidden" name="<%$NamePrefix%><%$CustomField->Id%>-Values-Magic" value="1">
+      <select name="<%$NamePrefix%><%$CustomField->Id%>-Values"
+        size="<%$Rows%>"
+        <%$CustomField->Type eq 'SelectMultiple' && 'MULTIPLE'%>>
+% my $CustomFieldValues = $CustomField->Values();
+% my $selected;
+% while (my $value = $CustomFieldValues->Next) {
+        <option value="<% $value->Name %>" 
+% if ($Object) {
+            <% $Values->HasEntry($value->Name) && ($selected = 1) && 'SELECTED' %>
+% } elsif ($Default) {
+            <% ($Default eq $value->Name) && ($selected = 1) && 'SELECTED' %>
+% }
+            ><% $value->Name%></option>
+% }
+        <option value="" <% !$selected && 'SELECTED' %>><&|/l&>(no value)</&></option>
+      </select>
+% }
+<%INIT>
+my $Values;
+if ($Object) {
+    $Values = $Object->CustomFieldValues($CustomField->id);
+    $NamePrefix ||= join('-', 'Object', ref($Object), $Object->Id, 'CustomField', '');
+}
+my $Type = $CustomField->Type;
+my $MaxValues = $CustomField->MaxValues;
+$Type .= ($MaxValues > 1) ? 'Some' : $MaxValues ? 'Single' : 'Multiple';
+if ($MaxValues == 1 and $Object and $Values) {
+    $Default = ($Values->Count ? $Values->First->Content : '');
+}
+return $m->comp(
+    "/Elements/CustomField/$Type",
+    %ARGS,
+    Rows => $Rows,
+    Cols => $Cols,
+    Default => $Default,
+    Object => $Object,
+    NamePrefix => $NamePrefix,
+    CustomField => $CustomField,
+);
+</%INIT>
+<%ARGS>
+$Object => undef
+$CustomField => undef
+$NamePrefix => undef
+$Rows => 5
+$Cols => 15
+$Default => undef
+</%ARGS>

Modified: rt/branches/autrijus-3.1/lib/RT/CustomField.pm
==============================================================================
--- rt/branches/autrijus-3.1/lib/RT/CustomField.pm	(original)
+++ rt/branches/autrijus-3.1/lib/RT/CustomField.pm	Fri Mar  5 12:26:12 2004
@@ -73,9 +73,7 @@
   smallint(6) 'Repeated'.
   varchar(255) 'Description'.
   int(11) 'SortOrder'.
-  varchar(255) 'ObjectType'.
-  varchar(255) 'IntermediateType'.
-  varchar(255) 'ParentType'.
+  varchar(255) 'LookupType'.
   smallint(6) 'Disabled'.
 
 =cut
@@ -93,9 +91,7 @@
                 Repeated => '0',
                 Description => '',
                 SortOrder => '0',
-                ObjectType => '',
-                IntermediateType => '',
-                ParentType => '',
+                LookupType => '',
                 Disabled => '0',
 
 		  @_);
@@ -107,9 +103,7 @@
                          Repeated => $args{'Repeated'},
                          Description => $args{'Description'},
                          SortOrder => $args{'SortOrder'},
-                         ObjectType => $args{'ObjectType'},
-                         IntermediateType => $args{'IntermediateType'},
-                         ParentType => $args{'ParentType'},
+                         LookupType => $args{'LookupType'},
                          Disabled => $args{'Disabled'},
 );
 
@@ -252,55 +246,19 @@
 =cut
 
 
-=head2 ObjectType
+=head2 LookupType
 
-Returns the current value of ObjectType. 
-(In the database, ObjectType is stored as varchar(255).)
+Returns the current value of LookupType. 
+(In the database, LookupType is stored as varchar(255).)
 
 
 
-=head2 SetObjectType VALUE
+=head2 SetLookupType VALUE
 
 
-Set ObjectType to VALUE. 
+Set LookupType to VALUE. 
 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
-(In the database, ObjectType will be stored as a varchar(255).)
-
-
-=cut
-
-
-=head2 IntermediateType
-
-Returns the current value of IntermediateType. 
-(In the database, IntermediateType is stored as varchar(255).)
-
-
-
-=head2 SetIntermediateType VALUE
-
-
-Set IntermediateType to VALUE. 
-Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
-(In the database, IntermediateType will be stored as a varchar(255).)
-
-
-=cut
-
-
-=head2 ParentType
-
-Returns the current value of ParentType. 
-(In the database, ParentType is stored as varchar(255).)
-
-
-
-=head2 SetParentType VALUE
-
-
-Set ParentType to VALUE. 
-Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
-(In the database, ParentType will be stored as a varchar(255).)
+(In the database, LookupType will be stored as a varchar(255).)
 
 
 =cut
@@ -380,11 +338,7 @@
 		{read => 1, write => 1, type => 'varchar(255)', default => ''},
         SortOrder => 
 		{read => 1, write => 1, type => 'int(11)', default => '0'},
-        ObjectType => 
-		{read => 1, write => 1, type => 'varchar(255)', default => ''},
-        IntermediateType => 
-		{read => 1, write => 1, type => 'varchar(255)', default => ''},
-        ParentType => 
+        LookupType => 
 		{read => 1, write => 1, type => 'varchar(255)', default => ''},
         Creator => 
 		{read => 1, auto => 1, type => 'int(11)', default => '0'},

Modified: rt/branches/autrijus-3.1/lib/RT/CustomField_Overlay.pm
==============================================================================
--- rt/branches/autrijus-3.1/lib/RT/CustomField_Overlay.pm	(original)
+++ rt/branches/autrijus-3.1/lib/RT/CustomField_Overlay.pm	Fri Mar  5 12:26:12 2004
@@ -95,11 +95,8 @@
 		MaxValues => '0',
 		Pattern  => '',
                 Description => '',
-                SortOrder => '0',
                 Disabled => '0',
-		ObjectType  => '',
-		IntermediateType  => '',
-		ParentType  => '',
+		LookupType  => '',
 		Repeated  => '0',
 
 		  @_);
@@ -107,10 +104,6 @@
     if ($args{TypeComposite}) {
 	@args{'Type', 'MaxValues'} = split(/-/, $args{TypeComposite}, 2);
     }
-    if ($args{ObjectTypeComposite}) {
-	@args{'ObjectType', 'IntermediateType', 'ParentType'}
-	    = split(/-/, $args{ObjectTypeComposite}, 3);
-    }
     
     if ( !exists $args{'Queue'}) {
 	# do nothing -- things below are strictly backward compat
@@ -119,6 +112,7 @@
         unless ( $self->CurrentUser->HasRight( Object => $RT::System, Right => 'AdminCustomFields') ) {
             return ( 0, $self->loc('Permission Denied') );
         }
+	$args{'LookupType'} = 'RT::Queue-RT::Ticket';
     }
     else {
         my $queue = RT::Queue->new($self->CurrentUser);
@@ -129,6 +123,7 @@
         unless ( $queue->CurrentUserHasRight('AdminCustomFields') ) {
             return ( 0, $self->loc('Permission Denied') );
         }
+	$args{'LookupType'} = 'RT::Queue-RT::Ticket';
     }
     my $rv = $self->SUPER::Create(
                          Name => $args{'Name'},
@@ -136,11 +131,8 @@
                          MaxValues => $args{'MaxValues'},
                          Pattern  => $args{'Pattern'},
                          Description => $args{'Description'},
-                         SortOrder => $args{'SortOrder'},
                          Disabled => $args{'Disabled'},
-			 ObjectType => $args{'ObjectType'},
-			 IntermediateType => $args{'IntermediateType'},
-			 ParentType => $args{'ParentType'},
+			 LookupType => $args{'LookupType'},
 			 Repeated => $args{'Repeated'},
 );
 
@@ -150,8 +142,7 @@
     my $OCF = RT::ObjectCustomField->new($self->CurrentUser);
     $OCF->Create(
 	CustomField => $self->Id,
-	ObjectType => 'RT::Queue',
-	ParentId => $args{'Queue'},
+	ObjectId => $args{'Queue'},
     );
 
     return $rv;
@@ -563,7 +554,17 @@
 
 sub SingleValue {
     my $self = shift;
-    if ($self->Type =~  /Single$/) {
+    if ($self->MaxValues == 1) {
+        return 1;
+    } 
+    else {
+        return undef;
+    }
+}
+
+sub UnlimitedValues {
+    my $self = shift;
+    if ($self->MaxValues == 0) {
         return 1;
     } 
     else {
@@ -665,13 +666,16 @@
     $self->SetMaxValues($max_values);
 }
 
-sub SetObjectTypeComposite {
+sub SetLookupType {
     my $self = shift;
-    my $composite = shift;
-    my ($o_type, $i_type, $p_type) = split(/-/, $composite, 3);
-    $self->SetObjectType("$o_type");
-    $self->SetIntermediateType("$i_type");
-    $self->SetParentType("$p_type");
+    my $lookup = shift;
+    if ($lookup ne $self->LookupType) {
+	# Okay... We need to invalidate our existing relationships
+	my $ObjectCustomFields = RT::ObjectCustomFields->new($self->CurrentUser);
+	$ObjectCustomFields->LimitToCustomField($self->Id);
+	$_->Delete foreach @{$ObjectCustomFields->ItemsArrayRef};
+    }
+    $self->SUPER::SetLookupType($lookup);
 }
 
 sub TypeComposite {
@@ -679,56 +683,42 @@
     join('-', $self->Type, $self->MaxValues);
 }
 
-sub ObjectTypeComposite {
-    my $self = shift;
-    join('-', $self->ObjectType, $self->IntermediateType, $self->ParentType);
-}
-
 sub TypeComposites {
     my $self = shift;
     return map { ("$_-1", "$_-0") } $self->Types;
 }
 
-sub ObjectTypeComposites {
+sub LookupTypes {
     my $self = shift;
     qw(
-	RT::Ticket--RT::Queue
-	RT::User--
-	RT::Group--
+	RT::Queue-RT::Ticket
+	RT::User
+	RT::Group
     );
 }
 
 my @FriendlyObjectTypes = (
     "[_1] objects",		    # loc
-    "[_2]'s [_1] objects",	    # loc
-    "[_3]'s [_2]'s [_1] objects",   # loc
+    "[_1]'s [_2] objects",	    # loc
+    "[_1]'s [_2]'s [_3] objects",   # loc
 );
 
-sub FriendlyObjectType {
+sub FriendlyLookupType {
     my $self = shift;
-    my $o_type = @_ ? shift : $self->ObjectType;
-    my $i_type = @_ ? shift : $self->IntermediateType;
-    my $p_type = @_ ? shift : $self->ParentType;
+    my $lookup = shift;
     my @types = map { s/^RT::// ? $self->loc($_) : $_ }
 		grep {defined and length}
-		$o_type, $i_type, $p_type or return;
+		split(/-/, $lookup || $self->LookupType) or return;
     return ( $self->loc( $FriendlyObjectTypes[$#types], @types ) );
 }
 
-sub FriendlyObjectTypeComposite {
-    my $self = shift;
-    my $composite = shift || $self->ObjectTypeComposite;
-    return $self->FriendlyObjectType(split(/-/, $composite, 3));
-}
-
-sub AddToParent {
+sub AddToObject {
     my $self  = shift;
     my $object = shift;
-    my $composite = shift || ref($object)."--";
     my $id = $object->Id || 0;
 
-    unless ($self->ObjectTypeComposite eq $composite) {
-	return ( 0, $self->loc('Object type mismatch') );
+    unless (index($self->LookupType, ref($object)) == 0) {
+	return ( 0, $self->loc('Lookup type mismatch') );
     }
 
     unless ( $object->CurrentUserHasRight('AdminCustomFields') ) {
@@ -737,23 +727,22 @@
 
     my $ObjectCF = RT::ObjectCustomField->new( $self->CurrentUser );
 
-    $ObjectCF->LoadByCols( ParentId => $id, CustomField => $self->Id );
+    $ObjectCF->LoadByCols( ObjectId => $id, CustomField => $self->Id );
     if ( $ObjectCF->Id ) {
         return ( 0, $self->loc("That is already the current value") );
     }
     my ( $id, $msg ) =
-      $ObjectCF->Create( ParentId => $id, CustomField => $self->Id );
+      $ObjectCF->Create( ObjectId => $id, CustomField => $self->Id );
 
     return ( $id, $msg );
 }
 
-sub RemoveFromParent {
+sub RemoveFromObject {
     my $self = shift;
     my $object = shift;
-    my $composite = shift || ref($object)."--";
     my $id = $object->Id || 0;
 
-    unless ($self->ObjectTypeComposite eq $composite) {
+    unless (index($self->LookupType, ref($object)) == 0) {
 	return ( 0, $self->loc('Object type mismatch') );
     }
 
@@ -763,7 +752,7 @@
 
     my $ObjectCF = RT::ObjectCustomField->new( $self->CurrentUser );
 
-    $ObjectCF->LoadByCols( ParentId => $id, CustomField => $self->Id );
+    $ObjectCF->LoadByCols( ObjectId => $id, CustomField => $self->Id );
     unless ( $ObjectCF->Id ) {
         return ( 0, $self->loc("This custom field does not apply to that object") );
     }
@@ -771,5 +760,78 @@
 
     return ( $id, $msg );
 }
+
+# {{{ AddValueForObject
+
+=head2 AddValueForObject HASH
+
+Adds a custom field value for a ticket. Takes a param hash of Object and Content
+
+=cut
+
+sub AddValueForObject {
+	my $self = shift;
+	my %args = ( Object => undef,
+                 Content => undef,
+		     @_ );
+	my $obj = $args{'Object'} or return;
+
+	my $newval = RT::ObjectCustomFieldValue->new($self->CurrentUser);
+	my $val = $newval->Create(ObjectType => ref($obj),
+	                    ObjectId => $obj->Id,
+                            Content => $args{'Content'},
+                            CustomField => $self->Id);
+
+    return($val);
+
+}
+
+
+# }}}
+
+# {{{ DeleteValueForObject
+
+=head2 DeleteValueForObject HASH
+
+Adds a custom field value for a ticket. Takes a param hash of Object and Content
+
+=cut
+
+sub DeleteValueForObject {
+	my $self = shift;
+	my %args = ( Object => undef,
+                 Content => undef,
+		     @_ );
+
+	my $oldval = RT::ObjectCustomFieldValue->new($self->CurrentUser);
+    $oldval->LoadByObjectContentAndCustomField (Object => $args{'Object'}, 
+                                                Content =>  $args{'Content'}, 
+                                                CustomField => $self->Id );
+    # check ot make sure we found it
+    unless ($oldval->Id) {
+        return(0, $self->loc("Custom field value [_1] could not be found for custom field [_2]", $args{'Content'}, $self->Name));
+    }
+    # delete it
+
+    my $ret = $oldval->Delete();
+    unless ($ret) {
+        return(0, $self->loc("Custom field value could not be found"));
+    }
+    return(1, $self->loc("Custom field value deleted"));
+}
+
+sub ValuesForObject {
+	my $self = shift;
+    my $object = shift;
+
+	my $values = new RT::ObjectCustomFieldValues($self->CurrentUser);
+	$values->LimitToCustomField($self->Id);
+    $values->LimitToObject($object);
+
+	return ($values);
+}
+
+
+# }}}
 
 1;

Modified: rt/branches/autrijus-3.1/lib/RT/CustomFields_Overlay.pm
==============================================================================
--- rt/branches/autrijus-3.1/lib/RT/CustomFields_Overlay.pm	(original)
+++ rt/branches/autrijus-3.1/lib/RT/CustomFields_Overlay.pm	Fri Mar  5 12:26:12 2004
@@ -181,31 +181,14 @@
 }
 # }}}
 
-sub LimitToParentId  {
+sub LimitToLookupType  {
     my $self = shift;
-    my $id = shift || 0;
- 
-    $self->Limit( FIELD => 'ParentId', VALUE => "$id" );
-}
-
-sub LimitToObjectType  {
-    my $self = shift;
-    my $o_type = shift;
- 
-    $self->Limit( FIELD => 'ObjectType', VALUE => "$o_type" );
-}
-
-sub LimitToComposite  {
-    my $self = shift;
-    my $composite = shift;
-    my ($o_type, $i_type, $p_type) = split(/-/, $composite, 3);
+    my $lookup = shift;
  
-    $self->Limit( FIELD => 'ObjectType', VALUE => "$o_type" );
-    $self->Limit( FIELD => 'IntermediateType', VALUE => "$i_type" );
-    $self->Limit( FIELD => 'ParentType', VALUE => "$p_type" );
+    $self->Limit( FIELD => 'LookupType', VALUE => "$lookup" );
 }
 
-sub LimitToGlobalOrParentId {
+sub LimitToGlobalOrObjectId {
     my $self = shift;
     my $id = shift || 0;
 
@@ -215,12 +198,12 @@
                 ALIAS2 => $object_cfs,
                 FIELD2 => 'CustomField' );
     $self->Limit( ALIAS           => $object_cfs,
-                 FIELD           => 'ParentId',
+                 FIELD           => 'ObjectId',
                  OPERATOR        => '=',
                  VALUE           => $id,
                  ENTRYAGGREGATOR => 'OR' );
     $self->Limit( ALIAS           => $object_cfs,
-                 FIELD           => 'ParentId',
+                 FIELD           => 'ObjectId',
                  OPERATOR        => '=',
                  VALUE           => 0,
                  ENTRYAGGREGATOR => 'OR' ) if $id;

Modified: rt/branches/autrijus-3.1/lib/RT/Interface/Web.pm
==============================================================================
--- rt/branches/autrijus-3.1/lib/RT/Interface/Web.pm	(original)
+++ rt/branches/autrijus-3.1/lib/RT/Interface/Web.pm	Fri Mar  5 12:26:12 2004
@@ -1096,6 +1096,141 @@
 
 # }}}
 
+sub ProcessObjectCustomFieldUpdates {
+    my %args = (
+        ARGSRef => undef,
+        @_
+    );
+
+    my @results;
+
+    my $ARGSRef = $args{'ARGSRef'};
+
+    # Build up a list of tickets that we want to work with
+    my %tickets_to_mod;
+    my %custom_fields_to_mod;
+    foreach my $arg ( keys %{$ARGSRef} ) {
+        if ( $arg =~ /^Object-([\w:]+)-(\d+)-CustomField-(\d+)-/ ) {
+
+            # For each of those tickets, find out what custom fields we want to work with.
+            $custom_fields_to_mod{$1}{$2}{$3} = 1;
+        }
+    }
+
+    # 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 =~ /^Object-$class-$id-CustomField-$cf-/ );
+		    my @values =
+		    ( ref( $ARGSRef->{$arg} ) eq 'ARRAY' ) 
+		    ? @{ $ARGSRef->{$arg} }
+		    : split /\n/, $ARGSRef->{$arg} ;
+		    if ( ( $arg =~ /-AddValue$/ ) || ( $arg =~ /-Value$/ ) ) {
+			foreach my $value (@values) {
+			    next unless length($value);
+			    my ( $val, $msg ) = $Object->AddCustomFieldValue(
+				Field => $cf,
+				Value => $value
+			    );
+			    push ( @results, $msg );
+			}
+		    }
+		    elsif ( $arg =~ /-DeleteValues$/ ) {
+			foreach my $value (@values) {
+			    next unless length($value);
+			    my ( $val, $msg ) = $Object->DeleteCustomFieldValue(
+				Field => $cf,
+				Value => $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;
+			foreach my $old_cf (@{$cf_values->ItemsArrayRef}) {
+			    if (!$delete_flag and @values and $old_cf->Content eq $values[0]) {
+				shift @values;
+				next;
+			    }
+
+			    $delete_flag ||= 1;
+			    $old_cf->Delete;
+			}
+
+			# now add/replace extra things, if any
+			foreach my $value (@values) {
+			    my ( $val, $msg ) = $Object->AddCustomFieldValue(
+				Field => $cf,
+				Value => $value
+			    );
+			    push ( @results, $msg );
+			}
+		    }
+		    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 ProcessTicketCustomFieldUpdates
 
 sub ProcessTicketCustomFieldUpdates {

Modified: rt/branches/autrijus-3.1/lib/RT/ObjectCustomField.pm
==============================================================================
--- rt/branches/autrijus-3.1/lib/RT/ObjectCustomField.pm	(original)
+++ rt/branches/autrijus-3.1/lib/RT/ObjectCustomField.pm	Fri Mar  5 12:26:12 2004
@@ -68,8 +68,7 @@
 Create takes a hash of values and creates a row in the database:
 
   int(11) 'CustomField'.
-  int(11) 'ParentId'.
-  int(11) 'SortOrder'.
+  int(11) 'ObjectId'.
   int(11) 'SortOrder'.
 
 =cut
@@ -81,15 +80,13 @@
     my $self = shift;
     my %args = ( 
                 CustomField => '0',
-                ParentId => '0',
-                SortOrder => '0',
+                ObjectId => '0',
                 SortOrder => '0',
 
 		  @_);
     $self->SUPER::Create(
                          CustomField => $args{'CustomField'},
-                         ParentId => $args{'ParentId'},
-                         SortOrder => $args{'SortOrder'},
+                         ObjectId => $args{'ObjectId'},
                          SortOrder => $args{'SortOrder'},
 );
 
@@ -138,19 +135,19 @@
 	return($CustomField);
 }
 
-=head2 ParentId
+=head2 ObjectId
 
-Returns the current value of ParentId. 
-(In the database, ParentId is stored as int(11).)
+Returns the current value of ObjectId. 
+(In the database, ObjectId is stored as int(11).)
 
 
 
-=head2 SetParentId VALUE
+=head2 SetObjectId VALUE
 
 
-Set ParentId to VALUE. 
+Set ObjectId to VALUE. 
 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
-(In the database, ParentId will be stored as a int(11).)
+(In the database, ObjectId will be stored as a int(11).)
 
 
 =cut
@@ -218,7 +215,7 @@
 		{read => 1, type => 'int(11)', default => ''},
         CustomField => 
 		{read => 1, write => 1, type => 'int(11)', default => '0'},
-        ParentId => 
+        ObjectId => 
 		{read => 1, write => 1, type => 'int(11)', default => '0'},
         SortOrder => 
 		{read => 1, write => 1, type => 'int(11)', default => '0'},

Modified: rt/branches/autrijus-3.1/lib/RT/ObjectCustomFieldValue_Overlay.pm
==============================================================================
--- rt/branches/autrijus-3.1/lib/RT/ObjectCustomFieldValue_Overlay.pm	(original)
+++ rt/branches/autrijus-3.1/lib/RT/ObjectCustomFieldValue_Overlay.pm	Fri Mar  5 12:26:12 2004
@@ -50,4 +50,22 @@
     
 }
 
+sub LoadByObjectContentAndCustomField {
+    my $self = shift;
+    my %args = ( Object => undef,
+                CustomField => undef,
+                Content => undef,
+                @_
+                );
+
+    my $obj = $args{'Object'} or return;
+
+    $self->LoadByCols( Content => $args{'Content'},
+                         CustomField => $args{'CustomField'},
+                         ObjectType => ref($obj),
+                         ObjectId => $obj->Id,);
+
+    
+}
+
 1;

Modified: rt/branches/autrijus-3.1/lib/RT/ObjectCustomFieldValues_Overlay.pm
==============================================================================
--- rt/branches/autrijus-3.1/lib/RT/ObjectCustomFieldValues_Overlay.pm	(original)
+++ rt/branches/autrijus-3.1/lib/RT/ObjectCustomFieldValues_Overlay.pm	Fri Mar  5 12:26:12 2004
@@ -66,6 +66,18 @@
 # }}}
 
 
+sub LimitToObject {
+    my $self = shift;
+    my $object = shift;
+    $self->Limit( FIELD => 'ObjectType',
+		  VALUE => ref($object),
+		  OPERATOR => '=');
+    return ($self->Limit( FIELD => 'ObjectId',
+			  VALUE => $object->Id,
+			  OPERATOR => '='));
+
+}
+
 =sub HasEntry VALUE
 
 Returns true if this CustomFieldValues collection has an entry with content that eq VALUE

Modified: rt/branches/autrijus-3.1/lib/RT/ObjectCustomFields_Overlay.pm
==============================================================================
--- rt/branches/autrijus-3.1/lib/RT/ObjectCustomFields_Overlay.pm	(original)
+++ rt/branches/autrijus-3.1/lib/RT/ObjectCustomFields_Overlay.pm	Fri Mar  5 12:26:12 2004
@@ -25,17 +25,30 @@
 use strict;
 no warnings qw(redefine);
 
-sub LimitToParentAndComposite {
+sub LimitToCustomField {
     my $self = shift;
-    my %args = @_;
-    my $composite = $args{Composite} or die "Must specify Composite";
-    my $ParentObj = $args{Parent};
-    my $ParentType = $args{ParentType} || ref($ParentObj) or die "Must specify ParentType";
-    my $ParentId = $args{ParentId} || ($ParentObj ? $ParentObj->Id || 0 : 0);
-    $self->Limit( FIELD => 'ParentId', VALUE => $ParentId );
+    my $id = shift;
+    $self->Limit( FIELD => 'CustomField', VALUE => $id );
+}
 
-    # $self->Limit( FIELD => 'ParentId', VALUE => '0' ) if $ParentId;
-    # XXX - Join CF here and limit its composites 
+sub LimitToObjectId {
+    my $self = shift;
+    my $id = shift;
+    $self->Limit( FIELD => 'ObjectId', VALUE => $id );
+}
+
+sub LimitToLookupType {
+    my $self = shift;
+    my $lookup = shift;
+    my $cfs = $self->NewAlias('CustomFields');
+    $self->Join( ALIAS1 => 'main',
+                FIELD1 => 'CustomField',
+                ALIAS2 => $cfs,
+                FIELD2 => 'id' );
+    $self->Limit( ALIAS           => $cfs,
+                 FIELD           => 'LookupType',
+                 OPERATOR        => '=',
+                 VALUE           => $lookup );
 }
 
 sub HasEntryForCustomField {

Modified: rt/branches/autrijus-3.1/lib/RT/Queue_Overlay.pm
==============================================================================
--- rt/branches/autrijus-3.1/lib/RT/Queue_Overlay.pm	(original)
+++ rt/branches/autrijus-3.1/lib/RT/Queue_Overlay.pm	Fri Mar  5 12:26:12 2004
@@ -421,7 +421,15 @@
 
 =cut
 
+# XXX XXX - this should become TicketCustomFields
+
 sub CustomFields {
+    my $self = shift;
+    warn "Queue->CustomFields is deprecated, use Queue->TicketCustomFields instead";
+    return $self->TicketCustomFields(@_);
+}
+
+sub TicketCustomFields {
     my $self = shift;
 
     my $cfs = RT::CustomFields->new( $self->CurrentUser );

Modified: rt/branches/autrijus-3.1/lib/RT/Record.pm
==============================================================================
--- rt/branches/autrijus-3.1/lib/RT/Record.pm	(original)
+++ rt/branches/autrijus-3.1/lib/RT/Record.pm	Fri Mar  5 12:26:12 2004
@@ -671,16 +671,307 @@
 
 # }}}
 
+# {{{ Routines dealing with custom fields
+
 sub CustomFields {
     my $self = shift;
     my $cfs = RT::CustomFields->new( $self->CurrentUser );
     $cfs->UnLimit;
-    $cfs->LimitToComposite(ref($self).'--');
-    $cfs->LimitToGlobalOrParentId($self->Id);
+
+    # XXX handle multiple types properly
+    foreach my $lookup ($self->_LookupTypes) {
+	$cfs->LimitToLookupType($lookup);
+	$cfs->LimitToGlobalOrObjectId($self->_LookupId($lookup));
+    }
     return $cfs;
 }
 
+sub _LookupId {
+    my $self = shift;
+    my $lookup = shift;
+    my @classes = ($lookup =~ /RT::(\w+)-/g);
+
+    foreach my $class (reverse @classes) {
+	my $method = "${class}Obj";
+	$self = $self->$method;
+    }
+
+    return $self->Id;
+}
+
+sub _LookupTypes { ref($_[0]) }
+
+# {{{ AddCustomFieldValue
+
+=item AddCustomFieldValue { Field => FIELD, Value => VALUE }
+
+VALUE should be a string.
+FIELD can be a CustomField object OR a CustomField ID.
+
+
+Adds VALUE as a value of CustomField FIELD.  If this is a single-value custom field,
+deletes the old value. 
+If VALUE isn't a valid value for the custom field, returns 
+(0, 'Error message' ) otherwise, returns (1, 'Success Message')
+
+=cut
+
+sub AddCustomFieldValue {
+    my $self = shift;
+#    unless ( $self->CurrentUserHasRight('ModifyTicket') ) {
+#        return ( 0, $self->loc("Permission Denied") );
+#    }
+    $self->_AddCustomFieldValue(@_);
+}
+
+sub _AddCustomFieldValue {
+    my $self = shift;
+    my %args = (
+        Field => undef,
+        Value => undef,
+	RecordTransaction => 1,
+        @_
+    );
+
+    my $cf = RT::CustomField->new( $self->CurrentUser );
+    if ( UNIVERSAL::isa( $args{'Field'}, "RT::CustomField" ) ) {
+        $cf->Load( $args{'Field'}->id );
+    }
+    else {
+        $cf->Load( $args{'Field'} );
+    }
+
+    unless ( $cf->Id ) {
+        return ( 0, $self->loc("Custom field [_1] not found", $args{'Field'}) );
+    }
+
+    # Load up a ObjectCustomFieldValues object for this custom field and this ticket
+    my $values = $cf->ValuesForObject( $self );
+
+    unless ( $cf->ValidateValue( $args{'Value'} ) ) {
+        return ( 0, $self->loc("Invalid value for custom field") );
+    }
+
+    # If the custom field only accepts a single value, delete the existing
+    # value and record a "changed from foo to bar" transaction
+    if ( $cf->SingleValue ) {
+
+        # We need to whack any old values here.  In most cases, the custom field should
+        # only have one value to delete.  In the pathalogical case, this custom field
+        # used to be a multiple and we have many values to whack....
+        my $cf_values = $values->Count;
+
+        if ( $cf_values > 1 ) {
+            my $i = 0;   #We want to delete all but the last one, so we can then
+                 # execute the same code to "change" the value from old to new
+            while ( my $value = $values->Next ) {
+                $i++;
+                if ( $i < $cf_values ) {
+                    my $old_value = $value->Content;
+                    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,
+                        OldValue => $old_value
+                      );
+                }
+            }
+        }
+
+        my $old_value;
+        if (my $value = $cf->ValuesForObject( $self )->First) {
+	    $old_value = $value->Content();
+	    return (1) if $old_value eq $args{'Value'};
+	}
+
+        my ( $new_value_id, $value_msg ) = $cf->AddValueForObject(
+            Object  => $self,
+            Content => $args{'Value'}
+        );
+
+        unless ($new_value_id) {
+            return ( 0,
+                $self->loc("Could not add new custom field value for ticket. [_1] ",
+                  ,$value_msg) );
+        }
+
+        my $new_value = RT::ObjectCustomFieldValue->new( $self->CurrentUser );
+        $new_value->Load($new_value_id);
+
+        # now that adding the new value was successful, delete the old one
+	if ($old_value) {
+	    my ($val, $msg) = $cf->DeleteValueForObject(Object => $self, Content => $old_value);
+	    unless ($val) { 
+	    		return (0,$msg);
+	    }
+	}
+
+	if ($args{'RecordTransaction'}) {
+        my ( $TransactionId, $Msg, $TransactionObj ) = $self->_NewTransaction(
+            Type     => 'CustomField',
+            Field    => $cf->Id,
+            OldValue => $old_value,
+            NewValue => $new_value->Content
+        );
+	}
+
+        if ( $old_value eq '' ) {
+            return ( 1, $self->loc("[_1] [_2] added", $cf->Name, $new_value->Content) );
+        }
+        elsif ( $new_value->Content eq '' ) {
+            return ( 1, $self->loc("[_1] [_2] deleted", $cf->Name, $old_value) );
+        }
+        else {
+            return ( 1, $self->loc("[_1] [_2] changed to [_3]", $cf->Name, $old_value, $new_value->Content ) );
+        }
+
+    }
+
+    # otherwise, just add a new value and record "new value added"
+    else {
+        my ( $new_value_id ) = $cf->AddValueForObject(
+            Object  => $self,
+            Content => $args{'Value'}
+        );
+
+        unless ($new_value_id) {
+            return ( 0,
+                $self->loc("Could not add new custom field value for ticket. "));
+        }
+    if ( $args{'RecordTransaction'} ) {
+        my ( $TransactionId, $Msg, $TransactionObj ) = $self->_NewTransaction(
+            Type     => 'CustomField',
+            Field    => $cf->Id,
+            NewValue => $args{'Value'}
+        );
+        unless ($TransactionId) {
+            return ( 0,
+                $self->loc( "Couldn't create a transaction: [_1]", $Msg ) );
+        }
+    }
+        return ( 1, $self->loc("[_1] added as a value for [_2]",$args{'Value'}, $cf->Name));
+    }
+
+}
+
+# }}}
+
+# {{{ DeleteCustomFieldValue
+
+=item DeleteCustomFieldValue { Field => FIELD, Value => VALUE }
+
+Deletes VALUE as a value of CustomField FIELD. 
+
+VALUE can be a string, a CustomFieldValue or a ObjectCustomFieldValue.
+
+If VALUE isn't a valid value for the custom field, returns 
+(0, 'Error message' ) otherwise, returns (1, 'Success Message')
+
+=cut
+
+sub DeleteCustomFieldValue {
+    my $self = shift;
+    my %args = (
+        Field => undef,
+        Value => undef,
+        @_);
+
+#    XXX - normalise CF related ACLs... ask obra!
+#    unless ( $self->CurrentUserHasRight('ModifyTicket') ) {
+#        return ( 0, $self->loc("Permission Denied") );
+#    }
+    my $cf = RT::CustomField->new( $self->CurrentUser );
+    if ( UNIVERSAL::isa( $args{'Field'}, "RT::CustomField" ) ) {
+        $cf->LoadById( $args{'Field'}->id );
+    }
+    else {
+        $cf->LoadById( $args{'Field'} );
+    }
+
+    unless ( $cf->Id ) {
+        return ( 0, $self->loc("Custom field not found") );
+    }
+
+
+     my ($val, $msg) = $cf->DeleteValueForObject(Object => $self, Content => $args{'Value'});
+     unless ($val) { 
+            return (0,$msg);
+     }
+        my ( $TransactionId, $Msg, $TransactionObj ) = $self->_NewTransaction(
+            Type     => 'CustomField',
+            Field    => $cf->Id,
+            OldValue => $args{'Value'}
+        );
+        unless($TransactionId) {
+            return(0, $self->loc("Couldn't create a transaction: [_1]", $Msg));
+        } 
+
+        return($TransactionId, $self->loc("[_1] is no longer a value for custom field [_2]", $args{'Value'}, $cf->Name));
+}
+
+# }}}
+
+# {{{ FirstCustomFieldValue
+
+=item FirstCustomFieldValue FIELD
+
+Return the content of the first value of CustomField FIELD for this ticket
+Takes a field id or name
+
+=cut
+
+sub FirstCustomFieldValue {
+    my $self = shift;
+    my $field = shift;
+    my $values = $self->CustomFieldValues($field);
+    if ($values->First) {
+        return $values->First->Content;
+    } else {
+        return undef;
+    }
+
+}
+
+
+
+# {{{ CustomFieldValues
+
+=item CustomFieldValues FIELD
+
+Return a ObjectCustomFieldValues object of all values of CustomField FIELD for this ticket.  
+Takes a field id or name.
+
+
+=cut
+
+sub CustomFieldValues {
+    my $self  = shift;
+    my $field = shift;
+
+    my $cf = RT::CustomField->new($self->CurrentUser);
+
+    if ($field =~ /^\d+$/) {
+        $cf->LoadById($field);
+    } else {
+	# $cf->LoadByNameAndQueue(Name => $field, Queue => $self->QueueObj->Id);
+	die "LoadByNameAndQueue not yet ported to Object";
+    }
+    my $cf_values = RT::ObjectCustomFieldValues->new( $self->CurrentUser );
+    $cf_values->LimitToCustomField($cf->id);
+    $cf_values->LimitToObject($self);
+    $cf_values->OrderBy( FIELD => 'id' );
+
+    # @values is a CustomFieldValues object;
+    return ($cf_values);
+}
+
+# }}}
 
+# }}}
 
 
 eval "require RT::Record_Vendor";

Modified: rt/branches/autrijus-3.1/lib/RT/Ticket_Overlay.pm
==============================================================================
--- rt/branches/autrijus-3.1/lib/RT/Ticket_Overlay.pm	(original)
+++ rt/branches/autrijus-3.1/lib/RT/Ticket_Overlay.pm	Fri Mar  5 12:26:12 2004
@@ -3522,279 +3522,6 @@
 
 # }}}
 
-# {{{ Routines dealing with custom fields
-
-
-# {{{ FirstCustomFieldValue
-
-=item FirstCustomFieldValue FIELD
-
-Return the content of the first value of CustomField FIELD for this ticket
-Takes a field id or name
-
-=cut
-
-sub FirstCustomFieldValue {
-    my $self = shift;
-    my $field = shift;
-    my $values = $self->CustomFieldValues($field);
-    if ($values->First) {
-        return $values->First->Content;
-    } else {
-        return undef;
-    }
-
-}
-
-
-
-# {{{ CustomFieldValues
-
-=item CustomFieldValues FIELD
-
-Return a ObjectCustomFieldValues object of all values of CustomField FIELD for this ticket.  
-Takes a field id or name.
-
-
-=cut
-
-sub CustomFieldValues {
-    my $self  = shift;
-    my $field = shift;
-
-    my $cf = RT::CustomField->new($self->CurrentUser);
-
-    if ($field =~ /^\d+$/) {
-        $cf->LoadById($field);
-    } else {
-        $cf->LoadByNameAndQueue(Name => $field, Queue => $self->QueueObj->Id);
-    }
-    my $cf_values = RT::ObjectCustomFieldValues->new( $self->CurrentUser );
-    $cf_values->LimitToCustomField($cf->id);
-    $cf_values->LimitToTicket($self->Id());
-    $cf_values->OrderBy( FIELD => 'id' );
-
-    # @values is a CustomFieldValues object;
-    return ($cf_values);
-}
-
-# }}}
-
-# {{{ AddCustomFieldValue
-
-=item AddCustomFieldValue { Field => FIELD, Value => VALUE }
-
-VALUE should be a string.
-FIELD can be a CustomField object OR a CustomField ID.
-
-
-Adds VALUE as a value of CustomField FIELD.  If this is a single-value custom field,
-deletes the old value. 
-If VALUE isn't a valid value for the custom field, returns 
-(0, 'Error message' ) otherwise, returns (1, 'Success Message')
-
-=cut
-
-sub AddCustomFieldValue {
-    my $self = shift;
-    unless ( $self->CurrentUserHasRight('ModifyTicket') ) {
-        return ( 0, $self->loc("Permission Denied") );
-    }
-    $self->_AddCustomFieldValue(@_);
-}
-
-sub _AddCustomFieldValue {
-    my $self = shift;
-    my %args = (
-        Field => undef,
-        Value => undef,
-	RecordTransaction => 1,
-        @_
-    );
-
-    my $cf = RT::CustomField->new( $self->CurrentUser );
-    if ( UNIVERSAL::isa( $args{'Field'}, "RT::CustomField" ) ) {
-        $cf->Load( $args{'Field'}->id );
-    }
-    else {
-        $cf->Load( $args{'Field'} );
-    }
-
-    unless ( $cf->Id ) {
-        return ( 0, $self->loc("Custom field [_1] not found", $args{'Field'}) );
-    }
-
-    # Load up a ObjectCustomFieldValues object for this custom field and this ticket
-    my $values = $cf->ValuesForTicket( $self->id );
-
-    unless ( $cf->ValidateValue( $args{'Value'} ) ) {
-        return ( 0, $self->loc("Invalid value for custom field") );
-    }
-
-    # If the custom field only accepts a single value, delete the existing
-    # value and record a "changed from foo to bar" transaction
-    if ( $cf->SingleValue ) {
-
-        # We need to whack any old values here.  In most cases, the custom field should
-        # only have one value to delete.  In the pathalogical case, this custom field
-        # used to be a multiple and we have many values to whack....
-        my $cf_values = $values->Count;
-
-        if ( $cf_values > 1 ) {
-            my $i = 0;   #We want to delete all but the last one, so we can then
-                 # execute the same code to "change" the value from old to new
-            while ( my $value = $values->Next ) {
-                $i++;
-                if ( $i < $cf_values ) {
-                    my $old_value = $value->Content;
-                    my ($val, $msg) = $cf->DeleteValueForTicket(Ticket => $self->Id, Content => $value->Content);
-                    unless ($val) {
-                        return (0,$msg);
-                    }
-                    my ( $TransactionId, $Msg, $TransactionObj ) =
-                      $self->_NewTransaction(
-                        Type     => 'CustomField',
-                        Field    => $cf->Id,
-                        OldValue => $old_value
-                      );
-                }
-            }
-        }
-
-        my $old_value;
-        if (my $value = $cf->ValuesForTicket( $self->Id )->First) {
-	    $old_value = $value->Content();
-	    return (1) if $old_value eq $args{'Value'};
-	}
-
-        my ( $new_value_id, $value_msg ) = $cf->AddValueForTicket(
-            Ticket  => $self->Id,
-            Content => $args{'Value'}
-        );
-
-        unless ($new_value_id) {
-            return ( 0,
-                $self->loc("Could not add new custom field value for ticket. [_1] ",
-                  ,$value_msg) );
-        }
-
-        my $new_value = RT::ObjectCustomFieldValue->new( $self->CurrentUser );
-        $new_value->Load($new_value_id);
-
-        # now that adding the new value was successful, delete the old one
-	if ($old_value) {
-	    my ($val, $msg) = $cf->DeleteValueForTicket(Ticket => $self->Id, Content => $old_value);
-	    unless ($val) { 
-	    		return (0,$msg);
-	    }
-	}
-
-	if ($args{'RecordTransaction'}) {
-        my ( $TransactionId, $Msg, $TransactionObj ) = $self->_NewTransaction(
-            Type     => 'CustomField',
-            Field    => $cf->Id,
-            OldValue => $old_value,
-            NewValue => $new_value->Content
-        );
-	}
-
-        if ( $old_value eq '' ) {
-            return ( 1, $self->loc("[_1] [_2] added", $cf->Name, $new_value->Content) );
-        }
-        elsif ( $new_value->Content eq '' ) {
-            return ( 1, $self->loc("[_1] [_2] deleted", $cf->Name, $old_value) );
-        }
-        else {
-            return ( 1, $self->loc("[_1] [_2] changed to [_3]", $cf->Name, $old_value, $new_value->Content ) );
-        }
-
-    }
-
-    # otherwise, just add a new value and record "new value added"
-    else {
-        my ( $new_value_id ) = $cf->AddValueForTicket(
-            Ticket  => $self->Id,
-            Content => $args{'Value'}
-        );
-
-        unless ($new_value_id) {
-            return ( 0,
-                $self->loc("Could not add new custom field value for ticket. "));
-        }
-    if ( $args{'RecordTransaction'} ) {
-        my ( $TransactionId, $Msg, $TransactionObj ) = $self->_NewTransaction(
-            Type     => 'CustomField',
-            Field    => $cf->Id,
-            NewValue => $args{'Value'}
-        );
-        unless ($TransactionId) {
-            return ( 0,
-                $self->loc( "Couldn't create a transaction: [_1]", $Msg ) );
-        }
-    }
-        return ( 1, $self->loc("[_1] added as a value for [_2]",$args{'Value'}, $cf->Name));
-    }
-
-}
-
-# }}}
-
-# {{{ DeleteCustomFieldValue
-
-=item DeleteCustomFieldValue { Field => FIELD, Value => VALUE }
-
-Deletes VALUE as a value of CustomField FIELD. 
-
-VALUE can be a string, a CustomFieldValue or a ObjectCustomFieldValue.
-
-If VALUE isn't a valid value for the custom field, returns 
-(0, 'Error message' ) otherwise, returns (1, 'Success Message')
-
-=cut
-
-sub DeleteCustomFieldValue {
-    my $self = shift;
-    my %args = (
-        Field => undef,
-        Value => undef,
-        @_);
-
-    unless ( $self->CurrentUserHasRight('ModifyTicket') ) {
-        return ( 0, $self->loc("Permission Denied") );
-    }
-    my $cf = RT::CustomField->new( $self->CurrentUser );
-    if ( UNIVERSAL::isa( $args{'Field'}, "RT::CustomField" ) ) {
-        $cf->LoadById( $args{'Field'}->id );
-    }
-    else {
-        $cf->LoadById( $args{'Field'} );
-    }
-
-    unless ( $cf->Id ) {
-        return ( 0, $self->loc("Custom field not found") );
-    }
-
-
-     my ($val, $msg) = $cf->DeleteValueForTicket(Ticket => $self->Id, Content => $args{'Value'});
-     unless ($val) { 
-            return (0,$msg);
-     }
-        my ( $TransactionId, $Msg, $TransactionObj ) = $self->_NewTransaction(
-            Type     => 'CustomField',
-            Field    => $cf->Id,
-            OldValue => $args{'Value'}
-        );
-        unless($TransactionId) {
-            return(0, $self->loc("Couldn't create a transaction: [_1]", $Msg));
-        } 
-
-        return($TransactionId, $self->loc("[_1] is no longer a value for custom field [_2]", $args{'Value'}, $cf->Name));
-}
-
-# }}}
-
-# }}}
-
 # {{{ Actions + Routines dealing with transactions
 
 # {{{ sub SetTold and _SetTold
@@ -4150,6 +3877,10 @@
 }
 
 # }}}
+
+sub _CustomFieldComposites {
+    "RT::Queue-RT::Ticket";
+}
 
 1;
 

Modified: rt/branches/autrijus-3.1/lib/RT/User_Overlay.pm
==============================================================================
--- rt/branches/autrijus-3.1/lib/RT/User_Overlay.pm	(original)
+++ rt/branches/autrijus-3.1/lib/RT/User_Overlay.pm	Fri Mar  5 12:26:12 2004
@@ -1550,10 +1550,6 @@
 
 # }}}
 
-sub CustomFieldValues {
-    # XXX
-}
-
 1;
 
 

Modified: rt/branches/autrijus-3.1/spec/schema.txt
==============================================================================
--- rt/branches/autrijus-3.1/spec/schema.txt	(original)
+++ rt/branches/autrijus-3.1/spec/schema.txt	Fri Mar  5 12:26:12 2004
@@ -7,9 +7,7 @@
   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
-  ObjectType varchar(255) NOT NULL,		    # Final target of the Object
-  IntermediateType varchar(255) NOT NULL,	    # Intermediate type
-  ParentType varchar(255) NOT NULL,		    # Toplevel type
+  LookupType varchar(255) NOT NULL,	# Lookup paths like "RT::Queue-RT::Ticket"
   Description varchar(255) NULL  ,
   SortOrder integer NOT NULL DEFAULT 0  ,   # not used!
 )
@@ -17,7 +15,7 @@
 TABLE ObjectCustomFields (
   id INTEGER NOT NULL  AUTO_INCREMENT,
   CustomField int NOT NULL  ,		    # CustomField ID
-  ParentId integer NOT NULL,		    # Final id of toplevel parent, or the
+  ObjectId integer NOT NULL,		    # Final id of toplevel parent, or the
 					    # object itself if ParentType is empty;
 					    # 0 means global as usual.
   SortOrder integer NOT NULL DEFAULT 0  ,

Modified: rt/branches/autrijus-3.1/spec/spec.txt
==============================================================================
--- rt/branches/autrijus-3.1/spec/spec.txt	(original)
+++ rt/branches/autrijus-3.1/spec/spec.txt	Fri Mar  5 12:26:12 2004
@@ -1,15 +1,15 @@
 User/Group CF and Txn UI first.
 ===============================
-Object<=>CF Edit interface; separate CFs into different kinds:
-    Currently only All-User, All-Group, All-Queue and some-Queue
-    To be created and picked on the "User->CF" and "Group->CF" tabs
-    use code from rtfm's ClassCustomFields as a base of ObjectCustomFields
 CF display for User and Group
-Binary CFs.
+User/Group search in Configuration->User/Group
+Binary/image/textarea CFs.
 Finish Txn display for User and Group
-ACL for per-CF editing
+ACL for per-CF editing (UI done, need verify API)
     AdminThis ACL for CFs controls CF data and metadata, but _not_ where it applies
     AdminCF ACL for Objects controls what CFs applies here, but _not_ CF's contents
+Display Group memberships for Users
+Requestor memberships display for Ticket Requestor
+Requestor-is-of-group ticket search
 
 
 



More information about the Rt-commit mailing list