# $Id$ ## no critic package AxKit::XSP::Handel::Checkout; use strict; use warnings; use vars qw($NS); use Handel::ConfigReader; use Handel::Constants qw(:checkout str_to_const); use Handel::Exception; use Handel::L10N qw(translate); use AxKit::XSP::Handel::Order; use base 'Apache::AxKit::Language::XSP'; $NS = 'http://today.icantfocus.com/CPAN/AxKit/XSP/Handel/Checkout'; #{ my @context = 'root'; sub start_document { return "use Handel::Checkout;\nuse Handel::Constants qw(:checkout);\n"; }; sub parse_char { my ($e, $text) = @_; my $tag = $e->current_element(); return unless length($text); if ($tag eq 'addmessage') { return "\n\$_xsp_handel_checkout_addmessage_hash{'text'} = q|" . $text . "|;\n"; } elsif ($tag =~ /^load(order|cart)$/) { return ".q|$text|"; }; return ''; }; sub parse_start { my ($e, $tag, %attr) = @_; AxKit::Debug(5, "[Handel] [Checkout] parse_start [$tag] context: " . join('->', @context)); if ($tag eq 'new') { throw Handel::Exception::Taglib( -text => translate('TAG_NOT_ALLOWED_IN_OTHERS', $tag) ) if ($context[-1] ne 'root'); push @context, $tag; my $code = "my \$_xsp_handel_checkout;my \$_xsp_handel_checkout_status;my \$_xsp_handel_checkout_new_options;my \$_xsp_handel_checkout_new_called;\n"; $code .= scalar keys %attr ? 'my %_xsp_handel_checkout_new_filter = ("' . join('", "', %attr) . '");' : 'my %_xsp_handel_checkout_new_filter;' ; return "\n{\n$code\n"; } elsif ($tag eq 'plugins') { push @context, $tag; my $code = ' if (!$_xsp_handel_checkout_new_called) { $_xsp_handel_checkout = Handel::Checkout->new(\%_xsp_handel_checkout_new_filter); $_xsp_handel_checkout_new_called++; }; foreach my $_xsp_handel_checkout_plugin ($_xsp_handel_checkout->plugins) { '; return $code; } elsif ($tag eq 'plugin') { throw Handel::Exception::Taglib( -text => translate('Tag [_1] not valid inside of tag [_2]', $tag, $context[-1]) ) if ($context[-1] ne 'plugins'); push @context, $tag; $e->start_expr($tag); $e->append_to_script("ref \$_xsp_handel_checkout_plugin;\n"); $e->end_expr($tag); } elsif ($tag eq 'messages') { push @context, $tag; my $code = ' if (!$_xsp_handel_checkout_new_called) { $_xsp_handel_checkout = Handel::Checkout->new(\%_xsp_handel_checkout_new_filter); $_xsp_handel_checkout_new_called++; }; foreach my $_xsp_handel_checkout_message ($_xsp_handel_checkout->messages) { '; return $code; } elsif ($tag eq 'message' || $tag =~ /^message\-(.*)$/) { my $property = $1; # I have no friggin clue how the regexp above on this tag can # yield checkout, but it does. :-) undef $property if ($property eq 'checkout'); throw Handel::Exception::Taglib( -text => translate('Tag [_1] not valid inside of tag [_2]', $tag, $context[-1]) ) if ($context[-1] ne 'messages'); push @context, $tag; $e->start_expr($tag); if ($property) { $e->append_to_script("\$_xsp_handel_checkout_message->$property;\n"); } else { $e->append_to_script("\$_xsp_handel_checkout_message;\n"); }; $e->end_expr($tag); } elsif ($tag eq 'addmessage') { my $code = 'my $_xsp_handel_checkout_addmessage_hash; if (!$_xsp_handel_checkout_new_called) { $_xsp_handel_checkout = Handel::Checkout->new(\%_xsp_handel_checkout_new_filter); $_xsp_handel_checkout_new_called++; }; '; $code .= scalar keys %attr ? 'my %_xsp_handel_checkout_addmessage_hash = ("' . join('", "', %attr) . '");' : 'my %_xsp_handel_checkout_addmessage_hash;' ; return "\n{\n$code\n"; } elsif ($tag eq 'phases') { push @context, $tag; my $code = ' if (!$_xsp_handel_checkout_new_called) { $_xsp_handel_checkout = Handel::Checkout->new(\%_xsp_handel_checkout_new_filter); $_xsp_handel_checkout_new_called++; }; foreach my $_xsp_handel_checkout_phase ($_xsp_handel_checkout->phases) { '; return $code; } elsif ($tag eq 'phase') { throw Handel::Exception::Taglib( -text => translate('Tag [_1] not valid inside of tag [_2]', $tag, $context[-1]) ) if ($context[-1] ne 'phases'); push @context, $tag; $e->start_expr($tag); $e->append_to_script("\$_xsp_handel_checkout_phase;\n"); $e->end_expr($tag); } elsif ($tag eq 'process') { push @context, $tag; my $code = ' if (!$_xsp_handel_checkout_new_called) { $_xsp_handel_checkout = Handel::Checkout->new(\%_xsp_handel_checkout_new_filter); $_xsp_handel_checkout_new_called++; }; $_xsp_handel_checkout_status = $_xsp_handel_checkout->process; '; return $code; } elsif ($tag =~ /^(ok|success(ful)?)$/) { push @context, $tag; my $code = ' if ($_xsp_handel_checkout_status == CHECKOUT_STATUS_OK) { '; return $code; } elsif ($tag =~ /^(error|fail(ure)?)$/) { push @context, $tag; my $code = ' if ($_xsp_handel_checkout_status != CHECKOUT_STATUS_OK) { '; return $code; } elsif ($tag eq 'loadorder') { push @context, $tag; my $code = ' if (!$_xsp_handel_checkout_new_called) { $_xsp_handel_checkout = Handel::Checkout->new(\%_xsp_handel_checkout_new_filter); $_xsp_handel_checkout_new_called++; }; $_xsp_handel_checkout->order(\'\''; return $code; } elsif ($tag eq 'loadcart') { push @context, $tag; my $code = ' if (!$_xsp_handel_checkout_new_called) { $_xsp_handel_checkout = Handel::Checkout->new(\%_xsp_handel_checkout_new_filter); $_xsp_handel_checkout_new_called++; }; $_xsp_handel_checkout->cart(\'\''; return $code; } elsif ($tag eq 'order') { push @context, $tag; AxKit::XSP::Handel::Order::push_context(qw(order results)); my $code = ' if (!$_xsp_handel_checkout_new_called) { $_xsp_handel_checkout = Handel::Checkout->new(\%_xsp_handel_checkout_new_filter); $_xsp_handel_checkout_new_called++; }; my $_xsp_handel_order_order = $_xsp_handel_checkout->order; if ($_xsp_handel_order_order) { '; return $code; }; return ''; }; sub parse_end { my ($e, $tag) = @_; AxKit::Debug(5, "[Handel] [Checkout] parse_end [$tag] context: " . join('->', @context)); if ($tag eq 'new') { pop @context; return "\n};\n"; } elsif ($tag eq 'plugins') { pop @context; return ' }; '; } elsif ($tag eq 'plugin') { pop @context; } elsif ($tag eq 'messages') { pop @context; return ' }; '; } elsif ($tag eq 'message' || $tag =~ /^message-(.*)$/) { pop @context; } elsif ($tag eq 'addmessage') { return ' $_xsp_handel_checkout->add_message(Handel::Checkout::Message->new(%_xsp_handel_checkout_addmessage_hash)); }; '; } elsif ($tag eq 'phases') { pop @context; return ' }; '; } elsif ($tag eq 'phase') { pop @context; } elsif ($tag eq 'process') { pop @context; } elsif ($tag =~ /^(ok|success(ful)?)$/) { pop @context; my $code = ' }; '; return $code; } elsif ($tag =~ /^(error|fail(ure)?)$/) { pop @context; my $code = ' }; '; return $code; } elsif ($tag eq 'loadorder') { pop @context; my $code = '); '; return $code; } elsif ($tag eq 'loadcart') { pop @context; my $code = '); '; return $code; } elsif ($tag eq 'order') { pop @context; AxKit::XSP::Handel::Order::pop_context(2); my $code = ' }; '; return $code; }; return ''; }; #}; 1; __END__ =head1 NAME AxKit::XSP::Handel::Checkout - AxKit XSP Checkout Taglib =head1 SYNOPSIS Add this taglib to AxKit in your http.conf or .htaccess: AxAddXSPTaglib AxKit::XSP::Handel::Checkout Add the namespace to your XSP file and use the tags: 11111111-1111-1111-1111-111111111111 Your order has be charged! ... Bad things happened! =head1 DESCRIPTION This tag library provides an interface to use C inside of your AxKit XSP pages. =head1 TAG HIERARCHY ... ... =head1 TAG REFERENCE =head2 Adds a message to the current checkouts messages collection: My new message... =head2 If process fails, anything in the error block is run: Something bad happened! You may also use fail and failure in addition to ok. =head2 Loads the specified cart into the current checkout process. It currently accepts the carts uuid value: 11111111-1111-1111-1111-11111111 =head2 Loads the specified order into the current checkout process. IT currently accepts the orders uuid value: 11111111-1111-1111-1111-11111111 =head2 If process succeeds, anything in the ok block is run: Your order is complete! You may also use success and successful in addition to ok. =head2 Returns the current message text. You may also access additional message properties by append -propertyname to the message tag: =head2 Returns the messages associated to this checkout process; usually containing failure information. =head2 Creates a new checkout process. See L for the available options. =head2 Returns the order currently associated with this checkout process. If you also load the Order taglib, all order properties are available: ... =head2 Returns the current phase value in the list of phases: =head2 Loops though the list of phases for the current checkout process: =head2 Returns the current plugin name in the list of loaded plugins: =head2 Loops through the list of loaded plugins for the current checkout process: =head2 Runs the current checkout process and sets ok/error: See L for the available options to process. =head1 AUTHOR Christopher H. Laco CPAN ID: CLACO claco@chrislaco.com http://today.icantfocus.com/blog/