Line # Revision Author
1 8 ahitrov@rambler.ru package SQL::AutoTable;
2
3 use strict;
4 use SQL::Common;
5 use Contenido::Globals;
6
7 my %typemap = (
8 'smallint' => 'integer',
9 'integer' => 'integer',
10 'integer[]' => 'string',
11 'varchar' => 'string',
12 'character varying' => 'string',
13 'char' => 'string',
14 'text' => 'text',
15 'boolean' => 'checkbox',
16 'timestamp with time zone' => 'datetime',
17 'timestamp without time zone' => 'datetime',
18 );
19
20 #некоторые умолчательные свойства некоторых документов
21 my $default_props = {
22 class => {
23 'hidden' => 1,
24 'readonly' => 1,
25 'column' => 3,
26 'rusname' => 'Класс документа',
27 },
28 name => {
29 'column' => 2,
30 'rusname' => 'Название',
31 'type' => 'string',
32 },
33 ctime => {
34 'readonly' => 1,
35 'auto' => 1,
36 'hidden' => 1,
37 'default' => 'CURRENT_TIMESTAMP',
38 'rusname' => 'Время создания документа',
39 },
40 mtime => {
41 'auto' => 1,
42 'hidden' => 1,
43 'default' => 'CURRENT_TIMESTAMP',
44 'rusname' => 'Время изменения документа',
45 },
46 dtime => {
47 'rusname' => 'Дата и время документа<sup style="color:#888;">&nbsp;1)</sup>',
48 'default' => 'CURRENT_TIMESTAMP',
49 'column' => 1,
50 },
51 sections => {
52 'type' => 'sections_list',
53 'rusname' => 'Секции',
54 'hidden' => 1,
55 },
56 status => {
57 'rusname' => 'Статус',
58 'type' => 'status'
59 },
60 };
61
62 sub modificators {
63 return {};
64 }
65
66 sub auto_init {
67 my $self = shift;
68 my $class = shift;
69
70 my $filter_set = {};
71 my @rp = (
72 {
73 'attr' => 'id',
74 'type' => 'integer',
75 'hidden' => 1,
76 'auto' => 1,
77 'readonly' => 1,
78 'db_field' => 'id',
79 'db_type' => 'integer',
80 }
81 );
82
83 my $modificators = $class->modificators();
84
85 my $sth = $keeper->SQL->column_info(undef, undef, $class->db_table, undef) || die "no connection to DB!";
86 while (my $row = $sth->fetchrow_arrayref) {
87 my ($field_name, $field_type, $default) = ($row->[3], $row->[5], $row->[12]);
88 $field_name =~ s/^"(.*)"$/$1/;
89
90 #skip data field for tables with _extra and skip id
91 next if (($field_name eq 'id') or (($field_name eq 'data') and $class->have_extra));
92
93 my $field = {
94 attr => $field_name,
95 db_field=> $field_name,
96 db_type => $field_type,
97 type => ($typemap{$field_type} || $field_type),
98 default => $default,
99 rusname => $field_name,
100 %{$default_props->{$field_name} || {}},
101 %{$modificators->{$field_name} || {}}
102 };
103 push @rp, $field;
104 }
105
106 # Создаем фильтры для каждого поля
107 $class->_register_filter($filter_set, $_) foreach @rp;
108
109 {
110 no strict 'refs';
111 ${$class.'::_rp'} = \@rp;
112 ${$class.'::filters'} = $filter_set;
113 ${$class.'::_init_ok'} = 1;
114 warn "$class table descriptor loaded ok!\n" if ($DEBUG);
115 }
116
117 return 1;
118 }
119
120 sub _register_filter {
121 my ($self, $filter_set, $field) = @_;
122 my $class = ref($self) || $self;
123 return if ($field->{no_filter} or !$field->{db_type});
124
125 my $name = 'd.'.$field->{attr};
126
127 # Специальныe случаи
128 if ($field->{attr} eq 'sections') {
129 # Игнорируем значение и передаем весь %opts
130 $filter_set->{s} = sub { return $class->_s_filter( %{$_[1]} ); };
131 } elsif ($field->{attr} eq 'id') {
132 $filter_set->{in_id} = sub { return (SQL::Common::_generic_int_filter($name, shift, 1, shift)); };
133 }
134 #todo возможно еще несколько фильтров для совместимости умолчательной сделать
135
136 #name всегда специальный образом работает
137 if ($field->{attr} eq 'name') {
138 $filter_set->{$field->{attr}} = sub { return (SQL::Common::_generic_name_filter($name, shift, 0, shift)); };
139 $filter_set->{'not_'.$field->{attr}} = sub { return (SQL::Common::_generic_name_filter($name, shift, 1, shift)); };
140 } elsif ($field->{db_type} eq 'integer' or $field->{db_type} eq 'smallint') {
141 $filter_set->{$field->{attr}} = sub { return (SQL::Common::_generic_int_filter($name, shift, 0, shift)); };
142 $filter_set->{'not_'.$field->{attr}} = sub { return (SQL::Common::_generic_int_filter($name, shift, 1, shift)); };
143 } elsif ($field->{db_type} eq 'float' or $field->{db_type} eq 'real' or $field->{db_type} eq 'double precision') {
144 $filter_set->{$field->{attr}} = sub { return (SQL::Common::_generic_float_filter($name, shift, 0, shift)); };
145 $filter_set->{'not_'.$field->{attr}} = sub { return (SQL::Common::_generic_float_filter($name, shift, 1, shift)); };
146 } elsif ($field->{db_type} eq 'text' or $field->{db_type} eq 'char' or $field->{db_type} eq 'character varying' or $field->{db_type} eq 'character') {
147 $filter_set->{$field->{attr}} = sub { return (SQL::Common::_generic_text_filter($name, shift, 0, shift)); };
148 $filter_set->{'not_'.$field->{attr}} = sub { return (SQL::Common::_generic_text_filter($name, shift, 1, shift)); };
149 } elsif ($field->{db_type} eq 'integer[]') {
150 $filter_set->{$field->{attr}} = sub { return (SQL::Common::_generic_intarray_filter($name, shift, 0, shift)); };
151 $filter_set->{'not_'.$field->{attr}} = sub { return (SQL::Common::_generic_intarray_filter($name, shift, 1, shift)); };
152 } elsif ($field->{db_type} eq 'boolean') {
153 $filter_set->{$field->{attr}} = sub { return (SQL::Common::_generic_boolean_filter($name, shift, 0, shift)); };
154 $filter_set->{'not_'.$field->{attr}} = sub { return (SQL::Common::_generic_boolean_filter($name, shift, 1, shift)); };
155 } elsif ($field->{db_type} eq 'date' or $field->{db_type} eq 'timestamp without time zone' or $field->{db_type} eq 'timestamp with time zone') {
156 $filter_set->{$field->{attr}} = sub { return (SQL::Common::_generic_date_filter($name, shift, 0, shift)); };
157 $filter_set->{'not_'.$field->{attr}} = sub { return (SQL::Common::_generic_date_filter($name, shift, 1, shift)); };
158 } elsif ($field->{db_type} eq 'time' or $field->{db_type} eq 'time without time zone') {
159 $filter_set->{$field->{attr}} = sub { return (SQL::Common::_generic_time_filter($name, shift, 0, shift)); };
160 $filter_set->{'not_'.$field->{attr}} = sub { return (SQL::Common::_generic_time_filter($name, shift, 1, shift)); };
161 } else {
162 warn "$class have field $field->{db_field} with type $field->{db_type} unsupported in autofilter just now sorry";
163 }
164 }
165
166 1;
167

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

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

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

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

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