1 package Koha::UI::Form::Builder::Item;
3 # This file is part of Koha.
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.
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.
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>.
21 use C4::Biblio qw( GetFrameworkCode GetMarcStructure IsMarcStructureInternal );
22 use C4::Koha qw( GetAuthorisedValues );
23 use C4::ClassSource qw( GetClassSources );
26 use Koha::DateUtils qw( dt_from_string );
31 Koha::UI::Form::Builder::Item
33 Helper to build a form to add or edit a new item.
43 my $form = Koha::UI::Form::Builder::Item->new(
45 biblionumber => $biblionumber,
46 item => $current_item,
51 biblionumber should be passed if we are creating a new item.
52 For edition, an hashref representing the item to edit item must be passed.
58 my ( $class, $params ) = @_;
61 $self->{biblionumber} = $params->{biblionumber};
62 $self->{item} = $params->{item};
68 =head3 generate_subfield_form
70 Generate subfield's info for given tag, subfieldtag, etc.
74 sub generate_subfield_form {
76 my ($self, $params) = @_;
77 my $tag = $params->{tag};
78 my $subfieldtag = $params->{subfieldtag};
79 my $value = $params->{value};
80 my $tagslib = $params->{tagslib};
81 my $libraries = $params->{libraries};
82 my $marc_record = $params->{marc_record};
83 my $restricted_edition = $params->{restricted_editition};
84 my $prefill_with_default_values = $params->{prefill_with_default_values};
85 my $branch_limit = $params->{branch_limit};
86 my $default_branches_empty = $params->{default_branches_empty};
87 my $readonly = $params->{readonly};
89 my $item = $self->{item};
90 my $subfield = $tagslib->{$tag}{$subfieldtag};
91 my $biblionumber = $self->{biblionumber};
93 my $frameworkcode = $biblionumber ? GetFrameworkCode($biblionumber) : q{};
96 my $dbh = C4::Context->dbh;
98 my $index_subfield = int( rand(1000000) );
99 if ( $subfieldtag eq '@' ) {
100 $subfield_data{id} = "tag_" . $tag . "_subfield_00_" . $index_subfield;
104 "tag_" . $tag . "_subfield_" . $subfieldtag . "_" . $index_subfield;
107 $subfield_data{tag} = $tag;
108 $subfield_data{subfield} = $subfieldtag;
109 $subfield_data{marc_lib} =
111 . $subfield->{lib} . "\">"
114 $subfield_data{mandatory} = $subfield->{mandatory};
115 $subfield_data{important} = $subfield->{important};
116 $subfield_data{repeatable} = $subfield->{repeatable};
117 $subfield_data{maxlength} = $subfield->{maxlength};
118 $subfield_data{display_order} = $subfield->{display_order};
119 $subfield_data{kohafield} =
120 $subfield->{kohafield} || 'items.more_subfields_xml';
122 if ( $prefill_with_default_values && ( !defined($value) || $value eq '' ) ) {
123 $value = $subfield->{defaultvalue} if !$item->{itemnumber}; # apply defaultvalue only to new items
126 # get today date & replace <<YYYY>>, <<YY>>, <<MM>>, <<DD>> if provided in the default value
127 my $today_dt = dt_from_string;
128 my $year = $today_dt->strftime('%Y');
129 my $shortyear = $today_dt->strftime('%y');
130 my $month = $today_dt->strftime('%m');
131 my $day = $today_dt->strftime('%d');
132 $value =~ s/<<YYYY>>/$year/g;
133 $value =~ s/<<YY>>/$shortyear/g;
134 $value =~ s/<<MM>>/$month/g;
135 $value =~ s/<<DD>>/$day/g;
137 # And <<USER>> with surname (?)
140 ? C4::Context->userenv->{'surname'}
143 $value =~ s/<<USER>>/$username/g;
147 $subfield_data{visibility} = "display:none;"
148 if ( ( $subfield->{hidden} > 4 ) || ( $subfield->{hidden} <= -4 ) );
150 my $pref_itemcallnumber = C4::Context->preference('itemcallnumber');
151 if ( $prefill_with_default_values
153 && $subfield->{kohafield}
154 && $subfield->{kohafield} eq 'items.itemcallnumber'
155 && $pref_itemcallnumber )
158 my $pref_itemcallnumber_part ( split( /,/, $pref_itemcallnumber ) )
161 substr( $pref_itemcallnumber_part, 0, 3 ); # 3-digit tag number
163 substr( $pref_itemcallnumber_part, 3 ); # Any and all subfields
164 $CNsubfields = undef if $CNsubfields eq '';
165 my $temp2 = $marc_record->field($CNtag);
168 $value = $temp2->as_string( $CNsubfields, ' ' );
173 if ( $subfield->{authorised_value} ) {
174 my @authorised_values;
177 # builds list, depending on authorised value...
178 if ( $subfield->{authorised_value} eq "LOST" ) {
179 my $ClaimReturnedLostValue =
180 C4::Context->preference('ClaimReturnedLostValue');
181 my $item_is_return_claim =
182 $ClaimReturnedLostValue
183 && exists $item->{itemlost}
184 && $ClaimReturnedLostValue eq $item->{itemlost};
185 $subfield_data{IS_RETURN_CLAIM} = $item_is_return_claim;
187 $subfield_data{IS_LOST_AV} = 1;
189 push @authorised_values, qq{};
190 my $av = GetAuthorisedValues( $subfield->{authorised_value} );
192 push @authorised_values, $r->{authorised_value};
193 $authorised_lib{ $r->{authorised_value} } = $r->{lib};
196 elsif ( $subfield->{authorised_value} eq "branches" ) {
197 push @authorised_values, "" if $default_branches_empty;
198 foreach my $thisbranch (@$libraries) {
199 push @authorised_values, $thisbranch->{branchcode};
200 $authorised_lib{ $thisbranch->{branchcode} } =
201 $thisbranch->{branchname};
202 $value = $thisbranch->{branchcode}
203 if $thisbranch->{selected} && !$value;
206 elsif ( $subfield->{authorised_value} eq "itemtypes" ) {
207 push @authorised_values, "";
210 $itemtypes = Koha::ItemTypes->search_with_localization(
211 { branchcode => $branch_limit } );
214 $itemtypes = Koha::ItemTypes->search_with_localization;
216 while ( my $itemtype = $itemtypes->next ) {
217 push @authorised_values, $itemtype->itemtype;
218 $authorised_lib{ $itemtype->itemtype } =
219 $itemtype->translated_description;
222 if (!$value && $biblionumber) {
223 my $itype_sth = $dbh->prepare(
224 "SELECT itemtype FROM biblioitems WHERE biblionumber = ?");
225 $itype_sth->execute($biblionumber);
226 ($value) = $itype_sth->fetchrow_array;
231 elsif ( $subfield->{authorised_value} eq "cn_source" ) {
232 push @authorised_values, "";
234 my $class_sources = GetClassSources();
236 C4::Context->preference("DefaultClassificationSource");
238 foreach my $class_source ( sort keys %$class_sources ) {
240 unless $class_sources->{$class_source}->{'used'}
241 or ( $value and $class_source eq $value )
242 or ( $class_source eq $default_source );
243 push @authorised_values, $class_source;
244 $authorised_lib{$class_source} =
245 $class_sources->{$class_source}->{'description'};
247 $value = $default_source if !$value && $prefill_with_default_values;
249 #---- "true" authorised value
252 push @authorised_values, qq{};
253 my $av = GetAuthorisedValues( $subfield->{authorised_value} );
255 push @authorised_values, $r->{authorised_value};
256 $authorised_lib{ $r->{authorised_value} } = $r->{lib};
260 if ( $subfield->{hidden} > 4 or $subfield->{hidden} <= -4 ) {
261 $subfield_data{marc_value} = {
263 id => $subfield_data{id},
264 maxlength => $subfield_data{maxlength},
268 grep { $_ eq $subfield->{authorised_value} }
269 (qw(branches itemtypes cn_source))
270 ) ? () : ( category => $subfield->{authorised_value} )
275 $subfield_data{marc_value} = {
282 values => \@authorised_values,
283 labels => \%authorised_lib,
287 grep { $_ eq $subfield->{authorised_value} }
288 (qw(branches itemtypes cn_source))
289 ) ? () : ( category => $subfield->{authorised_value} )
295 # it's a thesaurus / authority field
296 elsif ( $subfield->{authtypecode} ) {
297 $subfield_data{marc_value} = {
299 id => $subfield_data{id},
300 maxlength => $subfield_data{maxlength},
302 authtypecode => $subfield->{authtypecode},
306 # it's a plugin field
307 elsif ( $subfield->{value_builder} ) { # plugin
308 require Koha::FrameworkPlugin;
309 my $plugin = Koha::FrameworkPlugin->new(
311 name => $subfield->{'value_builder'},
317 record => $marc_record,
319 id => $subfield_data{id},
321 $plugin->build($pars);
322 if ( !$plugin->errstr ) {
323 my $class = 'buttonDot' . ( $plugin->noclick ? ' disabled' : '' );
324 $subfield_data{marc_value} = {
325 type => 'text_plugin',
326 id => $subfield_data{id},
327 maxlength => $subfield_data{maxlength},
330 nopopup => $plugin->noclick,
331 javascript => $plugin->javascript,
335 warn $plugin->errstr;
336 $subfield_data{marc_value} = {
338 id => $subfield_data{id},
339 maxlength => $subfield_data{maxlength},
341 }; # supply default input form
344 elsif ( $tag eq '' ) { # it's an hidden field
345 $subfield_data{marc_value} = {
347 id => $subfield_data{id},
348 maxlength => $subfield_data{maxlength},
352 elsif ( $subfield->{'hidden'} )
353 { # FIXME: shouldn't input type be "hidden" ?
354 $subfield_data{marc_value} = {
356 id => $subfield_data{id},
357 maxlength => $subfield_data{maxlength},
362 ( $value and length($value) > 100 )
363 or ( C4::Context->preference("marcflavour") eq "UNIMARC"
364 and 300 <= $tag && $tag < 400 && $subfieldtag eq 'a' )
365 or ( C4::Context->preference("marcflavour") eq "MARC21"
366 and 500 <= $tag && $tag < 600 )
369 # oversize field (textarea)
370 $subfield_data{marc_value} = {
372 id => $subfield_data{id},
377 # it's a standard field
378 $subfield_data{marc_value} = {
380 id => $subfield_data{id},
381 maxlength => $subfield_data{maxlength},
386 # If we're on restricted editing, and our field is not in the list of subfields to allow,
387 # then it is read-only
388 $subfield_data{marc_value}->{readonly} = $readonly;
390 return \%subfield_data;
396 Koha::UI::Form::Builder::Item->new(
397 { biblionumber => $biblionumber, item => $current_item } )->edit_form(
399 branchcode => $branchcode,
400 restricted_editition => $restrictededition,
402 @subfields_to_prefill
403 ? ( subfields_to_prefill => \@subfields_to_prefill )
406 prefill_with_default_values => 1,
407 branch_limit => C4::Context->userenv->{"branch"},
411 Returns the list of subfields to display on the add/edit item form.
413 Use it in the view with:
414 [% PROCESS subfields_for_item subfields => subfields %]
422 Pre-select a library (for logged in user)
424 =item restricted_editition
426 Flag to restrict the edition if the user does not have necessary permissions.
428 =item subfields_to_prefill
430 List of subfields to prefill (value of syspref SubfieldsToUseWhenPrefill)
432 =item subfields_to_allow
434 List of subfields to allow (value of syspref SubfieldsToAllowForRestrictedBatchmod or SubfieldsToAllowForRestrictedEditing)
436 =item ignore_not_allowed_subfields
438 If set, the subfields in subfields_to_allow will be ignored (ie. they will not be part of the subfield list.
439 If not set, the subfields in subfields_to_allow will be marked as readonly.
441 =item kohafields_to_ignore
443 List of subfields to ignore/skip
445 =item prefill_with_default_values
447 Flag to prefill with the default values defined in the framework.
451 Limit info depending on the library (so far only item types).
453 =item default_branches_empty
455 Flag to add an empty option to the library list.
457 =item ignore_invisible_subfields
459 Skip the subfields that are not visible on the editor.
461 When duplicating an item we do not want to retrieve the subfields that are hidden.
468 my ( $self, $params ) = @_;
470 my $branchcode = $params->{branchcode};
471 my $restricted_edition = $params->{restricted_editition};
472 my $subfields_to_prefill = $params->{subfields_to_prefill} || [];
473 my $subfields_to_allow = $params->{subfields_to_allow} || [];
474 my $ignore_not_allowed_subfields = $params->{ignore_not_allowed_subfields};
475 my $kohafields_to_ignore = $params->{kohafields_to_ignore} || [];
476 my $prefill_with_default_values = $params->{prefill_with_default_values};
477 my $branch_limit = $params->{branch_limit};
478 my $default_branches_empty = $params->{default_branches_empty};
479 my $ignore_invisible_subfields = $params->{ignore_invisible_subfields} || 0;
482 Koha::Libraries->search( {}, { order_by => ['branchname'] } )->unblessed;
483 for my $library (@$libraries) {
484 $library->{selected} = 1 if $branchcode && $library->{branchcode} eq $branchcode;
487 my $item = $self->{item};
488 my $marc_more_subfields = $item->{more_subfields_xml}
490 # FIXME Use Maybe MARC::Record::new_from_xml if encoding issues on subfield (??)
491 MARC::Record->new_from_xml( $item->{more_subfields_xml}, 'UTF-8' )
494 my $biblionumber = $self->{biblionumber};
495 my $biblio = Koha::Biblios->find($biblionumber);
496 my $frameworkcode = $biblio ? GetFrameworkCode($biblionumber) : q{};
497 my $marc_record = $biblio ? $biblio->metadata->record : undef;
499 my $tagslib = GetMarcStructure( 1, $frameworkcode );
500 foreach my $tag ( keys %{$tagslib} ) {
502 foreach my $subfieldtag ( keys %{ $tagslib->{$tag} } ) {
504 my $subfield = $tagslib->{$tag}{$subfieldtag};
506 next if IsMarcStructureInternal($subfield);
507 next if $subfield->{tab} ne "10";
509 if grep { $subfield->{kohafield} && $subfield->{kohafield} eq $_ }
510 @$kohafields_to_ignore;
513 if $ignore_invisible_subfields
514 && ( $subfield->{hidden} > 4 || $subfield->{hidden} <= -4 );
518 @$subfields_to_allow && !grep {
519 sprintf( "%s\$%s", $subfield->{tagfield}, $subfield->{tagsubfield} ) eq $_
520 } @$subfields_to_allow
523 next if $ignore_not_allowed_subfields;
524 $readonly = 1 if $restricted_edition;
532 !@$subfields_to_prefill
533 || ( @$subfields_to_prefill && grep { $_ eq $subfieldtag }
534 @$subfields_to_prefill )
537 my $kohafield = $subfield->{kohafield};
540 # This is a mapped field
541 ( my $attribute = $kohafield ) =~ s|^items\.||;
542 push @values, $subfield->{repeatable}
543 ? split '\s\|\s', $item->{$attribute}
544 : $item->{$attribute}
545 if defined $item->{$attribute};
548 # Not mapped, picked the values from more_subfields_xml's MARC
549 if ($marc_more_subfields) {
550 for my $f ( $marc_more_subfields->fields($tag) ) {
551 push @values, $f->subfield($subfieldtag);
557 @values = ('') unless @values;
559 for my $value (@values) {
560 my $subfield_data = $self->generate_subfield_form(
563 subfieldtag => $subfieldtag,
566 libraries => $libraries,
567 marc_record => $marc_record,
568 restricted_edition => $restricted_edition,
569 prefill_with_default_values => $prefill_with_default_values,
570 branch_limit => $branch_limit,
571 default_branches_empty => $default_branches_empty,
572 readonly => $readonly
575 push @subfields, $subfield_data;
581 $a->{display_order} <=> $b->{display_order}
582 || $a->{subfield} cmp $b->{subfield}