[Bps-public-commit] r17034 - in Prophet/branches/actions: . doc lib/Prophet lib/Prophet/Server lib/Prophet/Web t/WebToy t/WebToy/bin t/WebToy/lib t/WebToy/lib/App t/WebToy/lib/App/WebToy/Collection t/WebToy/lib/App/WebToy/Model t/WebToy/lib/App/WebToy/Server

jesse at bestpractical.com jesse at bestpractical.com
Thu Nov 27 13:55:50 EST 2008


Author: jesse
Date: Thu Nov 27 13:55:50 2008
New Revision: 17034

Added:
   Prophet/branches/actions/doc/web_form_handling
   Prophet/branches/actions/lib/Prophet/Server/Controller.pm
   Prophet/branches/actions/lib/Prophet/Web/
   Prophet/branches/actions/lib/Prophet/Web/Field.pm
   Prophet/branches/actions/t/WebToy/
   Prophet/branches/actions/t/WebToy/bin/
   Prophet/branches/actions/t/WebToy/bin/webtoy   (contents, props changed)
   Prophet/branches/actions/t/WebToy/lib/
   Prophet/branches/actions/t/WebToy/lib/App/
   Prophet/branches/actions/t/WebToy/lib/App/WebToy/
   Prophet/branches/actions/t/WebToy/lib/App/WebToy.pm
   Prophet/branches/actions/t/WebToy/lib/App/WebToy/CLI.pm
   Prophet/branches/actions/t/WebToy/lib/App/WebToy/Collection/
   Prophet/branches/actions/t/WebToy/lib/App/WebToy/Collection/WikiPage.pm
   Prophet/branches/actions/t/WebToy/lib/App/WebToy/Model/
   Prophet/branches/actions/t/WebToy/lib/App/WebToy/Model/WikiPage.pm
   Prophet/branches/actions/t/WebToy/lib/App/WebToy/Server/
   Prophet/branches/actions/t/WebToy/lib/App/WebToy/Server/Dispatcher.pm
   Prophet/branches/actions/t/WebToy/lib/App/WebToy/Server/View.pm
Modified:
   Prophet/branches/actions/Makefile.PL
   Prophet/branches/actions/lib/Prophet/Collection.pm
   Prophet/branches/actions/lib/Prophet/Server.pm
   Prophet/branches/actions/lib/Prophet/Server/ViewHelpers.pm

Log:
* iniital work on actions

Modified: Prophet/branches/actions/Makefile.PL
==============================================================================
--- Prophet/branches/actions/Makefile.PL	(original)
+++ Prophet/branches/actions/Makefile.PL	Thu Nov 27 13:55:50 2008
@@ -1,7 +1,7 @@
 #!/usr/bin/perl
 #
 use inc::Module::Install;
-name('Prophet'); #  App::Settings App::Settings::CLI
+name('Prophet'); #  App::Settings App::Settings::CLI App::WebToy App::WebToy::CLI
 author('clkao and jesse');
 license('Perl');
 

Added: Prophet/branches/actions/doc/web_form_handling
==============================================================================
--- (empty file)
+++ Prophet/branches/actions/doc/web_form_handling	Thu Nov 27 13:55:50 2008
@@ -0,0 +1,14 @@
+# in the dispatcher:
+
+    # get all form fields that match the spec
+    # bundle them by record
+    # order them by the desired order
+    # canonicalize
+    # validate
+    # execute if we're to execute
+      # on failure
+        # rerender the current page 
+      # on success
+        # go to "next page"
+
+

Modified: Prophet/branches/actions/lib/Prophet/Collection.pm
==============================================================================
--- Prophet/branches/actions/lib/Prophet/Collection.pm	(original)
+++ Prophet/branches/actions/lib/Prophet/Collection.pm	Thu Nov 27 13:55:50 2008
@@ -25,9 +25,10 @@
 has type => (
     is      => 'rw',
     isa     => 'Str',
+    lazy    => 1,
     default => sub {
         my $self = shift;
-        $self->record_class->record_type;
+        $self->record_class->new(app_handle => $self->app_handle)->record_type;
     },
 );
 
@@ -70,14 +71,13 @@
 sub matching {
     my $self    = shift;
     my $coderef = shift;
-
     return undef unless $self->handle->type_exists( type => $self->type );
-
     # find all items,
     Carp::cluck unless defined $self->type;
 
     my $records = $self->handle->list_records( type => $self->type );
 
+    
     # run coderef against each item;
     # if it matches, add it to items
     for my $key (@$records) {
@@ -93,6 +93,16 @@
 
 }
 
+=head2 items
+
+Returns a reference to an array of all the items found
+
+=head2 add_item
+
+=head2 count
+
+=cut
+
 __PACKAGE__->meta->make_immutable;
 no Moose;
 

Modified: Prophet/branches/actions/lib/Prophet/Server.pm
==============================================================================
--- Prophet/branches/actions/lib/Prophet/Server.pm	(original)
+++ Prophet/branches/actions/lib/Prophet/Server.pm	Thu Nov 27 13:55:50 2008
@@ -52,6 +52,10 @@
     my ( $self, $cgi ) = validate_pos( @_, { isa => 'Prophet::Server' }, { isa => 'CGI' } );
     $self->cgi($cgi);
 
+   
+    my $controller = Prophet::Server::Controller->new(cgi => $self->cgi); 
+    $controller->handle_actions();
+
      my $dispatcher_class = ref($self->app_handle) . "::Server::Dispatcher";
      if (!$self->app_handle->try_to_require($dispatcher_class)) {
          $dispatcher_class = "Prophet::Server::Dispatcher";

Added: Prophet/branches/actions/lib/Prophet/Server/Controller.pm
==============================================================================
--- (empty file)
+++ Prophet/branches/actions/lib/Prophet/Server/Controller.pm	Thu Nov 27 13:55:50 2008
@@ -0,0 +1,138 @@
+package Prophet::Server::Controller;
+use Moose;
+
+
+has cgi => (isa => 'CGI');
+
+has failed => ( isa => 'Bool');
+has failure_message => ( isa => 'Bool');
+
+=head1 NAME
+
+=head1 METHODS
+
+=head1 DESCRIPTION
+
+=cut
+
+=head1 METHODS
+
+=cut
+
+sub extract_actions_from_cgi {
+    my $self = shift;
+
+    my $cgi = $self->cgi;
+    my @params = $cgi->all_parameters;
+
+    my $bundles = $self->_bundle_params_by_action(\@params);   
+    for (values %$bundles) {
+        push  @action_hashes, $self->_bundle_to_hash($_);
+    } 
+   return \@action_hashes; 
+}
+
+
+sub _bundle_params_by_action {
+    my $self = shift;
+    my $params = shift;
+
+    my $bundles = {};
+    my @actions = $self->_find_actions_from_cgi_params($params);
+    foreach my $param (@$params) {
+        my $action = $self->_parse_cgi_param_name($param);
+    
+        $bundles{$action} 
+    }
+    
+
+    return $bundles;
+}
+
+sub find_actions_from_cgi {
+    my $self = shift;
+    my $params = shift;
+
+    my $cgi = $self->cgi;
+    my $actions = {};
+   foreach my $param (@$params) {
+        next unless $param =~ /^prophet-action(.*)$/;
+        my %attr = map {split(/=/) grep {$_} split(/|/,$1)};
+        $attr{value} = $cgi->param($param);
+
+        warn "Duplicate action definition for @{[$attr{name}]}." if ($actions{$attr{name}};
+        $actions{$attr{name}} = \%attr;
+        $actions{$attr{name}}->{params} = 
+            $self->params_for_action_from_cgi($attr{name});
+   } 
+
+}
+
+sub params_for_action_from_cgi {
+    my $self = shift;
+    my $action = shift;
+
+    my @params = grep { /^prophet-field|.*?|action=$action|/} 
+    $self->cgi->all_parameters
+}
+
+
+sub _parse_cgi_param_name {
+    my $self = shift;
+    my $param = shift;
+
+    my ($uuid, $prop, $value);
+    if ($param =~ /|uuid-(.*?)|) {
+        $uuid = $1;
+    }
+    if ($param =~ /|prop-(.*?)|) {
+        $prop = $1;
+    }
+    my $value = $self->cgi->param($param); 
+
+}
+
+sub _bundle_to_hash {
+    my $self = shift;
+}
+
+sub handle_actions {
+    my $self = shift;
+
+   my @workflow = qw(
+       extract_actions_from_cgi 
+       canonicalize_actions
+       validate_actions
+       execute_actions    
+    );
+    eval {
+        $self->$_() for @workflow;
+    }; 
+    
+    if (my $err = $@) {
+        $self->failed(1);
+        $self->failure_message($err);   
+    }
+}
+
+
+sub extract_actions_from_cgi {
+    my $self = shift;
+}
+
+sub canonicalize_actions {
+    my $self = shift;
+}
+
+sub validate_actions {
+
+}
+
+sub execute_actions {
+
+}
+__PACKAGE__->meta->make_immutable;
+no Moose;
+
+1;
+

Modified: Prophet/branches/actions/lib/Prophet/Server/ViewHelpers.pm
==============================================================================
--- Prophet/branches/actions/lib/Prophet/Server/ViewHelpers.pm	(original)
+++ Prophet/branches/actions/lib/Prophet/Server/ViewHelpers.pm	Thu Nov 27 13:55:50 2008
@@ -4,8 +4,10 @@
 
 package Prophet::Server::ViewHelpers;
 use base 'Exporter::Lite';
+use Params::Validate qw/validate/;
 use Template::Declare::Tags;
-our @EXPORT = qw(page content);
+use Prophet::Web::Field;
+our @EXPORT = qw(page content widget function);
 
 sub page (&;$) {
     unshift @_, undef if $#_ == 0;
@@ -35,5 +37,58 @@
     return $sub_ref;
 }
 
+sub function {
+    my %args = validate(
+        @_,
+        {   action => { regex => qr/^(?:create|update|delete)$/ },
+            record => 1,
+            order  => 0,
+            name   => {
+                regex    => qr/^(?:|[\w\d]+)$/,
+                optional => 1
+            },
+        }
+    );
+
+    my %bits = {
+        order => $args{order},
+        name  => $args{'name'},
+        uuid  => $args{'record'}->uuid
+    };
+
+    my $string
+        = "|"
+        . join( "|", map { $args{$_} ? $_ . "-" . $args{$_} : '' } keys %bits )
+        . "|";
+
+    input {
+        attr {
+            type => 'hidden',
+            name => "prophet-action|" . $string,
+
+            value => $args{'action'}
+        };
+    };
+
+}
+
+sub widget {
+    my %args = validate( @_, { prop => 1, record => 1 } );
+
+    my $f = Prophet::Web::Field->new(
+        name   => Prophet::Server::ViewHelpers->_generate_name(%args),
+        record => $args{record},
+        label  => $args{prop},
+        value  => $args{record}->prop( $args{'prop'} )
+    );
+    outs_raw($f->render);
+}
+
+sub _generate_name {
+    my $class = shift;
+    my %args = validate( @_, { prop => 1, record => 1 } );
+    my $r = $args{'record'};
+    return "prophet-field||uuid-".$r->uuid."|prop-".$args{prop}."|";
+}
 
 1;

Added: Prophet/branches/actions/lib/Prophet/Web/Field.pm
==============================================================================
--- (empty file)
+++ Prophet/branches/actions/lib/Prophet/Web/Field.pm	Thu Nov 27 13:55:50 2008
@@ -0,0 +1,57 @@
+package Prophet::Web::Field;
+use Moose;
+
+has name   => ( isa => 'Str',             is => 'rw' );
+has record => ( isa => 'Prophet::Record', is => 'rw' );
+has prop  => ( isa => 'Str',             is => 'rw' );
+has value  => ( isa => 'Str',             is => 'rw' );
+has label => ( isa => 'Str', is => 'rw', default => sub {''});
+has id    => ( isa => 'Str', is => 'rw' );
+has class => ( isa => 'Str', is => 'rw' );
+has value => ( isa => 'Str', is => 'rw' );
+
+sub _render_attr {
+    my $self = shift;
+    my $attr = shift;
+    my $value = $self->$attr() || return '';
+    return $attr . '="' . $self->$attr() . '"';
+}
+
+sub render_name {
+    my $self = shift;
+    $self->_render_attr('name');
+
+}
+
+sub render_id {
+    my $self = shift;
+    $self->_render_attr('id');
+}
+
+sub render_class {
+    my $self = shift;
+    $self->_render_attr('class');
+}
+
+sub render_value {
+    my $self = shift;
+    $self->_render_attr('value');
+}
+
+sub render {
+    my $self = shift;
+
+    my $output = <<EOF;
+<label @{[$self->render_name]}>@{[$self->label]}</label>
+<input type="text" @{[$self->render_name]} @{[$self->render_id]} @{[$self->render_class]} @{[$self->render_value]} />
+
+EOF
+
+    return $output;
+
+}
+
+__PACKAGE__->meta->make_immutable;
+no Moose;
+
+1;

Added: Prophet/branches/actions/t/WebToy/bin/webtoy
==============================================================================
--- (empty file)
+++ Prophet/branches/actions/t/WebToy/bin/webtoy	Thu Nov 27 13:55:50 2008
@@ -0,0 +1,13 @@
+#!/usr/bin/env perl 
+use warnings;
+use strict;
+use lib 'lib';
+use lib '../../lib';
+use App::WebToy::CLI;
+# Moose likes generating very noisy backtraces. Most users don't need to see
+# anything more than the root cause of the failure. Developers and the curious
+# can set environment variable SD_VERBOSE_ERROR to retain the backtraces.
+# When Moose's error throwing is more malleable we should switch to using that.
+my $cli = App::WebToy::CLI->new;
+$cli->run_one_command(@ARGV);
+

Added: Prophet/branches/actions/t/WebToy/lib/App/WebToy.pm
==============================================================================
--- (empty file)
+++ Prophet/branches/actions/t/WebToy/lib/App/WebToy.pm	Thu Nov 27 13:55:50 2008
@@ -0,0 +1,32 @@
+package App::WebToy;
+use Moose;
+use App::WebToy::Model::WikiPage;
+extends 'Prophet::App';
+
+=head1 NAME
+
+=head1 METHODS
+
+=head1 DESCRIPTION
+
+=cut
+
+=head1 METHODS
+
+=cut
+
+sub set_db_defaults {
+    my $self = shift;
+    $self->SUPER::set_db_defaults(@_);
+    my $record = App::WebToy::Model::WikiPage->new(app_handle => $self);
+    $record->create( props => { title => 'TitleOfPage',  content => 'Body!'});
+
+} 
+
+
+
+__PACKAGE__->meta->make_immutable;
+no Moose;
+
+1;
+

Added: Prophet/branches/actions/t/WebToy/lib/App/WebToy/CLI.pm
==============================================================================
--- (empty file)
+++ Prophet/branches/actions/t/WebToy/lib/App/WebToy/CLI.pm	Thu Nov 27 13:55:50 2008
@@ -0,0 +1,16 @@
+package App::WebToy::CLI;
+use Moose;
+extends 'Prophet::CLI';
+
+use App::WebToy;
+
+has 'app_class' => (
+    default => 'App::WebToy',
+);
+
+
+__PACKAGE__->meta->make_immutable;
+no Moose;
+
+1;
+

Added: Prophet/branches/actions/t/WebToy/lib/App/WebToy/Collection/WikiPage.pm
==============================================================================
--- (empty file)
+++ Prophet/branches/actions/t/WebToy/lib/App/WebToy/Collection/WikiPage.pm	Thu Nov 27 13:55:50 2008
@@ -0,0 +1,23 @@
+package App::WebToy::Collection::WikiPage;
+use base 'Prophet::Collection';
+use App::WebToy::Model::WikiPage;
+
+use constant record_class => 'App::WebToy::Model::WikiPage';
+
+
+
+=head1 NAME
+
+=head1 METHODS
+
+=head1 DESCRIPTION
+
+=cut
+
+=head1 METHODS
+
+=cut
+
+
+1;
+

Added: Prophet/branches/actions/t/WebToy/lib/App/WebToy/Model/WikiPage.pm
==============================================================================
--- (empty file)
+++ Prophet/branches/actions/t/WebToy/lib/App/WebToy/Model/WikiPage.pm	Thu Nov 27 13:55:50 2008
@@ -0,0 +1,29 @@
+package App::WebToy::Model::WikiPage;
+use Moose;
+extends 'Prophet::Record';
+has type => ( default => 'wikipage');
+
+
+
+sub declared_props {qw(title content tags mood)};
+
+=head1 NAME
+
+=head1 METHODS
+
+=head1 DESCRIPTION
+
+=cut
+
+=head1 METHODS
+
+=cut
+
+
+
+
+__PACKAGE__->meta->make_immutable;
+no Moose;
+
+1;
+

Added: Prophet/branches/actions/t/WebToy/lib/App/WebToy/Server/Dispatcher.pm
==============================================================================
--- (empty file)
+++ Prophet/branches/actions/t/WebToy/lib/App/WebToy/Server/Dispatcher.pm	Thu Nov 27 13:55:50 2008
@@ -0,0 +1,25 @@
+package App::WebToy::Server::Dispatcher;
+use Prophet::Server::Dispatcher -base;
+
+on qr'^GET/(.*)$' => sub {show_template($1)->(@_)};
+
+redispatch_to 'Prophet::Server::Dispatcher';
+
+
+sub show_template {
+    if(ref($_[0])) {
+        # called in oo context. do it now
+        my $self = shift;
+        my $template = shift;
+        $self->server->show_template($template, @_);
+    } else {
+
+    my $template = shift;
+    return sub {
+        my $self = shift;
+        $self->server->show_template($template, @_);
+    };
+    }
+}
+
+1;

Added: Prophet/branches/actions/t/WebToy/lib/App/WebToy/Server/View.pm
==============================================================================
--- (empty file)
+++ Prophet/branches/actions/t/WebToy/lib/App/WebToy/Server/View.pm	Thu Nov 27 13:55:50 2008
@@ -0,0 +1,37 @@
+package App::WebToy::Server::View;
+use base 'Prophet::Server::View';
+use Template::Declare::Tags;
+use Prophet::Server::ViewHelpers;
+use App::WebToy::Collection::WikiPage;
+
+=head1 NAME
+
+=head1 METHODS
+
+=head1 DESCRIPTION
+
+=cut
+
+=head1 METHODS
+
+=cut
+
+
+template 'abc' => sub {
+    my $self = shift;
+    my $c = App::WebToy::Collection::WikiPage->new(app_handle => $self->app_handle);
+    $c->matching(sub { return 1});
+    my $r = $c->items->[0];
+    h1 { $r->prop('title')};
+    form {
+    function( record => $r, action => 'update');
+        widget( record => $r, prop => 'title');
+
+        input {attr { label => 'save', type => 'submit'}};
+    }
+
+};
+
+
+1;
+



More information about the Bps-public-commit mailing list