package users::UserProfile;
use base "Contenido::Document";
use Digest::MD5;
use Contenido::Globals;
use Data::Dumper;
my %CREDENTIAL_FIELDS = (
'users::Email' => 'email',
'users::Phone' => 'phone',
'users::OA::VK' => 'vkontakte',
'users::OA::FaceBook' => 'facebook',
'users::OA::Google' => 'google',
'users::OA::Mailru' => 'mailru',
);
my %CREDENTIAL_REVERSE = (
'email' => 'users::Email',
'phone' => 'users::Phone',
'vkontakte' => 'users::OA::VK',
'facebook' => 'users::OA::FaceBook',
'google' => 'users::OA::Google',
'mailru' => 'users::OA::Mailru',
);
sub extra_properties
{
return (
{ 'attr' => 'status', 'type' => 'status', 'rusname' => 'Статус пользователя',
'cases' => [
[0, 'Блокированный'],
[1, 'Активный'],
[5, 'Временная активация'],
],
},
{ 'attr' => 'type', 'type' => 'status', 'rusname' => 'Тип аккаунта',
'cases' => [
[0, 'Обычный пользователь'],
[1, 'Продвинутый пользователь'],
[2, 'Модератор'],
[10, 'Администратор'],
],
},
{ 'attr' => 'visibility', 'type' => 'status', 'rusname' => 'Область видимости',
'cases' => [
[0, 'Данные моего аккаунта видны только мне'],
[1, 'Данные моего аккаунта видны всем'],
[2, 'Данные моего аккаунта видны друзьям'],
[3, 'Данные моего аккаунта видны друзьям и членам клубов'],
],
},
{ 'attr' => 'country', 'type' => 'string', 'rusname' => 'Страна' },
{ 'attr' => 'passwd', 'type' => 'password', 'rusname' => 'Пароль', 'rem' => '(<font color="red">Не отображается. Указывать при создании и для изменения</font>)' },
{ 'attr' => 'confirm', 'type' => 'string', 'rusname' => 'Код подтверждения', hidden => 1 },
{ 'attr' => 'secmail', 'type' => 'string', 'rusname' => 'E-mail (secondary)' },
{ 'attr' => 'q1', 'type' => 'string', 'rusname' => 'Контрольный вопрос 1' },
{ 'attr' => 'a1', 'type' => 'string', 'rusname' => 'Контрольный ответ 1' },
{ 'attr' => 'q2', 'type' => 'string', 'rusname' => 'Контрольный вопрос 2' },
{ 'attr' => 'a2', 'type' => 'string', 'rusname' => 'Контрольный ответ 2' },
{ 'attr' => 'account', 'type' => 'string', 'rusname' => 'Сумма на счете' },
{ 'attr' => 'interests', 'type' => 'text', 'rusname' => 'Жизненные интересы', rows => 10 },
{ 'attr' => 'origin', 'type' => 'text', 'rusname' => 'Ориджин', rows => 4 },
{ 'attr' => 'avatar', 'type' => 'image', 'rusname' => 'Аватар', crop => ['32x32','150x150'], preview => ['200x200'] },
)
}
sub post_init {
my $self = shift;
my $opts = shift;
$self->{passwd_prev} = $self->passwd;
return if exists $opts->{ids} || exists $opts{names} || exists $opts{light};
if ( $self->id && $state->{users}->use_credentials ) {
$self->{credentials_available} = {};
my $creds = $keeper->get_documents(
uid => $self->id,
table => 'users::SQL::CredentialsTable',
return_mode => 'array_ref',
);
if ( @$creds ) {
my %creds;
foreach my $cred ( @$creds ) {
$cred->{keeper} = undef;
my $main_field = $CREDENTIAL_FIELDS{$cred->class} if exists $CREDENTIAL_FIELDS{$cred->class};
$self->{credentials_available}{$main_field} = 1;
if ( $main_field ) {
my $multi_field = $main_field.'s';
$self->{$multi_field} = [] unless exists $self->{$multi_field};
push @{$self->{$multi_field}}, $cred;
$self->{$main_field} = $cred if $cred->main;
}
if ( ref $self->{credentials_available} eq 'HASH' ) {
foreach my $main_field ( keys %{$self->{credentials_available}} ) {
my $multi_field = $main_field.'s';
unless ( $self->{$main_field} ) {
$self->{$main_field} = $self->{$multi_field}->[0];
}
}
}
}
}
}
return;
}
sub name_full
{
my $self = shift;
my $name = $self->name;
if ( $name =~ /^(.*?),[\ \t]+(.*)$/ ) {
$name = $2.' '.$1;
}
return $name;
}
sub name_part
{
my $self = shift;
my $name = $self->name;
if ( $name =~ /^(.*?),[\ \t]+(.*)$/ ) {
$name = $2;
} else {
my @parts = split /\s+/, $name;
if ( @parts > 1 ) {
pop @parts;
}
$name = join ' ', @parts;
}
return $name;
}
sub name_family
{
my $self = shift;
my $name = $self->name;
if ( $name =~ /^(.*?),[\ \t]+(.*)$/ ) {
$name = $1;
} else {
my @parts = split /\s+/, $name;
if ( @parts > 1 ) {
$name = pop @parts;
}
}
return $name;
}
sub name_first
{
my $self = shift;
my @name = split /\s+/, $self->name_part;
return $name[0];
}
sub name_middle
{
my $self = shift;
my @name = split /\s+/, $self->name_part;
shift @name if @name;
my $name = @name ? join (' ', @name) : '';
return $name;
}
sub class_name
{
return 'Профиль пользователя';
}
sub class_description
{
return 'Профиль пользователя';
}
sub search_fields
{
return ('email', 'name', 'login');
}
sub class_table
{
return 'users::SQL::UserProfile';
}
sub contenido_status_style
{
my $self = shift;
if ( $self->status == 2 ) {
return 'color:green;';
} elsif ( $self->status == 3 ) {
return 'color:olive;';
} elsif ( $self->status == 4 ) {
return 'color:green;';
} elsif ( $self->status == 5 ) {
return 'color:red;';
}
}
sub get_credentials {
my ($self, $name, %opts) = @_;
my $objects;
if ( $name ) {
return undef unless exists $CREDENTIAL_REVERSE{$name};
my $names = $name.'s';
if ( exists $self->{credentials_available}{$name} ) {
$objects = $self->{$names};
}
} elsif ( my @keys = keys %{$self->{credentials_available}} ) {
$objects = {};
foreach my $key ( @keys ) {
my $names = $key.'s';
push @{$objects->{$key}}, $self->{$names};
}
}
return $objects;
}
sub confirm_credential {
my ($self, %opts) = @_;
return undef unless $self->id;
my $object;
if ( exists $opts{confirm} && $opts{name} && $opts{class} ) {
($object) = $self->keeper->get_documents(
class => $opts{class},
uid => $self->id,
name => lc($opts{name}),
limit => 1,
);
if ( ref $object && $object->confirm eq $opts{confirm} ) {
$object->status(1);
$object->store;
}
} elsif ( $opts{name} && $opts{class} ) {
($object) = $self->keeper->get_documents(
class => $opts{class},
uid => $self->id,
name => lc($opts{name}),
limit => 1,
);
if ( ref $object ) {
$object->status(1);
$object->store;
}
}
if ( ref $object && ($object->class eq 'users::Phone' || $object->class eq 'users::Email') && $object->main && $self->status == 5 ) {
$self->status(1);
$self->store;
}
return $object;
}
sub create_credential {
my ($self, %opts) = @_;
my $object;
if ( $opts{vkontakte} ) {
($object) = $self->keeper->get_documents(
class => 'users::OA::VK',
ext_id => $opts{vkontakte},
limit => 1,
);
return undef if ref $object && $object->uid != $self->id;
unless ( ref $object ) {
$object = users::OA::VK->new ($keeper);
$object->name( $opts{name} );
$object->ext_id( $opts{vkontakte} );
$object->status( 1 );
$object->opaque( $opts{opaque} || 0 );
$object->uid( $self->id );
$object->ava_url( $opts{avatar} );
$object->store;
}
} elsif ( $opts{facebook} ) {
($object) = $self->keeper->get_documents(
class => 'users::OA::FaceBook',
ext_id => $opts{facebook},
limit => 1,
);
return undef if ref $object && $object->uid != $self->id;
unless ( ref $object ) {
$object = users::OA::FaceBook->new ($keeper);
$object->name( $opts{name} );
$object->ext_id( $opts{facebook} );
$object->status( 1 );
$object->opaque( $opts{opaque} || 0 );
$object->uid( $self->id );
$object->ava_url( $opts{avatar} );
$object->store;
}
} elsif ( $opts{google} ) {
($object) = $self->keeper->get_documents(
class => 'users::OA::Google',
ext_id => $opts{google},
limit => 1,
);
return undef if ref $object && $object->uid != $self->id;
unless ( ref $object ) {
$object = users::OA::Google->new ($keeper);
$object->name( $opts{name} );
$object->ext_id( $opts{google} );
if ( $opts{email} ) {
$object->email( $opts{email} );
$self->create_credential( email => $opts{email}, status => 1 );
}
$object->status( 1 );
$object->opaque( $opts{opaque} || 0 );
$object->uid( $self->id );
$object->ava_url( $opts{avatar} );
$object->store;
}
} elsif ( $opts{mailru} ) {
($object) = $self->keeper->get_documents(
class => 'users::OA::Mailru',
ext_id => $opts{mailru},
limit => 1,
);
return undef if ref $object && $object->uid != $self->id;
unless ( ref $object ) {
$object = users::OA::Mailru->new ($keeper);
$object->name( $opts{name} );
$object->ext_id( $opts{mailru} );
if ( $opts{email} ) {
$object->email( $opts{email} );
$self->create_credential( email => $opts{email}, status => 1 );
}
$object->status( 1 );
$object->opaque( $opts{opaque} || 0 );
$object->uid( $self->id );
$object->ava_url( $opts{avatar} );
$object->store;
}
} elsif ( $opts{email} ) {
($object) = $self->keeper->get_documents(
class => 'users::Email',
name => lc($opts{email}),
limit => 1,
);
return undef if ref $object && $object->uid != $self->id;
unless ( ref $object ) {
$object = users::Email->new ($keeper);
$object->name( lc($opts{email}) );
$object->name_orig( $opts{email} );
$object->main( $opts{main} || 0 );
$object->status( $opts{status} || 0 );
$object->opaque( $opts{opaque} || 0 );
$object->uid( $self->id );
$object->confirm( Digest::MD5::md5_hex(int(rand(1000000)), $self->id, $opts{email}) );
$object->store;
} else {
if ( exists $opts{status} && $object->status != $opts{status} ) {
$object->status( $opts{status} );
$object->store;
}
}
if ( $opts{main} ) {
my $sql = $keeper->SQL->prepare('update profile_credentials set main = 0 where class = ? and uid = ? and id != ?');
$sql->execute( $object->class, $self->id, $object->id );
$sql->finish;
}
} elsif ( $opts{phone} ) {
($object) = $self->keeper->get_documents(
class => 'users::Phone',
name => $keeper->{users}->_phone_reduction( $opts{phone} ),
limit => 1,
);
return undef if ref $object && $object->uid != $self->id;
unless ( ref $object ) {
$object = users::Phone->new ($keeper);
$object->name( $keeper->{users}->_phone_reduction($opts{phone}) );
$object->name_format( $keeper->{users}->_phone_format($opts{phone}) );
$object->name_orig( $opts{phone} );
$object->main( $opts{main} || 0 );
$object->status( $opts{status} || 0 );
$object->opaque( $opts{opaque} || 0 );
$object->uid( $self->id );
$object->confirm( Digest::MD5::md5_hex(int(rand(1000000)), $self->id, $opts{email}) );
$object->store;
} else {
if ( exists $opts{status} && $object->status != $opts{status} ) {
$object->status( $opts{status} );
$object->store;
}
}
if ( $opts{main} ) {
my $sql = $keeper->SQL->prepare('update profile_credentials set main = 0 where class = ? and uid = ? and id != ?');
$sql->execute( $object->class, $self->id, $object->id );
$sql->finish;
}
}
return $object;
}
sub table_links
{
my $self = shift;
my @links;
if ( $state->{users}->use_credentials ) {
@links = (
{ name => 'E-mail', class => 'users::Email', filter => 'uid', field => 'uid' },
{ name => 'Phone', class => 'users::Phone', filter => 'uid', field => 'uid' },
);
}
return \@links;
}
sub pre_store
{
my $self = shift;
my $passwd_prev = $self->{passwd_prev} || '';
if ( $self->passwd && $self->passwd ne $passwd_prev ) {
warn "Pass = ".$self->passwd."\n" if $DEBUG;
my $pass = Digest::MD5::md5_hex($self->passwd);
warn "Pass_hex = $pass\n" if $DEBUG;
$self->passwd($pass);
} else {
$self->passwd($passwd_prev);
}
$self->login( lc($self->login) );
if ( $state->{users}->use_credentials ) {
foreach my $prop ( $self->structure ) {
my $name = $prop->{attr};
if ( ref($self->{$name}) =~ /^users\:\:OA\:\:/ ) {
my $obj = $self->{$name};
$self->{$name} = $obj->ext_id;
} elsif ( ref($self->{$name}) =~ /^users\:\:/ ) {
my $obj = $self->{$name};
$self->{$name} = $obj->name;
}
}
} else {
$self->email( $keeper->{users}->_email_reduction($self->email) );
}
my $default_section = $project->s_alias->{users} if ref $project->s_alias eq 'HASH' && exists $project->s_alias->{users};
if ( $default_section ) {
my $sections = $self->{sections};
if ( ref $sections eq 'ARRAY' && scalar @$sections ) {
my @new_sects = grep { $_ != $default_section } @$sections;
push @new_sects, $default_section;
$self->sections(@new_sects);
} elsif ( $sections && !ref $sections && $sections != $default_section ) {
my @new_sects = ($default_section, $sections);
$self->sections(@new_sects);
} else {
$self->sections($default_section);
}
}
return 1;
}
sub post_store
{
my $self = shift;
if ( $state->{users}->use_credentials && $self->email ) {
$self->create_credential( email => $self->email, main => 1, $self->status == 1 ? (status => 1) : () );
}
1;
}
sub post_delete
{
my $self = shift;
if ( $state->{users}->use_credentials ) {
my $creds = $keeper->get_documents(
table => 'users::SQL::CredentialsTable',
uid => $self->id,
return_mode => 'array_ref',
);
map { $_->delete( attachments => 1 ) } @$creds;
}
1;
}
1;