rt 4.2.15
[freeside.git] / rt / share / html / Elements / ColumnMap
index 5e5354a..4e9d35e 100644 (file)
@@ -2,7 +2,7 @@
 %#
 %# COPYRIGHT:
 %#
-%# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC
+%# This software is Copyright (c) 1996-2018 Best Practical Solutions, LLC
 %#                                          <sales@bestpractical.com>
 %#
 %# (Except where explicitly superseded by other copyright notices)
@@ -52,11 +52,13 @@ $Attr  => undef
 </%ARGS>
 <%ONCE>
 
-# This is scary and should totally be refactored -- jesse
-my $COLUMN_MAP = {
+use Scalar::Util;
+
+my ($COLUMN_MAP, $WCOLUMN_MAP);
+$WCOLUMN_MAP = $COLUMN_MAP = {
     id => {
         attribute => 'id',
-        title    => 'id', # loc
+        title     => '#', # loc
         align     => 'right',
         value     => sub { return $_[0]->id }
     },
@@ -64,8 +66,7 @@ my $COLUMN_MAP = {
     Created => {
         attribute => 'Created',
         title     => 'Created', # loc
-        date      => sub { return $_[0]->CreatedObj },
-        value     => sub { return $_[0]->CreatedObj->AsString }
+        value     => sub { return $_[0]->CreatedObj },
     },
     CreatedRelative => {
         attribute => 'Created',
@@ -73,15 +74,14 @@ my $COLUMN_MAP = {
         value     => sub { return $_[0]->CreatedObj->AgeAsString }
     },
     CreatedBy => {
-        attribute => 'CreatedBy',
+        attribute => 'Creator',
         title     => 'Created By', # loc
         value     => sub { return $_[0]->CreatorObj->Name }
     },
     LastUpdated => {
         attribute => 'LastUpdated',
         title     => 'Last Updated', # loc
-        date      => sub { return $_[0]->LastUpdatedObj },
-        value     => sub { return $_[0]->LastUpdatedObj->AsString }
+        value     => sub { return $_[0]->LastUpdatedObj },
     },
     LastUpdatedRelative => {
         attribute => 'LastUpdated',
@@ -98,19 +98,47 @@ my $COLUMN_MAP = {
         attribute => sub { return shift @_ },
         title     => sub { return pop @_ },
         value     => sub {
-            # Display custom field contents, separated by newlines.
-            # For Image custom fields we also show a thumbnail here.
+            my $self = $WCOLUMN_MAP->{CustomField};
+            my $cf   = $self->{load}->(@_);
+            return unless $cf->Id;
+            return $self->{render}->( $cf, $cf->ValuesForObject($_[0])->ItemsArrayRef );
+        },
+        load      => sub {
+            # Cache the CF object on a per-request basis, to avoid
+            # having to load it for every row
+            my $key = join("-","CF",
+                           $_[0]->CustomFieldLookupType,
+                           $_[0]->CustomFieldLookupId,
+                           $_[-1]);
+
+            my $cf = $m->notes($key);
+            unless ($cf) {
+                $cf = $_[0]->LoadCustomFieldByIdentifier($_[-1]);
+                RT->Logger->debug("Unable to load $_[-1] for ".$_[0]->CustomFieldLookupType." ".$_[0]->CustomFieldLookupId)
+                    unless $cf->Id;
+                $m->notes($key, $cf);
+            }
+
+            return $cf;
+          },
+          render    => sub {
+            my ($cf, $ocfvs) = @_;
+            my $comp = $m->comp_exists("/Elements/ShowCustomField".$cf->Type)
+                     ? "/Elements/ShowCustomField".$cf->Type
+                     : undef;
 
-            my $values = $_[0]->CustomFieldValues( $_[-1] );
             my @values = map {
-                (
-                    ($_->CustomFieldObj->Type eq 'Image')
-                        ? \($m->scomp( '/Elements/ShowCustomFieldImage', Object => $_ ))
-                        : $_->Content
-                ),
-                \'<br />',
-            } @{ $values->ItemsArrayRef };
-            pop @values; # Remove that last <br />
+                $comp
+                    ? \($m->scomp( $comp, Object => $_ ))
+                    : $_->Content
+            } @$ocfvs;
+
+            if (@values > 1) {
+                for my $value (splice @values) {
+                    push @values, \"<li>", $value, \"</li> \n";
+                }
+                @values = (\"<ul class='cf-values'>", @values, \"</ul>");
+            }
             return @values;
         },
     },
@@ -118,27 +146,29 @@ my $COLUMN_MAP = {
     CheckBox => {
         title => sub {
             my $name = $_[1] || 'SelectedTickets';
-            my $checked = $m->request_args->{ $name .'All' }? 'checked="checked"': '';
+            my $checked = $DECODED_ARGS->{ $name .'All' }? 'checked="checked"': '';
 
-            return \qq{<input type="checkbox" name="${name}All" value="1" $checked
-                              onclick="setCheckbox(this.form, '$name', this.checked)" />};
+            return \qq{<input type="checkbox" name="}, $name, \qq{All" value="1" $checked
+                              onclick="setCheckbox(this, },
+                              $m->interp->apply_escapes($name,'j'),
+                              \qq{)" />};
         },
         value => sub {
             my $id = $_[0]->id;
 
             my $name = $_[2] || 'SelectedTickets';
-            return \qq{<input type="checkbox" name="$name" value="$id" checked="checked" />}
-                if $m->request_args->{ $name . 'All'};
+            return \qq{<input type="checkbox" name="}, $name, \qq{" value="$id" checked="checked" />}
+                if $DECODED_ARGS->{ $name . 'All'};
 
-            my $arg = $m->request_args->{ $name };
+            my $arg = $DECODED_ARGS->{ $name };
             my $checked = '';
             if ( $arg && ref $arg ) {
-                $checked = 'checked="checked"' if grep $_ == $id, @$arg;
+                $checked = 'checked="checked"' if grep $_ == $id, grep { defined and length } @$arg;
             }
             elsif ( $arg ) {
                 $checked = 'checked="checked"' if $arg == $id;
             }
-            return \qq{<input type="checkbox" name="$name" value="$id" $checked />}
+            return \qq{<input type="checkbox" name="}, $name, \qq{" value="$id" $checked />}
         },
     },
     RadioButton => {
@@ -147,10 +177,10 @@ my $COLUMN_MAP = {
             my $id = $_[0]->id;
 
             my $name = $_[2] || 'SelectedTicket';
-            my $arg = $m->request_args->{ $name };
+            my $arg = $DECODED_ARGS->{ $name };
             my $checked = '';
             $checked = 'checked="checked"' if $arg && $arg == $id;
-            return \qq{<input type="radio" name="SelectedTicket" value="$id" $checked />};
+            return \qq{<input type="radio" name="}, $name, \qq{" value="$id" $checked />};
         },
     },
     (map {
@@ -160,18 +190,60 @@ my $COLUMN_MAP = {
     } qw(WebPath WebBaseURL WebURL)),
     WebRequestPath    => { value => sub { substr( $m->request_path, 1 ) } },
     WebRequestPathDir => { value => sub { substr( $m->request_comp->dir_path, 1 ) } },
+    WebHomePath       => {
+        value => sub {
+            my $path = RT->Config->Get("WebPath");
+            if (not $session{CurrentUser}->Privileged) {
+                $path .= "/SelfService";
+            }
+            return \$path;
+        },
+    },
+    CurrentUser       => { value => sub { $session{CurrentUser}->id } },
+    CurrentUserName   => { value => sub { $session{CurrentUser}->Name } },
 };
 
 $COLUMN_MAP->{'CF'} = $COLUMN_MAP->{'CustomField'};
 
+Scalar::Util::weaken($WCOLUMN_MAP);
+
+my $ROLE_MAP = {};
+
 </%ONCE>
 <%INIT>
 $m->callback( COLUMN_MAP => $COLUMN_MAP, CallbackName => 'Once', CallbackOnce => 1 );
-$m->callback( COLUMN_MAP => $COLUMN_MAP );
+
+my $generic_with_roles;
+
+# Add in roles
+my $RecordClass = $Class;
+$RecordClass =~ s/_/:/g;
+if ($RecordClass->DOES("RT::Record::Role::Roles")) {
+    unless ($ROLE_MAP->{$RecordClass}) {
+        for my $role ($RecordClass->Roles) {
+            my $attrs = $RecordClass->Role($role);
+            $ROLE_MAP->{$RecordClass}{$role} = {
+                title => $role,
+                attribute => $attrs->{Column} || "$role.EmailAddress",
+                value => sub { return \($m->scomp("/Elements/ShowPrincipal", Object => $_[0]->RoleGroup($role) ) ) },
+            };
+            $ROLE_MAP->{$RecordClass}{$role . "s"} = $ROLE_MAP->{$RecordClass}{$role}
+                unless $attrs->{Single};
+        }
+    }
+    $generic_with_roles = { %{$COLUMN_MAP}, %{$ROLE_MAP->{$RecordClass}} };
+} else {
+    $generic_with_roles = { %{$COLUMN_MAP} };
+}
+
+$m->callback( COLUMN_MAP => $generic_with_roles );
 
 # first deal with class specific things
-my $class_map = $m->comp("/Elements/$Class/ColumnMap", Attr => $Attr, Name => $Name );
-return $class_map if defined $class_map;
-return GetColumnMapEntry( Map => $COLUMN_MAP, Name => $Name, Attribute => $Attr );
+if (RT::Interface::Web->ComponentPathIsSafe($Class) and $m->comp_exists("/Elements/$Class/ColumnMap")) {
+    my $class_map = $m->comp("/Elements/$Class/ColumnMap", Attr => $Attr, Name => $Name, GenericMap => $generic_with_roles );
+    return $class_map if defined $class_map;
+}
+
+return GetColumnMapEntry( Map => $generic_with_roles, Name => $Name, Attribute => $Attr );
 
 </%INIT>