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