Revision 740 (by ahitrov, 2018/11/12 22:03:41) in-core e-mail sender

package Contenido::State;

# ----------------------------------------------------------------------------
# Contenido::State - класс, описывающий текущее состояние проекта. 
# Объект этого класса создается при старте Apache-сервера и заполняется 
# данными из handler.pl или startup.pl. Конкретные данные (порт, URL, 
# стадию и т.д.) изменяются в startup.pl с помощью стандартного механизма 
# sandbox (@@PORT@@). 
# ----------------------------------------------------------------------------

use strict;
use vars qw($VERSION $AUTOLOAD);
$VERSION = '4.2';

use Utils;
use Contenido::Globals;

use @MEMCACHED_BACKEND@;

sub new
{
    my ($proto) = shift;
    my $class = ref($proto) || $proto;
    my $self = {};
    bless($self, $class);

    $self->{project} = '@PROJECT@';
    $self->{project_version} = '@PROJECT_VERSION@';
    $self->{core_version} = '@CORE_VERSION@';

    $self->{db_type} = lc('@DB_TYPE@') || 'single';
    $self->{db_keepalive} = (lc('@PERSISTENT_CONN@') eq 'no') ? 0:1;
    $self->{db_host} = (($self->{db_type} eq 'remote') and '@BASE_HOST@') ? lc('@BASE_HOST@') : 'localhost';
    $self->{db_name} = '@PGSQL_BASE@';
    $self->{db_user} = '@BASE_USER@';
    $self->{db_password} = '@BASE_PASSWD@';
    $self->{db_port} = '@PGSQL_PORT@';
    $self->{db_prepare} = lc('@PGSQL_REAL_PREPARE@') eq 'yes' ? 1 : 0;
    $self->{db_enable_utf8} = lc('@PGSQL_ENABLE_UTF@') eq 'yes' ? -1 : 0;
    $self->{db_client_encoding} = '@PGSQL_CLIENT_ENCODING@';

    $self->{db_encode_data} = '@PGSQL_ENCODE_DATA@';
    $self->{db_decode_data} = '@PGSQL_DECODE_DATA@' || 'utf-8';

    $self->{serialize_with} = lc('@SERIALIZE_WITH@') || 'dumper';

    $self->{master_db_host}     = (($self->{db_type} eq 'remote') and '@MASTER_BASE_HOST@') ? lc('@MASTER_BASE_HOST@') : 'localhost';
    $self->{master_db_name}     = '@MASTER_BASE_NAME@';
    $self->{master_db_user}     = '@MASTER_BASE_USER@';
    $self->{master_db_password} = '@MASTER_BASE_PASSWD@';
    $self->{master_db_port}     = '@MASTER_BASE_PORT@';

    $self->{session_dir} = '@SESSIONS@';
    $self->{session_directory} = '@SESSIONS@';

    $self->{crosslinks_dir} = '@CROSSLINKS@';
    $self->{crosslinks_directory} = '@CROSSLINKS@';

    $self->{httpd_port} = '@HTTPD_PORT@';
    $self->{httpd_server} = '@HTTPD_SERVER@';
    $self->{httpd_root} = 'http://'.$self->{httpd_server}.'/';

    $self->{plugins} = '@PLUGINS@';

    $self->{prefix} = '@PREFIX@';

    $self->{images_directory} = '@IMAGES@';
    $self->{images_dir} = '@IMAGES@';
    
    $self->{proxy_image_location} = '@PROXY_IMAGE_LOCATION@';
    $self->{proxy_image_secret} = '@PROXY_IMAGE_SECRET@';


    $self->{binary_directory} = '@BINARY@';
    $self->{binary_dir} = '@BINARY@';

    {
        my $files_dir = '@FILES@';
        $self->{files_dir} = [split /\s+/ms, $files_dir];
    }

    $self->{composite_binary} = '@COMPOSITE@';
    $self->{convert_binary} = '@CONVERT@';
    $self->{file_web_storage} = lc('@FILE_WEB_STORAGE@');

    $self->{core_src} = '@CORE_SRC@';
    $self->{plug_src} = '@PLUG_SRC@';
    $self->{proj_src} = '@PROJ_SRC@';

    $self->{log_dir} = '@PROJECT_LOG@';
    $self->{run_dir} = '@PROJECT_RUN@';
    $self->{tmp_dir} = '@PROJECT_TMP@';
    $self->{usr_dir} = '@PROJECT_USR@';

    $self->{var_dir} = '@PROJECT_VAR@';
    $self->{data_dir} = $self->{var_dir};
    $self->{data_directory} = $self->{var_dir};

    $self->{preview} = '@PREVIEW@';
    $self->{mason_comp} = '@MASON_COMP@';

    $self->{auth_cookie} = '@AUTH_COOKIE@';

    $self->{is_dev_server} = lc('@DEVELOPMENT@') eq 'yes';
    $self->{development}    = lc('@DEVELOPMENT@') eq 'yes';

    $self->{contenido_version} = '@CONTENIDO_VERSION@' + 0;
    $self->{version} = $self->{contenido_version};

    $self->{__debug__} = (lc('@DEBUG@') eq 'yes');
    $self->{__debug_format__} = '@DEBUG_FORMAT@';
    $self->{__debug_stack_trace__} = lc('@DEBUG_STACK_TRACE@') eq 'yes';
    $self->{__debug_min_level__} = '@DEBUG_MIN_LEVEL@';
    $self->{__debug_max_level__} = '@DEBUG_MAX_LEVEL@';
    $self->{__sql_debug__} = lc('@DEBUG_SQL@') eq 'yes';

    $self->{project_name} = '@PROJECT_NAME@';
    $self->{multidomain} = lc('@MULTIDOMAIN@') eq 'yes';
    $self->{stage} = 'REAL';

    $state->{readonly} = (lc('@READONLY@') eq 'yes');

    $self->{store_method} = lc('@STORE_METHOD@');
    $Contenido::Globals::store_method = $self->{store_method};

    $self->{cascade} = (lc('@CASCADE@') eq 'yes');

    $self->{locale} = '@LOCALE@';

    # Конфигурационные параметры memcached
    $self->{memcached_backend}  = '@MEMCACHED_BACKEND@';
    $self->{memcached_enable}   = lc( '@MEMCACHED_ENABLE@' ) eq 'yes' ? 1 : 0;
    $self->{memcached_select_timeout} = '@MEMCACHED_SELECT_TIMEOUT@' || 0.2;
    $self->{memcached_servers}  = [ split(/\s+/, '@MEMCACHED_SERVERS@') ];
    $self->{memcached_enable_compress}  = lc( '@MEMCACHED_ENABLE_COMPRESS@' ) eq 'yes' ? 1 : 0;
    $self->{memcached_delayed}      = lc('@MEMCACHED_DELAYED@') eq 'yes' ? 1 : 0;
    $self->{memcached_set_mode} = lc('@MEMCACHED_SET_MODE@') eq 'add' ? 'add' : 'set';
    $self->{memcached_namespace} = lc( $self->{'project'} ).'|';

    $self->{memcached_object_expire} = undef;

    $self->{options_expire} = '@OPTIONS_EXPIRE@';

	$self->{preamble_handler} = '@PREAMBLE_HANDLER@';
	$self->{preamble_handler_path} = '@PREAMBLE_HANDLER_PATH@';

    $self->{email_enable} = lc('@EMAIL_ENABLE@') eq 'yes' ? 1 : 0;
    if ( $self->{email_enable} ) {
	$self->{email_mailer} = lc ('@EMAIL_MAILER@') eq 'smtp' ? 'smtp' : 'sendmail';
	$self->{email_from} = '@EMAIL_FROM@';
	$self->{email_auth_login} = '@EMAIL_LOGIN@';
	$self->{email_auth_password} = '@EMAIL_PASSWORD@';
	if ( $self->{email_mailer} eq 'smtp' ) {
		$self->{email_smtp_server} = '@EMAIL_SMTP_SERVER@';
		$self->{email_smtp_hello} = '@EMAIL_SMTP_HELLO@';
		$self->{email_smtp_timeout} = int(@EMAIL_SMTP_TIMEOUT@) || 10;
		$self->{email_smtp_ssl} = lc ('@EMAIL_SMTP_SSL@') eq 'yes' ? 1 : 0;
		$self->{email_smtp_port} = int(@EMAIL_SMTP_PORT@) || ($self->{email_smtp_ssl} ? 465 : 25);
	}
    }

    $self->_refresh_();
    $self->_init_();

    my @plugins = split(/\s+/, $self->plugins());
    for my $plugin ($self->{project}, @plugins) {
        $self->{lc($plugin)} = {};
        $self->{attributes}->{lc($plugin)} = 'SCALAR';

        my $class = $plugin.'::State';
        eval ("use $class");
        
        if ( $@ ) {
            warn "Contenido Error: Не могу определить состояние плагина $plugin ($class) по причине '$@'.\n";
        } else {
            warn "Contenido Init: Загружен класс $class для плагина $plugin.\n"         if ($self->debug());
            eval {
                $self->{lc($plugin)} = $class->new();
            };
            if ( $@ ) {
                warn "Contenido Error: Не могу выполнить инициализацию состояния плагина $plugin ($class) по причине '$@'.\n";
            }
        }
    }




    return $self;   
}



sub _refresh_
{
    my $self = shift;
    $self->{debug} = $self->{__debug__};
    #выставляем $DEBUG и $DEBUG_SQL в правильные значения!!!
    $DEBUG_SQL = $self->{__sql_debug__};
    $DEBUG = $self->{__debug__};
}


# ----------------------------------------------------------------------------
# Вывод информации об объекте...
# ----------------------------------------------------------------------------
sub info
{
    my $self = shift;
    return undef        unless ref($self);

    $log->info("Объект Contenido::State заполнен следующими параметрами:");
    foreach my $attribute (sort (keys( %{ $self->{attributes} } )))
    {
        my $la = length($attribute);
        warn "\t".$attribute.("\t" x (2-int($la/8))).": ".$self->{$attribute}."\n";
    }

    my @plugins = split(/\s+/, $self->plugins());
    for my $plugin ($self->{project}, @plugins) {
        if (ref($self->{lc($plugin)})) {
            eval {
                $self->{lc($plugin)}->info();
            };
        }
    }
}



# ----------------------------------------------------------------------------
# Инициализация.
#  - Создает внутри объекта хэш с типами полей - это нужно для быстрой
#   работы метода AUTOLOAD...
# ----------------------------------------------------------------------------
sub _init_
{
    my $self = shift;

    foreach my $attribute ( qw(
                project project_version

                httpd_port httpd_server httpd_root
                data_directory data_dir
                images_directory images_dir
                session_directory session_dir
                binary_directory binary_dir
                crosslinks_directory crosslinks_dir

                stage
                db_keepalive db_host db_name db_user db_password db_port db_type db_client_encoding db_enable_utf8
                db_encode_data db_decode_data

                mason_comp
		multidomain
                project_name
                preview
                
                proxy_image_location
                proxy_image_secret

                debug
                auth_cookie

                plugins

                development
                is_dev_server

                contenido_version version

                store_method cascade

                readonly

                locale

                memcached_enable memcached_servers
		memcached_select_timeout
                memcached_backend memcached_enable_compress
                memcached_set_mode
                memcached_object_expire
		memcached_namespace
                convert_binary

                email_enable email_mailer
                email_from email_auth_login email_auth_password 
                email_smtp_server email_smtp_hello email_smtp_timeout email_smtp_ssl email_smtp_port
             ) )
    {
        $self->{attributes}->{ $attribute } = 'SCALAR';
    }
}



# ----------------------------------------------------------------------------
# Это умный AUTOLOAD. Ловит методов для установки/чтения полей...
# Версия 0.2
# ----------------------------------------------------------------------------

sub AUTOLOAD
{
    my $self = shift;
    my $attribute = $AUTOLOAD;

    $attribute =~ s/.*:://;
    return undef    unless  $attribute =~ /[^A-Z]/;     # Отключаем методы типа DESTROY

    if (! exists($self->{attributes}->{$attribute}))
    {
        $log->error("Вызов метода, для которого не существует обрабатываемого свойства: ->$attribute()");
        return  undef;
    }

    $self->{ $attribute } = shift @_    if (scalar(@_) > 0);
    return $self->{ $attribute };
}


1;