Revision 3 (by ahitrov@rambler.ru, 2010/03/24 15:19:32) The CORE
package Contenido::User;

# ----------------------------------------------------------------------------
# ������������
# ----------------------------------------------------------------------------

use strict;
use warnings;
use locale;

use base 'Contenido::Object';

use Contenido::Section;
use Contenido::Globals;

# ���� ���������� �������
sub class_table
{
    return 'SQL::UserTable';
}

sub class_name
{
    return '������������';
}

sub class_description
{
    return '������������';
}


sub extra_properties
{
    return (
        { 'attr' => 'status',	'type' => 'status',
            'cases' => [
                    [0, '�� �������'],
                    [1, '�������'],
                   ],
        },
	{ 'attr' => 'passwd',	'type' => 'password',	'rusname' => '������ (<font color="red">�� ������������. ��������� ��� �������� � ��� ���������</font>)' },
    )
}

# ----------------------------------------------------------------------------
# �����������. ������� ����� ������ ������������... 
#
# ������ �������������:
#  Contenido::User->new()
#  Contenido::User->new($keeper)
#  Contenido::User->new($keeper,$login)
# ----------------------------------------------------------------------------
sub new
{
    my ($proto, $keeper, %args) = @_;
    my $class = ref($proto) || $proto;
    my $login = $args{login};
    my $id    = $args{id};
    my $self;
    if (defined($login) && (length($login)>0) && defined($keeper)) {
        $self=$keeper->get_user_by_login($login, class=>$class);
    } elsif (defined($login) && ($id>0) and defined($keeper)) {
        $self=$keeper->get_user_by_id($login, class=>$class);
    } else {
        $self = {};
        bless($self, $class);
        $self->init();
        $self->keeper($keeper)      if (defined($keeper));
        $self->{class} = $class;
        $self->login($login)        if (defined($login) && (length $login > 0));
    }

    return $self;        
}

#������������ Contenido �������� �� 1 ������� �����������
sub _get_table {
    return class_table()->new();
}

sub pre_store
{
  my $self = shift;

  if ( $self->id ) {
	unless ( $self->passwd ) {
		my $up = $keeper->get_document_by_id ( $self->id,
			class   => ref $self,
		);

		unless (ref $up && $up->passwd) { return 0 }
		$self->passwd($up->passwd);
	}
  }
  return 1;
}


# ----------------------------------------------------------------------------
# ���������� 1, ���� ���� ������������ ������ � �������� ������.
#
# ������� � ������ Contenido 4.0
#  � �� ����� ���� - ���� ������������ ����� ������ ������ � ������ � �������� ���������������.
#  ������ ������ - ��� ������ �� ����� �������.
# ----------------------------------------------------------------------------
sub check_group {
    my ($self, $group) = @_;

    my @groups = $self->groups();
    my %G = map { $_ => 1 } @groups;

    return exists($G{$group});
}


# ----------------------------------------------------------------------------
# ���������� ������� ������� � ��������� ������:
# 0 - ��� ������� �� � ������ ������ �� � ţ ��������
# 1 - ���� ������ � �������� ������ ������ �� � ����� ������ ������� ���
# 2 - ���� ������ ��������������� � ������ ������ ��� ţ �������� �� �����-���� ������
# �������� - ������������� ������
# ----------------------------------------------------------------------------
sub get_section_access
{
    my $self = shift;
    my $sectionid = shift;
    do { $log->error("����� get_section_access() ����� �������� ������ � ��������, �� �� �������"); die } unless ref($self);

    # ��� ����������� ������ ��������� ������
    my $section = ref $sectionid ? $sectionid : $self->keeper()->get_section_by_id($sectionid);
    do { $log->error("����� ->get_section_access: �� ������� ������ $sectionid"); return 2 } unless defined $section;
    my $section_id = ref $sectionid ? $sectionid->id : $sectionid;

    # 1. ���������, ���� �� ������ � ��������������� ��������� ������
    my $exact = $self->check_group($section_id);
    return 2 if $exact;

    # 2.����������, ���� �� ������ � ��������� ������ ������
    my @ancestors = $section->ancestors(); # ������
    my $ancestor_access = 0;
    # 2.1. ���� � ����� �� ���� ��������� (�������) �� ���� ������� � ��������� ������
    foreach (@ancestors)
    {
        if ($self->check_group($_))
        {
            $ancestor_access = 1;
            last;
        }
    }
    return 2 if $ancestor_access;

    # 3. ����������, ���� �� ������ � �������� ������ ������
    my @descendants = $section->descendants(); # �������
    my $descendant_access = 0;
    # 3.1. ���� � ����� �� ���� �������-�������� �� ���� ������� � ��������� ������
    foreach (@descendants)
    {
        if ($self->check_group($_))
        {
            $descendant_access = 1;
            last;
        }
    }
    return 1 if $descendant_access;
    return 0;
}


# ----------------------------------------------------------------------------
# ����������� �������� �� ����������� ������� ������������ � ������
# ----------------------------------------------------------------------------
sub section_accesses
{
    my $self = shift;
    my ($user, $section) = @_;
    
    #another dirty hack for documents without sections
    return 2 unless ($section);

    my $section_id = ref $section ? $section->id : $section;
    unless (defined $user->{_section_accesses_}->{$section_id})
    {
        $user->{_section_accesses_}->{$section_id} = $user->get_section_access($section);
    }
    return $user->{_section_accesses_}->{$section_id};
}


# ----------------------------------------------------------------------------
# ��� ������� ���������� ���� ��� $self->{section_acesses}, �� �����������.
# �� ���� ���������� ��� ���������� ���� ������� ���� �������� ��� ������, �
#  ����� �������� �� ���� �����...
# ----------------------------------------------------------------------------
sub get_accesses {
    my $self = shift;
    my $keeper = $self->keeper();

    my $tree = $keeper->get_tree(light => 1);
    # ������ ������ �� ������ ������� ������...
    my $trefs = {};
    my @tree_ = ($tree);
    $self->{_section_accesses_} = {};
    for my $to (@tree_) {
        if (ref($to->{childs}) eq 'ARRAY') {
            push (@tree_, @{ $to->{childs} });
        }
        $trefs->{$to->id()} = $to;
        $self->{_section_accesses_}->{ $to->id() } = 0;
    }

    # ��������� ��� ������� ��������������...
    my @groups = $self->groups();
    for my $g (@groups) {
        next    if (!exists($trefs->{$g}) || !ref($trefs->{$g}) );

        # ��� ������
        my @ancestors = ();
		my $pid = $trefs->{$g}->pid() || '';
        push (@ancestors, $trefs->{$pid})  if (
                                        exists($trefs->{$pid}) 
                                        &&
                                        ref($trefs->{$pid})
                                        && ($g != 1)
                                    );
        for my $a (@ancestors) {
            push (@ancestors, $trefs->{ $trefs->{ $a->id() }->pid() })  if (exists($trefs->{ $trefs->{ $a->id() }->pid() }) && ref($trefs->{ $trefs->{ $a->id() }->pid() }) && ($a->id() != 1))
        }
        for my $a (@ancestors) {
            $self->{_section_accesses_}->{$a->id()} = 1 if ($self->{_section_accesses_}->{$a->id()} < 1);
        }

        # ��� �������
        my @descendants = ();
        push (@descendants, @{ $trefs->{$g}->{childs} })    if (
                                        exists($trefs->{$g}->{childs}) 
                                        &&
                                        (ref($trefs->{$g}->{childs}) eq 'ARRAY')
                                    );
        for my $d (@descendants) {
            push (@descendants, @{ $trefs->{$d->id()}->{childs} })  if (exists($trefs->{ $d->id() }->{childs}) && (ref($trefs->{ $d->id() }->{childs}) eq 'ARRAY'));
        }
        for my $d (@descendants) {
            $self->{_section_accesses_}->{$d->id()} = 2;
        }

        $self->{_section_accesses_}->{$g} = 2;
    }
    undef $trefs;
    undef @tree_;
    undef $tree;
    return $self->{_section_accesses_};
}

# ----------------------------------------------------------------------------
# ��������� ������ �������, ������������ �����. ��� �� ����������� �������!
# ��� ����� ���� ������ ������ �����������.
# ----------------------------------------------------------------------------
sub get_available_classes {
    my $self = shift;
    my $class = ref $self || do { $log->error("����� get_available_classes() ����� �������� ������ � ��������, �� �� �������"); die };

    return $state->{available_documents};
}

1;