[Jifty-commit] r2905 - in jifty/branches/template-declare: . lib/Jifty lib/Jifty/Plugin lib/Jifty/Plugin/Authentication lib/Jifty/Plugin/ErrorTemplates lib/Jifty/Plugin/SkeletonApp

jifty-commit at lists.jifty.org jifty-commit at lists.jifty.org
Sun Mar 4 16:24:17 EST 2007


Author: jesse
Date: Sun Mar  4 16:24:16 2007
New Revision: 2905

Added:
   jifty/branches/template-declare/lib/Jifty/Plugin/ErrorTemplates.pm
Removed:
   jifty/branches/template-declare/lib/Jifty/View/Declare/WebServices.pm
Modified:
   jifty/branches/template-declare/   (props changed)
   jifty/branches/template-declare/lib/Jifty/Config.pm
   jifty/branches/template-declare/lib/Jifty/Plugin/Authentication/Password.pm
   jifty/branches/template-declare/lib/Jifty/Plugin/ErrorTemplates/View.pm
   jifty/branches/template-declare/lib/Jifty/Plugin/SkeletonApp/View.pm
   jifty/branches/template-declare/lib/Jifty/View/Declare/CoreTemplates.pm
   jifty/branches/template-declare/lib/Jifty/View/Declare/Handler.pm
   jifty/branches/template-declare/lib/Jifty/View/Declare/Helpers.pm

Log:
 r52975 at pinglin:  jesse | 2007-03-04 22:22:24 +0100
  * T::D branch passes all tests


Modified: jifty/branches/template-declare/lib/Jifty/Config.pm
==============================================================================
--- jifty/branches/template-declare/lib/Jifty/Config.pm	(original)
+++ jifty/branches/template-declare/lib/Jifty/Config.pm	Sun Mar  4 16:24:16 2007
@@ -268,7 +268,6 @@
         },
         {       Halo => {},},
         {ErrorTemplates => {},},
-        {SkeletonApp => {},},
         {OnlineDocs => {},},
         {        CompressedCSSandJS => {},},
         {AdminUI => {},}

Modified: jifty/branches/template-declare/lib/Jifty/Plugin/Authentication/Password.pm
==============================================================================
--- jifty/branches/template-declare/lib/Jifty/Plugin/Authentication/Password.pm	(original)
+++ jifty/branches/template-declare/lib/Jifty/Plugin/Authentication/Password.pm	Sun Mar  4 16:24:16 2007
@@ -7,4 +7,18 @@
 # Your plugin goes here.  If takes any configuration or arguments, you
 # probably want to override L<Jifty::Plugin/init>.
 
+=head1 NAME
+
+Jifty::Plugin::Authentication::Password
+
+=head1 DESCRIPTION
+
+When finished, this plugin will provide password authentication for 
+your Jifty application. (It adds a "password" column to your "User" model class).
+
+Right now, it's useless and should be ignored.
+
+
+=cut
+
 1;

Added: jifty/branches/template-declare/lib/Jifty/Plugin/ErrorTemplates.pm
==============================================================================
--- (empty file)
+++ jifty/branches/template-declare/lib/Jifty/Plugin/ErrorTemplates.pm	Sun Mar  4 16:24:16 2007
@@ -0,0 +1,20 @@
+use strict;
+use warnings;
+
+package Jifty::Plugin::ErrorTemplates;
+use base qw/Jifty::Plugin/;
+
+# Your plugin goes here.  If takes any configuration or arguments, you
+# probably want to override L<Jifty::Plugin/init>.
+
+=head1 NAME
+
+Jifty::Plugin::ErrorTemplates
+
+=head1 DESCRIPTION
+
+This plugin provides superusers with online documentation for Jifty and your application's API. It's included by default when using Jifty. (That's a bug).
+
+=cut
+
+1;

Modified: jifty/branches/template-declare/lib/Jifty/Plugin/ErrorTemplates/View.pm
==============================================================================
--- jifty/branches/template-declare/lib/Jifty/Plugin/ErrorTemplates/View.pm	(original)
+++ jifty/branches/template-declare/lib/Jifty/Plugin/ErrorTemplates/View.pm	Sun Mar  4 16:24:16 2007
@@ -52,34 +52,57 @@
                               in case the error in question is caused by the Jifty app's wrapper, for instance.
 =cut
 
-sub wrapper (&) {
-    my $code = shift;
-    html {
-        head {
-            title { _('Internal error') }
-            link { attr { rel => 'stylesheet', type => 'text/css', href => "/__jifty/error/error.css", media => 'all'}};
-        }
-        body {
-            div { attr { id => 'headers'};
-            h1 { 'Internal Error' };
-        div { attr { id => 'content'};
-                          a { attr { name => 'content'}};
- if (Jifty->config->framework('AdminMode') ) {
-     div { attr { class => "warning admin_mode" };
-        outs('Alert:' .  tangent( label => 'administration mode' , url => '/__jifty/admin/') .'is enabled.' ) }
- }
- Jifty->web->render_messages;
-    $code->();
-  }
-                              
-                          }
-                      }}
-                  }
+{
+    no warnings qw'redefine';
+
+    sub wrapper ($) {
+        my $code = shift;
+        html {
+            head {
+                title { _('Internal error') } link {
+                    attr {
+                        rel   => 'stylesheet',
+                        type  => 'text/css',
+                        href  => "/__jifty/error/error.css",
+                        media => 'all'
+                    }
+                };
+                }
+                body {
+                div {
+                    attr { id => 'headers' };
+                    h1  {'Internal Error'};
+                    div {
+                        attr { id => 'content' };
+                        a { attr { name => 'content' } };
+                        if ( Jifty->config->framework('AdminMode') ) {
+                            div {
+                                attr { class => "warning admin_mode" };
+                                outs(
+                                    'Alert:'
+                                        . tangent(
+                                        label => 'administration mode',
+                                        url   => '/__jifty/admin/'
+                                        )
+                                        . 'is enabled.'
+                                );
+                                }
+                        }
+                        Jifty->web->render_messages;
+                        $code->();
+                        }
+
+                    }
+                }
+            }
+    }
+}
+
 
 template '__jifty/error/dhandler' => sub {
     my $error = get('error');
                             Jifty->log->error( "Unhandled web error " . $error );
-                            wrapper {
+                            page {
                               title is 'Something went awry';
                               show('_elements/error_text', error => $error );
                         };
@@ -98,7 +121,7 @@
     my $file = get('path');
     Jifty->log->error( "404: user tried to get to " . $file );
     Jifty->handler->apache->header_out( Status => '404' );
-    with( title => _("Something's not quite right") ), wrapper => {
+    with( title => _("Something's not quite right") ), page {
 
         with( id => "overview" ),
         div {

Modified: jifty/branches/template-declare/lib/Jifty/Plugin/SkeletonApp/View.pm
==============================================================================
--- jifty/branches/template-declare/lib/Jifty/Plugin/SkeletonApp/View.pm	(original)
+++ jifty/branches/template-declare/lib/Jifty/Plugin/SkeletonApp/View.pm	Sun Mar  4 16:24:16 2007
@@ -8,6 +8,18 @@
 
 use Scalar::Defer;
 
+=head1 NAME
+
+Jifty::Plugin::SkeletonApp::View
+
+=head1 DESCRIPTION
+
+This somewhat-finished (But not quite) template library implements
+Jifty's "pony" Application. It could certainly use some refactoring. (And some of the menu stuff should get factored out into a dispatcher or the other plugins that implement it.
+
+
+=cut
+
 template '_elements/nav' => sub {
     my $top = Jifty->web->navigation;
     $top->child( Home => url => "/", sort_order => 1, label => _('Home') );

Modified: jifty/branches/template-declare/lib/Jifty/View/Declare/CoreTemplates.pm
==============================================================================
--- jifty/branches/template-declare/lib/Jifty/View/Declare/CoreTemplates.pm	(original)
+++ jifty/branches/template-declare/lib/Jifty/View/Declare/CoreTemplates.pm	Sun Mar  4 16:24:16 2007
@@ -2,8 +2,345 @@
 
 use strict;
 use warnings;
-use vars qw( $r );
 
 use Jifty::View::Declare -base;
 
+use Scalar::Defer;
+
+=head1 NAME 
+
+Jifty::View::Declare::CoreTemplates
+
+=head1 DESCRIPTION
+
+This library contains templates that Jifty can't function without:
+
+=over
+
+=item PubSub
+
+=item Validate
+
+=item Autocomplete
+
+=item Canonicalize
+
+=item YAML and XML webservice endpoints for core jifty functionality
+
+=cut
+
+template '__jifty/subs' => sub {
+    my ($forever) = get(qw(forever)) || 1;
+
+    Jifty->handler->apache->content_type("text/html; charset=utf-8");
+    Jifty->handler->apache->headers_out->{'Pragma'}        = 'no-cache';
+    Jifty->handler->apache->headers_out->{'Cache-control'} = 'no-cache';
+    Jifty->handler->apache->send_http_header;
+
+    my $writer = XML::Writer->new;
+    $writer->xmlDecl( "UTF-8", "yes" );
+
+    my $begin = <<'END';
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/2002/REC-xhtml1-20020801/DTD/xhtml1-strict.dtd">
+<html><head><title></title></head>
+END
+    chomp $begin;
+
+    if ($forever) {
+        my $whitespace = " " x ( 1024 - length $begin );
+        $begin =~ s/<body>$/$whitespace/s;
+    }
+
+    Jifty->web->out($begin);
+    $writer->startTag("body");
+
+    while (1) {
+        my $sent = _write_subs_once($writer);
+        flush STDOUT;
+        last if ( $sent && !$forever );
+        sleep 1;
+    }
+    $writer->endTag();
+    return;
+
+};
+
+sub _write_subs_once {
+    my $writer = shift;
+    Jifty::Subs::Render->render(
+        Jifty->web->session->id,
+        sub {
+            my ( $mode, $name, $content ) = @_;
+            $writer->startTag( "pushfrag", mode => $mode );
+            $writer->startTag( "fragment", id   => $name );
+            $writer->dataElement( "content", $content );
+            $writer->endTag();
+            $writer->endTag();
+        }
+    );
+}
+
+template '__jifty/autocomplete.xml' => sub {
+
+    # Note: the only point to this file is to set the content_type; the actual
+    # behavior is accomplished inside the framework.  It will go away once we
+    # have infrastructure for serving things of various content-types.
+    Jifty->handler->apache->content_type('text/xml; charset=UTF-8');
+    my $ref = Jifty->web->response->result('autocomplete')->content;
+    my @options = @{ $ref->{'completions'} || [] };
+    body {
+        ul {
+            foreach my $item (@options) {
+                if ( !ref($item) ) {
+                    li { $item };
+                }
+                elsif ( exists $item->{label} ) {
+                    li {
+                        with( class => "informal" ), span { $item->{label} };
+                        with( class => "hidden_value" ),
+                          span { $item->{value} };
+                    };
+                }
+                else {
+                    li { $item->{value} };
+                }
+            }
+        };
+    };
+};
+
+
+template '__jifty/validator.xml' => sub {
+    Jifty->handler->apache->content_type('text/xml; charset=UTF-8');
+    my $output = "";
+    use XML::Writer;
+    my $writer = XML::Writer->new( OUTPUT => \$output );
+    $writer->xmlDecl( "UTF-8", "yes" );
+    $writer->startTag("validation");
+    for my $ra ( Jifty->web->request->actions ) {
+        my $action = Jifty->web->new_action_from_request($ra);
+        $writer->startTag( "validationaction", id => $action->register_name );
+        for my $arg ( $action->argument_names ) {
+            if ( not $action->arguments->{$arg}->{ajax_validates} ) {
+                $writer->emptyTag( "ignored",
+                    id => $action->error_div_id($arg) );
+                $writer->emptyTag( "ignored",
+                    id => $action->warning_div_id($arg) );
+            }
+            elsif ( not defined $action->argument_value($arg)
+                    or length $action->argument_value($arg) == 0 )
+            {
+                $writer->emptyTag( "blank", id => $action->error_div_id($arg) );
+                $writer->emptyTag( "blank",
+                    id => $action->warning_div_id($arg) );
+            }
+            elsif ( $action->result->field_error($arg) ) {
+                $writer->dataElement(
+                    "error",
+                    $action->result->field_error($arg),
+                    id => $action->error_div_id($arg)
+                );
+                $writer->emptyTag( "ok", id => $action->warning_div_id($arg) );
+            }
+            elsif ( $action->result->field_warning($arg) ) {
+                $writer->dataElement(
+                    "warning",
+                    $action->result->field_warning($arg),
+                    id => $action->warning_div_id($arg)
+                );
+                $writer->emptyTag( "ok", id => $action->error_div_id($arg) );
+            }
+            else {
+                $writer->emptyTag( "ok", id => $action->error_div_id($arg) );
+                $writer->emptyTag( "ok", id => $action->warning_div_id($arg) );
+            }
+        }
+        $writer->endTag();
+        $writer->startTag( "canonicalizeaction", id => $action->register_name );
+        for my $arg ( $action->argument_names ) {
+            no warnings 'uninitialized';
+            if ( $ra->arguments->{$arg} eq $action->argument_value($arg) ) {
+
+                # if the value doesn' t change, it can be ignored .
+
+# canonicalizers can change other parts of the action, so we want to send all changes
+                $writer->emptyTag( "ignored",
+                    name => $action->form_field_name($arg) );
+            }
+            elsif ( not defined $action->argument_value($arg)
+                or length $action->argument_value($arg) == 0 )
+            {
+                $writer->emptyTag( "blank",
+                    name => $action->form_field_name($arg) );
+            }
+            else {
+                if ( $action->result->field_canonicalization_note($arg) ) {
+                    $writer->dataElement(
+                        "canonicalization_note",
+                        $action->result->field_canonicalization_note($arg),
+                        id => $action->canonicalization_note_div_id($arg)
+                    );
+                }
+                $writer->dataElement(
+                    "update",
+                    $action->argument_value($arg),
+                    name => $action->form_field_name($arg)
+                );
+            }
+        }
+        $writer->endTag();
+    }
+    $writer->endTag();
+    Jifty->web->out($output);
+};
+
+template '__jifty/webservices/xml' => sub {
+    my $output = "";
+    my $writer = XML::Writer->new(
+        OUTPUT => \$output,
+        UNSAFE => 1
+    );
+    $writer->xmlDecl( "UTF-8", "yes" );
+    $writer->startTag("response");
+    for my $f ( Jifty->web->request->fragments ) {
+
+        # Set up the region stack
+        local Jifty->web->{'region_stack'} = [];
+        my @regions;
+        do {
+            push @regions, $f;
+        } while ( $f = $f->parent );
+
+        for $f ( reverse @regions ) {
+            my $new =
+              Jifty->web->get_region( join '-',
+                grep { $_ } Jifty->web->qualified_region, $f->name );
+
+            # Arguments can be complex mapped hash values.  Get their
+            # real values by mapping.
+            my %defaults = %{ $f->arguments || {} };
+            for ( keys %defaults ) {
+                my ( $key, $value ) = Jifty::Request::Mapper->map(
+                    destination => $_,
+                    source      => $defaults{$_}
+                );
+                delete $defaults{$_};
+                $defaults{$key} = $value;
+            }
+
+            $new ||= Jifty::Web::PageRegion->new(
+                name           => $f->name,
+                path           => $f->path,
+                region_wrapper => $f->wrapper,
+                parent         => Jifty->web->current_region,
+                defaults       => \%defaults,
+            );
+            $new->enter;
+        }
+
+        # Stuff the rendered region into the XML
+        $writer->startTag( "fragment",
+            id => Jifty->web->current_region->qualified_name );
+        my %args = %{ Jifty->web->current_region->arguments };
+        $writer->dataElement( "argument", $args{$_}, name => $_ )
+          for sort keys %args;
+        $writer->cdataElement( "content",
+            Jifty->web->current_region->as_string );
+        $writer->endTag();
+
+        Jifty->web->current_region->exit while Jifty->web->current_region;
+    }
+
+    my %results = Jifty->web->response->results;
+    for ( keys %results ) {
+        $writer->startTag(
+            "result",
+            moniker => $_,
+            class   => $results{$_}->action_class
+        );
+        $writer->dataElement( "success", $results{$_}->success );
+
+        $writer->dataElement( "message", $results{$_}->message )
+          if $results{$_}->message;
+        $writer->dataElement( "error", $results{$_}->error )
+          if $results{$_}->error;
+
+        my %warnings = $results{$_}->field_warnings;
+        my %errors   = $results{$_}->field_errors;
+        my %fields;
+        $fields{$_}++ for keys(%warnings), keys(%errors);
+        for ( sort keys %fields ) {
+            next unless $warnings{$_} or $errors{$_};
+            $writer->startTag( "field", name => $_ );
+            $writer->dataElement( "warning", $warnings{$_} )
+              if $warnings{$_};
+            $writer->dataElement( "error", $errors{$_} )
+              if $errors{$_};
+            $writer->endTag();
+        }
+
+        # XXX TODO: Hack because we don't have a good way to serialize
+        # Jifty::DBI::Record's yet, which are technically circular data
+        # structures at some level (current_user of a
+        # current_user->user_object is itself)
+        use Scalar::Util qw(blessed);
+        my $content = $results{$_}->content;
+
+
+        $content = _stripkids($content);
+        use XML::Simple;
+        $writer->raw(
+            XML::Simple::XMLout(
+                $content,
+                NoAttr   => 1,
+                RootName => "content",
+                NoIndent => 1
+            )
+        ) if keys %{$content};
+
+        $writer->endTag();
+    }
+
+    $writer->endTag();
+    Jifty->handler->apache->content_type('text/xml; charset=UTF-8');
+
+    # For some reason, this line is needed, lest we end up outputting ISO-8859-1 text
+    utf8::decode($output);
+
+    outs_raw($output);
+};
+
+        sub _stripkids {
+            my $top = shift;
+            if ( not ref $top ) { return $top }
+            elsif (
+                blessed($top)
+                and (  $top->isa("Jifty::DBI::Record")
+                    or $top->isa("Jifty::DBI::Collection") )
+              )
+            {
+                return undef;
+            }
+            elsif ( ref $top eq 'HASH' ) {
+                foreach my $item ( keys %$top ) {
+                    $top->{$item} = _stripkids( $top->{$item} );
+                }
+            }
+            elsif ( ref $top eq 'ARRAY' ) {
+                for ( 0 .. $#{$top} ) {
+                    $top->[$_] = _stripkids( $top->[$_] );
+                }
+            }
+            return $top;
+        }
+
+
+template '__jifty/webservices/yaml' => sub {
+    Jifty->handler->apache->content_type("text/x-yaml");
+    outs( Jifty::YAML::Dump( { Jifty->web->response->results } ) );
+};
+
+
+1;
 1;

Modified: jifty/branches/template-declare/lib/Jifty/View/Declare/Handler.pm
==============================================================================
--- jifty/branches/template-declare/lib/Jifty/View/Declare/Handler.pm	(original)
+++ jifty/branches/template-declare/lib/Jifty/View/Declare/Handler.pm	Sun Mar  4 16:24:16 2007
@@ -28,7 +28,6 @@
     my $class = shift;
     my $self = {};
     bless $self,$class;
-    warn "Initting T::D with ". YAML::Dump(\@_);
     Template::Declare->init(@_);
     return $self;
 }
@@ -65,7 +64,6 @@
 =cut
 
 sub template_exists { my $pkg =shift;  
-warn "Checking for ".join(',', at _);
 
 return Template::Declare->resolve_template(@_);}
 

Modified: jifty/branches/template-declare/lib/Jifty/View/Declare/Helpers.pm
==============================================================================
--- jifty/branches/template-declare/lib/Jifty/View/Declare/Helpers.pm	(original)
+++ jifty/branches/template-declare/lib/Jifty/View/Declare/Helpers.pm	Sun Mar  4 16:24:16 2007
@@ -92,6 +92,16 @@
     return Jifty->web->new_action(@_);
 }
 
+
+=head2 render_region 
+
+A shortcut for Jifty::Web::PageRegion->new(@_)->render which does the
+Template::Declare magic necessary to not mix its output with your current
+page's.
+
+
+=cut
+
 sub render_region(@) {
     unshift @_, 'name' if @_ % 2;
     Template::Declare->new_buffer_frame;
@@ -101,6 +111,35 @@
     Jifty->web->out($content);
 }
 
+
+=head2 render_action $action_object, $fields, $args_to_pass_to_action
+
+Renders an action out of whole cloth.
+
+Arguments
+
+=over 
+
+=item $action_object
+
+A Jifty::Action object which has already been initialized
+
+=item $fields
+
+A reference to an array of fields that should be rendered when
+displaying this action. If left undefined, all of the 
+action's fields will be rendered.
+
+=item $args_to_pass_to_action
+
+A hashref of arguments that should be passed to $action->form_field for
+every field of this action.
+
+=back
+
+
+=cut
+
 sub render_action(@) {
     my ( $action, $fields, $field_args ) = @_;
     my @f = $fields && @$fields ? @$fields : $action->argument_names;
@@ -152,6 +191,16 @@
     Jifty->web->current_user;
 }
 
+=head2 get args
+
+Returns arguments as set in the dispatcher or with L</set> below.
+If called in scalar context, pulls the first item in C<args> and returns it.
+If called in list context, returns the values of all items in C<args>.
+
+
+
+=cut
+
 sub get {
     if (wantarray) {
         map { request->argument($_) } @_;
@@ -160,6 +209,15 @@
     }
 }
 
+
+=head2 set key => val [ key => val ...]
+
+Sets arguments for later grabbing with L<get>.
+
+
+=cut
+
+
 sub set {
     while ( my ( $arg, $val ) = ( shift @_, shift @_ ) ) {
         request->argument( $arg => $val );
@@ -167,13 +225,29 @@
 
 }
 
+=head2 render_param $action @args
+
+Takes an action and one or more arguments to pass to L<Jifty::Action->form_field>.
+
+=cut
+
 sub render_param {
     my $action = shift;
     outs_raw( $action->form_field(@_) );
     return '';
 }
 
-# template 'foo' => page {{ title is 'Foo' } ... };
+=head2 page 
+
+ template 'foo' => page {{ title is 'Foo' } ... };
+
+Renders an HTML page wrapped in L</wrapper>, after calling
+"/_elements/nav" and setting a content type. Generally, you shouldn't
+be using "/_elements/nav" but a Dispatcher rule instead.
+
+=cut
+
+
 sub page (&) {
     my $code = shift;
     sub {
@@ -183,6 +257,15 @@
     };
 }
 
+
+=head2 wrapper $coderef
+
+Render a page. $coderef is a L<Template::Declare> coderef. 
+This badly wants to be redone.
+
+=cut
+
+
 sub wrapper ($) {
     my $content_code = shift;
 
@@ -257,6 +340,13 @@
         $done_header . Template::Declare->buffer->data );
 }
 
+
+=head2 render_header $title
+
+Renders an HTML "doctype", <head> and the first part of a page body. This bit isn't terribly well thought out and we're not happy with it.
+
+=cut
+
 sub render_header {
     my ($title) = @_;
     outs_raw(


More information about the Jifty-commit mailing list