Revision 217

Date:
2012/06/16 14:31:03
Author:
ahitrov
Revision Log:
1. New serializer (JSON) and project param-key
SERIALIZE_WITH = dumper|json
2. New port version
3. Plugin Skeleton updated
4. Text pre-formatting for WYSIWYG

Files:

Legend:

 
Added
 
Removed
 
Modified
  • utf8/core/comps/contenido/components/inputs/wysiwyg.msn

     
    12 12 % if ($request->{images_staff_printed}) {
    13 13 onclick="storeCaret(this)" onkeyup="storeCaret(this)" onselect="storeCaret(this)" \
    14 14 % }
    15 <% $prop->{readonly} ? 'readonly ' : '' %> name="<% $name %>" rows="<% $prop->{rows} || 8 %>" cols="<% $prop->{cols} || 8 %>" style="width: 95%;"><% $check %></textarea>
    15 <% $prop->{readonly} ? 'readonly ' : '' %> name="<% $name %>" rows="<% $prop->{rows} || 8 %>" cols="<% $prop->{cols} || 8 %>" style="width: 95%;"><& /inc/text_format.msn, text => $check &></textarea>
    16 16
    17 17 <%args>
    18 18 $name => undef
     
    21 21 $object => undef
    22 22 </%args>
    23 23 <%init>
    24 $check = html_escape($check) unless $prop->{no_escape};
    25 24 </%init>
  • utf8/core/GNUmakefile

     
    1208 1208 PGSQL_ENCODE_DATA \
    1209 1209 PGSQL_DECODE_DATA \
    1210 1210 PGSQL_ENABLE_UTF \
    1211 SERIALIZE_WITH \
    1211 1212 PLUG_SRC \
    1212 1213 PLUGINS \
    1213 1214 PLUGIN_COMP \
  • utf8/core/lib/Contenido/File.pm

     
    113 113 #убираем начальный /
    114 114 $filename =~ s#^/##;
    115 115
    116 my $success = 0;
    116 117 foreach my $dir (@{$state->{"files_dir"}}) {
    117 no strict "refs";
    118 &{"Contenido::File::Scheme::".uc(scheme($dir))."::remove"}($dir."/".$filename);
    118 no strict "refs";
    119 my $scheme = uc(scheme($dir));
    120 my $res;
    121 if ( !$success || $scheme eq 'FILE' ) {
    122 $res = &{"Contenido::File::Scheme::".$scheme."::remove"}($dir."/".$filename);
    123 }
    124 if ( $res && $scheme eq 'HTTP' && $state->{file_web_storage} eq 'common' ) {
    125 $success = 1;
    126 }
    119 127 }
    120 128
    121 129 1;
  • utf8/core/lib/Contenido/Keeper.pm

     
    57 57 $self->{db_client_encoding} = $local_state->{attributes}{db_client_encoding} ? $local_state->db_client_encoding() : '';
    58 58 $self->{db_enable_utf8} = $local_state->{attributes}{db_enable_utf8} ? $local_state->db_enable_utf8() : 0;
    59 59
    60 $self->{serialize_with} = $local_state->{serialize_with};
    61
    60 62 $self->{data_dir} = $self->{data_directory} = $local_state->data_directory();
    61 63 $self->{images_dir} = $self->{images_directory} = $local_state->images_directory();
    62 64 $self->{binary_dir} = $self->{binary_directory} = $local_state->binary_directory();
     
    95 97
    96 98 foreach my $attribute ( qw(
    97 99 db_host db_name db_user db_password db_port
    100 serialize_with
    98 101
    99 102 data_directory data_dir
    100 103 images_directory images_dir
     
    313 316 $self->set_object_to_cache($item, 30, $opts) if ($opts->{with_cache});
    314 317 $total++;
    315 318 if ( exists $item->{$hash_by} && defined $item->{$hash_by} ) {
    316 $items{$item->{$hash_by}} = $item;
    319 $items{$item->{$hash_by}} = $item;
    317 320 } else {
    318 $log->warning( "Can not HASH BY parameter [$hash_by]. It doesn't exists in row or the field is empty");
    321 $log->warning( "Can not HASH BY parameter [$hash_by]. It doesn't exists in row or the field is empty");
    319 322 }
    320 323 }
    321 324 }
  • utf8/core/lib/Contenido/Object.pm

     
    20 20 use Contenido::Globals;
    21 21 use Contenido::File;
    22 22 use Data::Dumper;
    23 use Data::Recursive::Encode;
    24 use JSON::XS;
    23 25
    24 26 use DBD::Pg;
    25 27 use Encode;
    26 28
    27 29 use SQL::ProtoTable;
    28 30
    31 our $json_n = JSON::XS->new->utf8(0);
    32 our $json_u = JSON::XS->new->utf8(1);
    33
    29 34 # required properties теперь берутся из свойств таблицы
    30 35 sub required_properties {
    31 36 my $self=shift;
     
    219 224 $virtual_fields{$attr} = 1;
    220 225 } else {
    221 226 #инициализируем из dump все кроме виртуальных свойств
    222 push @funct_exra_fields, "$attr=>$func_start_encode\$dump->{$attr}$func_end_encode";
    227 push @funct_exra_fields, "$attr=>(\$keeper->serialize_with eq 'json' ? Encode::encode('utf-8', \$dump->{$attr}, Encode::FB_HTMLCREF) : $func_start_encode\$dump->{$attr}$func_end_encode)";
    223 228 }
    224 229 }
    225 230 }
     
    234 239 # Чтение из одного дампа в базе данных
    235 240 # --------------------------------------------------------------------------------------------
    236 241 my $funct_eval_dump .= '
    237 my $dump = Contenido::Object::eval_dump(\\$row->[-1]);
    242 my $dump = $keeper->serialize_with eq \'json\' ? (Contenido::Object::eval_json(\\$row->[-1]) || {}) : Contenido::Object::eval_dump(\\$row->[-1]);
    238 243 ';
    239 244 $funct = $funct_begin.$funct_begin_if_light.$funct_start_obj.join(', ', @funct_default_fields).$funct_end_obj.$funct_elsif_light.$funct_eval_dump.$funct_start_obj.join(', ', (@funct_default_fields, @funct_exra_fields)).$funct_end_obj.$funct_endif_light;
    240 245 } else {
    241 246 $funct = $funct_begin.$funct_start_obj.join(', ', @funct_default_fields).$funct_end_obj;
    242 247 }
    248 # warn "Restore function: [$funct]\n";
    243 249
    244 250 create_method($class, 'init_from_db', $funct);
    245 251
     
    299 305
    300 306 my $extra_fields = [];
    301 307 my $virtual_fields = {};
    302 {
    308
    309 if ( $self->keeper->serialize_with eq 'json' ) {
    303 310 no strict 'refs';
    304 local $Data::Dumper::Indent = 0;
    305 311 #пропускаем virtual attributes
    306 312 #да я знаю что так писать нельзя но блин крута как смотрится
    307 313 $extra_fields = ${$self->{class}.'::extra_fields'};
    308 314 $virtual_fields = ${$self->{class}.'::virtual_fields'};
    309 315 #надо использовать все extra поля кроме тех что находятся в virtual_fields списке
    310 316 if ($state->db_encode_data) {
    317 return Encode::decode('utf-8', $json_n->encode ({map { $_=> Encode::decode($state->db_encode_data, $self->{$_}, Encode::FB_HTMLCREF) } grep { !$virtual_fields->{$_} && (defined $self->{$_}) } @$extra_fields}));
    318 } else {
    319 my $content = Encode::decode('utf-8', $json_n->encode ({map { $_=>$self->{$_} } grep { !$virtual_fields->{$_} && (defined $self->{$_}) } @$extra_fields}));
    320 # warn "Store content is [$content]. UTF-8 Flag [".Encode::is_utf8($content)."]\n";
    321 return $content;
    322 }
    323 } else {
    324 no strict 'refs';
    325 #пропускаем virtual attributes
    326 #да я знаю что так писать нельзя но блин крута как смотрится
    327 $extra_fields = ${$self->{class}.'::extra_fields'};
    328 $virtual_fields = ${$self->{class}.'::virtual_fields'};
    329 #надо использовать все extra поля кроме тех что находятся в virtual_fields списке
    330 local $Data::Dumper::Indent = 0;
    331 if ($state->db_encode_data) {
    311 332 return Data::Dumper::Dumper({map { $_=> Encode::decode($state->db_encode_data, $self->{$_}, Encode::FB_HTMLCREF) } grep { !$virtual_fields->{$_} && (defined $self->{$_}) } @$extra_fields});
    312 333 } else {
    313 334 return Data::Dumper::Dumper({map { $_=>$self->{$_} } grep { !$virtual_fields->{$_} && (defined $self->{$_}) } @$extra_fields});
     
    334 355 # --------------------------------------------------------------------------------------------
    335 356 # Чтение из одного дампа в базе данных
    336 357 # --------------------------------------------------------------------------------------------
    337 my $dump_ = eval_dump(\$row->[-1]);
    358 my $dump_ = $self->keeper->serialize_with eq 'json' ? eval_json(\$row->[-1]) : eval_dump(\$row->[-1]);
    338 359 if ($dump_) {
    339 360 foreach (@$extra_fields) {
    340 361 $self->{$_} = $dump_->{$_};
     
    347 368 }
    348 369 }
    349 370
    371 sub _serialize {
    372 my $self = shift;
    373 my $data = shift;
    374 if ( $self->keeper->serialize_with eq 'json' ) {
    375 return $json_n->encode($data);
    376 } else {
    377 local $Data::Dumper::Indent = 0;
    378 return Data::Dumper::Dumper($data);
    379 }
    380 }
    381
    350 382 # ----------------------------------------------------------------------------
    351 383 # Выбирает хеш из перл-дампа по атрибуту
    352 384 # Пример:
     
    355 387 sub get_data {
    356 388 my $self = shift;
    357 389 my $attr = shift;
    358 my $data = eval_dump(\$self->{$attr});
    390 my $encode = shift;
    391 my $data = $self->keeper->serialize_with eq 'json' ? ( $encode ? Data::Recursive::Encode->encode_utf8(eval_json(\$self->{$attr})) : eval_json(\$self->{$attr}) ) : eval_dump(\$self->{$attr});
    359 392 return ($data || {});
    360 393 }
    361 394
     
    372 405 my $attr = shift;
    373 406
    374 407 Contenido::Image->new (
    375 img => $self->get_data($attr),
    408 img => $self->get_data($attr, 'encode'),
    376 409 attr => $attr,
    377 410 );
    378 411 }
     
    392 425 my $self = shift;
    393 426 my $attr = shift;
    394 427 my %args = ref $_[0] ? %{$_[0]} : @_;
    395 my $pics = $self->get_data($attr);
    428 my $pics = $self->get_data($attr, 'encode');
    396 429
    397 430 # Дефолты
    398 431 $args{order} ||= 'direct';
     
    459 492 foreach ($self->required_properties()) {
    460 493
    461 494 my $value = $self->{$_->{attr}};
    462 $value = undef if (defined($value) and $value eq '') and (lc($_->{db_type}) eq 'float' or lc($_->{db_type} eq 'integer'));
    463 $value = undef if lc $_->{db_type} eq 'integer[]' && ref $value ne 'ARRAY';
    464 $value = undef if lc $_->{db_type} eq 'integer_ref[]' && ref $value ne 'ARRAY';
    495 if ( exists $_->{db_field} && $_->{db_field} ) {
    496 $value = undef if (defined($value) and $value eq '') and (lc($_->{db_type}) eq 'float' or lc($_->{db_type} eq 'integer'));
    497 $value = undef if lc $_->{db_type} eq 'integer[]' && ref $value ne 'ARRAY';
    498 $value = undef if lc $_->{db_type} eq 'integer_ref[]' && ref $value ne 'ARRAY';
    499 }
    465 500
    466 501 #пропустить readonly если у документа уже есть id
    467 502 if ($self->id() and $_->{readonly}) {
     
    993 1028 return eval ${$_[0]};
    994 1029 }
    995 1030
    1031 sub eval_json {
    1032 return undef unless ${$_[0]};
    1033 my $value = $json_u->decode( ${$_[0]});
    1034 # map { $_ = Encode::encode(\'utf-8\', $_) unless ref $_; } values %$value;
    1035 return $value;
    1036 }
    1037
    996 1038 sub create_method {
    997 1039 my ($class, $sub_name, $code) = @_;
    998 1040
     
    1069 1111 # оставлена для обратной совместимости...
    1070 1112 sub get_image {
    1071 1113 my $self = shift;
    1072 $self->get_data(shift);
    1114 if ( $self->keeper->serialize_with eq 'json' ) {
    1115 return $self->get_data(shift, 'encode');
    1116 } else {
    1117 return $self->get_data(shift);
    1118 }
    1073 1119 }
    1074 1120
    1075 1121 sub raw_restore {
  • utf8/core/lib/Contenido/State.pm.proto

     
    42 42 $self->{db_encode_data} = '@PGSQL_ENCODE_DATA@';
    43 43 $self->{db_decode_data} = '@PGSQL_DECODE_DATA@' || 'utf-8';
    44 44
    45 $self->{serialize_with} = lc('@SERIALIZE_WITH@') || 'dumper';
    46
    45 47 $self->{master_db_host} = (($self->{db_type} eq 'remote') and '@MASTER_BASE_HOST@') ? lc('@MASTER_BASE_HOST@') : 'localhost';
    46 48 $self->{master_db_name} = '@MASTER_BASE_NAME@';
    47 49 $self->{master_db_user} = '@MASTER_BASE_USER@';
     
    231 233
    232 234 stage
    233 235 db_keepalive db_host db_name db_user db_password db_port db_type db_client_encoding db_enable_utf8
    234
    235 236 db_encode_data db_decode_data
    236 237
    237 238 mason_comp
  • utf8/core/ports/all/common-sense/GNUmakefile

     
    5 5
    6 6 include ../../etc/perl.mk
    7 7
    8 PORTVERSION = 3.4
    8 PORTVERSION = 3.5
    9 9 PERL_MAKEMAKER = yes
    10 10 MASTER_CPAN_SUBDIR = ../../authors/id/M/ML/MLEHMANN
    11 11
  • utf8/core/project-default.mk

     
    34 34
    35 35 # additional ports if any
    36 36 PROJECT_REQUIRED ?=
    37 SERIALIZE_WITH ?=
    37 38
    38 39 # defaults
    39 40 PRELOADS ?=
  • utf8/core/skel/plugin/lib/plugin/State.pm.proto

     
    11 11 my $self = {};
    12 12 bless $self, $class;
    13 13
    14 # configured
    15 $self->{debug} = (lc('@DEBUG@') eq 'yes');
    16 $self->{project} = '@PROJECT@';
    17
    14 18 # зашитая конфигурация плагина
    15 # $self->{db_type} = 'remote';
    16 # $self->{db_keepalive} = 0;
    17 # $self->{db_host} = '';
    18 # $self->{db_name} = '';
    19 # $self->{db_user} = '';
    20 # $self->{db_password} = '';
    21 # $self->{db_port} = '';
    19 $self->{db_type} = 'none'; ### For REAL database use 'remote'
    20 $self->{db_keepalive} = 0;
    21 $self->{db_host} = '';
    22 $self->{db_name} = '';
    23 $self->{db_user} = '';
    24 $self->{db_password} = '';
    25 $self->{db_port} = '';
    26 $self->{store_method} = 'toast';
    27 $self->{cascade} = 1;
    28 $self->{db_prepare} = 0;
    22 29
    30 $self->{memcached_enable} = lc( '@MEMCACHED_ENABLE@' ) eq 'yes' ? 1 : 0;
    31 $self->{memcached_enable_compress} = 1;
    32 $self->{memcached_backend} = '@MEMCACHED_BACKEND@';
    33 $self->{memcached_servers} = [qw(@MEMCACHED_SERVERS@)];
    34 $self->{memcached_busy_lock} = 60;
    35 $self->{memcached_delayed} = lc('@MEMCACHED_DELAYED@') eq 'yes' ? 1 : 0;
    36
    37 $self->{serialize_with} = 'json'; ### or 'dumper'
    38
    39 # not implemented really (core compatibility)
    40 $self->{binary_directory} = '/nonexistent';
    41 $self->{data_directory} = '/nonexistent';
    42 $self->{images_directory} = '/nonexistent';
    43 $self->{preview} = '0';
    44
    23 45 $self->_init_();
    24 46 $self;
    25 47 }
     
    39 61
    40 62 # зашитая конфигурация плагина
    41 63 $self->{attributes}->{$_} = 'SCALAR' for qw(
    42 # db_type
    43 # db_keepalive
    44 # db_host
    45 # db_port
    46 # db_name
    47 # db_user
    48 # db_password
    64 debug
    65 project
    66
    67 db_type
    68 db_keepalive
    69 db_host
    70 db_port
    71 db_name
    72 db_user
    73 db_password
    74 store_method
    75 cascade
    76 db_prepare
    77 db_client_encoding
    78
    79 memcached_enable
    80 memcached_enable_compress
    81 memcached_backend
    82 memcached_servers
    83 memcached_busy_lock
    84 memcached_delayed
    85
    86 binary_directory
    87 data_directory
    88 images_directory
    89 preview
    49 90 );
    50 91 }
    51 92

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

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

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

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

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