This commit is contained in:
parent
5605c056c7
commit
e7f4623d9d
1 changed files with 91 additions and 37 deletions
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue