From e7f4623d9d0b572a5e94975d3e7cc42e3b819957 Mon Sep 17 00:00:00 2001 From: JT Smith Date: Fri, 19 Sep 2008 23:40:16 +0000 Subject: [PATCH] --- lib/WebGUI/Crud.pm | 128 ++++++++++++++++++++++++++++++++------------- 1 file changed, 91 insertions(+), 37 deletions(-) diff --git a/lib/WebGUI/Crud.pm b/lib/WebGUI/Crud.pm index 3d5013b90..80a12821f 100644 --- a/lib/WebGUI/Crud.pm +++ b/lib/WebGUI/Crud.pm @@ -2,6 +2,7 @@ package WebGUI::Crud; use strict; use Class::InsideOut qw(readonly private id register); +use JSON; use Tie::IxHash; use WebGUI::DateTime; use WebGUI::Exception; @@ -13,7 +14,7 @@ readonly session => my %session; #------------------------------------------------------------------- sub create { - my ($class, $session, $properties) = @_; + my ($class, $session, $data) = @_; # validate unless (defined $session && $session->isa('WebGUI::Session')) { @@ -25,38 +26,49 @@ sub create { my $tableKey = $class->crud_getTableKey; my $tableName = $class->crud_getTableName; my $db = $session->db; + my $dbh = $db->dbh; # get creation date my $now = WebGUI::DateTime->new($session, time())->toDatabase; + $data->{lastUpdated} = $now; + # add defaults + my $properties = $class->crud_getProperties; + foreach my $property (keys %{$properties}) { + $data->{$property} ||= $properties->{$property}{defaultValue}; + } + # determine sequence my $sequenceKey = $class->crud_getSequenceKey; my $clause; my @params; if ($sequenceKey) { - $clause = "where `".$sequenceKey."`=?"; - push @params, $properties->{$sequenceKey}; + $clause = "where ".$dbh->quote_identifier($sequenceKey)."=?"; + push @params, $data->{$sequenceKey}; } - my $sequenceNumber = $db->getScalar("select max(sequenceNumber) from `".$tableName."` $clause", \@params); + my $sequenceNumber = $db->getScalar("select max(sequenceNumber) from ".$dbh->quote_identifier($tableName)." $clause", \@params); $sequenceNumber++; - + # create object - my $id = $db->setRow($tableName, $tableKey, {$tableKey=>'new', dateCreated=>$now, lastUpdated=>$now, sequenceNumber=>$sequenceNumber}); + my $id = $db->setRow($tableName, $tableKey, {$tableKey=>'new', dateCreated=>$now, sequenceNumber=>$sequenceNumber}); my $self = $class->new($session, $id); - $self->update($properties); + $self->update($data); return $self; } #------------------------------------------------------------------- sub crud_createTable { my ($class, $session) = @_; - $session->db->write('create table `'.$class->crud_getTableName.'` ( - `'.$class->crud_getTableKey.'` varchar(22) binary not null primary key, + my $db = $session->db; + my $dbh = $db->dbh; + $db->write('create table '.$dbh->quote_identifier($class->crud_getTableName).' ( + '.$dbh->quote_identifier($class->crud_getTableKey).' varchar(22) binary not null primary key, sequenceNumber int not null default 1, dateCreated datetime, lastUpdated datetime )'); $class->crud_updateTable($session); + return 1; } #------------------------------------------------------------------- @@ -75,7 +87,10 @@ sub crud_definition { #------------------------------------------------------------------- sub crud_dropTable { my ($class, $session) = @_; - $session->db->write("drop table `".$class->crud_getTableName."`"); + my $db = $session->db; + my $dbh = $db->dbh; + $db->write("drop table ".$dbh->quote_identifier($class->crud_getTableName).""); + return 1; } #------------------------------------------------------------------- @@ -107,7 +122,8 @@ sub crud_getTableKey { sub crud_updateTable { my ($class, $session) = @_; my $db = $session->db; - my $tableName = '`'.$class->crud_getTableName.'`'; + my $dbh = $db->dbh; + my $tableName = $dbh->quote_identifier($class->crud_getTableName); # find out what fields already exist my %tableFields = (); @@ -124,20 +140,21 @@ sub crud_updateTable { if (exists $tableFields{$property}) { ### have to figure out field type matching #unless ($fieldType eq $tableFields{$property}) { - # $db->write("alter table $tableName change column `".$property."` `".$property."` $fieldType"); + # $db->write("alter table $tableName change column ".$dbh->quote_identifier($property)." ".$dbh->quote_identifier($property)." $fieldType"); #} delete $tableFields{$property}; } else { - $db->write("alter table $tableName add column `".$property."` $fieldType"); + $db->write("alter table $tableName add column ".$dbh->quote_identifier($property)." $fieldType"); delete $tableFields{$property}; } } # delete fields that are no longer in the definition foreach my $property (keys %tableFields) { - $db->write("alter table $tableName drop column `".$property."`"); + $db->write("alter table $tableName drop column ".$dbh->quote_identifier($property)); } + return 1; } #------------------------------------------------------------------- @@ -145,6 +162,7 @@ sub delete { my $self = shift; $self->session->db->deleteRow($self->crud_getTableName, $self->crud_getTableKey, $self->getId); $self->reorder; + return 1; } #------------------------------------------------------------------- @@ -154,23 +172,25 @@ sub demote { my $tableName = $self->crud_getTableName; my $sequenceKey = $self->crud_getSequenceKey; my @params = ($self->get('sequenceNumber') + 1); + my $db = $self->session->db; + my $dbh = $db->dbh; my $clause = ''; # determine sequence if ($sequenceKey) { - $clause = "`".$sequenceKey."`=? and"; + $clause = $dbh->quote_identifier($sequenceKey)."=? and"; unshift @params, $self->get($sequenceKey) } # update database - my $db = $self->session->db; $db->beginTransaction; - my ($id) = $db->quickArray("select `".$tableKey."` from `".$tableName."` where $clause sequenceNumber=?", \@params); + my ($id) = $db->quickArray("select ".$dbh->quote_identifier($tableKey)." from ".$dbh->quote_identifier($tableName)." where $clause sequenceNumber=?", \@params); if ($id ne "") { - $db->write("update `".$tableName."` set sequenceNumber=sequenceNumber+1 where `".$tableKey."`=?",[$self->getId]); - $db->write("update `".$tableName."` set sequenceNumber=sequenceNumber-1 where `".$tableKey."`=?",[$id]); + $db->write("update ".$dbh->quote_identifier($tableName)." set sequenceNumber=sequenceNumber+1 where ".$dbh->quote_identifier($tableKey)."=?",[$self->getId]); + $db->write("update ".$dbh->quote_identifier($tableName)." set sequenceNumber=sequenceNumber-1 where ".$dbh->quote_identifier($tableKey)."=?",[$id]); } $db->commit; + return 1; } #------------------------------------------------------------------- @@ -183,15 +203,17 @@ sub get { } # return a copy of all properties - my %copy = %{$self->objectData}; + my %copy = %{$self->objectData}; return \%copy; } #------------------------------------------------------------------- sub getAll { my ($class, $session, $options) = @_; + my $db = $session->db; + my $dbh = $db->dbh; my @objects; - my $ids = $session->db->read("select `".$class->crud_getTableKey."` from `".$class->crud_getTableName."`"); + my $ids = $session->db->read("select ".$dbh->quote_identifier($class->crud_getTableKey)." from ".$dbh->quote_identifier($class->crud_getTableName)); while (my ($id) = $ids->array) { if ($options->{return} eq "ids") { push @objects, $id; @@ -223,15 +245,23 @@ sub new { } # retrieve object data - my $properties = $session->db->getRow($class->crud_getTableName, $tableKey, $id); - if ($properties->{$tableKey} eq '') { + my $data = $session->db->getRow($class->crud_getTableName, $tableKey, $id); + if ($data->{$tableKey} eq '') { WebGUI::Error::ObjectNotFound->throw(error=>'no such '.$tableKey, id=>$id); } + # deserialize data + my $properties = $class->crud_getProperties; + foreach my $name (keys %{$properties}) { + if ($properties->{$name}{serialize}) { + $data->{$name} = JSON->new->decode($data->{$name}); + } + } + # set up object my $self = register($class); my $refId = id $self; - $objectData{$refId} = $properties; + $objectData{$refId} = $data; $session{$refId} = $session; return $self; } @@ -245,22 +275,24 @@ sub promote { my $sequenceKeyValue = $self->get($sequenceKey); my @params = ($self->get('sequenceNumber')-1); my $clause = ''; + my $db = $self->session->db; + my $dbh = $db->dbh; # determine sequence type if ($sequenceKey) { - $clause = "`".$sequenceKey."`=? and"; + $clause = $dbh->quote_identifier($sequenceKey)."=? and"; unshift @params, $self->get($sequenceKey) } # make database changes - my $db = $self->session->db; $db->beginTransaction; - my ($id) = $db->quickArray("select `".$tableKey."` from `".$tableName."` where `".$sequenceKey."`=? $clause", \@params); + my ($id) = $db->quickArray("select ".$dbh->quote_identifier($tableKey)." from ".$dbh->quote_identifier($tableName)." where ".$dbh->quote_identifier($sequenceKey)."=? $clause", \@params); if ($id ne "") { - $db->write("update `".$tableName."` set sequenceNumber=sequenceNumber-1 where `".$tableKey."`=?",[$self->getId]); - $db->write("update `".$tableName."` set sequenceNumber=sequenceNumber+1 where `".$tableKey."`=?",[$id]); + $db->write("update ".$dbh->quote_identifier($tableName)." set sequenceNumber=sequenceNumber-1 where ".$dbh->quote_identifier($tableKey)."=?",[$self->getId]); + $db->write("update ".$dbh->quote_identifier($tableName)." set sequenceNumber=sequenceNumber+1 where ".$dbh->quote_identifier($tableKey)."=?",[$id]); } $db->commit; + return 1; } #------------------------------------------------------------------- @@ -272,16 +304,17 @@ sub reorder { my $sequenceKeyValue = $self->get($sequenceKey); my $i = 1; my $db = $self->session->db; + my $dbh = $db->dbh; # find all the items in this sequence - my $clause = ($sequenceKey) ? "where `".$sequenceKey."`=?" : ''; - my $current = $db->read("select `".$tableKey."` from `".$tableName."` + my $clause = ($sequenceKey) ? "where ".$dbh->quote_identifier($sequenceKey)."=?" : ''; + my $current = $db->read("select ".$dbh->quote_identifier($tableKey)." from ".$dbh->quote_identifier($tableName)." $clause order by sequenceNumber", [$sequenceKeyValue]); # query to update items in the sequence - $clause = ($sequenceKey) ? "and `".$sequenceKey."`=?" : ''; - my $change = $db->prepare("update `".$tableName."` set sequenceNumber=? - where `".$tableKey."`=? $clause"); + $clause = ($sequenceKey) ? "and ".$dbh->quote_identifier($sequenceKey)."=?" : ''; + my $change = $db->prepare("update ".$dbh->quote_identifier($tableName)." set sequenceNumber=? + where ".$dbh->quote_identifier($tableKey)."=? $clause"); # make the changes $db->beginTransaction; @@ -293,21 +326,42 @@ sub reorder { $i++; } $db->commit; + return 1; } #------------------------------------------------------------------- sub update { - my ($self, $properties) = @_; + my ($self, $data) = @_; + + # validate incoming data + my $properties = $self->crud_getProperties; + foreach my $property (keys %{$data}) { + + # don't save fields that aren't part of our definition + unless (exists $properties->{$property} || $property eq 'lastUpdated') { + delete $data->{$property}; + next; + } + + # set a default value if it's empty or undef + $data->{$property} ||= $properties->{$property}{defaultValue}; + + # serialize if needed + if ($properties->{$property}{serialize}) { + $data->{property} = JSON->new->encode($data->{property}); + } + } # set last updated - $properties->{lastUpdated} = WebGUI::DateTime->new($self->session, time())->toDatabase; + $data->{lastUpdated} ||= WebGUI::DateTime->new($self->session, time())->toDatabase; # update memory my $refId = id $self; - %{$objectData{$refId}} = (%{$objectData{$refId}}, %{$properties}); + %{$objectData{$refId}} = (%{$objectData{$refId}}, %{$data}); # update the database $self->session->db->setRow($self->crud_getTableName, $self->crud_getTableKey, $objectData{$refId}); + return 1; }