1 # BEGIN BPS TAGGED BLOCK {{{
5 # This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
6 # <jesse@bestpractical.com>
8 # (Except where explicitly superseded by other copyright notices)
13 # This work is made available to you under the terms of Version 2 of
14 # the GNU General Public License. A copy of that license should have
15 # been provided with this software, but in any event can be snarfed
18 # This work is distributed in the hope that it will be useful, but
19 # WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 # General Public License for more details.
23 # You should have received a copy of the GNU General Public License
24 # along with this program; if not, write to the Free Software
25 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 # CONTRIBUTION SUBMISSION POLICY:
30 # (The following paragraph is not intended to limit the rights granted
31 # to you to modify and distribute this software under the terms of
32 # the GNU General Public License and is only of importance to you if
33 # you choose to contribute your changes and enhancements to the
34 # community by submitting them to Best Practical Solutions, LLC.)
36 # By intentionally submitting any modifications, corrections or
37 # derivatives to this work, or any other work intended for use with
38 # Request Tracker, to Best Practical Solutions, LLC, you confirm that
39 # you are the copyright holder for those contributions and you grant
40 # Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
41 # royalty-free, perpetual, license to use, copy, create derivative
42 # works based on those contributions, and sublicense and distribute
43 # those contributions and any derivatives thereof.
45 # END BPS TAGGED BLOCK }}}
49 RT::SavedSearch - an API for saving and retrieving search form values.
57 SavedSearch is an object that can belong to either an RT::User or an
58 RT::Group. It consists of an ID, a description, and a number of
65 use_ok(RT::SavedSearch);
67 # Real tests are in lib/t/20savedsearch.t
73 package RT::SavedSearch;
84 my $class = ref($proto) || $proto;
87 bless ($self, $class);
88 $self->CurrentUser(@_);
94 Takes a privacy specification, an object ID, and a search ID. Loads
95 the given search ID if it belongs to the stated user or group.
96 Returns a tuple of status and message, where status is true on
103 my ($privacy, $id) = @_;
104 my $object = $self->_GetObject($privacy);
107 $self->{'Attribute'} = $object->Attributes->WithId($id);
108 if ($self->{'Attribute'}->Id) {
109 $self->{'Id'} = $self->{'Attribute'}->Id;
110 $self->{'Privacy'} = $privacy;
111 $self->{'Type'} = $self->{'Attribute'}->SubValue('SearchType');
112 return (1, $self->loc("Loaded search [_1]", $self->Name));
114 $RT::Logger->error("Could not load attribute " . $id
115 . " for object " . $privacy);
116 return (0, $self->loc("Search attribute load failure"));
119 $RT::Logger->error("Could not load object $privacy when loading search");
120 return (0, $self->loc("Could not load object for [_1]", $privacy));
127 Takes a privacy, an optional type, a name, and a hashref containing the
128 search parameters. Saves the given parameters to the appropriate user/
129 group object, and loads the resulting search. Returns a tuple of status
130 and message, where status is true on success. Defaults are:
134 SearchParams: (empty hash)
140 my %args = ('Privacy' => 'RT::User-' . $self->CurrentUser->Id,
142 'Name' => 'new search',
143 'SearchParams' => {},
145 my $privacy = $args{'Privacy'};
146 my $type = $args{'Type'};
147 my $name = $args{'Name'};
148 my %params = %{$args{'SearchParams'}};
150 $params{'SearchType'} = $type;
151 my $object = $self->_GetObject($privacy);
153 my ($att_id, $att_msg) = $object->AddAttribute(
154 'Name' => 'SavedSearch',
155 'Description' => $name,
156 'Content' => \%params);
158 $self->{'Attribute'} = $object->Attributes->WithId($att_id);
159 $self->{'Id'} = $att_id;
160 $self->{'Privacy'} = $privacy;
161 $self->{'Type'} = $type;
162 return (1, $self->loc("Saved search [_1]", $name));
164 $RT::Logger->error("SavedSearch save failure: $att_msg");
165 return (0, $self->loc("Failed to create search attribute"));
168 return (0, $self->loc("Failed to load object for [_1]", $privacy));
174 Updates the parameters of an existing search. Takes the arguments
175 "Name" and "SearchParams"; SearchParams should be a hashref containing
176 the new parameters of the search. If Name is not specified, the name
183 my %args = ('Name' => '',
184 'SearchParams' => {},
187 return(0, $self->loc("No search loaded")) unless $self->Id;
188 return(0, $self->loc("Could not load search attribute"))
189 unless $self->{'Attribute'}->Id;
190 my ($status, $msg) = $self->{'Attribute'}->SetSubValues(%{$args{'SearchParams'}});
191 if ($status && $args{'Name'}) {
192 ($status, $msg) = $self->{'Attribute'}->SetDescription($args{'Name'});
194 return ($status, $self->loc("Search update: [_1]", $msg));
199 Deletes the existing search. Returns a tuple of status and message,
200 where status is true upon success.
207 my ($status, $msg) = $self->{'Attribute'}->Delete;
209 return (1, $self->loc("Deleted search"));
211 return (0, $self->loc("Delete failed: [_1]", $msg));
220 Returns the name of the search.
226 return unless ref($self->{'Attribute'}) eq 'RT::Attribute';
227 return $self->{'Attribute'}->Description();
232 Returns the given named parameter of the search, e.g. 'Query', 'Format'.
239 return unless ref($self->{'Attribute'}) eq 'RT::Attribute';
240 return $self->{'Attribute'}->SubValue($param);
245 Returns the numerical id of this search.
251 return $self->{'Id'};
256 Returns the principal object to whom this search belongs, in a string
257 "<class>-<id>", e.g. "RT::Group-16".
263 return $self->{'Privacy'};
268 Returns the type of this search, e.g. 'Ticket'. Useful for denoting the
269 saved searches that are relevant to a particular search page.
275 return $self->{'Type'};
280 # _GetObject: helper routine to load the correct object whose parameters
287 my ($obj_type, $obj_id) = split(/\-/, $privacy);
288 unless ($obj_type eq 'RT::User' || $obj_type eq 'RT::Group') {
289 $RT::Logger->error("Tried to load a search belonging to an $obj_type, which is neither a user nor a group");
296 \$object = $obj_type->new(\$self->CurrentUser);
297 \$object->Load(\$obj_id);
299 unless (ref($object) eq $obj_type) {
300 $RT::Logger->error("Could not load object of type $obj_type with ID $obj_id");
304 # Do not allow the loading of a user object other than the current
305 # user, or of a group object of which the current user is not a member.
307 if ($obj_type eq 'RT::User'
308 && $object->Id != $self->CurrentUser->UserObj->Id()) {
309 $RT::Logger->debug("Permission denied for user other than self");
312 if ($obj_type eq 'RT::Group' &&
313 !$object->HasMemberRecursively($self->CurrentUser->PrincipalObj)) {
314 $RT::Logger->debug("Permission denied, ".$self->CurrentUser->Name.
315 " is not a member of group");
322 eval "require RT::SavedSearch_Vendor";
323 die $@ if ($@ && $@ !~ qr{^Can't locate RT/SavedSearch_Vendor.pm});
324 eval "require RT::SavedSearch_Local";
325 die $@ if ($@ && $@ !~ qr{^Can't locate RT/SavedSearch_Local.pm});