package Mojolicious::Plugin::XML::Loy; use Mojo::Base 'Mojolicious::Plugin'; use Mojo::Loader; use Mojo::Util 'deprecated'; use XML::Loy; our $VERSION = '0.08'; my %base_classes; # Register Plugin sub register { my ($plugin, $mojo, $param) = @_; my $namespace = 'XML::Loy::'; my $max_size = 1024 * 1024; # Load parameter from Config file if (my $config_param = $mojo->config('XML-Loy')) { $param = { %$config_param, %$param }; }; # Set Namespace if (exists $param->{namespace}) { deprecated 'namespace parameter is DEPRECATED in favor of minus symbol'; $namespace = delete $param->{namespace}; $namespace .= '::' if $namespace; }; if (exists $param->{max_size} && $param->{max_size} =~ /^\d+$/) { $max_size = delete $param->{max_size}; }; # Start Mojo::Loader instance my $loader = Mojo::Loader->new; # Create new XML helpers foreach my $helper (keys %$param) { # Already defined if (exists $mojo->renderer->helpers->{$helper}) { $mojo->log->debug("Helper '$helper' already defined"); next; }; my @helper = @{ $param->{ $helper } }; my $base = shift @helper; # Deprecated in M::P::XML::Loy 0.4 if ($base eq 'Loy') { deprecated 'Loy is DEPRECATED as a base in favor of -Loy'; $base = '-Loy'; }; if ($base eq '-Loy') { $base = 'XML::Loy'; } elsif ($base =~ m/^(?:Atom(?:\:\:Threading)|XRD|HostMeta|ActivityStreams)$/) { deprecated $base . ' is DEPRECATED as a base in favor of -' . $base; $base = '-' . $base; }; if (index($base, '-') == 0) { $base =~ s/^-//; $base = ($base eq 'Loy' ? 'XML::Loy' : $namespace . "$base"); }; # Load module if not loaded unless (exists $base_classes{$base}) { # Load base class if (my $e = $loader->load($base)) { for ($mojo->log) { $_->error("Exception: $e") if ref $e; $_->error(qq{Unable to load base class "$base"}); }; next; }; my $mime = $base->mime; my $prefix = $base->_prefix; # Establish mime types if ($mime && $prefix) { # Apply mime type $mojo->types->type($prefix => $mime); }; # module loaded $base_classes{$base} = [$prefix => $mime]; }; # Code generation for ad-hoc helper my $code = 'sub { shift;' . ' { use bytes; return if length("@_") > ' . $max_size . '} ' . ' my $doc = ' . $base . '->new( @_ );'; # Extend base class if (@helper) { $code .= '$doc->extension(' . join(',', map( '"' . qq{$_"}, @helper)) . ");"; }; $code .= 'return $doc };'; # Eval code my $code_ref = eval $code; # Evaluation error $mojo->log->fatal($@ . ': ' . $!) and next if $@; # Create helper $mojo->helper($helper => $code_ref); }; # Plugin wasn't registered before unless (exists $mojo->renderer->helpers->{'new_xml'}) { # Default 'new_xml' helper $mojo->helper( new_xml => sub { shift; return XML::Loy->new( @_ ); }); # Add 'render_xml' helper $mojo->helper( render_xml => sub { my ($c, $xml) = @_; my $format = 'xml'; # Check format based on mime type my $class = ref $xml; if ($base_classes{$class}) { if ($base_classes{$class}->[0] && $base_classes{$class}->[1]) { $format = $base_classes{$class}->[0]; }; }; # render XML with correct mime type return $c->render( 'data' => $xml->to_pretty_xml, 'format' => $format, @_ ); }); }; }; 1; __END__ =pod =head1 NAME Mojolicious::Plugin::XML::Loy - XML Generation with Mojolicious =head1 SYNOPSIS # Mojolicious $mojo->plugin( 'XML::Loy' => { new_activity => [-Atom, -ActivityStreams], new_hostmeta => [-XRD, -HostMeta], new_myXML => [-Loy, -Atom, -Atom::Threading] }); # In controllers use the generic new_xml helper my $xml = $c->new_xml('entry'); # Create a new XML::Loy document my $xml = $app->new_xml('html'); $xml->add('header')->add( title => 'XML-Loy example' => 'My Title!' ); for ($xml->add('body' => { style => 'color: red' })) { $_->add(p => 'First paragraph'); $_->add(p => { -type => 'raw' } => 'Second') ->add(b => 'paragraph'); }; # Render document with the correct mime-type $c->render_xml($xml); # Content-Type: application/xml # # #
# # # XML-Loy example #
# #

First paragraph

#

Secondparagraph

# # # Use newly created helper my $xrd = $c->new_hostmeta; # Create a document based on the defined xml profile $xrd->host('sojolicio.us'); # Render document with the correct mime-type $c->render_xml($xrd); # Content-Type: application/xrd+xml # # # sojolicio.us # =head1 DESCRIPTION L is a plugin to support XML document generation based on L. =head1 METHODS L inherits all methods from L and implements the following new ones. =head2 register # Mojolicious $mojo->plugin(XML::Loy => { max_size => 2048, new_activity => [-Atom, -ActivityStreams] }); # Mojolicious::Lite plugin XML::Loy => { new_activity => [-Atom, -ActivityStreams] }; # In your config file { XML::Loy => { new_activity => [-Atom, -ActivityStreams] } }; Called when registering the plugin. Accepts new xml profiles, defined by the name of the associated generation helper and an array reference defining the profile. The first element in the array is the base class, followed by all extensions. To create a helper extending the base class, use C<-Loy> as the first element. $mojo->plugin('XML::Loy' => { new_myXML => [-Loy, 'MyXML::Loy::Extension'] }); In addition to that, the C in bytes of xml documents to be parsed can be defined (defaults to C<1024 * 1024>). All parameters can be set either on registration or as part of the configuration file with the key C. B The C parameter is DEPRECATED. =head1 HELPERS =head2 new_xml my $xml = $c->new_xml('entry'); print $xml->to_pretty_xml; Creates a new generic L document. All helpers created on registration accept the parameters as defined in the constructors of the L base classes. =head2 render_xml $c->render_xml($xml); $c->render_xml($xml, status => 404); Renders documents based on L using the defined mime-type of the base class. =head1 DEPENDENCIES L, L. =head1 AVAILABILITY https://github.com/Akron/Mojolicious-Plugin-XML-Loy =head1 COPYRIGHT AND LICENSE Copyright (C) 2011-2013, L. This program is free software, you can redistribute it and/or modify it under the same terms as Perl. =cut