]>
Commit | Line | Data |
---|---|---|
84fb5b46 MKG |
1 | %# BEGIN BPS TAGGED BLOCK {{{ |
2 | %# | |
3 | %# COPYRIGHT: | |
4 | %# | |
403d7b0b | 5 | %# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC |
84fb5b46 MKG |
6 | %# <sales@bestpractical.com> |
7 | %# | |
8 | %# (Except where explicitly superseded by other copyright notices) | |
9 | %# | |
10 | %# | |
11 | %# LICENSE: | |
12 | %# | |
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 | |
16 | %# from www.gnu.org. | |
17 | %# | |
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. | |
22 | %# | |
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., 51 Franklin Street, Fifth Floor, Boston, MA | |
26 | %# 02110-1301 or visit their web page on the internet at | |
27 | %# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. | |
28 | %# | |
29 | %# | |
30 | %# CONTRIBUTION SUBMISSION POLICY: | |
31 | %# | |
32 | %# (The following paragraph is not intended to limit the rights granted | |
33 | %# to you to modify and distribute this software under the terms of | |
34 | %# the GNU General Public License and is only of importance to you if | |
35 | %# you choose to contribute your changes and enhancements to the | |
36 | %# community by submitting them to Best Practical Solutions, LLC.) | |
37 | %# | |
38 | %# By intentionally submitting any modifications, corrections or | |
39 | %# derivatives to this work, or any other work intended for use with | |
40 | %# Request Tracker, to Best Practical Solutions, LLC, you confirm that | |
41 | %# you are the copyright holder for those contributions and you grant | |
42 | %# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, | |
43 | %# royalty-free, perpetual, license to use, copy, create derivative | |
44 | %# works based on those contributions, and sublicense and distribute | |
45 | %# those contributions and any derivatives thereof. | |
46 | %# | |
47 | %# END BPS TAGGED BLOCK }}} | |
48 | <div class="edit-saved-searches"> | |
49 | <&| /Widgets/TitleBox, title => loc($Title)&> | |
50 | ||
51 | %# Hide all the save functionality if the user shouldn't see it. | |
52 | % if ( $can_modify ) { | |
53 | <span class="label"><&|/l&>Privacy</&>:</span> | |
54 | <& SelectSearchObject, Name => 'SavedSearchOwner', Objects => \@Objects, Object => ( $Object && $Object->id ) ? $Object->Object : '' &> | |
55 | <br /> | |
56 | <span class="label"><&|/l&>Description</&>:</span> | |
57 | <input size="25" name="SavedSearchDescription" value="<% $Description || '' %>" /> | |
58 | ||
59 | % if ($Id ne 'new') { | |
60 | <nobr> | |
61 | % if ( $Dirty ) { | |
62 | <input type="submit" class="button" name="SavedSearchRevert" value="<%loc('Revert')%>" /> | |
63 | % } | |
64 | <input type="submit" class="button" name="SavedSearchDelete" value="<%loc('Delete')%>" /> | |
65 | % if ( $AllowCopy ) { | |
66 | <input type="submit" class="button" name="SavedSearchCopy" value="<%loc('Save as New')%>" /> | |
67 | % } | |
68 | </nobr> | |
69 | % } | |
70 | % if ( $Object && $Object->Id ) { | |
71 | <input type="submit" class="button" id="SavedSearchSave" name="SavedSearchSave" value="<%loc('Update')%>" /> | |
72 | % } else { | |
73 | <input type="submit" class="button" id="SavedSearchSave" name="SavedSearchSave" value="<%loc('Save')%>" /> | |
74 | %} | |
75 | % } | |
76 | <br /> | |
77 | <hr /> | |
78 | <span class="label"><&|/l&>Load saved search</&>:</span> | |
79 | <& SelectSearchesForObjects, Name => 'SavedSearchLoad', Objects => \@Objects, SearchType => $Type &> | |
80 | <input type="submit" value="<% loc('Load') %>" id="SavedSearchLoadSubmit" name="SavedSearchLoadSubmit" class="button" /> | |
81 | ||
82 | </&> | |
83 | </div> | |
84 | <%INIT> | |
85 | return unless $session{'CurrentUser'}->HasRight( | |
86 | Right => 'LoadSavedSearch', | |
87 | Object => $RT::System, | |
88 | ); | |
89 | ||
90 | my $can_modify = $session{'CurrentUser'}->HasRight( | |
91 | Right => 'CreateSavedSearch', | |
92 | Object => $RT::System, | |
93 | ); | |
94 | ||
95 | use RT::SavedSearch; | |
96 | my @Objects = RT::SavedSearch->new($session{CurrentUser})->_PrivacyObjects; | |
97 | push @Objects, RT::System->new( $session{'CurrentUser'} ) | |
98 | if $session{'CurrentUser'}->HasRight( Object=> $RT::System, | |
99 | Right => 'SuperUser' ); | |
100 | ||
101 | my $is_dirty = sub { | |
102 | my %arg = ( | |
103 | Query => {}, | |
104 | SavedSearch => {}, | |
105 | SearchFields => [qw(Query Format OrderBy Order RowsPerPage)], | |
106 | @_ | |
107 | ); | |
108 | ||
109 | my $obj = $arg{'SavedSearch'}->{'Object'}; | |
110 | return 0 unless $obj && $obj->id; | |
111 | ||
112 | foreach( @{ $arg{'SearchFields'} } ) { | |
113 | return 1 if $obj->SubValue( $_ ) ne $arg{'Query'}->{$_}; | |
114 | } | |
115 | ||
116 | return 0; | |
117 | }; | |
118 | ||
119 | # If we're modifying an old query, check if it's been changed | |
120 | my $Dirty = $is_dirty->( | |
121 | Query => $CurrentSearch, | |
122 | SavedSearch => { Id => $Id, Object => $Object, Description => $Description }, | |
123 | SearchFields => \@SearchFields, | |
124 | ); | |
125 | ||
126 | </%INIT> | |
127 | ||
128 | <%ARGS> | |
129 | $Id => 'new' | |
130 | $Object => undef | |
131 | $Type => 'Ticket' | |
132 | $Description => '' | |
133 | $CurrentSearch => {} | |
134 | @SearchFields => () | |
135 | $AllowCopy => 1 | |
136 | $Title => loc('Saved searches') | |
137 | </%ARGS> | |
138 | ||
139 | <%METHOD Init> | |
140 | <%ARGS> | |
141 | $Query => {} | |
142 | $SavedSearch => {} | |
143 | @SearchFields => qw(Query Format OrderBy Order RowsPerPage) | |
144 | </%ARGS> | |
145 | <%INIT> | |
146 | ||
147 | $SavedSearch->{'Id'} = ( $ARGS{Type} && $ARGS{Type} eq 'Chart' ? | |
148 | $ARGS{'SavedChartSearchId'} : $ARGS{'SavedSearchId'} ) || 'new'; | |
149 | $SavedSearch->{'Description'} = $ARGS{'SavedSearchDescription'} || undef; | |
150 | $SavedSearch->{'Privacy'} = $ARGS{'SavedSearchOwner'} || undef; | |
151 | ||
152 | my @results; | |
153 | ||
154 | if ( $ARGS{'SavedSearchRevert'} ) { | |
155 | $ARGS{'SavedSearchLoad'} = $SavedSearch->{'Id'}; | |
156 | } | |
157 | ||
158 | if ( $ARGS{'SavedSearchLoad'} ) { | |
159 | my ($container, $id ) = _parse_saved_search ($ARGS{'SavedSearchLoad'}); | |
160 | if ( $container ) { | |
af59614d MKG |
161 | my $search = RT::Attribute->new( $session{'CurrentUser'} ); |
162 | $search->Load( $id ); | |
84fb5b46 MKG |
163 | $SavedSearch->{'Id'} = $ARGS{'SavedSearchLoad'}; |
164 | $SavedSearch->{'Object'} = $search; | |
165 | $SavedSearch->{'Description'} = $search->Description; | |
166 | $Query->{$_} = $search->SubValue($_) foreach @SearchFields; | |
167 | ||
168 | if ( $ARGS{'SavedSearchRevert'} ) { | |
169 | push @results, loc('Loaded original "[_1]" saved search', $SavedSearch->{'Description'} ); | |
170 | } else { | |
171 | push @results, loc('Loaded saved search "[_1]"', $SavedSearch->{'Description'} ); | |
172 | } | |
173 | } | |
174 | else { | |
175 | push @results, loc( 'Can not load saved search "[_1]"', | |
176 | $ARGS{'SavedSearchLoad'} ); | |
177 | return @results; | |
178 | } | |
179 | } | |
180 | elsif ( $ARGS{'SavedSearchDelete'} ) { | |
181 | # We set $SearchId to 'new' above already, so peek into the %ARGS | |
182 | my ($container, $id) = _parse_saved_search( $SavedSearch->{'Id'} ); | |
183 | if ( $container && $container->id ) { | |
184 | # We have the object the entry is an attribute on; delete the entry... | |
185 | my ($val, $msg) = $container->Attributes->DeleteEntry( Name => 'SavedSearch', id => $id ); | |
186 | unless ( $val ) { | |
187 | push @results, $msg; | |
188 | return @results; | |
189 | } | |
190 | } | |
191 | $SavedSearch->{'Id'} = 'new'; | |
192 | $SavedSearch->{'Object'} = undef; | |
193 | $SavedSearch->{'Description'} = undef; | |
194 | push @results, loc("Deleted saved search"); | |
195 | } | |
196 | elsif ( $ARGS{'SavedSearchCopy'} ) { | |
197 | my ($container, $id ) = _parse_saved_search( $ARGS{'SavedSearchId'} ); | |
af59614d MKG |
198 | $SavedSearch->{'Object'} = RT::Attribute->new( $session{'CurrentUser'} ); |
199 | $SavedSearch->{'Object'}->Load( $id ); | |
84fb5b46 MKG |
200 | if ( $ARGS{'SavedSearchDescription'} && $ARGS{'SavedSearchDescription'} ne $SavedSearch->{'Object'}->Description ) { |
201 | $SavedSearch->{'Description'} = $ARGS{'SavedSearchDescription'}; | |
202 | } else { | |
203 | $SavedSearch->{'Description'} = loc( "[_1] copy", $SavedSearch->{'Object'}->Description ); | |
204 | } | |
205 | $SavedSearch->{'Id'} = 'new'; | |
206 | $SavedSearch->{'Object'} = undef; | |
207 | } | |
208 | ||
209 | if ( $SavedSearch->{'Id'} && $SavedSearch->{'Id'} ne 'new' | |
210 | && !$SavedSearch->{'Object'} ) | |
211 | { | |
212 | my ($container, $id ) = _parse_saved_search( $ARGS{'SavedSearchId'} ); | |
af59614d MKG |
213 | $SavedSearch->{'Object'} = RT::Attribute->new( $session{'CurrentUser'} ); |
214 | $SavedSearch->{'Object'}->Load( $id ); | |
84fb5b46 MKG |
215 | $SavedSearch->{'Description'} ||= $SavedSearch->{'Object'}->Description; |
216 | } | |
217 | ||
218 | return @results; | |
219 | ||
220 | </%INIT> | |
221 | </%METHOD> | |
222 | ||
223 | <%METHOD Save> | |
224 | <%ARGS> | |
225 | $Query => {} | |
226 | $SavedSearch => {} | |
227 | @SearchFields => qw(Query Format OrderBy Order RowsPerPage) | |
228 | </%ARGS> | |
229 | <%INIT> | |
230 | ||
231 | return unless $ARGS{'SavedSearchSave'} || $ARGS{'SavedSearchCopy'}; | |
232 | ||
233 | my @results; | |
234 | my $obj = $SavedSearch->{'Object'}; | |
235 | my $id = $SavedSearch->{'Id'}; | |
236 | my $desc = $SavedSearch->{'Description'}; | |
237 | my $privacy = $SavedSearch->{'Privacy'}; | |
238 | ||
239 | my %params = map { $_ => $Query->{$_} } @SearchFields; | |
240 | my ($new_obj_type, $new_obj_id) = split(/\-/, ($privacy || '')); | |
241 | ||
242 | if ( $obj && $obj->id ) { | |
243 | # permission check | |
244 | if ($obj->Object->isa('RT::System')) { | |
245 | unless ($session{'CurrentUser'}->HasRight( Object=> $RT::System, Right => 'SuperUser')) { | |
246 | push @results, loc("No permission to save system-wide searches"); | |
247 | return @results; | |
248 | } | |
249 | } | |
250 | ||
251 | $obj->SetSubValues( %params ); | |
252 | $obj->SetDescription( $desc ); | |
253 | ||
254 | my $obj_type = ref($obj->Object); | |
255 | # We need to get current obj_id now, because when we change obj_type to | |
256 | # RT::System, $obj->Object->Id returns 1, not the old one :( | |
257 | my $obj_id = $obj->Object->Id; | |
258 | ||
259 | if ( $new_obj_type && $new_obj_id ) { | |
260 | my ($val, $msg); | |
261 | ||
262 | # we need to check right before we change any of ObjectType and ObjectId, | |
263 | # or it will fail the 2nd change if we use SetObjectType and | |
264 | # SetObjectId sequentially | |
265 | ||
266 | if ( $obj->CurrentUserHasRight('update') ) { | |
267 | if ( $new_obj_type ne $obj_type ) { | |
268 | ( $val, $msg ) = $obj->__Set( | |
269 | Field => 'ObjectType', | |
270 | Value => $new_obj_type, | |
271 | ); | |
272 | push @results, loc( 'Unable to set privacy object: [_1]', $msg ) | |
273 | unless ($val); | |
274 | } | |
275 | if ( $new_obj_id != $obj_id ) { | |
276 | ( $val, $msg ) = $obj->__Set( | |
277 | Field => 'ObjectId', | |
278 | Value => $new_obj_id, | |
279 | ); | |
280 | push @results, loc( 'Unable to set privacy id: [_1]', $msg ) | |
281 | unless ($val); | |
282 | } | |
283 | } | |
284 | else { | |
285 | # two loc are just for convenience so we don't need to | |
286 | # write an extra i18n translation item | |
287 | push @results, | |
288 | loc( 'Unable to set privacy object or id: [_1]', | |
289 | loc('Permission Denied') ) | |
290 | } | |
291 | } else { | |
292 | push @results, loc('Unable to determine object type or id'); | |
293 | } | |
294 | push @results, loc('Updated saved search "[_1]"', $desc); | |
295 | } | |
296 | elsif ( $id eq 'new' ) { | |
297 | my $saved_search = RT::SavedSearch->new( $session{'CurrentUser'} ); | |
298 | my ($status, $msg) = $saved_search->Save( | |
299 | Privacy => $privacy, | |
300 | Name => $desc, | |
301 | Type => $SavedSearch->{'Type'}, | |
302 | SearchParams => \%params, | |
303 | ); | |
304 | ||
305 | if ( $status ) { | |
af59614d MKG |
306 | $SavedSearch->{'Object'} = RT::Attribute->new( $session{'CurrentUser'} ); |
307 | $SavedSearch->{'Object'}->Load( $saved_search->Id ); | |
84fb5b46 MKG |
308 | # Build new SearchId |
309 | $SavedSearch->{'Id'} = | |
310 | ref( $session{'CurrentUser'}->UserObj ) . '-' | |
311 | . $session{'CurrentUser'}->UserObj->Id | |
312 | . '-SavedSearch-' | |
313 | . $SavedSearch->{'Object'}->Id; | |
314 | } | |
315 | else { | |
316 | push @results, loc("Can't find a saved search to work with").': '.loc($msg); | |
317 | } | |
318 | } | |
319 | else { | |
320 | push @results, loc("Can't save this search"); | |
321 | } | |
322 | ||
323 | return @results; | |
324 | ||
325 | </%INIT> | |
326 | </%METHOD> |