DoctorKarma/lib/DoctorKarma/DAO/User.pm

348 lines
8.8 KiB
Perl

package DoctorKarma::DAO::User;
use v5.30.0;
use strict;
use warnings;
use Types::Standard qw/Str Int InstanceOf ArrayRef Maybe HasMethods/;
use Params::ValidationCompiler qw(validation_for);
use DateTime::Format::ISO8601;
{
my $validator = validation_for(
params => {
dbh => { type => HasMethods [ 'selectrow_hashref', 'do' ] }
}
);
sub new {
my $class = shift;
my %params = $validator->(@_);
my $self = bless {}, $class;
$self->{dbh} = $params{dbh};
return $self;
}
}
sub _logger {
my $self = shift;
if ( !defined $self->{logger} ) {
$self->{logger} = DoctorKarma::Logger->new;
}
return $self->{logger};
}
sub _db {
my $self = shift;
return $self->{dbh};
}
{
my $validator = validation_for(
params => {
user => { type => InstanceOf ['DoctorKarma::Model::User'] }
}
);
sub store {
my $self = shift;
my %params = $validator->(@_);
my $user = $params{user};
my $db = $self->_db;
my $logger = $self->_logger;
my $insert = <<'EOF';
INSERT INTO users (id, first_name, username, karma) VALUES (?, ?, ?, 0);
EOF
my $username = "\@@{[$user->username]}:" // '';
my $user_id = $user->id_user;
$logger->log_info("Trying to register ${username}${user_id}.");
my $success = 0 +
$db->do( $insert, {}, $user->id_user, $user->username, $user->karma );
if ($success) {
$logger->log_info("${username}${user_id} registered.");
return 1;
}
}
}
{
my $validator = validation_for(
params => {
user => { type => InstanceOf ['DoctorKarma::Model::User'] },
first_name => { type => Str },
}
);
sub update_firstname {
my $self = shift;
my %params = $validator->(@_);
my $user = $params{user};
my $first_name = $params{first_name};
my $db = $self->_db;
my $logger = $self->_logger;
my $success = 0 + $db->do( <<'EOF', {}, $first_name, $user->id_user );
UPDATE users SET first_name = ? WHERE id = ?;
EOF
if ($success) {
my $old_first_name = $user->first_name // 'NULL';
$logger->log_info(<<"EOF");
Updated first_name for id @{[$user->id_user]}
From: ${old_first_name} -> ${first_name}.
EOF
return 1;
}
}
}
{
my $validator = validation_for(
params => {
user => { type => InstanceOf ['DoctorKarma::Model::User'] },
}
);
sub substract_1_karma {
my $self = shift;
my %params = $validator->(@_);
my $user = $params{user};
my $db = $self->_db;
my $logger = $self->_logger;
$db->do( <<'EOF', {}, $user->id_user );
UPDATE users SET karma=karma-1 WHERE id = ?;
EOF
my $user_with_new_karma = $self->recover_id( id => $user->id_user );
$user->karma( $user_with_new_karma->karma );
$logger->log_info( 'User '
. $user->first_name . ':'
. $user->username . ':'
. $user->id_user
. ' has now '
. $user->karma
. ' of karma.' );
}
}
{
my $validator = validation_for(
params => {
user => { type => InstanceOf ['DoctorKarma::Model::User'] },
}
);
sub add_1_karma {
my $self = shift;
my %params = $validator->(@_);
my $user = $params{user};
my $db = $self->_db;
my $logger = $self->_logger;
$db->do( <<'EOF', {}, $user->id_user );
UPDATE users SET karma=karma+1 WHERE id = ?;
EOF
my $user_with_new_karma = $self->recover_id( id => $user->id_user );
$user->karma( $user_with_new_karma->karma );
$logger->log_info( 'User '
. $user->first_name . ':'
. ( $user->username // '' ) . ':'
. $user->id_user
. ' has now '
. $user->karma
. ' of karma.' );
}
}
{
my $validator = validation_for(
params => {
user => { type => InstanceOf ['DoctorKarma::Model::User'] },
last_karma_given_date =>
{ type => InstanceOf ['DateTime'], optional => 1 },
}
);
sub update_last_karma_given_date {
my $self = shift;
my %params = $validator->(@_);
my $db = $self->_db;
my $last_karma_given_date = $params{last_karma_given_date};
my $user = $params{user};
$db->do( <<'EOF', {}, $last_karma_given_date . '', $user->id_user );
UPDATE users SET last_karma_given_date=? WHERE id = ?;
EOF
my $user_with_new_last_karma =
$self->recover_id( id => $user->id_user );
$user->last_karma_given_date( $user->last_karma_given_date );
}
}
{
my $validator = validation_for(
params => {
user => { type => InstanceOf ['DoctorKarma::Model::User'] },
username => { type => Maybe [Str] },
}
);
sub update_username {
my $self = shift;
my %params = $validator->(@_);
my $user = $params{user};
my $username = $params{username};
my $db = $self->_db;
my $logger = $self->_logger;
my $success = 0 + $db->do( <<'EOF', {}, $username, $user->id_user );
UPDATE users SET username = ? WHERE id = ?;
EOF
if ($success) {
my $old_username = $user->username ? '@' . $user->username : 'NULL';
$username = $username ? "\@$username" : 'NULL';
$logger->log_info(<<"EOF");
Updated username for id @{[$user->id_user]}
From: ${old_username} -> ${username}.
EOF
return 1;
}
}
}
{
my $validator = validation_for(
params => {
id => { type => Int },
}
);
sub recover_id {
my $self = shift;
my %params = $validator->(@_);
my $user_id = $params{id};
my $query = <<'EOF';
SELECT id as id_user, first_name, username, karma, last_karma_given_date
FROM users
WHERE id = ?;
EOF
return $self->_recover_by_query(
query => $query,
arguments => [$user_id]
);
}
}
{
my $validator = validation_for(
params => {
username => { type => Str },
}
);
sub recover_username {
my $self = shift;
my %params = $validator->(@_);
my $username = $params{username};
my $query = <<'EOF';
SELECT id as user_id, first_name, username, karma, last_karma_given_date
FROM users
WHERE username = ?;
EOF
return $self->_recover_by_query(
query => $query,
arguments => [$username]
);
}
}
sub get_top_ten_hate_karma {
my $self = shift;
my $db = $self->_db;
my $users = [];
my $users_db = $db->selectall_arrayref( <<'EOF', { Slice => {} } );
SELECT first_name, karma, username, last_karma_given_date, id as id_user
FROM users
WHERE first_name IS NOT NULL
ORDER BY karma ASC
LIMIT 10
EOF
for my $user_db (@$users_db) {
for my $key_field ( keys %$user_db ) {
$user_db->{$key_field} // delete $user_db->{$key_field};
}
push @$users, DoctorKarma::Model::User->new(%$user_db);
}
return $users;
}
sub get_top_ten_karma {
my $self = shift;
my $db = $self->_db;
my $users = [];
my $users_db = $db->selectall_arrayref( <<'EOF', { Slice => {} } );
SELECT first_name, karma, username, last_karma_given_date, id as id_user
FROM users
WHERE first_name IS NOT NULL
ORDER BY karma DESC
LIMIT 10
EOF
for my $user_db (@$users_db) {
for my $key_field ( keys %$user_db ) {
$user_db->{$key_field} // delete $user_db->{$key_field};
}
push @$users, DoctorKarma::Model::User->new(%$user_db);
}
return $users;
}
{
my $validator = validation_for(
params => {
query => { type => Str },
arguments => { type => ArrayRef },
}
);
sub _recover_by_query {
my $self = shift;
my %params = $validator->(@_);
my $query = $params{query};
my $arguments = $params{arguments};
my $db = $self->_db;
my $user_db = $db->selectrow_hashref( $query, {}, @$arguments );
if ( defined $user_db ) {
for my $key_field ( keys %$user_db ) {
$user_db->{$key_field} // delete $user_db->{$key_field};
}
if ( defined $user_db->{last_karma_given_date} ) {
my $iso8601 = DateTime::Format::ISO8601->new;
$user_db->{last_karma_given_date} =
$iso8601->parse_datetime( $user_db->{last_karma_given_date} );
}
return DoctorKarma::Model::User->new(%$user_db);
}
return undef;
}
}
1