Apache-Voodoo

 view release on metacpan or  search on metacpan

lib/Apache/Voodoo/Table.pm  view on Meta::CPAN

	}

	if (@errors) {
		Apache::Voodoo::Exception::RunTime::BadConfig->throw("Configuration Errors:\n\t".join("\n\t",@errors));
	}
}

sub table {
	my $self = shift;
	if ($_[0]) {
		$self->{'table'} = $_[0];
	}
	return $self->{'table'};
}

sub success {
	my $self = shift;

	return $self->{'success'};
}

sub edit_details {
	my $self = shift;

	# if there wasn't a successful edit, then there's no details :)
	return unless $self->{'success'};

	return $self->{'edit_details'} || [];
}

sub add_details {
	my $self = shift;

	# if there wasn't a successful add, then there's no details :)
	return unless $self->{'success'};

	return $self->{'add_details'} || [];
}

sub add_insert_callback {
	my $self    = shift;
	my $sub_ref = shift;

	push(@{$self->{'insert_callbacks'}},$sub_ref);
}

sub add_update_callback {
	my $self    = shift;
	my $sub_ref = shift;

	push(@{$self->{'update_callbacks'}},$sub_ref);
}

sub list_param_parser {
	my $self    = shift;
	my $sub_ref = shift;

	$self->{'list_param_parser'} = $sub_ref;
}

sub validate_add {
	my $self   = shift;
	my $p      = shift;

	my $dbh    = $p->{'dbh'};
	my $params = $p->{'params'};

	my $errors = {};

	# call each of the insert callbacks
	foreach (@{$self->{'insert_callbacks'}}) {
		my $callback_errors = $_->($dbh,$params);
		@{$errors}{keys %{$callback_errors}} = values %{$callback_errors};
	}

	# do all the normal parameter checking
	my ($values,$e) = $self->{valid}->validate($params);

	# copy the errors from the process_params
	$errors = { %{$errors}, %{$e} } if ref($e) eq "HASH";

	# check to see if the user supplied primary key (optional) is unique
	if ($self->{'pkey_user_supplied'}) {
		if ($params->{$self->{'pkey'}} =~ /$self->{'pkey_regexp'}/) {
			my $res = $dbh->selectall_arrayref("
				SELECT 1
				FROM   $self->{'table'}
				WHERE  $self->{'pkey'} = ?",
				undef,
				$params->{$self->{'pkey'}} );

			if ($res->[0]->[0] == 1) {
				$errors->{'DUP_'.$self->{'pkey'}} = 1;
			}
		}
		else {
			$errors->{'BAD_'.$self->{'pkey'}} = 1;
		}
	}

	# check each unique column constraint
	foreach (@{$self->{'unique'}}) {
		my $res = $dbh->selectall_arrayref("
			SELECT 1
			FROM   $self->{'table'}
			WHERE  $_ = ?",
			undef,
			$values->{$_});
		if ($res->[0]->[0] == 1) {
			$errors->{"DUP_$_"} = 1;
		}
	}

	return ($values,$errors);
}

sub validate_edit {
	my $self   = shift;
	my $p      = shift;

	my $dbh    = $p->{'dbh'};
	my $params = $p->{'params'};

	unless ($params->{$self->{'pkey'}} =~ /$self->{'pkey_regexp'}/) {
		return $self->display_error("Invalid ID");
	}

	my $errors = {};
	# call each of the update callbacks
	foreach (@{$self->{'update_callbacks'}}) {
		# call back should return a list of error strings
		my $callback_errors = $_->($dbh,$params);
		@{$errors}{keys %{$callback_errors}} = values %{$callback_errors};
	}

	# run the standard error checks
	my ($values,$e) = $self->{valid}->validate($params);

	# copy the errors from the process_params
	$errors = { %{$errors}, %{$e} } if ref($e) eq "HASH";

	# check all the unique columns
	foreach (@{$self->{'unique'}}) {
		my $res = $dbh->selectall_arrayref("
			SELECT 1
			FROM   $self->{'table'}
			WHERE  $_ = ? AND $self->{'pkey'} != ?",
			undef,
			$values->{$_},
		$params->{$self->{'pkey'}});
		if ($res->[0]->[0] == 1) {
			$errors->{"DUP_$_"} = 1;
		}
	}

	return $values,$errors;
}

sub add {
	my $self = shift;
	my $p = shift;

	my $dbh    = $p->{'dbh'};
	my $params = $p->{'params'};

	my $errors = {};

	$self->{'success'} = 0;
	$self->{'add_details'} = [];

	if ($params->{'cm'} eq "add") {
		my ($values,$errors) = $self->validate_add($p);

		if (scalar keys %{$errors}) {
			$errors->{'HAS_ERRORS'} = 1;

			# copy values back into form
			foreach (keys(%{$values})) {
				$errors->{$_} = $values->{$_};
			}
		}
		else {
			# copy clean dates,times into params for insertion
			foreach (@{$self->{'dates'}},@{$self->{'times'}}) {
				$values->{$_->{'name'}} = $values->{$_->{'name'}."_CLEAN"};
			}

			my $c = join(",",          @{$self->{'columns'}});		# the column names
			my $q = join(",",map {"?"} @{$self->{'columns'}});		# the ? mark placeholders

			my @v = map { $values->{$_} } @{$self->{'columns'}};	# and the values

			# store the values as they went into the db here incase the caller wants to
			# use them for something.
			foreach (@{$self->{'columns'}}) {
				push(@{$self->{'add_details'}},[$_,'',$values->{$_}]);
			}

			if ($self->{'pkey_user_supplied'}) {
				$c .= ",".$self->{'pkey'};
				$q .= ",?";

				push(@v,$params->{$self->{'pkey'}});
			}


			my $insert_statement = "INSERT INTO $self->{'table'} ($c) VALUES ($q)";

			$dbh->do($insert_statement, undef, @v);

			$self->{'success'} = 1;
			return 1;
		}
	}

	# populate drop downs (also maintaining previous state).
	foreach (@{$self->{'references'}}) {
		my $query = "SELECT
		                 $_->{'pkey'},
		                 $_->{'slabel'}
		             FROM
		                $_->{'table'}
		                $_->{'sextra'}";

		my $res = $dbh->selectall_arrayref($query);

		$errors->{$_->{'fkey'}} = $self->prep_select($res,$errors->{$_->{'fkey'}} || $_->{'sdefault'});
	}

	# If we get here the user is just loading the page
	# for the first time or had errors.
	return $errors;
}

sub edit {
	my $self = shift;
	my $p    = shift;
	my $additional_constraint = shift;

	$self->{'success'} = 0;
	$self->{'edit_details'} = [];

	my $dbh    = $p->{'dbh'};
	my $params = $p->{'params'};

	# make sure our additional constraint won't break the sql
	$additional_constraint =~ s/^\s*(where|and|or)\s+//go;
	if (length($additional_constraint)) {
		$additional_constraint = "AND $additional_constraint";
	}

	unless ($params->{$self->{'pkey'}} =~ /$self->{'pkey_regexp'}/) {
		return $self->display_error("Invalid ID");
	}

	# find the record to be updated
	my $res = $dbh->selectall_arrayref("
		SELECT ".
			join(",",@{$self->{'columns'}}). "
		FROM
			$self->{'table'}
		WHERE
			$self->{'pkey'} = ?
			$additional_constraint",
		undef,
		$params->{$self->{'pkey'}});

	unless (defined($res->[0])) {
		return $self->display_error("No record with that ID found");
	}

	my %original_values;
	for (my $i=0; $i <= $#{$self->{'columns'}}; $i++) {
		$original_values{$self->{'columns'}->[$i]} = $res->[0]->[$i];
	}

	my $errors = {};
	if ($params->{'cm'} eq "update") {
		my ($values,$errors) = $self->validate_edit($p);

		if (scalar keys %{$errors}) {
			$errors->{'has_errors'} = 1;

			# copy values into template
			$errors->{$self->{'pkey'}} = $params->{$self->{'pkey'}};
			foreach (keys(%{$values})) {
				$errors->{$_} = $values->{$_};
			}
		}
		else {
			# copy clean dates,times into params for insertion
			foreach (@{$self->{'dates'}},@{$self->{'times'}}) {
				$values->{$_->{'name'}} = $values->{$_->{'name'}."_CLEAN"};
			}

			# let's figure out what they changed so caller can do something with that info if they want
			foreach (@{$self->{'columns'}}) {
				if ($values->{$_} ne $original_values{$_}) {
					push(@{$self->{'edit_details'}},[$_,$original_values{$_},$values->{$_}]);
				}
			}
			my $update_statement = "
				UPDATE
					$self->{'table'}
				SET ".
					join("=?,",@{$self->{'columns'}})."=?
				WHERE
					$self->{'pkey'} = ?
				$additional_constraint";

			# $self->debug($update_statement);
			# $self->debug((map {$values->{$_}} @{$self->{'columns'}}),$params->{$self->{'pkey'}});

			$dbh->do($update_statement,
			          undef,
			          (map { $values->{$_} } @{$self->{'columns'}}),
			          $params->{$self->{'pkey'}});

			$self->{'success'} = 1;
			return 1;
		}
	}
	else {
		foreach (@{$self->{'columns'}}) {
			$errors->{$_} = $original_values{$_};
		}

		$errors->{$self->{'pkey'}} = $params->{$self->{'pkey'}};

		# pretty up dates
		foreach (@{$self->{'dates'}}) {
			$errors->{$_->{'name'}} = $self->sql_to_date($errors->{$_->{'name'}});
		}

		# pretty up times
		foreach (@{$self->{'times'}}) {
			$errors->{$_->{'name'}} = $self->sql_to_time($errors->{$_->{'name'}});
		}
	}



( run in 0.505 second using v1.01-cache-2.11-cpan-39bf76dae61 )