Permalink
Cannot retrieve contributors at this time
613 lines (493 sloc)
15 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ###################################################################### | |
| # | |
| # EPrints::MetaField::Set; | |
| # | |
| ###################################################################### | |
| # | |
| # | |
| ###################################################################### | |
| =pod | |
| =head1 NAME | |
| B<EPrints::MetaField::Set> - no description | |
| =head1 DESCRIPTION | |
| not done | |
| =over 4 | |
| =cut | |
| package EPrints::MetaField::Set; | |
| use EPrints::MetaField::Text; | |
| @ISA = EPrints::MetaField::Text; | |
| use strict; | |
| sub render_single_value | |
| { | |
| my( $self, $session, $value ) = @_; | |
| return $self->render_option( $session , $value ); | |
| } | |
| sub set_value | |
| { | |
| my( $self, $object, $value ) = @_; | |
| if( $self->get_property( "multiple" ) && !$self->get_property( "sub_name" ) ) | |
| { | |
| $value = [] if !defined $value; | |
| my %seen; | |
| @$value = grep { | |
| EPrints::Utils::is_set( $_ ) # multiple values must be defined | |
| && !$seen{$_}++ # set values must be unique | |
| } @$value; | |
| } | |
| return $object->set_value_raw( $self->{name}, $value ); | |
| } | |
| ###################################################################### | |
| =pod | |
| =item ( $options , $labels ) = $field->tags_and_labels( $session ) | |
| Return a reference to an array of options for this | |
| field, plus an array of UTF-8 encoded labels for these options in the | |
| current language. | |
| =cut | |
| ###################################################################### | |
| sub tags_and_labels | |
| { | |
| my( $self , $session ) = @_; | |
| my @tags = $self->tags( $session ); | |
| my %labels = (); | |
| foreach( @tags ) | |
| { | |
| $labels{$_} = EPrints::Utils::tree_to_utf8( | |
| $self->render_option( $session, $_ ) ); | |
| } | |
| if( $self->get_property( 'order_labels' ) ) | |
| { | |
| # Order the labels alphabetically | |
| my @otags = sort { $a ne 'other' && $b ne 'other' && ($labels{$a} cmp $labels{$b}) } @tags; | |
| return (\@otags, \%labels ); | |
| } | |
| return (\@tags, \%labels); | |
| } | |
| sub tags | |
| { | |
| my( $self, $session ) = @_; | |
| EPrints::abort( "no options in tags()" ) if( !defined $self->{options} ); | |
| return @{$self->{options}}; | |
| } | |
| ###################################################################### | |
| =pod | |
| =item $xhtml = $field->render_option( $session, $option ) | |
| Return the title of option $option in the language of $session as an | |
| XHTML DOM object. | |
| =cut | |
| ###################################################################### | |
| sub render_option | |
| { | |
| my( $self, $session, $option ) = @_; | |
| if( defined $self->get_property("render_option") ) | |
| { | |
| return $self->call_property( "render_option", $session, $option ); | |
| } | |
| $option = "" if !defined $option; | |
| my $phrasename = $self->{confid}."_fieldopt_".$self->{name}."_".$option; | |
| # if the option is empty, and no explicit phrase is defined, print | |
| # UNDEFINED rather than an error phrase. | |
| if( $option eq "" && !$session->get_lang->has_phrase( $phrasename, $session ) ) | |
| { | |
| $phrasename = "lib/metafield:unspecified"; | |
| } | |
| return $session->html_phrase( $phrasename ); | |
| } | |
| sub render_input_field_actual | |
| { | |
| my( $self, $session, $value, $dataset, $staff, $hidden_fields, $obj, $basename ) = @_; | |
| if( $self->get_property( "input_ordered" ) ) | |
| { | |
| return $self->SUPER::render_input_field_actual( | |
| $session, $value, $dataset, $staff, $hidden_fields, $obj, $basename ); | |
| } | |
| my $required = $self->get_property( "required" ); | |
| my %settings; | |
| my $default = $value; | |
| $default = [ $value ] unless( $self->get_property( "multiple" ) ); | |
| $default = [] if( !defined $value ); | |
| # called as a seperate function because subject does this | |
| # bit differently, and overrides render_set_input. | |
| return $self->render_set_input( $session, $default, $required, $obj, $basename ); | |
| } | |
| sub input_tags_and_labels | |
| { | |
| my( $self, $session, $obj ) = @_; | |
| my @tags = $self->tags( $session ); | |
| if( defined $self->get_property("input_tags") ) | |
| { | |
| @tags = $self->call_property( "input_tags", $session, $obj ); | |
| } | |
| return $self->tags_and_labels( $session ); | |
| } | |
| # this is only called by the compound renderer | |
| sub get_basic_input_elements | |
| { | |
| my( $self, $session, $value, $basename, $staff, $obj ) = @_; | |
| my( $tags, $labels ) = $self->input_tags_and_labels( $session, $obj ); | |
| # If it's not multiple and not required there | |
| # must be a way to unselect it. | |
| $tags = [ "", @{$tags} ]; | |
| my $unspec = EPrints::Utils::tree_to_utf8( $self->render_option( $session, undef ) ); | |
| $labels = { ""=>$unspec, %{$labels} }; | |
| my @classes; | |
| push @classes, join('_', 'ep', $self->{dataset}->base_id, $self->name); | |
| push @classes, join('_', 'eptype', $self->{dataset}->base_id, $self->type); | |
| return( [ [ { el=>$session->render_option_list( | |
| values => $tags, | |
| labels => $labels, | |
| name => $basename, | |
| class => join(" ", @classes), | |
| id => $basename, | |
| default => $value, | |
| multiple => 0, | |
| height => 1 ) } ]] ); | |
| } | |
| # basic input renderer for "set" type fields | |
| sub render_set_input | |
| { | |
| my( $self, $session, $default, $required, $obj, $basename ) = @_; | |
| my( $tags, $labels ) = $self->input_tags_and_labels( $session, $obj ); | |
| my $input_style = $self->get_property( "input_style" ); | |
| my @classes; | |
| push @classes, join('_', 'ep', $self->{dataset}->base_id, $self->name); | |
| push @classes, join('_', 'eptype', $self->{dataset}->base_id, $self->type); | |
| push @classes, join('_', 'eptype', $self->{dataset}->base_id, $self->type, $input_style) if $input_style; | |
| if( | |
| !$self->get_property( "multiple" ) && | |
| !$required ) | |
| { | |
| # If it's not multiple and not required there | |
| # must be a way to unselect it. | |
| $tags = [ "", @{$tags} ]; | |
| my $unspec = EPrints::Utils::tree_to_utf8( $self->render_option( $session, undef ) ); | |
| $labels = { ""=>$unspec, %{$labels} }; | |
| } | |
| if( $input_style eq "short" ) | |
| { | |
| return( $session->render_option_list( | |
| checkbox => ($self->{form_input_style} eq "checkbox" ?1:0), | |
| values => $tags, | |
| labels => $labels, | |
| name => $basename, | |
| class => join(" ", @classes), | |
| id => $basename, | |
| default => $default, | |
| multiple => $self->{multiple}, | |
| height => $self->{input_rows} ) ); | |
| } | |
| my( $list ); | |
| if( $input_style eq "long" ) | |
| { | |
| $list = $session->make_element( "dl", class=>"ep_field_set_long" ); | |
| } | |
| else | |
| { | |
| $list = $session->make_doc_fragment; | |
| } | |
| foreach my $opt ( @{$tags} ) | |
| { | |
| # "group" set options under headings | |
| my $phraseid = $self->{confid}."_optheading_".$self->{name}."_".$opt; | |
| if( $session->get_lang->has_phrase( $phraseid ) ) | |
| { | |
| my $div = $session->make_element( "div", class => "ep_optheading" ); | |
| $div->appendChild( $session->html_phrase( $phraseid ) ); | |
| $list->appendChild( $div ); | |
| } | |
| my $row; | |
| if( $input_style eq "long" ) | |
| { | |
| $row = $session->make_element( "dt" ); | |
| } | |
| else | |
| { | |
| $row = $session->make_element( "div" ); | |
| } | |
| my $label1 = $session->make_element( "label", for=>$basename."_".$opt ); | |
| $row->appendChild( $label1 ); | |
| my $checked = undef; | |
| my $type = "radio"; | |
| if( $self->{multiple} ) | |
| { | |
| $type = "checkbox"; | |
| foreach( @{$default} ) | |
| { | |
| $checked = "checked" if( $_ eq $opt ); | |
| } | |
| } | |
| else | |
| { | |
| $type = "radio"; | |
| if( defined $default->[0] && $default->[0] eq $opt ) | |
| { | |
| $checked = "checked"; | |
| } | |
| } | |
| $label1->appendChild( $session->render_noenter_input_field( | |
| type => $type, | |
| name => $basename, | |
| id => $basename."_".$opt, | |
| value => $opt, | |
| class => join(" ", @classes), | |
| checked => $checked ) ); | |
| $label1->appendChild( $session->make_text( " ".$labels->{$opt} )); | |
| $list->appendChild( $row ); | |
| next unless( $input_style eq "long" ); | |
| my $dd = $session->make_element( "dd" ); | |
| my $label2 = $session->make_element( "label", for=>$basename."_".$opt ); | |
| $dd->appendChild( $label2 ); | |
| my $phrasename = $self->{confid}."_optdetails_".$self->{name}."_".$opt; | |
| $label2->appendChild( $session->html_phrase( $phrasename )); | |
| $list->appendChild( $dd ); | |
| } | |
| return $list; | |
| } | |
| sub form_value_actual | |
| { | |
| my( $self, $session, $obj, $basename ) = @_; | |
| if( $self->get_property( "input_ordered" ) ) | |
| { | |
| return $self->SUPER::form_value_actual( $session, $obj, $basename ); | |
| } | |
| my @values = grep { | |
| $_ ne "-" # for the ------- in defaults at top | |
| } $session->param( $basename ); | |
| return $self->get_property( "multiple" ) ? \@values : $values[0]; | |
| } | |
| # the ordering for set is NOT the same as for normal | |
| # fields. | |
| sub get_values | |
| { | |
| my( $self, $session, $dataset, %opts ) = @_; | |
| my @tags = $self->tags( $session ); | |
| return \@tags; | |
| } | |
| sub get_value_label | |
| { | |
| my( $self, $session, $value ) = @_; | |
| return $self->render_option( $session, $value ); | |
| } | |
| sub ordervalue_basic | |
| { | |
| my( $self , $value , $session , $langid ) = @_; | |
| return "" unless( EPrints::Utils::is_set( $value ) ); | |
| my $label = $self->get_value_label( $session, $value ); | |
| return EPrints::Utils::tree_to_utf8( $label ); | |
| } | |
| sub split_search_value | |
| { | |
| my( $self, $session, $value ) = @_; | |
| return $self->EPrints::MetaField::split_search_value( $session, $value ); | |
| } | |
| sub render_search_input | |
| { | |
| my( $self, $session, $searchfield ) = @_; | |
| my $frag = $session->make_doc_fragment; | |
| $frag->appendChild( $self->render_search_set_input( | |
| $session, | |
| $searchfield ) ); | |
| if( $self->get_property( "multiple" ) ) | |
| { | |
| my @set_tags = ( "ANY", "ALL" ); | |
| my %set_labels = ( | |
| "ANY" => $session->phrase( "lib/searchfield:set_any" ), | |
| "ALL" => $session->phrase( "lib/searchfield:set_all" ) ); | |
| $frag->appendChild( $session->make_text(" ") ); | |
| $frag->appendChild( | |
| $session->render_option_list( | |
| name=>$searchfield->get_form_prefix."_merge", | |
| values=>\@set_tags, | |
| default=>$searchfield->get_merge, | |
| labels=>\%set_labels ) ); | |
| } | |
| if( $searchfield->get_match ne $self->property( "match" ) ) | |
| { | |
| $frag->appendChild( | |
| $session->render_hidden_field( | |
| $searchfield->get_form_prefix . "_match", | |
| $searchfield->get_match | |
| ) ); | |
| } | |
| return $frag; | |
| } | |
| sub render_search_set_input | |
| { | |
| my( $self, $session, $searchfield ) = @_; | |
| my $prefix = $searchfield->get_form_prefix; | |
| my $value = $searchfield->get_value; | |
| my( $tags, $labels ) = ( [], {} ); | |
| # find all the fields we're searching to get their options | |
| # too if we need to! | |
| my @allfields = @{$searchfield->get_fields}; | |
| if( scalar @allfields == 1 ) | |
| { | |
| ( $tags, $labels ) = $self->tags_and_labels( $session ); | |
| } | |
| else | |
| { | |
| my( $t ) = {}; | |
| foreach my $field ( @allfields ) | |
| { | |
| my ( $t2, $l2 ) = $field->tags_and_labels( $session ); | |
| foreach( @{$t2} ) { $t->{$_}=1; } | |
| foreach( keys %{$l2} ) { $labels->{$_}=$l2->{$_}; } | |
| } | |
| my @tags = keys %{$t}; | |
| $tags = \@tags; | |
| } | |
| my $max_rows = $self->get_property( "search_rows" ); | |
| my $height = scalar @$tags; | |
| $height = $max_rows if( $height > $max_rows ); | |
| my @defaults = ();; | |
| # Do we have any values already? | |
| if( defined $value && $value ne "" ) | |
| { | |
| @defaults = split /\s/, $value; | |
| } | |
| return $session->render_option_list( | |
| checkbox => ($self->{search_input_style} eq "checkbox"?1:0), | |
| name => $prefix, | |
| default => \@defaults, | |
| multiple => 1, | |
| labels => $labels, | |
| values => $tags, | |
| height => $height ); | |
| } | |
| sub from_search_form | |
| { | |
| my( $self, $session, $prefix ) = @_; | |
| my @vals = (); | |
| foreach( $session->param( $prefix ) ) | |
| { | |
| next if m/^\s*$/; | |
| # ignore the "--------" divider. | |
| next if m/^-$/; | |
| push @vals,$_; | |
| } | |
| # We have some values. Join them together. | |
| my $val = join ' ', @vals; | |
| $val = undef if $val eq ''; | |
| return( | |
| $val, | |
| scalar($session->param( $prefix."_match" )), | |
| scalar($session->param( $prefix."_merge" )) | |
| ); | |
| } | |
| sub render_search_description | |
| { | |
| my( $self, $session, $sfname, $value, $merge, $match ) = @_; | |
| my $phraseid; | |
| if( $merge eq "ANY" ) | |
| { | |
| $phraseid = "lib/searchfield:desc_any_in"; | |
| } | |
| else | |
| { | |
| $phraseid = "lib/searchfield:desc_all_in"; | |
| } | |
| my $valuedesc = $session->make_doc_fragment; | |
| my $max_to_show = $self->get_property( "render_max_search_values" ); | |
| my @list = split( ' ', $value ); | |
| for( my $i=0; $i<scalar @list; ++$i ) | |
| { | |
| if( $max_to_show && $i == $max_to_show ) | |
| { | |
| $valuedesc->appendChild( $session->html_phrase( "lib/searchfield:n_more_values", | |
| n => $session->xml->create_text_node( scalar @list - $i ), | |
| total => $session->xml->create_text_node( scalar @list ) ) ); | |
| last; | |
| } | |
| if( $i>0 ) | |
| { | |
| $valuedesc->appendChild( $session->make_text( ", " ) ); | |
| } | |
| $valuedesc->appendChild( $session->make_text( '"' ) ); | |
| $valuedesc->appendChild( | |
| $self->get_value_label( $session, $list[$i] ) ); | |
| $valuedesc->appendChild( $session->make_text( '"' ) ); | |
| } | |
| return $session->html_phrase( | |
| $phraseid, | |
| name => $sfname, | |
| value => $valuedesc ); | |
| } | |
| sub get_search_conditions_not_ex | |
| { | |
| my( $self, $session, $dataset, $search_value, $match, $merge, | |
| $search_mode ) = @_; | |
| return EPrints::Search::Condition->new( | |
| '=', | |
| $dataset, | |
| $self, | |
| $search_value ); | |
| } | |
| sub get_search_group { return 'set'; } | |
| sub get_property_defaults | |
| { | |
| my( $self ) = @_; | |
| my %defaults = $self->SUPER::get_property_defaults; | |
| $defaults{input_style} = "short"; | |
| $defaults{search_input_style} = "checkbox"; | |
| $defaults{form_input_style} = "select"; | |
| $defaults{input_rows} = $EPrints::MetaField::FROM_CONFIG; | |
| $defaults{input_ordered} = 0; | |
| $defaults{search_rows} = $EPrints::MetaField::FROM_CONFIG; | |
| $defaults{options} = $EPrints::MetaField::REQUIRED; | |
| $defaults{input_tags} = $EPrints::MetaField::UNDEF; | |
| $defaults{render_option} = $EPrints::MetaField::UNDEF; | |
| $defaults{render_max_search_values} = 5; | |
| $defaults{text_index} = 1; | |
| $defaults{sql_index} = 1; | |
| $defaults{match} = "EQ"; | |
| $defaults{merge} = "ANY"; | |
| $defaults{order_labels} = 0; | |
| return %defaults; | |
| } | |
| sub get_xml_schema_type | |
| { | |
| my( $self ) = @_; | |
| return $self->get_xml_schema_field_type; | |
| } | |
| sub render_xml_schema_type | |
| { | |
| my( $self, $session ) = @_; | |
| my $type = $session->make_element( "xs:simpleType", name => $self->get_xml_schema_type ); | |
| my( $tags, $labels ) = $self->tags_and_labels( $session ); | |
| my $restriction = $session->make_element( "xs:restriction", base => "xs:string" ); | |
| $type->appendChild( $restriction ); | |
| foreach my $value (@$tags) | |
| { | |
| my $enumeration = $session->make_element( "xs:enumeration", value => $value ); | |
| $restriction->appendChild( $enumeration ); | |
| if( defined $labels->{$value} ) | |
| { | |
| my $annotation = $session->make_element( "xs:annotation" ); | |
| $enumeration->appendChild( $annotation ); | |
| my $documentation = $session->make_element( "xs:documentation" ); | |
| $annotation->appendChild( $documentation ); | |
| $documentation->appendChild( $session->make_text( $labels->{$value} ) ); | |
| } | |
| } | |
| return $type; | |
| } | |
| ###################################################################### | |
| 1; | |
| =head1 COPYRIGHT | |
| =for COPYRIGHT BEGIN | |
| Copyright 2019 University of Southampton. | |
| EPrints 3.4 is supplied by EPrints Services. | |
| http://www.eprints.org/eprints-3.4/ | |
| =for COPYRIGHT END | |
| =for LICENSE BEGIN | |
| This file is part of EPrints 3.4 L<http://www.eprints.org/>. | |
| EPrints 3.4 and this file are released under the terms of the | |
| GNU Lesser General Public License version 3 as published by | |
| the Free Software Foundation unless otherwise stated. | |
| EPrints 3.4 is distributed in the hope that it will be useful, | |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
| See the GNU Lesser General Public License for more details. | |
| You should have received a copy of the GNU Lesser General Public | |
| License along with EPrints 3.4. | |
| If not, see L<http://www.gnu.org/licenses/>. | |
| =for LICENSE END | |