[Jifty-commit] r961 - in jifty/branches/jifty-jsan: . lib
lib/Jifty/Action lib/Jifty/Model lib/Jifty/Script
lib/Jifty/Test/WWW lib/Jifty/Upgrade lib/Jifty/Web t t/TestApp/t
jifty-commit at lists.jifty.org
jifty-commit at lists.jifty.org
Sat Apr 29 12:57:35 EDT 2006
Author: trs
Date: Sat Apr 29 12:57:33 2006
New Revision: 961
Added:
jifty/branches/jifty-jsan/lib/Jifty/Model/Metadata.pm
jifty/branches/jifty-jsan/lib/Jifty/Upgrade/
jifty/branches/jifty-jsan/lib/Jifty/Upgrade/Internal.pm
jifty/branches/jifty-jsan/t/TestApp/t/04-sessions.t
Removed:
jifty/branches/jifty-jsan/lib/Jifty/Model/Schema.pm
jifty/branches/jifty-jsan/t/04-sessions.t
Modified:
jifty/branches/jifty-jsan/ (props changed)
jifty/branches/jifty-jsan/Makefile.PL
jifty/branches/jifty-jsan/lib/Jifty.pm
jifty/branches/jifty-jsan/lib/Jifty/Action/Record.pm
jifty/branches/jifty-jsan/lib/Jifty/Everything.pm
jifty/branches/jifty-jsan/lib/Jifty/Handle.pm
jifty/branches/jifty-jsan/lib/Jifty/Model/Session.pm
jifty/branches/jifty-jsan/lib/Jifty/Request.pm
jifty/branches/jifty-jsan/lib/Jifty/Script/Schema.pm
jifty/branches/jifty-jsan/lib/Jifty/Test.pm
jifty/branches/jifty-jsan/lib/Jifty/Test/WWW/Mechanize.pm
jifty/branches/jifty-jsan/lib/Jifty/Upgrade.pm
jifty/branches/jifty-jsan/lib/Jifty/Web/Session.pm
Log:
r10176 at zot (orig r951): alexmv | 2006-04-28 02:06:35 -0400
r12674 at zoq-fot-pik: chmrr | 2006-04-28 01:59:48 -0400
* Move session tests into TestApp, in preperation for them needing a database
r10177 at zot (orig r952): alexmv | 2006-04-28 02:06:43 -0400
r12675 at zoq-fot-pik: chmrr | 2006-04-28 02:01:16 -0400
* Indent
r10178 at zot (orig r953): alexmv | 2006-04-28 02:06:53 -0400
r12676 at zoq-fot-pik: chmrr | 2006-04-28 02:01:51 -0400
* Check if it can ->name before calling
r10179 at zot (orig r954): alexmv | 2006-04-28 02:07:02 -0400
r12677 at zoq-fot-pik: chmrr | 2006-04-28 02:03:32 -0400
* Allow passing just a value, instead of having to specify the type
(value, fallback, doublefallback)
r10180 at zot (orig r955): alexmv | 2006-04-28 15:49:53 -0400
r12682 at zoq-fot-pik: chmrr | 2006-04-28 15:48:33 -0400
* _db_version -> _jifty_metadata, jifty schema versioning
r10181 at zot (orig r956): alexmv | 2006-04-28 15:49:59 -0400
r12683 at zoq-fot-pik: chmrr | 2006-04-28 15:49:31 -0400
* Sessions stored in the database
r10182 at zot (orig r957): alexmv | 2006-04-28 16:05:43 -0400
r12686 at zoq-fot-pik: chmrr | 2006-04-28 16:05:27 -0400
* POD nits
r10183 at zot (orig r958): alexmv | 2006-04-28 16:28:38 -0400
r12688 at zoq-fot-pik: chmrr | 2006-04-28 16:28:22 -0400
* Class 'load' and 'store' methods always act as the superuser
r10184 at zot (orig r959): alexmv | 2006-04-28 17:04:39 -0400
r12690 at zoq-fot-pik: chmrr | 2006-04-28 17:04:20 -0400
* Bump DBD::SQLite dependency to 1.11, which supports blobs transparently
r10185 at zot (orig r960): alexmv | 2006-04-28 17:48:13 -0400
r12692 at zoq-fot-pik: chmrr | 2006-04-28 17:47:58 -0400
* Typxo caught by Bart Bunting <bart at bunting.net.au>
Modified: jifty/branches/jifty-jsan/Makefile.PL
==============================================================================
--- jifty/branches/jifty-jsan/Makefile.PL (original)
+++ jifty/branches/jifty-jsan/Makefile.PL Sat Apr 29 12:57:33 2006
@@ -11,7 +11,7 @@
requires('Class::Container');
requires('Clone');
requires('Compress::Zlib');
-requires('DBD::SQLite');
+requires('DBD::SQLite' => 1.11 );
requires('Data::Page');
requires('DateTime');
requires('Date::Manip');
Modified: jifty/branches/jifty-jsan/lib/Jifty.pm
==============================================================================
--- jifty/branches/jifty-jsan/lib/Jifty.pm (original)
+++ jifty/branches/jifty-jsan/lib/Jifty.pm Sat Apr 29 12:57:33 2006
@@ -5,7 +5,7 @@
use encoding 'utf8';
# Work around the fact that Time::Local caches thing on first require
BEGIN { local $ENV{'TZ'} = "GMT"; require Time::Local;}
-our $VERSION = '0.60321';
+our $VERSION = '0.60428';
=head1 NAME
Modified: jifty/branches/jifty-jsan/lib/Jifty/Action/Record.pm
==============================================================================
--- jifty/branches/jifty-jsan/lib/Jifty/Action/Record.pm (original)
+++ jifty/branches/jifty-jsan/lib/Jifty/Action/Record.pm Sat Apr 29 12:57:33 2006
@@ -163,7 +163,7 @@
# XXX This assumes a ->name and a ->id method
$info->{valid_values} = [
- { display_from => 'name',
+ { display_from => $refers_to->can('name') ? "name" : "id",
value_from => 'id',
collection => $collection
}
Modified: jifty/branches/jifty-jsan/lib/Jifty/Everything.pm
==============================================================================
--- jifty/branches/jifty-jsan/lib/Jifty/Everything.pm (original)
+++ jifty/branches/jifty-jsan/lib/Jifty/Everything.pm Sat Apr 29 12:57:33 2006
@@ -37,8 +37,8 @@
use Jifty::View::Static::Handler ();
use Jifty::View::Mason::Handler ();
-use Jifty::Model::Schema ();
-
+use Jifty::Model::Metadata ();
+use Jifty::Model::Session ();
use Jifty::Request ();
Modified: jifty/branches/jifty-jsan/lib/Jifty/Handle.pm
==============================================================================
--- jifty/branches/jifty-jsan/lib/Jifty/Handle.pm (original)
+++ jifty/branches/jifty-jsan/lib/Jifty/Handle.pm Sat Apr 29 12:57:33 2006
@@ -101,18 +101,50 @@
=cut
sub check_schema_version {
- my $appv
- = version->new( Jifty->config->framework('Database')->{'Version'} );
- require Jifty::Model::Schema;
- my $dbv = Jifty::Model::Schema->new->in_db;
- die
- "Schema has no version in the database; perhaps you need to run this:\n\t bin/jifty schema --setup\n"
- unless defined $dbv;
-
- die
- "Schema version in database ($dbv) doesn't match application schema version ($appv)\n"
- . "Please run `bin/jifty schema --setup` to upgrade the database.\n"
- unless $appv == $dbv;
+ require Jifty::Model::Metadata;
+
+ # Application db version check
+ {
+ my $dbv = Jifty::Model::Metadata->load("application_db_version");
+ my $appv = Jifty->config->framework('Database')->{'Version'};
+
+ # Backwards compatibility -- it used to be in _db_version
+ if ( not defined $dbv ) {
+ my @v;
+ eval {
+ local $SIG{__WARN__} = sub { };
+ @v = Jifty->handle->fetch_result(
+ "SELECT major, minor, rev FROM _db_version");
+ };
+ $dbv = join( ".", @v ) if @v == 3;
+ }
+
+ die
+ "Application schema has no version in the database; perhaps you need to run this:\n"
+ . "\t bin/jifty schema --setup\n"
+ unless defined $dbv;
+
+ die
+ "Application schema version in database ($dbv) doesn't match application schema version ($appv)\n"
+ . "Please run `bin/jifty schema --setup` to upgrade the database.\n"
+ unless version->new($appv) == version->new($dbv);
+ }
+
+ # Jifty db version check
+ {
+
+ # If we got here, the application had a version (somehow) so
+ # this is an upgrade. If $dbv is undef, it's because it's
+ # from before when the _jifty_metadata table existed.
+ my $dbv
+ = version->new( Jifty::Model::Metadata->load("jifty_db_version")
+ || '0.60426' );
+ my $appv = version->new($Jifty::VERSION);
+ die
+ "Internal jifty schema version in database ($dbv) doesn't match running jifty version ($appv)\n"
+ . "Please run `bin/jifty schema --setup` to upgrade the database.\n"
+ unless $appv == $dbv;
+ }
}
Added: jifty/branches/jifty-jsan/lib/Jifty/Model/Metadata.pm
==============================================================================
--- (empty file)
+++ jifty/branches/jifty-jsan/lib/Jifty/Model/Metadata.pm Sat Apr 29 12:57:33 2006
@@ -0,0 +1,96 @@
+use warnings;
+use strict;
+
+=head1 NAME
+
+Jifty::Model::Metadata - Tracks Jifty-related metadata
+
+=head1 SYNOPSIS
+
+ my $app = Jifty->new(config_file => "$ProjectRoot/etc/config.yml");
+ my $application_version = Jifty::Model::Metadata->load("application_db_version");
+
+=head1 DESCRIPTION
+
+Every Jifty application automatically inherits this table, which
+describes information about the Jifty database. It uses this
+information to smartly upgrade between application versions, as well
+as versions of Jifty itself, for instance.
+
+=cut
+
+package Jifty::Model::Metadata::Schema;
+use Jifty::DBI::Schema;
+
+column key => type is 'text';
+column value => type is 'text';
+
+package Jifty::Model::Metadata;
+use version;
+
+use base qw( Jifty::Record );
+
+=head2 table
+
+Schemas are stored in the table C<_jifty_metadata>.
+
+=cut
+
+sub table {'_jifty_metadata'}
+
+=head2 since
+
+The metadata table first appeared in Jifty version 0.60427
+
+=cut
+
+sub since {'0.60427'}
+
+=head2 load KEY
+
+Fetches the given C<KEY> from the metadata store. Returns undef if
+such a key cannot be found.
+
+=cut
+
+sub load {
+ my $self = shift;
+ $self = $self->new( current_user => Jifty::CurrentUser->superuser )
+ unless ref $self;
+ return undef unless $self->_handle and $self->_handle->dbh->ping;
+
+ my ($key) = @_;
+
+ # This may barf all over the place. That's almost expected in
+ # some circumstances, so we eat all warnings and errors right
+ # here, right now.
+ eval {
+ local $SIG{__WARN__} = sub { };
+ $self->load_by_cols( key => $key );
+ };
+ return undef unless $self->id;
+ return $self->value;
+}
+
+=head2 store KEY => VALUE
+
+Stores the given C<KEY> in the database, overwriting the previous
+value if it existed.
+
+=cut
+
+sub store {
+ my $self = shift;
+ $self = $self->new( current_user => Jifty::CurrentUser->superuser )
+ unless ref $self;
+
+ my ( $key, $value ) = @_;
+ $self->load_by_cols( key => $key );
+ if ( $self->id ) {
+ $self->set_value($value);
+ } else {
+ $self->create( key => $key, value => $value );
+ }
+}
+
+1;
Modified: jifty/branches/jifty-jsan/lib/Jifty/Model/Session.pm
==============================================================================
--- jifty/branches/jifty-jsan/lib/Jifty/Model/Session.pm (original)
+++ jifty/branches/jifty-jsan/lib/Jifty/Model/Session.pm Sat Apr 29 12:57:33 2006
@@ -1,2 +1,109 @@
-package Jifty::Model::Session;
-"TRUE, THIS IS A STUB FILE. SORRY";
+use warnings;
+use strict;
+
+=head1 NAME
+
+Jifty::Model::Session - Jifty session tracking
+
+=head1 DESCRIPTION
+
+Every Jifty application automatically inherits this table, which
+tracks session information for the application. Individual keys in
+the session structure are stored as rows, making session updates take
+constant time, and also reducing the need for locking.
+
+=cut
+
+package Jifty::Model::Session::Schema;
+use Jifty::DBI::Schema;
+
+column session_id => type is 'varchar(32)';
+column key => type is 'text';
+column value => type is 'blob',
+ filters are 'Jifty::DBI::Filter::Storable';
+column created => type is 'timestamp',
+ filters are 'Jifty::DBI::Filter::DateTime';
+column updated => type is 'timestamp',
+ filters are 'Jifty::DBI::Filter::DateTime';
+column key_type => type is 'varchar(32)';
+
+package Jifty::Model::Session;
+
+use base qw( Jifty::Record );
+use DateTime;
+
+=head2 table
+
+Sessions are stored in the table C<_jifty_sessions>.
+
+=cut
+
+sub table {'_jifty_sessions'}
+
+=head2 since
+
+Sessions first started getting stored in the database in Jifty version
+0.60428
+
+=cut
+
+sub since { '0.60428' }
+
+=head2 current_user
+
+Everyone is treated as the superuser when dealing with session
+objects. This avoids infinite recursion, as otherwise it would try to
+look up the current user in the session object to find out who we
+are...
+
+=cut
+
+sub current_user { return Jifty::CurrentUser->superuser }
+
+=head2 new_session_id
+
+Returns a random new session id. This is a 32-character hex string.
+
+=cut
+
+sub new_session_id {
+ return Digest::MD5::md5_hex(
+ Digest::MD5::md5_hex( time() . {} . rand() . $$ ) );
+}
+
+=head2 create
+
+Defaults the created and updated times to now.
+
+=cut
+
+sub create {
+ my $self = shift;
+ my %args = (
+ session_id => $self->new_session_id,
+ key_type => "key",
+ created => DateTime->now,
+ updated => DateTime->now,
+ @_,
+ );
+
+ return $self->SUPER::create(%args);
+}
+
+=head2 set_value [VALUE]
+
+Updates the C<updated> column, in addition to setting the value.
+
+=cut
+
+sub set_value {
+ my $self = shift;
+ my $value = shift;
+
+ return undef unless $self->id;
+
+ $self->set_updated( DateTime->now );
+ $self->_set( column => 'value', value => $value );
+}
+
+1;
Modified: jifty/branches/jifty-jsan/lib/Jifty/Request.pm
==============================================================================
--- jifty/branches/jifty-jsan/lib/Jifty/Request.pm (original)
+++ jifty/branches/jifty-jsan/lib/Jifty/Request.pm Sat Apr 29 12:57:33 2006
@@ -138,9 +138,13 @@
for my $a (values %actions) {
my %arguments;
for my $arg (keys %{$a->{fields} || {}}) {
- for my $type (qw/doublefallback fallback value/) {
- $arguments{$arg} = $a->{fields}{$arg}{$type}
- if exists $a->{fields}{$arg}{$type};
+ if (ref $a->{fields}{$arg}) {
+ for my $type (qw/doublefallback fallback value/) {
+ $arguments{$arg} = $a->{fields}{$arg}{$type}
+ if exists $a->{fields}{$arg}{$type};
+ }
+ } else {
+ $arguments{$arg} = $a->{fields}{$arg};
}
}
$self->add_action(moniker => $a->{moniker},
Modified: jifty/branches/jifty-jsan/lib/Jifty/Script/Schema.pm
==============================================================================
--- jifty/branches/jifty-jsan/lib/Jifty/Script/Schema.pm (original)
+++ jifty/branches/jifty-jsan/lib/Jifty/Script/Schema.pm Sat Apr 29 12:57:33 2006
@@ -48,7 +48,8 @@
if ( $self->{create_all_tables} ) {
$self->create_all_tables();
} elsif ( $self->{'setup_tables'} ) {
- $self->upgrade_tables();
+ $self->upgrade_jifty_tables();
+ $self->upgrade_appliction_tables();
} else {
print "Done.\n";
}
@@ -66,7 +67,7 @@
# Import Jifty
Jifty::Util->require("Jifty");
- Jifty::Util->require("Jifty::Model::Schema");
+ Jifty::Util->require("Jifty::Model::Metadata");
}
@@ -143,7 +144,7 @@
logger_component => 'SchemaTool',
);
};
- if ( $@ =~ /doesn't match application schema version/i ) {
+ if ( $@ =~ /doesn't match (application schema|running jifty) version/i) {
# We found an out-of-date DB. Upgrade it
$self->{setup_tables} = 1;
} elsif ( $@ =~ /no version in the database/i ) {
@@ -179,13 +180,14 @@
sub create_all_tables {
my $self = shift;
- my $schema = Jifty::Model::Schema->new;
my $log = Log::Log4perl->get_logger("SchemaTool");
$log->info(
"Generating SQL for application $self->{'_application_class'}...");
my $appv
= version->new( Jifty->config->framework('Database')->{'Version'} );
+ my $jiftyv
+ = version->new( $Jifty::VERSION || '0.60426' );
for my $model ( __PACKAGE__->models ) {
@@ -196,9 +198,9 @@
# This *will* try to generate SQL for abstract base classes you might
# stick in $AC::Model::.
next unless $model->isa( 'Jifty::Record' );
- do { log->info("Skipping $model"); next }
+ do { $log->info("Skipping $model"); next }
if ( $model->can( 'since' )
- and $appv < $model->since );
+ and ($model =~ /^Jifty::Model::/ ? $jiftyv : $appv) < $model->since );
$log->info("Using $model");
my $ret = $self->{'_schema_generator'}->add_model( $model->new );
@@ -219,8 +221,9 @@
$ret or die "error creating a table: " . $ret->error_message;
}
- # Update the version in the database
- $schema->update($appv);
+ # Update the versions in the database
+ Jifty::Model::Metadata->store( application_db_version => $appv);
+ Jifty::Model::Metadata->store( jifty_db_version => $jiftyv);
# Load initial data
eval {
@@ -235,52 +238,79 @@
# Commit it all
Jifty->handle->commit;
}
- $log->info("Set up version $appv");
+ $log->info("Set up version $appv, jifty version $jiftyv");
}
-=head2 upgrade_tables
+=head2 upgrade_jifty_tables
-Upgrade your app's tables to match your current model.
+Upgrade Jifty's internal tables.
+
+=cut
+
+sub upgrade_jifty_tables {
+ my $self = shift;
+ my $dbv = version->new( Jifty::Model::Metadata->load( 'jifty_db_version' ) || '0.60426' );
+ my $appv = version->new( $Jifty::VERSION );
+
+ $self->upgrade_tables( "Jifty" => $dbv, $appv, "Jifty::Upgrade::Internal" );
+ Jifty::Model::Metadata->store( jifty_db_version => $appv );
+}
+
+=head2 upgrade_appliction_tables
+
+Upgrade the application's tables.
+
+=cut
+
+sub upgrade_appliction_tables {
+ my $self = shift;
+ my $dbv = version->new( Jifty::Model::Metadata->load( 'application_db_version' ) );
+ my $appv
+ = version->new( Jifty->config->framework('Database')->{'Version'} );
+
+ $self->upgrade_tables( $self->{_application_class} => $dbv, $appv );
+ Jifty::Model::Metadata->store( application_db_version => $appv );
+}
+
+=head2 upgrade_tables BASECLASS, FROM, TO, [UPGRADECLASS]
+
+Given a C<BASECLASS> to upgrade, and two L<version> objects, C<FROM>
+and C<TO>, performs the needed transforms to the database.
+C<UPGRADECLASS>, if not specified, defaults to C<BASECLASS>::Upgrade
=cut
sub upgrade_tables {
my $self = shift;
+ my ($baseclass, $dbv, $appv, $upgradeclass ) = @_;
+ $upgradeclass ||= $baseclass."::Upgrade";
- my $schema = Jifty::Model::Schema->new;
my $log = Log::Log4perl->get_logger("SchemaTool");
# Find current versions
- my $dbv = $schema->in_db;
- my $appv
- = version->new( Jifty->config->framework('Database')->{'Version'} );
if ( $appv < $dbv ) {
- print "Version $appv from module older than $dbv in database!\n";
- exit;
+ print "$baseclass version $appv from module older than $dbv in database!\n";
+ return;
} elsif ( $appv == $dbv ) {
-
# Shouldn't happen
- print "Version $appv up to date.\n";
- exit;
+ print "$baseclass version $appv up to date.\n";
+ return;
}
$log->info(
- "Gerating SQL to update $self->{'_application_class'} $dbv database to $appv"
+ "Gerating SQL to upgrade $baseclass $dbv database to $appv"
);
- my %UPGRADES;
-
# Figure out what versions the upgrade knows about.
+ my %UPGRADES;
eval {
- my $upgrader = $self->{'_application_class'} . "::Upgrade";
- Jifty::Util->require($upgrader);
-
- $UPGRADES{$_} = [ $upgrader->upgrade_to($_) ]
+ Jifty::Util->require($upgradeclass);
+ $UPGRADES{$_} = [ $upgradeclass->upgrade_to($_) ]
for grep { $appv >= version->new($_) and $dbv < version->new($_) }
- $upgrader->versions();
+ $upgradeclass->versions();
};
- for my $model ( __PACKAGE__->models ) {
+ for my $model ( grep {/^\Q$baseclass\E::Model::/} __PACKAGE__->models ) {
# We don't want to get the Collections, for example.
do {next} unless $model->isa( 'Jifty::Record' );
@@ -372,7 +402,6 @@
}
}
}
- $schema->update($appv);
$log->info("Upgraded to version $appv");
Jifty->handle->commit;
}
Modified: jifty/branches/jifty-jsan/lib/Jifty/Test.pm
==============================================================================
--- jifty/branches/jifty-jsan/lib/Jifty/Test.pm (original)
+++ jifty/branches/jifty-jsan/lib/Jifty/Test.pm Sat Apr 29 12:57:33 2006
@@ -183,12 +183,12 @@
# Remove testing db
if (Jifty->handle) {
- Jifty->handle->disconnect();
- Log::Log4perl->get_logger("SchemaTool")->less_logging(3);
- my $schema = Jifty::Script::Schema->new;
- $schema->{drop_database} = 1;
- $schema->run;
- Log::Log4perl->get_logger("SchemaTool")->more_logging(3);
+ Jifty->handle->disconnect();
+ Log::Log4perl->get_logger("SchemaTool")->less_logging(3);
+ my $schema = Jifty::Script::Schema->new;
+ $schema->{drop_database} = 1;
+ $schema->run;
+ Log::Log4perl->get_logger("SchemaTool")->more_logging(3);
}
}
}
Modified: jifty/branches/jifty-jsan/lib/Jifty/Test/WWW/Mechanize.pm
==============================================================================
--- jifty/branches/jifty-jsan/lib/Jifty/Test/WWW/Mechanize.pm (original)
+++ jifty/branches/jifty-jsan/lib/Jifty/Test/WWW/Mechanize.pm Sat Apr 29 12:57:33 2006
@@ -13,13 +13,15 @@
=head1 NAME
-Jifty::Test::WWW::Mechanize - Subclass of L<Test::WWW::Mechanize> with extra Jifty features
+Jifty::Test::WWW::Mechanize - Subclass of L<Test::WWW::Mechanize> with
+extra Jifty features
=head1 METHODS
=head2 new
-Overrides L<Test::WWW::Mechanize>'s C<new> to automatically give the bot a cookie jar.
+Overrides L<Test::WWW::Mechanize>'s C<new> to automatically give the
+bot a cookie jar.
=cut
@@ -32,8 +34,8 @@
=head2 moniker_for ACTION, FIELD1 => VALUE1, FIELD2 => VALUE2
-Finds the moniker of the first action of type I<ACTION> whose "constructor"
-field I<FIELD1> is I<VALUE1>, and so on.
+Finds the moniker of the first action of type I<ACTION> whose
+"constructor" field I<FIELD1> is I<VALUE1>, and so on.
=cut
@@ -63,9 +65,10 @@
=head2 fill_in_action MONIKER, FIELD1 => VALUE1, FIELD2 => VALUE2, ...
-Finds the fields on the current page with the names FIELD1, FIELD2, etc in the MONIKER
-action, and fills them in. Returns the L<HTML::Form> object of the form
-that the action is in, or undef if it can't find all the fields.
+Finds the fields on the current page with the names FIELD1, FIELD2,
+etc in the MONIKER action, and fills them in. Returns the
+L<HTML::Form> object of the form that the action is in, or undef if it
+can't find all the fields.
=cut
@@ -90,11 +93,13 @@
=head2 fill_in_action_ok MONIKER, FIELD1 => VALUE1, FIELD2 => VALUE2, ...
-Finds the fields on the current page with the names FIELD1, FIELD2, etc in the MONIKER
-action, and fills them in. Returns the L<HTML::Form> object of the form
-that the action is in, or undef if it can't find all the fields.
+Finds the fields on the current page with the names FIELD1, FIELD2,
+etc in the MONIKER action, and fills them in. Returns the
+L<HTML::Form> object of the form that the action is in, or undef if it
+can't find all the fields.
-Also, passes if it finds all of the fields and fails if any of the fields are missing.
+Also, passes if it finds all of the fields and fails if any of the
+fields are missing.
=cut
@@ -135,8 +140,8 @@
=head2 action_field_value MONIKER, FIELD
-Finds the fields on the current page with the names FIELD in the action
-MONIKER, and returns its value, or undef if it can't be found.
+Finds the fields on the current page with the names FIELD in the
+action MONIKER, and returns its value, or undef if it can't be found.
=cut
@@ -153,14 +158,6 @@
return $input->value;
}
-=head2 field_error_text MONIKER, FIELD
-
-Finds the error span on the current page for the name FIELD in the action
-MONIKER, and returns the text (tags stripped) from it. (If the field can't be
-found.
-
-=cut
-
# When it sees something like
# http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd as a DOCTYPE, this will make
# it open static/dtd/xhtml1-strict.dtd instead -- great for offline hacking!
@@ -180,6 +177,14 @@
$_[-1] = 1; # just return please
};
+=head2 field_error_text MONIKER, FIELD
+
+Finds the error span on the current page for the name FIELD in the
+action MONIKER, and returns the text (tags stripped) from it. (If the
+field can't be found.
+
+=cut
+
sub field_error_text {
my $self = shift;
my $moniker = shift;
@@ -199,8 +204,9 @@
=head2 uri
-L<WWW::Mechanize> has a bug where it returns the wrong value for C<uri> after
-redirect. This fixes that. See http://rt.cpan.org/NoAuth/Bug.html?id=9059
+L<WWW::Mechanize> has a bug where it returns the wrong value for
+C<uri> after redirect. This fixes that. See
+http://rt.cpan.org/NoAuth/Bug.html?id=9059
=cut
@@ -208,7 +214,8 @@
=head2 get_html_ok URL
-Calls C<get> URL, followed by testing the HTML using L<Test::HTML::Lint>.
+Calls C<get> URL, followed by testing the HTML using
+L<Test::HTML::Lint>.
=cut
@@ -222,7 +229,8 @@
=head2 submit_html_ok
-Calls C<submit>, followed by testing the HTML using L<Test::HTML::Lint>.
+Calls C<submit>, followed by testing the HTML using
+L<Test::HTML::Lint>.
=cut
@@ -269,7 +277,6 @@
my $session = Jifty::Web::Session->new;
$session->load($1);
- $session->_session->release_all_locks();
return $session;
}
Modified: jifty/branches/jifty-jsan/lib/Jifty/Upgrade.pm
==============================================================================
--- jifty/branches/jifty-jsan/lib/Jifty/Upgrade.pm (original)
+++ jifty/branches/jifty-jsan/lib/Jifty/Upgrade.pm Sat Apr 29 12:57:33 2006
@@ -28,13 +28,14 @@
=cut
-sub since {
- my ($version, $sub) = @_;
- if (exists $UPGRADES{$version}) {
- $UPGRADES{$version} = sub { $UPGRADES{$version}->(); $sub->(); }
- } else {
- $UPGRADES{$version} = $sub;
- }
+sub since {
+ my ($version, $sub) = @_;
+ my $package = (caller)[0];
+ if (exists $UPGRADES{$package}{$version}) {
+ $UPGRADES{$package}{$version} = sub { $UPGRADES{$package}{$version}->(); $sub->(); }
+ } else {
+ $UPGRADES{$package}{$version} = $sub;
+ }
}
=head2 versions
@@ -46,7 +47,8 @@
=cut
sub versions {
- return sort keys %UPGRADES;
+ my $class = shift;
+ return sort keys %{$UPGRADES{$class} || {}};
}
=head2 upgrade_to I<VERSION>
@@ -57,9 +59,9 @@
=cut
sub upgrade_to {
- my $self = shift;
+ my $class = shift;
my $version = shift;
- return $UPGRADES{$version} || sub {};
+ return $UPGRADES{$class}{$version} || sub {};
}
1;
Added: jifty/branches/jifty-jsan/lib/Jifty/Upgrade/Internal.pm
==============================================================================
--- (empty file)
+++ jifty/branches/jifty-jsan/lib/Jifty/Upgrade/Internal.pm Sat Apr 29 12:57:33 2006
@@ -0,0 +1,23 @@
+use strict;
+use warnings;
+
+package Jifty::Upgrade::Internal;
+use Jifty::Upgrade;
+use base qw/Jifty::Upgrade/;
+use Jifty::Model::Metadata;
+
+=head2 Version 0.60427
+
+Version metadata, previously stored in _db_version, get migrated to
+_jifty_metadata, so it could be used to store more than one row
+usefully.
+
+=cut
+
+since '0.60427' => sub {
+ my @v = Jifty->handle->fetch_result("SELECT major, minor, rev FROM _db_version");
+ Jifty->handle->simple_query("DROP TABLE _db_version");
+ Jifty::Model::Metadata->store( application_db_version => version->new(join'.', at v));
+};
+
+1;
Modified: jifty/branches/jifty-jsan/lib/Jifty/Web/Session.pm
==============================================================================
--- jifty/branches/jifty-jsan/lib/Jifty/Web/Session.pm (original)
+++ jifty/branches/jifty-jsan/lib/Jifty/Web/Session.pm Sat Apr 29 12:57:33 2006
@@ -2,231 +2,239 @@
use strict;
package Jifty::Web::Session;
-use base qw/Jifty::Object Class::Accessor::Fast/;
+use base qw/Jifty::Object/;
use CGI::Cookie;
-
-# We don't use Class::Accessor::Fast as we want to do our own 'set' and 'get' here
-#__PACKAGE__->mk_accessors(qw(_session));
+use DateTime;
=head1 NAME
Jifty::Web::Session - A Jifty session handler
-=head1 DESCRIPTION
-
-* Jifty sessions
-
-* User gets a per-app session cookie in their first response from the server
-* User gets an updated cookie on any request where:
- 1) if the cookie parameters have changed
- 2) if the user's current sessionid doesn't match the cookie's session id
+=cut
-* The session cookie is handed out after all processing, but before any page
- content is displayed
+=head2 new
-* The user gets a cookie even if we're doing a redirect.
+Returns a new, empty session.
-* In the future, we might want to not give the user a cookie.
+=cut
+sub new {
+ my $class = shift;
+ return bless {}, $class;
+}
+=head2 id
-* Debugging
+Returns the session's id if it has been loaded, or C<undef> otherwise.
-** Should log:
- * User presented a session cookie
- * Loaded session from disk
- * Failed to load session from disk (expired)
- * Created a new session
- * Sent a session cookie to the user.
+=cut
+sub id {
+ my $self = shift;
+ return $self->loaded ? $self->_session->session_id : undef;
+}
-=head2 load
+=head2 load [ID]
-Load up the current session from a cookie
+Load up the current session from the given C<ID>, or the appropriate
+cookie (see L</cookie_name>) otherwise. If both of those fail,
+creates a session in the database.
=cut
-
sub load {
- my $self = shift;
+ my $self = shift;
my $session_id = shift;
- require Apache::Session::File;
-
unless ($session_id) {
my %cookies = CGI::Cookie->fetch();
my $cookiename = $self->cookie_name;
- $session_id = $cookies{$cookiename} ? $cookies{$cookiename}->value() : undef;
+ $session_id
+ = $cookies{$cookiename} ? $cookies{$cookiename}->value() : undef;
}
- $Storable::Deparse = 1;
- $Storable::Eval = 1;
- my %session;
-
- my $session_dir = Jifty::Util->absolute_path( Jifty->config->framework('Web')->{'SessionDir'} );
-
- eval {
- tie %session, 'Apache::Session::File', ( $session_id ? $session_id : undef ),
- {
- Directory => $session_dir,
- LockDirectory => $session_dir,
- };
-
- };
- if ($@) {
- tie %session, 'Apache::Session::File', undef,
- {
- Directory => $session_dir,
- LockDirectory => $session_dir,
- };
- }
+ my $session = Jifty::Model::Session->new;
+ $session->load_by_cols(
+ session_id => $session_id,
+ key_type => "session"
+ )
+ if $session_id;
- $self->_session( tied(%session) );
- $session{_session_id} = $session{_session_id} || $session_id;
+ $session->create( key_type => "session" ) unless $session->id;
+ $self->_session($session);
}
=head2 unload
-Flush the session to disk and quit.
+Flush the session, and leaves the session object blank.
=cut
sub unload {
my $self = shift;
- return unless($self->_session);
- $self->_session->save();
- $self->_session->{object_store}->close;
- $self->_session->release_all_locks();
+ return unless $self->loaded;
$self->_session(undef);
}
=head2 loaded
-Returns true if the session has already been loaded
+Returns true if the session has already been loaded.
=cut
sub loaded {
my $self = shift;
- return $self->_session && $self->get('_session_id');
+ return $self->_session;
}
sub _session {
my $self = shift;
$self->{'_session'} = shift if (@_);
- return ($self->{'_session'});
+ return ( $self->{'_session'} );
}
-=head2 get KEY
+=head2 get KEY [TYPE]
-Returns the value for C<KEY> for the current user's session
+Returns the value for C<KEY> for the current user's session. C<TYPE>,
+which defaults to "key", allows accessing of other namespaces in the
+session, including "metadata" and "continuation".
=cut
sub get {
- my $self = shift;
- my $key = shift;
- return($self->_session ? $self->_session->FETCH($key) : undef);
-
+ my $self = shift;
+ my $key = shift;
+ my $key_type = shift || "key";
+
+ return undef unless $self->loaded;
+
+ my $setting = Jifty::Model::Session->new;
+ $setting->load_by_cols(
+ session_id => $self->id,
+ key_type => $key_type,
+ key => $key
+ );
+ return $setting->value;
}
+=head2 set KEY => VALUE, [TYPE]
-=head2 set KEY => VALUE
-
-Sets the value C<VALUE> for C<KEY> for the current user's session
+Sets the value C<VALUE> for C<KEY> for the session. C<TYPE>, which
+defaults to "key", allows values to be set in other namespaces,
+including "metadata" and "continuation".
=cut
sub set {
- my $self = shift;
- my $key = shift;
- my $value = shift;
-
- ($self->_session ? $self->_session->STORE($key => $value) : undef);
-
+ my $self = shift;
+ my $key = shift;
+ my $value = shift;
+ my $key_type = shift || "key";
+
+ return undef unless $self->loaded;
+ $self->_session->set_updated( DateTime->now );
+
+ my $setting = Jifty::Model::Session->new;
+ $setting->load_by_cols(
+ session_id => $self->id,
+ key_type => $key_type,
+ key => $key
+ );
+ if ( $setting->id ) {
+ $setting->set_value($value);
+ } else {
+ $setting->create(
+ session_id => $self->id,
+ key_type => $key_type,
+ key => $key,
+ value => $value
+ );
+ }
}
+=head2 remove KEY, [TYPE]
-=head2 remove KEY
-
-Remove key C<KEY> from the cache.
+Remove key C<KEY> from the cache. C<TYPE> defaults to "key".
=cut
sub remove {
- my $self = shift;
- my $key = shift;
- $self->set($key => undef);
+ my $self = shift;
+ my $key = shift;
+ my $key_type = shift || "key";
+
+ return undef unless $self->loaded;
+ $self->_session->set_updated( DateTime->now );
+
+ my $setting = Jifty::Model::Session->new;
+ $setting->load_by_cols(
+ session_id => $self->id,
+ key_type => $key_type,
+ key => $key
+ );
+ $setting->delete if $setting->id;
}
+=head2 set_continuation ID CONT
-=head2 set_continuation KEY VALUE
-
-Stores a continuation in the session
+Stores a continuation in the session.
=cut
-
sub set_continuation {
my $self = shift;
- my $key = shift;
- my $val = shift;
-
- $self->set( '_continuation_'.$key => $val);
-
+ $self->set( @_, "continuation" );
}
+=head2 get_continuation ID
-
-=head2 get_continuation KEY
-
-Pulls a continuation from the current session. Expects a continuation id
+Pulls a continuation from the current session. Expects a continuation
+C<ID>.
=cut
-sub get_continuation {
+sub get_continuation {
my $self = shift;
- my $key = shift;
- $self->get('_continuation_'.$key);
+ $self->get( @_, "continuation" );
}
-=head2 remove_continuation CONTINUATION_ID
+=head2 remove_continuation ID
-Removes a continuation with id CONTINUATION id from the store.
+Removes a continuation with id C<ID> from the store.
=cut
sub remove_continuation {
my $self = shift;
- my $key = shift;
- $self->remove('_continuation_'.$key);
+ $self->remove( @_, "continuation" );
}
-
=head2 continuations
-Return a hash of all the continuations in this session. Keyed by continuation_C<id>.
+Return a hash of all the continuations in this session, keyed by the
+continuations' C<id>.
=cut
-
sub continuations {
my $self = shift;
- my %continuations;
- # XXX TODO: we're deeply abusing the API. that's uncool. We want to replace Apache::Session
- map { $continuations{$_} = $self->get($_) } grep { /^_continuation_/ } keys %{$self->_session->{'data'}};
- return %continuations;
-}
-
+ return () unless $self->loaded;
+ my $conts = Jifty::Model::SessionCollection->new;
+ $conts->limit( column => "key_type", value => "continuation" );
+ $conts->limit( column => "session_id", value => $self->id );
+ my %continuations;
+ $continuations{ $_->key } = $_->value while $_ = $conts->next;
+ return %continuations;
+}
=head2 set_cookie
-Sets the session cookie
+Sets the session cookie.
=cut
@@ -239,22 +247,23 @@
= $cookies{$cookie_name} ? $cookies{$cookie_name}->value() : undef;
my $cookie = new CGI::Cookie(
-name => $cookie_name,
- -value => $self->get('_session_id'),
- -expires => $self->get('_expires'),
+ -value => $self->id,
+ -expires => $self->expires,
);
# XXX TODO might need to change under mod_perl
if ( not $cookies{$cookie_name}
or ( $cookies{$cookie_name} ne $cookie->as_string ) )
{
- Jifty->web->response->add_header( 'Set-Cookie' => $cookie->as_string );
+ Jifty->web->response->add_header(
+ 'Set-Cookie' => $cookie->as_string );
}
}
-
=head2 cookie_name
-Returns the current session's cookie_name. (It's a generic thing for all users
+Returns the current session's cookie_name -- it is the same for all
+users, but various accorting to the port the server is running on.
=cut
@@ -262,25 +271,19 @@
my $self = shift;
my $cookiename = "JIFTY_SID_" . ( $ENV{'SERVER_PORT'} || 'NOPORT' );
return ($cookiename);
-
}
-=head2 expires
+=head2 expires [VALUE]
-Return this cache entry's expirey date, in the format expected by Cache::Cache;
+Get or set the session's expiration date, in a format expected by
+Cache::Cache.
=cut
-
sub expires {
- my $self = shift;
- if(@_) {
- my $expiry = shift;
- $self->set('_expires' => $expiry);
- }
- return ($self->get('_expires'));
+ my $self = shift;
+ $self->set( 'expires' => shift, "metadata" ) if @_;
+ return ( $self->get( 'expires', "metadata" ) );
}
-
-
1;
Added: jifty/branches/jifty-jsan/t/TestApp/t/04-sessions.t
==============================================================================
--- (empty file)
+++ jifty/branches/jifty-jsan/t/TestApp/t/04-sessions.t Sat Apr 29 12:57:33 2006
@@ -0,0 +1,37 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+BEGIN {chdir "t/TestApp"}
+use lib '../../lib';
+use Jifty::Test tests => 11;
+
+use_ok('Jifty');
+Jifty->new();
+
+use_ok('Jifty::Web::Session');
+
+my $s = Jifty::Web::Session->new();
+
+isa_ok($s,'Jifty::Web::Session');
+
+$s->load();
+ok($s->loaded);
+is($s->get('foo'), undef);
+$s->set( foo => 'bar');
+is($s->get('foo'), 'bar');
+
+my $id = $s->id;
+$s->unload;
+ok(!$s->loaded);
+
+$s->load();
+ok($s->loaded);
+isnt($s->id, $id);
+is($s->get('foo'), undef);
+
+$s->load($id);
+is($s->get('foo'), 'bar');
+
+1;
More information about the Jifty-commit
mailing list