[Jifty-commit] r4949 - in jifty/trunk: . lib/Jifty lib/Jifty/Action lib/Jifty/Action/Record lib/Jifty/Manual lib/Jifty/Plugin/REST t/TestApp/t

Jifty commits jifty-commit at lists.jifty.org
Sun Jan 27 07:13:44 EST 2008


Author: sartak
Date: Sun Jan 27 07:13:42 2008
New Revision: 4949

Modified:
   jifty/trunk/   (props changed)
   jifty/trunk/META.yml
   jifty/trunk/Makefile.PL
   jifty/trunk/lib/Jifty/Action/Record.pm
   jifty/trunk/lib/Jifty/Action/Record/Create.pm
   jifty/trunk/lib/Jifty/Action/Record/Update.pm
   jifty/trunk/lib/Jifty/ClassLoader.pm
   jifty/trunk/lib/Jifty/Manual/AccessControl.pod
   jifty/trunk/lib/Jifty/Plugin/REST/Dispatcher.pm
   jifty/trunk/lib/Jifty/Record.pm
   jifty/trunk/lib/Jifty/TestServer.pm
   jifty/trunk/lib/Jifty/Web/Menu.pm
   jifty/trunk/lib/Jifty/Web/Session.pm
   jifty/trunk/t/TestApp/t/15-template-subclass.t
   jifty/trunk/t/TestApp/t/16-template-region.t

Log:
 r51069 at onn:  sartak | 2008-01-27 07:13:17 -0500
 Revert a mismerge


Modified: jifty/trunk/META.yml
==============================================================================
--- jifty/trunk/META.yml	(original)
+++ jifty/trunk/META.yml	Sun Jan 27 07:13:42 2008
@@ -28,6 +28,7 @@
   Class::Accessor::Named: 0
   Crypt::OpenSSL::RSA: 0
   DBD::SQLite: 0
+  Data::Dump::Streamer: 0
   Devel::Cover: 0
   Devel::EvalContext: 0
   Devel::Events::Objects: 0.02
@@ -42,12 +43,13 @@
   Module::Install::Admin: 0.50
   Module::Refresh: 0.09
   Net::LDAP: 0
-  Net::OAuth::Request: 0.04
+  Net::OAuth::Request: 0.05
   Net::OpenID::Consumer: 0
   Net::Server::Fork: 0
   Net::Server::PreFork: 0
   PAR::Dist::FromCPAN: 0
   Proc::ProcessTable: 0
+  Template::Declare: 0.28
   Test::Base: 0.44
   Test::HTML::Lint: 0
   Test::HTTP::Server::Simple: 0.02

Modified: jifty/trunk/Makefile.PL
==============================================================================
--- jifty/trunk/Makefile.PL	(original)
+++ jifty/trunk/Makefile.PL	Sun Jan 27 07:13:42 2008
@@ -50,7 +50,7 @@
 requires('Hook::LexWrap');
 requires('IPC::PubSub' => '0.23' );
 requires('IPC::Run3');
-requires('Jifty::DBI' => '0.47' );            # Jifty::DBI::Collection Jifty::DBI::Handle Jifty::DBI::Record::Cachable Jifty::DBI::SchemaGenerator
+requires('Jifty::DBI' => '0.49' );            # Jifty::DBI::Collection Jifty::DBI::Handle Jifty::DBI::Record::Cachable Jifty::DBI::SchemaGenerator
 requires('Locale::Maketext::Extract' => '0.20');
 requires('Locale::Maketext::Lexicon' => '0.60');
 requires('Log::Log4perl' => '1.04');

Modified: jifty/trunk/lib/Jifty/Action/Record.pm
==============================================================================
--- jifty/trunk/lib/Jifty/Action/Record.pm	(original)
+++ jifty/trunk/lib/Jifty/Action/Record.pm	Sun Jan 27 07:13:42 2008
@@ -497,13 +497,13 @@
 =head2 possible_fields
 
 Returns the list of fields on the object that the action can update.
-This defaults to all of the fields of the object.
+This defaults to all of the non-C<private> fields of the object.
 
 =cut
 
 sub possible_fields {
     my $self = shift;
-    return map { $_->name } grep { $_->container || $_->type ne "serial" } $self->record->columns;
+    return map { $_->name } grep { $_->container || $_->type ne "serial" and not $_->private and not $_->virtual } $self->record->columns;
 }
 
 =head2 take_action

Modified: jifty/trunk/lib/Jifty/Action/Record/Create.pm
==============================================================================
--- jifty/trunk/lib/Jifty/Action/Record/Create.pm	(original)
+++ jifty/trunk/lib/Jifty/Action/Record/Create.pm	Sun Jan 27 07:13:42 2008
@@ -120,6 +120,19 @@
     $self->result->message(_("Created"))
 }
 
+=head2 possible_fields
+
+Create actions do not provide fields for columns marked as C<private>
+or C<protected>.
+
+=cut
+
+sub possible_fields {
+    my $self = shift;
+    my @names = $self->SUPER::possible_fields;
+    return map {$_->name} grep {not $_->protected} map {$self->record->column($_)} @names;
+}
+
 =head1 SEE ALSO
 
 L<Jifty::Action::Record>, L<Jifty::Record>

Modified: jifty/trunk/lib/Jifty/Action/Record/Update.pm
==============================================================================
--- jifty/trunk/lib/Jifty/Action/Record/Update.pm	(original)
+++ jifty/trunk/lib/Jifty/Action/Record/Update.pm	Sun Jan 27 07:13:42 2008
@@ -36,7 +36,7 @@
     my $arguments = $self->SUPER::arguments(@_);
 
     # Mark read-only columns for read-only display
-    for my $column ( $self->record->columns ) {
+    for my $column ( map {$self->record->column($_)} $self->possible_fields ) {
         if ( not $column->writable and $column->readable ) {
             $arguments->{$column->name}{'render_mode'} = 'read';
         }
@@ -205,6 +205,20 @@
     $self->result->message(_("Updated"))
 }
 
+
+=head2 possible_fields
+
+Update actions do not provide fields for columns marked as C<private>
+or C<protected>.
+
+=cut
+
+sub possible_fields {
+    my $self = shift;
+    my @names = $self->SUPER::possible_fields;
+    return map {$_->name} grep {not $_->protected} map {$self->record->column($_)} @names;
+}
+
 =head1 SEE ALSO
 
 L<Jifty::Action::Record>, L<Jifty::Record>

Modified: jifty/trunk/lib/Jifty/ClassLoader.pm
==============================================================================
--- jifty/trunk/lib/Jifty/ClassLoader.pm	(original)
+++ jifty/trunk/lib/Jifty/ClassLoader.pm	Sun Jan 27 07:13:42 2008
@@ -67,7 +67,7 @@
 
 =item I<Application>::Action::I<[Verb]>I<[Something]>
 
-If I<Application>::Model::I<Something> is a valid model class and I<Verb> is one of "Create", "Search", "Update", or "Delete", then it creates a subclass of I<Application>::Action::Record::I<Verb>
+If I<Application>::Model::I<Something> is a valid model class and I<Verb> is one of "Create", "Search", "Update", or "Delete", then it creates a subclass of I<Application>::Action::Record::I<Verb>  Models can control which actions are generated by overriding L<Jifty::Record/autogenerate_action>.  See also L<Jifty::Record/is_private> and L<Jifty::Record/is_protected>.
 
 =item I<Application>::Action::I<Something>
 
@@ -226,13 +226,14 @@
 
         # Don't generate the action unless it really is a model
         if ( eval { $modelclass->isa('Jifty::Record') } ) {
-
-            $AUTOGENERATED{$module} = 1;
-            return $self->return_class(
-                  "package $module;\n"
-                . "use base qw/$base\::Action::Record::$1/;\n"
-                . "sub record_class { '$modelclass' };\n"
-            );
+            if ($modelclass->autogenerate_action($1)) {
+                $AUTOGENERATED{$module} = 1;
+                return $self->return_class(
+                      "package $module;\n"
+                    . "use base qw/$base\::Action::Record::$1/;\n"
+                    . "sub record_class { '$modelclass' };\n"
+                );
+            }
         }
 
     }
@@ -373,7 +374,7 @@
     my($short) = $full =~ /::Model::(\w*)/;
     Jifty::Util->require($full . "Collection");
     Jifty::Util->require($base . "::Action::" . $_ . $short)
-        for qw/Create Update Delete Search/;
+        for grep {$full->autogenerate_action($_)} qw/Create Update Delete Search/;
 }
 
 

Modified: jifty/trunk/lib/Jifty/Manual/AccessControl.pod
==============================================================================
--- jifty/trunk/lib/Jifty/Manual/AccessControl.pod	(original)
+++ jifty/trunk/lib/Jifty/Manual/AccessControl.pod	Sun Jan 27 07:13:42 2008
@@ -21,7 +21,7 @@
 if C<current_user_can('write')> returns false.
 
 
-On C<delete()>, we reject the operation  if C<current_user_can('delete')>
+On C<delete()>, we reject the operation if C<current_user_can('delete')>
 returns false.
 
 Out of the box, C<current_user_can> returns 1. When you want to actually 

Modified: jifty/trunk/lib/Jifty/Plugin/REST/Dispatcher.pm
==============================================================================
--- jifty/trunk/lib/Jifty/Plugin/REST/Dispatcher.pm	(original)
+++ jifty/trunk/lib/Jifty/Plugin/REST/Dispatcher.pm	Sun Jan 27 07:13:42 2008
@@ -94,7 +94,7 @@
 
 HTML is output only if the Accept: header or an extension does not request a
 specific format.
-    };
+};
     last_rule;
 }
 
@@ -387,7 +387,7 @@
 
 =cut
 
-sub model  { _resolve($_[0], 'Jifty::Record', Jifty->class_loader->models) }
+sub model  { _resolve($_[0], 'Jifty::Record', grep {not $_->is_private} Jifty->class_loader->models) }
 
 sub _resolve {
     my $name = shift;
@@ -416,9 +416,15 @@
 =cut
 
 sub list_models {
-    list(['model'], map { s/::/./g; $_ } Jifty->class_loader->models);
+    list(['model'], map { s/::/./g; $_ } grep {not $_->is_private} Jifty->class_loader->models);
 }
 
+=head2 valid_column
+
+Returns true if the column is a valid column to observe on the model
+
+=cut
+
 our @column_attrs = 
 qw( name
     documentation
@@ -436,6 +442,10 @@
     valid_values
 );
 
+sub valid_column {
+    my ( $model, $column ) = @_;
+    return scalar grep { $_->name eq $column and not $_->virtual and not $_->private } $model->new->columns;
+}
 
 =head2 list_model_columns
 
@@ -449,12 +459,14 @@
 
     my %cols;
     for my $col ( $model->new->columns ) {
+        next if $col->private or $col->virtual;
         $cols{ $col->name } = { };
         for ( @column_attrs ) {
             my $val = $col->$_();
-            $cols{ $col->name }->{ $_ } = $val
+            $cols{ $col->name }->{ $_ } = Scalar::Defer::force($val)
                 if defined $val and length $val;
         }
+        $cols{ $col->name }{writable} = 0 if exists $cols{$col->name}{writable} and $col->protected;
     }
 
     outs( [ 'model', $model ], \%cols );
@@ -473,6 +485,9 @@
     my $col = $model->new->collection_class->new;
     $col->unlimit;
 
+    # Check that the field is actually a column
+    abort(404) unless valid_column($model, $column);
+
     # If we don't load the PK, we won't get data
     $col->columns("id", $column);
     $col->order_by( column => $column );
@@ -498,7 +513,7 @@
     $rec->can($field) or abort(404);
 
     # Check that the field is actually a column (and not some other method)
-    abort(404) if not scalar grep { $_->name eq $field } $rec->columns;
+    abort(404) unless valid_column($model, $column);
 
     outs( [ 'model', $model, $column, $key, $field ],
           Jifty::Util->stringify($rec->$field()) );
@@ -515,6 +530,10 @@
 sub show_item {
     my ($model, $column, $key) = (model($1), $2, $3);
     my $rec = $model->new;
+
+    # Check that the field is actually a column
+    abort(404) unless valid_column($model, $column);
+
     $rec->load_by_cols( $column => $key );
     $rec->id or abort(404);
     outs( ['model', $model, $column, $key], $rec->jifty_serialize_format );
@@ -659,9 +678,8 @@
         my $item = $collection->first
             or return outs($ret, []);
 
-        # make sure $field exists and is a real column
-        $item->can($field)    or abort(404);
-        $item->column($field) or abort(404);
+        # Check that the field is actually a column
+        abort(404) unless valid_column($model, $field);
 
         my @values;
 

Modified: jifty/trunk/lib/Jifty/Record.pm
==============================================================================
--- jifty/trunk/lib/Jifty/Record.pm	(original)
+++ jifty/trunk/lib/Jifty/Record.pm	Sun Jan 27 07:13:42 2008
@@ -853,4 +853,46 @@
     return \%data;
 }
 
+=head2 autogenerate_action
+
+Controls which of the L<Jifty::Action::Record> subclasses are
+automatically set up for this model; this subroutine is passed one of
+the strings C<Create>, C<Update>, C<Delete> or C<Search>, and should
+return a true value if that action should be autogenerated.
+
+The default method returns 0 for all action classes if the model is
+marked as L</is_private>.  It returns 0 for all actions that are not
+C<Search> if the model is marked as L</is_protected>; otherwise, it
+returns true.
+
+=cut
+
+sub autogenerate_action {
+    my $class = shift;
+    my($action) = @_;
+
+    return 0 if $class->is_private;
+    return 0 if $class->is_protected and $action ne "Search";
+
+    return 1;
+}
+
+=head2 is_private
+
+Override this method to return true to not generate any actions for
+this model, and to hide it from REST introspection.
+
+=cut
+
+sub is_private { 0 }
+
+=head2 is_protected
+
+Override this method to return true to only generate Search actions
+for this model.
+
+=cut
+
+sub is_protected { return shift->is_private }
+
 1;

Modified: jifty/trunk/lib/Jifty/TestServer.pm
==============================================================================
--- jifty/trunk/lib/Jifty/TestServer.pm	(original)
+++ jifty/trunk/lib/Jifty/TestServer.pm	Sun Jan 27 07:13:42 2008
@@ -6,7 +6,9 @@
 use Test::Builder;
 my $Tester = Test::Builder->new;
 
-my $INC = [grep { defined } map { File::Spec->rel2abs($_) } @INC ];
+# explicitly ignore ClassLoader objects in @INC,
+# which'd be ignored in the end, though.
+my $INC = [grep { defined } map { File::Spec->rel2abs($_) } grep { !ref } @INC ];
 my @perl = ($^X, map { "-I$_" } @$INC);
 
 =head1 NAME

Modified: jifty/trunk/lib/Jifty/Web/Menu.pm
==============================================================================
--- jifty/trunk/lib/Jifty/Web/Menu.pm	(original)
+++ jifty/trunk/lib/Jifty/Web/Menu.pm	Sun Jan 27 07:13:42 2008
@@ -1,5 +1,9 @@
 package Jifty::Web::Menu;
 
+use strict;
+use warnings;
+
+
 use base qw/Class::Accessor::Fast/;
 use URI;
 use Scalar::Util qw(weaken);
@@ -372,21 +376,39 @@
     my %args = ( class => 'yuimenu', first => 0, id => undef, @_ );
     my @kids = $self->children or return;
     
+    # Add the appropriate YUI class to each kid
+    for my $kid ( @kids ) {
+        # Skip it if it's a group heading
+        next if $kid->render_children_inline and $kid->children;
+
+        # Figure out the correct object to be setting the class on
+        my $object =   ( defined $kid->link
+                     and ref $kid->link
+                     and $kid->link->can('class') )
+                         ? $kid->link : $kid;
+
+        my $class = defined $object->class ? $object->class . ' ' : '';
+        $class .= "$args{class}itemlabel";
+        $object->class( $class );
+    }
+
+    # We're rendering this inline, so just render a UL (and any submenus as normal)
     if ( $self->render_children_inline ) {
         Jifty->web->out( $args{'first'} ? '<ul class="first-of-type">' : '<ul>' );
         for my $kid ( @kids ) {
-            Jifty->web->out( qq{<li class="${class}item } . ($kid->active? 'active' : '') . qq{">});
+            Jifty->web->out( qq(<li class="$args{class}item ) . ($kid->active? 'active' : '') . qq{">});
             Jifty->web->out( $kid->as_link );
             $kid->_render_as_yui_menu_item( class => 'yuimenu' );
             Jifty->web->out( qq{</li>});
         }
         Jifty->web->out('</ul>');
     }
+    # Render as normal submenus
     else {
         Jifty->web->out(
             qq{<div}
             . ($args{'id'} ? qq( id="$args{'id'}") : "")
-            . qq{ class="$class"><div class="bd">}
+            . qq( class="$args{class}"><div class="bd">)
         );
 
         my $count    = 1;
@@ -394,6 +416,9 @@
         my $openlist = 0;
 
         for my $kid ( @kids ) {
+            # We want to render the children of this child inline, so close
+            # any open <ul>s, render it as an <h6>, and then render it's
+            # children.
             if ( $kid->render_children_inline and $kid->children ) {
                 Jifty->web->out('</ul>') if $openlist;
                 
@@ -412,12 +437,13 @@
                 $openlist = 0;
                 $count_h6++;
             }
+            # It's a normal child
             else {
                 if ( not $openlist ) {
                     Jifty->web->out( $count == 1 ? '<ul class="first-of-type">' : '<ul>' );
                     $openlist = 1;
                 }
-                Jifty->web->out( qq{<li class="${class}item } . ($kid->active? 'active' : '') . qq{">});
+                Jifty->web->out( qq(<li class="$args{class}item ) . ($kid->active? 'active' : '') . qq{">});
                 Jifty->web->out( $kid->as_link );
                 $kid->_render_as_yui_menu_item( class => 'yuimenu' );
                 Jifty->web->out( qq{</li>});

Modified: jifty/trunk/lib/Jifty/Web/Session.pm
==============================================================================
--- jifty/trunk/lib/Jifty/Web/Session.pm	(original)
+++ jifty/trunk/lib/Jifty/Web/Session.pm	Sun Jan 27 07:13:42 2008
@@ -304,7 +304,7 @@
     $conts->limit( column => "session_id", value => $self->id );
 
     my %continuations;
-    $continuations{ $_->key } = $_->value while $_ = $conts->next;
+    $continuations{ $_->data_key } = $_->value while $_ = $conts->next;
     return %continuations;
 }
 

Modified: jifty/trunk/t/TestApp/t/15-template-subclass.t
==============================================================================
--- jifty/trunk/t/TestApp/t/15-template-subclass.t	(original)
+++ jifty/trunk/t/TestApp/t/15-template-subclass.t	Sun Jan 27 07:13:42 2008
@@ -59,7 +59,7 @@
 sub in_region {
     qq|<script type="text/javascript">
 new Region('$_[0]',{},'$_[1]',null);
-</script><div id="region-$_[0]">$_[2]</div>|;
+</script><div id="region-$_[0]" class="jifty-region">$_[2]</div>|;
 }
 
 plan tests => 2 + scalar(@tests) * 2;

Modified: jifty/trunk/t/TestApp/t/16-template-region.t
==============================================================================
--- jifty/trunk/t/TestApp/t/16-template-region.t	(original)
+++ jifty/trunk/t/TestApp/t/16-template-region.t	Sun Jan 27 07:13:42 2008
@@ -14,7 +14,7 @@
 <span>1</span>
 <span>2</span><script type="text/javascript">
 new Region('special',{'id':3},'/foo/item',null);
-</script><div id="region-special">
+</script><div id="region-special" class="jifty-region">
 <span>3</span></div>|
     },
 


More information about the Jifty-commit mailing list