package HTML::FormFu::Attribute; use strict; use Exporter qw( import ); use HTML::FormFu::Util qw( append_xml_attribute remove_xml_attribute literal _parse_args ); our @EXPORT_OK = qw( mk_attrs mk_attr_accessors mk_attr_modifiers mk_inherited_accessors mk_output_accessors mk_inherited_merging_accessors mk_item_accessors mk_accessors ); sub mk_accessors { my $class = shift; for my $name (@_) { my $sub = sub { my $self = shift; if ( @_ == 1 ) { $self->{$name} = $_[0]; return $self; } elsif (@_) { $self->{$name} = [@_]; return $self; } else { return $self->{$name}; } }; no strict 'refs'; *{"$class\::$name"} = $sub; } } sub mk_item_accessors { my $class = shift; for my $name (@_) { my $sub = sub { my $self = shift; if (@_) { $self->{$name} = $_[0]; return $self; } else { return $self->{$name}; } }; no strict 'refs'; *{"$class\::$name"} = $sub; } } sub mk_attrs { my ( $self, @names ) = @_; my $class = ref $self || $self; for my $name (@names) { my $sub = sub { my $self = shift; if ( !exists $self->{$name} ) { $self->{$name} = {}; } return $self->{$name} if !@_; my $attr_slot = $self->{$name}; my %attrs = ( @_ == 1 ) ? %{ $_[0] } : @_; while ( my ( $key, $value ) = each %attrs ) { $attr_slot->{$key} = $value; } return $self; }; my $xml_sub = sub { my $self = shift; my %attrs = ( @_ == 1 ) ? %{ $_[0] } : @_; return $self->$name( map { $_, literal( $attrs{$_} ) } keys %attrs ); }; no strict 'refs'; *{"$class\::$name"} = $sub; *{"$class\::${name}_xml"} = $xml_sub; # add shortcuts my $short = $name; if ( $short =~ s/attributes$/attrs/ ) { *{"$class\::$short"} = $sub; *{"$class\::${short}_xml"} = $xml_sub; } } mk_add_attrs( $class, @names ); mk_del_attrs( $class, @names ); return; } sub mk_attr_accessors { my ( $self, @names ) = @_; my $class = ref $self || $self; for my $name (@names) { my $sub = sub { return ( $_[0]->attributes->{$name} ) if @_ == 1; my $self = shift; $self->attributes->{$name} = $_[0]; return $self; }; my $xml_sub = sub { my $self = shift; my @args; for my $item (@_) { if ( ref $item eq 'HASH' ) { push @args, { map { $_, literal($_) } keys %$item }; } elsif ( ref $item eq 'ARRAY' ) { push @args, [ map { literal($_) } @$item ]; } else { push @args, literal($item); } } return $self->$name(@args); }; no strict 'refs'; *{"$class\::$name"} = $sub; *{"$class\::${name}_xml"} = $xml_sub; # add shortcuts my $short = $name; if ( $short =~ s/attributes$/attrs/ ) { *{"$class\::$short"} = $sub; *{"$class\::${short}_xml"} = $xml_sub; } } return; } sub mk_add_attrs { my ( $self, @names ) = @_; my $class = ref $self || $self; for my $name (@names) { my $sub = sub { my $self = shift; my %attrs = ( @_ == 1 ) ? %{ $_[0] } : @_; while ( my ( $key, $value ) = each %attrs ) { append_xml_attribute( $self->{$name}, $key, $value ); } return $self; }; my $xml_sub = sub { my $self = shift; my %attrs = ( @_ == 1 ) ? %{ $_[0] } : @_; my $method = "add_$name"; return $self->$method( { map { $_, literal( $attrs{$_} ) } keys %attrs } ); }; no strict 'refs'; *{"$class\::add_$name"} = $sub; *{"$class\::add_${name}_xml"} = $xml_sub; # add shortcuts my $short = $name; if ( $short =~ s/attributes$/attrs/ ) { *{"$class\::add_$short"} = $sub; *{"$class\::add_${short}_xml"} = $xml_sub; } } return; } sub mk_del_attrs { my ( $self, @names ) = @_; my $class = ref $self || $self; for my $name (@names) { my $sub = sub { my $self = shift; my %attrs = ( @_ == 1 ) ? %{ $_[0] } : @_; while ( my ( $key, $value ) = each %attrs ) { remove_xml_attribute( $self->{$name}, $key, $value ); } return $self; }; my $xml_sub = sub { my $self = shift; my %attrs = ( @_ == 1 ) ? %{ $_[0] } : @_; my $method = "del_$name"; return $self->$method( { map { $_, literal( $attrs{$_} ) } keys %attrs } ); }; no strict 'refs'; *{"$class\::del_$name"} = $sub; *{"$class\::del_${name}_xml"} = $xml_sub; # add shortcuts my $short = $name; if ( $short =~ s/attributes$/attrs/ ) { *{"$class\::del_$short"} = $sub; *{"$class\::del_${short}_xml"} = $xml_sub; } } return; } sub mk_inherited_accessors { my ( $self, @names ) = @_; my $class = ref $self || $self; for my $name (@names) { my $sub = sub { my $self = shift; if (@_) { $self->{$name} = $_[0]; return $self; } # micro optimization! this method's called a lot, so access # parent hashkey directly, instead of calling parent() while ( defined( my $parent = $self->{parent} ) && !defined $self->{$name} ) { $self = $parent; } return $self->{$name}; }; no strict 'refs'; *{"$class\::$name"} = $sub; } return; } sub mk_inherited_merging_accessors { my ( $self, @names ) = @_; my $class = ref $self || $self; $class->mk_inherited_accessors(@names); for my $name (@names) { my $sub = sub { my $self = shift; if (@_) { my %attrs = ( @_ == 1 ) ? %{ $_[0] } : @_; while ( my ( $key, $value ) = each %attrs ) { append_xml_attribute( $self->{$name}, $key, $value ); } return $self; } # micro optimization! this method's called a lot, so access # parent hashkey directly, instead of calling parent() while ( defined( my $parent = $self->{parent} ) && !defined $self->{$name} ) { $self = $parent; } return $self->{$name}; }; no strict 'refs'; *{"$class\::add_$name"} = $sub; } return; } sub mk_output_accessors { my ( $self, @names ) = @_; my $class = ref $self || $self; for my $name (@names) { my $sub = sub { my $self = shift; if (@_) { $self->{$name} = $_[0]; return $self; } return $self->{$name}; }; my $xml_sub = sub { my ( $self, $arg ) = @_; return $self->$name( literal($arg) ); }; my $loc_sub = sub { my ( $self, $mess, @args ) = @_; if ( ref $mess eq 'ARRAY' ) { ( $mess, @args ) = ( @$mess, @args ); } return $self->$name( literal( $self->form->localize( $mess, @args ) ) ); }; no strict 'refs'; *{"$class\::$name"} = $sub; *{"$class\::${name}_xml"} = $xml_sub; *{"$class\::${name}_loc"} = $loc_sub; } return; } 1; __END__ =head1 NAME HTML::FormFu::Attribute =head1 SYNOPSIS =head1 DESCRIPTION =head1 METHODS =head1 AUTHOR Carl Franks, C Based on the original source code of L, by Sebastian Riedel, C. =head1 LICENSE This library is free software, you can redistribute it and/or modify it under the same terms as Perl itself.