Revision 296 (by ahitrov, 2013/03/26 17:59:01) Promosite (anthill) project source
#!/usr/bin/perl

use strict;
use warnings "all";
use locale;
use Data::Dumper;

use FindBin;
BEGIN {
	require "$FindBin::RealBin/../lib/Modules.pm";
}

use Contenido::Globals;
use Contenido::Init;
use ErrorTee;
use PidFile;
use P::WebFetcher;


# begin
Contenido::Init->init();

my $keeper_module = $state->project.'::Keeper';
$keeper = $keeper_module->new($state);

PidFile->new($keeper, compat=>1);                # db-based locking (run only on one host)
#PidFile->new($keeper, compat=>1, per_host=>1);   # db-based locking (run on whole cluster)

for my $plugin ( split(/\s+/, $state->plugins) ) {
	my $class = $plugin.'::Apache';
	eval { $class->child_init(); };
	if ( $@ ) {
		print("Не могу выполнить метод child_init плагина $plugin ($class) по причине '$@'");
	}
}

############################################
# please use:
#     $state->{log_dir} for logging
#     $state->{tmp_dir} for temporary files
###########################################
my @prjSec = $keeper->get_documents (
                class   => 'promosuite::ProjectSection',
		ids     => 1,
        );

my $SOURCES = {};
my $SRC = $keeper->get_documents (
	class           => 'promosuite::Source',
	return_mode     => 'array_ref',
	no_limit        => 1,
);
map { $SOURCES->{$_->auth_id} = $_ } grep { $_->auth_id } @$SRC;

my $MEDIASRC = $keeper->{media}->get_documents (
	class           => 'media::Source',
	return_mode     => 'hash_ref',
	no_limit        => 1,
);

foreach my $prjSecId (@prjSec) {
	my ($prjParam) = $keeper->get_documents (
		s       => $prjSecId,
		class   => 'promosuite::Project',
		limit   => 1,
        );

	if ( $prjParam->media_import ) {
		my $last_id = $prjParam->media_last;

		my @media_import_aliases = split( /\ +/, $prjParam->media_import );
		
		my $sect = "";
		my @sect_ids = ();

		foreach my $alias (@media_import_aliases) {
			$sect = $keeper->{media}->get_rubric($alias);
			@sect_ids = ();
			push @sect_ids, $sect->id       if ref $sect;
		}

		my @news = $keeper->{media}->get_documents (
			s       => \@sect_ids,
			class   => 'media::News',
			status  => [5,8],
			limit   => 30,
			order   => [qw|date direct|],
		);
		my @media_ids = map { $_->id } @news;

		my ($section) = $keeper->get_sections (
			s       => $prjSecId,
			class   => 'promosuite::NewsSection',
			status  => 1,
			limit   => 1,
		);
		next  unless  ref $section;

		my $loaded = @media_ids ? $keeper->get_documents (
			s		=> $section->id,
			class           => 'promosuite::News',
			ext_id		=> \@media_ids,
			light		=> 1,
			return_mode	=> 'hash_ref',
			hash_by		=> 'ext_id',
		) : {};

		foreach my $msg (@news) {
			next if exists $loaded->{$msg->id};

			my $message = promosuite::News->new ( $keeper );
			$message->ext_id( $msg->id );
			$message->dtime( $msg->dtime );
			$message->name( Convert::Cyrillic::cstocs('KOI8', 'UTF8', $msg->name) );
			$message->abstr( Convert::Cyrillic::cstocs('KOI8', 'UTF8', $msg->abstract) );
			$message->body( Convert::Cyrillic::cstocs('KOI8', 'UTF8', $msg->body) );
			$message->sections( $section->id );
			### Get Source
			if ( exists $SOURCES->{$msg->source} ) {
				$message->source_id( $SOURCES->{$msg->source}->id );
			} else {
				my $msrc = $MEDIASRC->{$msg->source};
				my $src = promosuite::Source->new ($keeper);
				$src->name( Convert::Cyrillic::cstocs('KOI8', 'UTF8', $msrc->name) );
				$src->auth_id( $msrc->id );
				$src->url( $msrc->url );
				$src->status(1);
				$src->sections( $project->s_alias->{sources} );
				$src->store;
				$message->source_id( $src->id );
				$SOURCES->{$msg->source} = $src;
			}
			### /Get Source
			### Store images
			my $image_hash;
			my $idx = 0;
			local $Data::Dumper::Indent = 0;
			foreach my $image ($msg->get_pics('image_set')) {
				my $source_id = $image->source;
				my $src;
				if ( $source_id ) {
					if ( exists $SOURCES->{$source_id} ) {
						$src = $SOURCES->{$source_id};
					} else {
						my $msrc = $MEDIASRC->{$msg->source};
						$src = promosuite::Source->new ($keeper);
						$src->name( Convert::Cyrillic::cstocs('KOI8', 'UTF8', $msrc->name) );
						$src->auth_id( $msrc->id );
						$src->url( $msrc->url );
						$src->status(1);
						$src->sections( $project->s_alias->{sources} );
						#$src->store;
						#$SOURCES->{$msg->source} = $src;
					}
				}
				my $image_data = store_image(
					$image->name(),
					"/images/".$message->get_file_name(),
					$message,
					"pictures",
					[qw(240x240)]
				);
				if ($image_data) {
					@{%{$image_data->{'mini'}}}{'filename', 'width', 'height'} = @{%{$image_data->{'mini'}{'240x240'}}}{'filename', 'width', 'height'};
					$image_data->{number} = ++$idx;
					if ( ref $src ) {
						$image_data->{sid} = $src->id;
						$image_data->{url} = $src->url;
						$image_data->{copyright} = Convert::Cyrillic::cstocs('KOI8', 'UTF8', $src->name);
					}
					$image_hash->{"image_".($idx)} = $image_data;
				}
			}
			if ($image_hash) {
				$image_hash->{"maxnumber"} = $idx;
				local $Data::Dumper::Indent = 0;
				$message->pictures(Dumper($image_hash));
			}
			### /Store images
			$message->url( $msg->url );
			$message->status(3);
			$message->store;
		}
		$last_id = $news[0]->id;
		$prjParam->media_last( $last_id );
		$prjParam->store;
	}
}

sub store_image {
        my $url         = shift || return;
        my $filename    = shift || return;
        my $object      = shift || return;
        my $field       = shift || return;
        my $resolutions = shift || return;

    my $f = P::WebFetcher->new();

        my $buffer = $f->fetch("http://www.rambler.ru/news".$url);

        return unless $buffer;

        my $suffix = $url =~ /(jpe?g|gif|png)$/i ? lc $1 : "bin";

        my $filename_tmp = $state->{"tmp_dir"}."/".join("_", split("/", $filename));
        my $fh_tmp = IO::File->new(">".$filename_tmp.".".$suffix) || die "Can't open temporary file";

        syswrite $fh_tmp, $buffer, length $buffer;
        undef $fh_tmp;

        my $image_hash;

        @{%{$image_hash}}{"filename", "width", "height"} = (
                $filename.".".$suffix,
                Image::Size::imgsize($filename_tmp.".".$suffix),
        );

        unless (Contenido::File::store($filename.".".$suffix, $filename_tmp.".".$suffix)) {
                print "NEWS LOADER WARNING: Can't store file! (name: ".$filename.".".$suffix.")\n";
                return;
        }

        for my $resolution (@$resolutions) {
                my $c_line = $state->{"convert_binary"}." -geometry '".$resolution.">' -quality 80 ".$filename_tmp.".".$suffix." ".$filename_tmp.".".$resolution.".".$suffix;
                my $result = `$c_line 2>&1`;

                if (length $result  > 0) {
                        print "Contenido Error: При вызове '$c_line' произошла ошибка '$result' ($@)\n";
                }

                @{%{$image_hash->{"mini"}{$resolution}}}{"filename", "width", "height"} = (
                        $filename.".".$resolution.".".$suffix,
                        Image::Size::imgsize($filename_tmp.".".$resolution.".".$suffix),
                );

                unless (Contenido::File::store($filename.".".$resolution.".".$suffix, $filename_tmp.".".$resolution.".".$suffix)) {
                        print "NEWS LOADER WARNING: Can't store file! (name: ".$filename.".".$resolution.".".$suffix.")\n";
                }

                unlink $filename_tmp.".".$resolution.".".$suffix if -e $filename_tmp.".".$resolution.".".$suffix;
        }

        unlink $filename_tmp.".".$suffix if -e $filename_tmp.".".$suffix;

        return $image_hash;
}

Небольшая справка по веткам

cnddist – контейнер, в котором хранятся все дистрибутивы всех библиотек и программных пакетов, которые использовались при построении различных версий Contenido. Если какой-то библиотеки в данном хранилище нет, инсталлятор сделает попытку "подтянуть" ее с веба (например, с CPAN). Если библиотека слишком старая, есть очень большая вероятность, что ее там уже нет. Поэтому мы храним весь хлам от всех сборок. Если какой-то дистрибутив вдруг отсутствует в cnddist - напишите нам, мы положим его туда.

koi8 – отмирающая ветка, чей код, выдача и все внутренние библиотеки заточены на кодировку KOI8-R. Вносятся только те дополнения, которые касаются внешнего вида и функционала админки, баги ядра, обязательные обновления портов и мелочи, которые легко скопипастить. В дальнейшем планируется полная остановка поддержки по данной ветке.

utf8 – актуальная ветка, заточенная под UTF-8.

Внутри каждой ветки: core – исходники ядра; install – скрипт установки инсталляции; plugins – плагины; samples – "готовые к употреблению" проекты, которые можно поставить, запустить и посмотреть, как они работают.