Bug 28445: Start form with empty library for batch mod
[srvgit] / Koha / UI / Form / Builder / Item.pm
1 package Koha::UI::Form::Builder::Item;
2
3 # This file is part of Koha.
4 #
5 # Koha is free software; you can redistribute it and/or modify it
6 # under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 3 of the License, or
8 # (at your option) any later version.
9 #
10 # Koha is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with Koha; if not, see <http://www.gnu.org/licenses>.
17
18 use Modern::Perl;
19 use C4::Context;
20 use C4::Biblio qw( GetFrameworkCode GetMarcBiblio GetMarcStructure IsMarcStructureInternal );
21 use C4::Koha qw( GetAuthorisedValues );
22 use C4::ClassSource qw( GetClassSources );
23
24 use Koha::DateUtils qw( dt_from_string );
25 use Koha::Libraries;
26
27 =head1 NAME
28
29 Koha::UI::Form::Builder::Item
30
31 Helper to build a form to add or edit a new item.
32
33 =head1 API
34
35 =head2 Class methods
36
37 =cut
38
39 =head3 new
40
41     my $form = Koha::UI::Form::Builder::Item->new(
42         {
43             biblionumber => $biblionumber,
44             item => $current_item,
45         }
46     );
47
48 Constructor.
49 biblionumber should be passed if we are creating a new item.
50 For edition, an hashref representing the item to edit item must be passed.
51
52 =cut
53
54
55 sub new {
56     my ( $class, $params ) = @_;
57
58     my $self;
59     $self->{biblionumber} = $params->{biblionumber};
60     $self->{item} = $params->{item};
61
62     bless $self, $class;
63     return $self;
64 }
65
66 =head3 generate_subfield_form
67
68 Generate subfield's info for given tag, subfieldtag, etc.
69
70 =cut
71
72 sub generate_subfield_form {
73
74     my ($self, $params)    = @_;
75     my $tag         = $params->{tag};
76     my $subfieldtag = $params->{subfieldtag};
77     my $value       = $params->{value};
78     my $tagslib     = $params->{tagslib};
79     my $libraries   = $params->{libraries};
80     my $marc_record = $params->{marc_record};
81     my $restricted_edition = $params->{restricted_editition};
82     my $prefill_with_default_values = $params->{prefill_with_default_values};
83     my $branch_limit = $params->{branch_limit};
84     my $default_branches_empty = $params->{default_branches_empty};
85
86     my $item         = $self->{item};
87     my $subfield     = $tagslib->{$tag}{$subfieldtag};
88     my $biblionumber = $self->{biblionumber};
89
90     my $frameworkcode = $biblionumber ? GetFrameworkCode($biblionumber) : q{};
91
92     my %subfield_data;
93     my $dbh = C4::Context->dbh;
94
95     my $index_subfield = int( rand(1000000) );
96     if ( $subfieldtag eq '@' ) {
97         $subfield_data{id} = "tag_" . $tag . "_subfield_00_" . $index_subfield;
98     }
99     else {
100         $subfield_data{id} =
101           "tag_" . $tag . "_subfield_" . $subfieldtag . "_" . $index_subfield;
102     }
103
104     $subfield_data{tag}      = $tag;
105     $subfield_data{subfield} = $subfieldtag;
106     $subfield_data{marc_lib} =
107         "<span title=\""
108       . $subfield->{lib} . "\">"
109       . $subfield->{lib}
110       . "</span>";
111     $subfield_data{mandatory}     = $subfield->{mandatory};
112     $subfield_data{important}     = $subfield->{important};
113     $subfield_data{repeatable}    = $subfield->{repeatable};
114     $subfield_data{maxlength}     = $subfield->{maxlength};
115     $subfield_data{display_order} = $subfield->{display_order};
116     $subfield_data{kohafield} =
117       $subfield->{kohafield} || 'items.more_subfields_xml';
118
119     if ( $prefill_with_default_values && ( !defined($value) || $value eq '' ) ) {
120         $value = $subfield->{defaultvalue};
121         if ($value) {
122
123 # get today date & replace <<YYYY>>, <<YY>>, <<MM>>, <<DD>> if provided in the default value
124             my $today_dt  = dt_from_string;
125             my $year      = $today_dt->strftime('%Y');
126             my $shortyear = $today_dt->strftime('%y');
127             my $month     = $today_dt->strftime('%m');
128             my $day       = $today_dt->strftime('%d');
129             $value =~ s/<<YYYY>>/$year/g;
130             $value =~ s/<<YY>>/$shortyear/g;
131             $value =~ s/<<MM>>/$month/g;
132             $value =~ s/<<DD>>/$day/g;
133
134             # And <<USER>> with surname (?)
135             my $username = (
136                   C4::Context->userenv
137                 ? C4::Context->userenv->{'surname'}
138                 : "superlibrarian"
139             );
140             $value =~ s/<<USER>>/$username/g;
141         }
142     }
143
144     $subfield_data{visibility} = "display:none;"
145       if ( ( $subfield->{hidden} > 4 ) || ( $subfield->{hidden} <= -4 ) );
146
147     my $pref_itemcallnumber = C4::Context->preference('itemcallnumber');
148     if (  $prefill_with_default_values
149         && !$value
150         && $subfield->{kohafield}
151         && $subfield->{kohafield} eq 'items.itemcallnumber'
152         && $pref_itemcallnumber )
153     {
154         foreach
155           my $pref_itemcallnumber_part ( split( /,/, $pref_itemcallnumber ) )
156         {
157             my $CNtag =
158               substr( $pref_itemcallnumber_part, 0, 3 );    # 3-digit tag number
159             my $CNsubfields =
160               substr( $pref_itemcallnumber_part, 3 );    # Any and all subfields
161             $CNsubfields = undef if $CNsubfields eq '';
162             my $temp2 = $marc_record->field($CNtag);
163
164             next unless $temp2;
165             $value = $temp2->as_string( $CNsubfields, ' ' );
166             last if $value;
167         }
168     }
169
170     if ( $subfield->{authorised_value} ) {
171         my @authorised_values;
172         my %authorised_lib;
173
174         # builds list, depending on authorised value...
175         if ( $subfield->{authorised_value} eq "LOST" ) {
176             my $ClaimReturnedLostValue =
177               C4::Context->preference('ClaimReturnedLostValue');
178             my $item_is_return_claim =
179                  $ClaimReturnedLostValue
180               && exists $item->{itemlost}
181               && $ClaimReturnedLostValue eq $item->{itemlost};
182             $subfield_data{IS_RETURN_CLAIM} = $item_is_return_claim;
183
184             $subfield_data{IS_LOST_AV} = 1;
185
186             push @authorised_values, qq{};
187             my $av = GetAuthorisedValues( $subfield->{authorised_value} );
188             for my $r (@$av) {
189                 push @authorised_values, $r->{authorised_value};
190                 $authorised_lib{ $r->{authorised_value} } = $r->{lib};
191             }
192         }
193         elsif ( $subfield->{authorised_value} eq "branches" ) {
194             push @authorised_values, "" if $default_branches_empty;
195             foreach my $thisbranch (@$libraries) {
196                 push @authorised_values, $thisbranch->{branchcode};
197                 $authorised_lib{ $thisbranch->{branchcode} } =
198                   $thisbranch->{branchname};
199                 $value = $thisbranch->{branchcode}
200                   if $thisbranch->{selected} && !$value;
201             }
202         }
203         elsif ( $subfield->{authorised_value} eq "itemtypes" ) {
204             push @authorised_values, "";
205             my $itemtypes;
206             if ($branch_limit) {
207                 $itemtypes = Koha::ItemTypes->search_with_localization(
208                     { branchcode => $branch_limit } );
209             }
210             else {
211                 $itemtypes = Koha::ItemTypes->search_with_localization;
212             }
213             while ( my $itemtype = $itemtypes->next ) {
214                 push @authorised_values, $itemtype->itemtype;
215                 $authorised_lib{ $itemtype->itemtype } =
216                   $itemtype->translated_description;
217             }
218
219             if (!$value && $biblionumber) {
220                 my $itype_sth = $dbh->prepare(
221                     "SELECT itemtype FROM biblioitems WHERE biblionumber = ?");
222                 $itype_sth->execute($biblionumber);
223                 ($value) = $itype_sth->fetchrow_array;
224             }
225
226             #---- class_sources
227         }
228         elsif ( $subfield->{authorised_value} eq "cn_source" ) {
229             push @authorised_values, "";
230
231             my $class_sources = GetClassSources();
232             my $default_source =
233               C4::Context->preference("DefaultClassificationSource");
234
235             foreach my $class_source ( sort keys %$class_sources ) {
236                 next
237                   unless $class_sources->{$class_source}->{'used'}
238                   or ( $value and $class_source eq $value )
239                   or ( $class_source eq $default_source );
240                 push @authorised_values, $class_source;
241                 $authorised_lib{$class_source} =
242                   $class_sources->{$class_source}->{'description'};
243             }
244             $value = $default_source if !$value && $prefill_with_default_values;
245
246             #---- "true" authorised value
247         }
248         else {
249             push @authorised_values, qq{};
250             my $av = GetAuthorisedValues( $subfield->{authorised_value} );
251             for my $r (@$av) {
252                 push @authorised_values, $r->{authorised_value};
253                 $authorised_lib{ $r->{authorised_value} } = $r->{lib};
254             }
255         }
256
257         if ( $subfield->{hidden} > 4 or $subfield->{hidden} <= -4 ) {
258             $subfield_data{marc_value} = {
259                 type      => 'hidden',
260                 id        => $subfield_data{id},
261                 maxlength => $subfield_data{maxlength},
262                 value     => $value,
263                 (
264                     (
265                         grep { $_ eq $subfield->{authorised_value} }
266                           (qw(branches itemtypes cn_source))
267                     ) ? () : ( category => $subfield->{authorised_value} )
268                 ),
269             };
270         }
271         else {
272             $subfield_data{marc_value} = {
273                 type => 'select',
274                 id   => "tag_"
275                   . $tag
276                   . "_subfield_"
277                   . $subfieldtag . "_"
278                   . $index_subfield,
279                 values  => \@authorised_values,
280                 labels  => \%authorised_lib,
281                 default => $value,
282                 (
283                     (
284                         grep { $_ eq $subfield->{authorised_value} }
285                           (qw(branches itemtypes cn_source))
286                     ) ? () : ( category => $subfield->{authorised_value} )
287                 ),
288             };
289         }
290     }
291
292     # it's a thesaurus / authority field
293     elsif ( $subfield->{authtypecode} ) {
294         $subfield_data{marc_value} = {
295             type         => 'text_auth',
296             id           => $subfield_data{id},
297             maxlength    => $subfield_data{maxlength},
298             value        => $value,
299             authtypecode => $subfield->{authtypecode},
300         };
301     }
302
303     # it's a plugin field
304     elsif ( $subfield->{value_builder} ) {    # plugin
305         require Koha::FrameworkPlugin;
306         my $plugin = Koha::FrameworkPlugin->new(
307             {
308                 name       => $subfield->{'value_builder'},
309                 item_style => 1,
310             }
311         );
312         my $pars = {
313             dbh     => $dbh,
314             record  => $marc_record,
315             tagslib => $tagslib,
316             id      => $subfield_data{id},
317         };
318         $plugin->build($pars);
319         if ( !$plugin->errstr ) {
320             my $class = 'buttonDot' . ( $plugin->noclick ? ' disabled' : '' );
321             $subfield_data{marc_value} = {
322                 type       => 'text_plugin',
323                 id         => $subfield_data{id},
324                 maxlength  => $subfield_data{maxlength},
325                 value      => $value,
326                 class      => $class,
327                 nopopup    => $plugin->noclick,
328                 javascript => $plugin->javascript,
329             };
330         }
331         else {
332             warn $plugin->errstr;
333             $subfield_data{marc_value} = {
334                 type      => 'text',
335                 id        => $subfield_data{id},
336                 maxlength => $subfield_data{maxlength},
337                 value     => $value,
338             };    # supply default input form
339         }
340     }
341     elsif ( $tag eq '' ) {    # it's an hidden field
342         $subfield_data{marc_value} = {
343             type      => 'hidden',
344             id        => $subfield_data{id},
345             maxlength => $subfield_data{maxlength},
346             value     => $value,
347         };
348     }
349     elsif ( $subfield->{'hidden'} )
350     {                         # FIXME: shouldn't input type be "hidden" ?
351         $subfield_data{marc_value} = {
352             type      => 'text',
353             id        => $subfield_data{id},
354             maxlength => $subfield_data{maxlength},
355             value     => $value,
356         };
357     }
358     elsif (
359         ( $value and length($value) > 100 )
360         or ( C4::Context->preference("marcflavour") eq "UNIMARC"
361             and 300 <= $tag && $tag < 400 && $subfieldtag eq 'a' )
362         or ( C4::Context->preference("marcflavour") eq "MARC21"
363             and 500 <= $tag && $tag < 600 )
364       )
365     {
366         # oversize field (textarea)
367         $subfield_data{marc_value} = {
368             type  => 'textarea',
369             id    => $subfield_data{id},
370             value => $value,
371         };
372     }
373     else {
374         # it's a standard field
375         $subfield_data{marc_value} = {
376             type      => 'text',
377             id        => $subfield_data{id},
378             maxlength => $subfield_data{maxlength},
379             value     => $value,
380         };
381     }
382
383     # Getting list of subfields to keep when restricted editing is enabled
384     # FIXME Improve the following block, no need to do it for every subfields
385     my $subfieldsToAllowForRestrictedEditing =
386       C4::Context->preference('SubfieldsToAllowForRestrictedEditing');
387     my $allowAllSubfields = (
388         not defined $subfieldsToAllowForRestrictedEditing
389           or $subfieldsToAllowForRestrictedEditing eq q||
390     ) ? 1 : 0;
391     my @subfieldsToAllow = split( / /, $subfieldsToAllowForRestrictedEditing );
392
393 # If we're on restricted editing, and our field is not in the list of subfields to allow,
394 # then it is read-only
395     $subfield_data{marc_value}->{readonly} =
396       (       not $allowAllSubfields
397           and $restricted_edition
398           and !grep { $tag . '$' . $subfieldtag eq $_ } @subfieldsToAllow )
399       ? 1
400       : 0;
401
402     return \%subfield_data;
403 }
404
405     my $subfields =
406       Koha::UI::Form::Builder::Item->new(
407         { biblionumber => $biblionumber, item => $current_item } )->edit_form(
408         {
409             branchcode           => $branchcode,
410             restricted_editition => $restrictededition,
411             (
412                 @subfields_to_prefill
413                 ? ( subfields_to_prefill => \@subfields_to_prefill )
414                 : ()
415             ),
416             prefill_with_default_values => 1,
417             branch_limit => C4::Context->userenv->{"branch"},
418         }
419     );
420
421 Returns the list of subfields to display on the add/edit item form.
422
423 Use it in the view with:
424   [% PROCESS subfields_for_item subfields => subfields %]
425
426 Parameters:
427
428 =over
429
430 =item branchcode
431
432 Pre-select a library (for logged in user)
433
434 =item restricted_editition
435
436 Flag to restrict the edition if the user does not have necessary permissions.
437
438 =item subfields_to_prefill
439
440 List of subfields to prefill (value of syspref SubfieldsToUseWhenPrefill)
441
442 =item subfields_to_allow
443
444 List of subfields to allow (value of syspref SubfieldsToAllowForRestrictedBatchmod)
445
446 =item subfields_to_ignore
447
448 List of subfields to ignore/skip
449
450 =item prefill_with_default_values
451
452 Flag to prefill with the default values defined in the framework.
453
454 =item branch_limit
455
456 Limit info depending on the library (so far only item types).
457
458 =item default_branches_empty
459
460 Flag to add an empty option to the library list.
461
462 =back
463
464 =cut
465
466 sub edit_form {
467     my ( $self, $params ) = @_;
468
469     my $branchcode         = $params->{branchcode};
470     my $restricted_edition = $params->{restricted_editition};
471     my $subfields_to_prefill = $params->{subfields_to_prefill} || [];
472     my $subfields_to_allow = $params->{subfields_to_allow} || [];
473     my $subfields_to_ignore= $params->{subfields_to_ignore} || [];
474     my $prefill_with_default_values = $params->{prefill_with_default_values};
475     my $branch_limit = $params->{branch_limit};
476     my $default_branches_empty = $params->{default_branches_empty};
477
478     my $libraries =
479       Koha::Libraries->search( {}, { order_by => ['branchname'] } )->unblessed;
480     for my $library (@$libraries) {
481         $library->{selected} = 1 if $branchcode && $library->{branchcode} eq $branchcode;
482     }
483
484     my $item           = $self->{item};
485     my $biblionumber   = $self->{biblionumber};
486     my $frameworkcode  = $biblionumber ? GetFrameworkCode($biblionumber) : q{};
487     my $marc_record    = $biblionumber ? GetMarcBiblio( { biblionumber => $biblionumber } ) : undef;
488     my @subfields;
489     my $tagslib = GetMarcStructure( 1, $frameworkcode );
490     foreach my $tag ( keys %{$tagslib} ) {
491
492         foreach my $subfieldtag ( keys %{ $tagslib->{$tag} } ) {
493
494             my $subfield = $tagslib->{$tag}{$subfieldtag};
495
496             next if IsMarcStructureInternal($subfield);
497             next if $subfield->{tab} ne "10";
498             next if @$subfields_to_allow && !grep { $subfield->{kohafield} eq $_ } @$subfields_to_allow;
499             next
500               if grep { $subfield->{kohafield} && $subfield->{kohafield} eq $_ }
501               @$subfields_to_ignore;
502
503             my @values = ();
504
505             my $subfield_data;
506
507             if (
508                 !@$subfields_to_prefill
509                 || ( @$subfields_to_prefill && grep { $_ eq $subfieldtag }
510                     @$subfields_to_prefill )
511               )
512             {
513                 my $kohafield = $subfield->{kohafield};
514                 if ($kohafield) {
515
516                     # This is a mapped field
517                     ( my $attribute = $kohafield ) =~ s|^items\.||;
518                     push @values, $subfield->{repeatable}
519                       ? split '\s\|\s', $item->{$attribute}
520                       : $item->{$attribute}
521                       if defined $item->{$attribute};
522                 }
523                 else {
524                   # Not mapped, picked the values from more_subfields_xml's MARC
525                     my $marc_more = $item->{marc_more_subfields_xml};
526                     if ($marc_more) {
527                         for my $f ( $marc_more->fields($tag) ) {
528                             push @values, $f->subfield($subfieldtag);
529                         }
530                     }
531                 }
532             }
533
534             @values = ('') unless @values;
535
536             for my $value (@values) {
537                 my $subfield_data = $self->generate_subfield_form(
538                     {
539                         tag                => $tag,
540                         subfieldtag        => $subfieldtag,
541                         value              => $value,
542                         tagslib            => $tagslib,
543                         libraries          => $libraries,
544                         marc_record        => $marc_record,
545                         restricted_edition => $restricted_edition,
546                         prefill_with_default_values => $prefill_with_default_values,
547                         branch_limit       => $branch_limit,
548                         default_branches_empty => $default_branches_empty,
549                     }
550                 );
551                 push @subfields, $subfield_data;
552             }
553         }
554     }
555
556     @subfields = sort {
557              $a->{display_order} <=> $b->{display_order}
558           || $a->{subfield} cmp $b->{subfield}
559     } @subfields;
560
561     return \@subfields;
562
563 }
564
565 1;