Revision 474
- Date:
- 2015/02/25 13:22:42
- Files:
-
- /utf8/plugins/tags/comps
- /utf8/plugins/tags/comps/contenido
- /utf8/plugins/tags/comps/contenido/tags
- /utf8/plugins/tags/comps/contenido/tags/autohandler (Diff) (Checkout)
- /utf8/plugins/tags/comps/contenido/tags/dhandler (Diff) (Checkout)
- /utf8/plugins/tags/comps/contenido/tags/index.html (Diff) (Checkout)
- /utf8/plugins/tags/config.proto (Diff) (Checkout)
- /utf8/plugins/tags/lib
- /utf8/plugins/tags/lib/tags
- /utf8/plugins/tags/lib/tags/Apache.pm (Diff) (Checkout)
- /utf8/plugins/tags/lib/tags/Cloud.pm (Diff) (Checkout)
- /utf8/plugins/tags/lib/tags/Init.pm (Diff) (Checkout)
- /utf8/plugins/tags/lib/tags/Keeper.pm (Diff) (Checkout)
- /utf8/plugins/tags/lib/tags/SQL
- /utf8/plugins/tags/lib/tags/SQL/TagsCloudTable.pm (Diff) (Checkout)
- /utf8/plugins/tags/lib/tags/SQL/TagsTable.pm (Diff) (Checkout)
- /utf8/plugins/tags/lib/tags/Section.pm (Diff) (Checkout)
- /utf8/plugins/tags/lib/tags/State.pm.proto (Diff) (Checkout)
- /utf8/plugins/tags/lib/tags/Tag.pm (Diff) (Checkout)
- /utf8/plugins/tags/sql
- /utf8/plugins/tags/sql/TOAST
- /utf8/plugins/tags/sql/TOAST/tags.sql (Diff) (Checkout)
- /utf8/plugins/tags/sql/TOAST/tags_cloud.sql (Diff) (Checkout)
Legend:
- Added
- Removed
- Modified
-
utf8/plugins/tags/comps/contenido/tags/autohandler
1 <%init> 2 3 $r->content_type('text/html'); 4 $m->call_next(); 5 6 </%init> -
utf8/plugins/tags/comps/contenido/tags/dhandler
1 <& $call, %ARGS &> 2 <%init> 3 4 my $call; 5 if ( $r->uri eq '/contenido/tags/' ) { 6 $call = 'index.html'; 7 } else { 8 &abort404; 9 } 10 11 </%init> -
utf8/plugins/tags/comps/contenido/tags/index.html
1 <& "/contenido/components/header.msn" &> 2 <& "/contenido/components/naviline.msn" &> 3 4 <p>PLugin [tags]</p> 5 6 </body> 7 </html> -
utf8/plugins/tags/config.proto
1 ############################################################################# 2 # 3 # Параметры данного шаблона необходимо ВРУЧНУЮ добавить в config.mk проекта 4 # и привести в соответствие с требованиями проекта 5 # 6 ############################################################################# 7 8 PLUGINS += tags 9 10 TAGS_DEST = <список через пробел классов тегируемых документов> 11 REWRITE += TAGS_DEST -
utf8/plugins/tags/lib/tags/Apache.pm
1 package tags::Apache; 2 3 use strict; 4 use warnings 'all'; 5 6 use tags::State; 7 use Contenido::Globals; 8 9 10 sub child_init { 11 # встраиваем keeper плагина в keeper проекта 12 $keeper->{tags} = tags::Keeper->new($state->tags); 13 } 14 15 sub request_init { 16 } 17 18 sub child_exit { 19 } 20 21 1; -
utf8/plugins/tags/lib/tags/Cloud.pm
1 package zvukiru::TagLink; 2 3 use base 'Contenido::Link'; 4 5 sub class_name 6 { 7 return 'Тег к объекту'; 8 } 9 10 sub class_description 11 { 12 return 'Организация облака тегов'; 13 } 14 15 sub extra_properties 16 { 17 return ( 18 ); 19 } 20 21 sub available_sources 22 { 23 return [ qw(tags::Tag) ]; 24 } 25 26 sub available_destinations 27 { 28 return $state->{tags}->tags_destinations; 29 } 30 31 sub class_table 32 { 33 return 'tags::SQL::TagsCloudTable'; 34 } 35 36 sub pre_store 37 { 38 my $self = shift; 39 40 return 1; 41 } 42 43 1; -
utf8/plugins/tags/lib/tags/Init.pm
1 package tags::Init; 2 3 use strict; 4 use warnings 'all'; 5 6 use Contenido::Globals; 7 use tags::Apache; 8 use tags::Keeper; 9 use tags::Section; 10 use tags::Tag; 11 use tags::Cloud; 12 use tags::SQL::TagsCloudTable 13 use tags::SQL::TagsTable 14 15 # загрузка всех необходимых плагину классов 16 # tags::SQL::SomeTable 17 # tags::SomeClass 18 Contenido::Init::load_classes(qw( 19 tags::Section; 20 tags::Tag; 21 tags::Cloud; 22 tags::SQL::TagsCloudTable 23 tags::SQL::TagsTable 24 )); 25 26 sub init { 27 push @{ $state->{'available_documents'} }, 28 qw ( 29 tags::Tag 30 ); 31 push @{ $state->{'available_sections'} }, 32 qw ( 33 tags::Section 34 ); 35 push @{ $state->{'available_links'} }, 36 qw ( 37 tags::Cloud 38 ); 39 0; 40 } 41 42 1; -
utf8/plugins/tags/lib/tags/Keeper.pm
1 package tags::Keeper; 2 3 use strict; 4 use warnings 'all'; 5 use base qw(Contenido::Keeper); 6 7 8 use Contenido::Globals; 9 10 11 1; -
utf8/plugins/tags/lib/tags/Section.pm
1 package tags::Section; 2 3 use base 'Contenido::Section'; 4 5 sub extra_properties 6 { 7 return ( 8 { 'attr' => 'default_document_class', 'default' => 'tags::Tag' }, 9 ) 10 } 11 12 sub class_name 13 { 14 return 'Секция тегов'; 15 } 16 17 sub class_description 18 { 19 return 'Секция тегов'; 20 } 21 22 1; -
utf8/plugins/tags/lib/tags/SQL/TagsCloudTable.pm
1 package tags::SQL::TagsCloudTable; 2 3 use strict; 4 use base 'SQL::LinkTable'; 5 6 sub db_table 7 { 8 return 'tags_cloud'; 9 } 10 11 # ---------------------------------------------------------------------------- 12 # Свойства храним в массивах, потому что порядок важен! 13 # Это общие свойства - одинаковые для всех документов. 14 # 15 # attr - обязательный параметр, название атрибута; 16 # type - тип аттрибута, требуется для отображдения; 17 # rusname - русское название, опять же требуется для отображения; 18 # hidden - равен 1, когда 19 # readonly - инициализации при записи только без изменения в дальнейшем 20 # db_field - поле в таблице 21 # default - значение по умолчанию (поле всегда имеет это значение) 22 # ---------------------------------------------------------------------------- 23 sub required_properties 24 { 25 my $self = shift; 26 27 my @parent_properties = $self->SUPER::required_properties; 28 return ( 29 @parent_properties, 30 ); 31 } 32 33 ########### FILTERS DESCRIPTION #################################################################################### 34 35 1; 36 -
utf8/plugins/tags/lib/tags/SQL/TagsTable.pm
1 package tags::SQL::TagsTable; 2 3 use strict; 4 use base 'SQL::DocumentTable'; 5 6 sub db_table 7 { 8 return 'tags'; 9 } 10 11 sub available_filters { 12 my @available_filters = qw( 13 _class_filter 14 _status_filter 15 _in_id_filter 16 _id_filter 17 _name_filter 18 _class_excludes_filter 19 _prev_to_filter 20 _next_to_filter 21 _s_filter 22 23 _excludes_filter 24 _link_filter 25 _alias_filter 26 ); 27 return \@available_filters; 28 } 29 30 # ---------------------------------------------------------------------------- 31 # Свойства храним в массивах, потому что порядок важен! 32 # Это общие свойства - одинаковые для всех документов. 33 # 34 # attr - обязательный параметр, название атрибута; 35 # type - тип аттрибута, требуется для отображдения; 36 # rusname - русское название, опять же требуется для отображения; 37 # hidden - равен 1, когда 38 # readonly - инициализации при записи только без изменения в дальнейшем 39 # db_field - поле в таблице 40 # default - значение по умолчанию (поле всегда имеет это значение) 41 # ---------------------------------------------------------------------------- 42 sub required_properties 43 { 44 my $self = shift; 45 46 my @parent_properties = grep { $_->{attr} ne 'dtime' && $_->{attr} ne 'sections' } $self->SUPER::required_properties; 47 return ( 48 @parent_properties, 49 { 50 'attr' => 'alias', 51 'type' => 'string', 52 'rusname' => 'Алиас', 53 'column' => 3, 54 'db_field' => 'alias', 55 'db_type' => 'text', 56 }, 57 { # Подменяем секцию 58 'attr' => 'sections', 59 'type' => 'parent', 60 'rusname' => 'Родительская секция', 61 'db_field' => 'sections', 62 'db_type' => 'integer', 63 }, 64 ); 65 } 66 67 ########### FILTERS DESCRIPTION #################################################################################### 68 sub _s_filter { 69 my ($self,%opts)=@_; 70 return undef unless ( exists $opts{s} ); 71 return &SQL::Common::_generic_int_filter('d.sections', $opts{s}); 72 } 73 74 sub _alias_filter { 75 my ($self,%opts)=@_; 76 return undef unless ( exists $opts{alias} ); 77 return &SQL::Common::_generic_text_filter('d.alias', $opts{alias}); 78 } 79 80 sub _link_filter { 81 my ($self,%opts)=@_; 82 83 my @wheres=(); 84 my @binds=(); 85 86 # Связь определенного класса 87 if (exists($opts{lclass})) { 88 my ($where, $values) = SQL::Common::_generic_text_filter('l.class', $opts{lclass}); 89 push (@wheres, $where); 90 push (@binds, ref($values) ? @$values:$values) if (defined $values); 91 } 92 93 my $lclass = $opts{lclass} || 'Contenido::Link'; 94 my $link_table = $lclass->_get_table->db_table(); 95 96 # Ограничение по статусу связи 97 if ( exists $opts{lstatus} ) { 98 my ($where, $values) = SQL::Common::_generic_int_filter('l.status', $opts{lstatus}); 99 push (@wheres, $where); 100 push (@binds, ref($values) ? @$values:$values) if (defined $values); 101 } 102 103 # Связь с определенным документ(ом/тами) по цели линка 104 if ( exists $opts{ldest} ) { 105 my ($where, $values) = SQL::Common::_generic_int_filter('l.dest_id', $opts{ldest}); 106 push (@wheres, $where); 107 push (@binds, ref($values) ? @$values:$values) if (defined $values); 108 if ($self->_single_class) { 109 return (\@wheres, \@binds, " join $link_table as l on l.source_id=d.id"); 110 } elsif ( exists $opts{ldestclass} ) { 111 my ($where, $values) = SQL::Common::_generic_text_filter('l.dest_class', $opts{ldestclass}); 112 push (@wheres, $where); 113 push (@binds, ref($values) ? @$values:$values) if (defined $values); 114 115 return (\@wheres, \@binds, " join $link_table as l on l.source_id=d.id and l.source_class=d.class"); 116 } else { 117 return (\@wheres, \@binds, " join $link_table as l on l.source_id=d.id and l.source_class=d.class"); 118 } 119 } 120 121 # Связь с определенным документ(ом/тами) по источнику линка 122 if ( exists $opts{lsource} ) { 123 my ($where, $values) = SQL::Common::_generic_int_filter('l.source_id', $opts{lsource}); 124 push (@wheres, $where); 125 push (@binds, ref($values) ? @$values:$values) if (defined $values); 126 if ($self->_single_class) { 127 return (\@wheres, \@binds, " join $link_table as l on l.dest_id=d.id"); 128 } elsif ( exists $opts{lsourceclass} ) { 129 my ($where, $values) = SQL::Common::_generic_text_filter('l.source_class', $opts{lsourceclass}); 130 push (@wheres, $where); 131 push (@binds, ref($values) ? @$values:$values) if (defined $values); 132 133 return (\@wheres, \@binds, " join $link_table as l on l.dest_id=d.id and l.dest_class=d.class"); 134 } else { 135 return (\@wheres, \@binds, " join $link_table as l on l.dest_id=d.id and l.dest_class=d.class"); 136 } 137 } 138 139 return (undef); 140 } 141 142 143 1; -
utf8/plugins/tags/lib/tags/State.pm.proto
1 package tags::State; 2 3 use strict; 4 use warnings 'all'; 5 use vars qw($AUTOLOAD); 6 7 8 sub new { 9 my ($proto) = @_; 10 my $class = ref($proto) || $proto; 11 my $self = {}; 12 bless $self, $class; 13 14 # configured 15 $self->{project} = '@PROJECT@'; 16 $self->{debug} = (lc('@DEBUG@') eq 'yes'); 17 $self->{contenido_notab} = 0; 18 $self->{tab_name} = 'Теги'; 19 $self->{project_name} = '@PROJECT_NAME@'; 20 $self->{default_expire} = '@DEFAULT_EXPIRE@' || 300; 21 $self->{default_object_expire} = '@DEFAULT_OBJECT_EXPIRE@' || 600; 22 23 # зашитая конфигурация плагина 24 $self->{db_type} = 'none'; ### For REAL database use 'remote' 25 $self->{db_keepalive} = 0; 26 $self->{db_host} = ''; 27 $self->{db_name} = ''; 28 $self->{db_user} = ''; 29 $self->{db_password} = ''; 30 $self->{db_port} = ''; 31 $self->{store_method} = 'toast'; 32 $self->{cascade} = 1; 33 $self->{db_prepare} = 0; 34 35 $self->{memcached_enable} = lc( '@MEMCACHED_ENABLE@' ) eq 'yes' ? 1 : 0; 36 $self->{memcached_backend} = '@MEMCACHED_BACKEND@'; 37 $self->{memcached_select_timeout} = '@MEMCACHED_SELECT_TIMEOUT@' || 0.2; 38 $self->{memcached_servers} = [qw(@MEMCACHED_SERVERS@)]; 39 $self->{memcached_enable_compress} = lc( '@MEMCACHED_ENABLE_COMPRESS@' ) eq 'yes' ? 1 : 0; 40 $self->{memcached_delayed} = lc('@MEMCACHED_DELAYED@') eq 'yes' ? 1 : 0; 41 $self->{memcached_set_mode} = lc('@MEMCACHED_SET_MODE@') eq 'add' ? 'add' : 'set'; 42 $self->{memcached_busy_lock} = 60; 43 $self->{memcached_namespace} = lc( $self->{'project'} ).'|plugin_tags|'; 44 45 $self->{serialize_with} = 'json'; ### or 'dumper' 46 47 # not implemented really (core compatibility) 48 $self->{data_directory} = ''; 49 $self->{images_directory} = ''; 50 $self->{binary_directory} = ''; 51 $self->{preview} = ''; 52 53 $self->{tags_destinations} = [qw(@TAGS_DEST@)] 54 55 $self->_init_(); 56 $self; 57 } 58 59 sub info { 60 my $self = shift; 61 return unless ref $self; 62 63 for (sort keys %{$self->{attributes}}) { 64 my $la = length $_; 65 warn "\t$_".("\t" x (2-int($la/8))).": $self->{$_}\n"; 66 } 67 } 68 69 sub _init_ { 70 my $self = shift; 71 72 # зашитая конфигурация плагина 73 $self->{attributes}->{$_} = 'SCALAR' for qw( 74 debug 75 project 76 tab_name 77 78 db_type 79 db_keepalive 80 db_host 81 db_port 82 db_name 83 db_user 84 db_password 85 store_method 86 cascade 87 db_prepare 88 db_client_encoding 89 90 memcached_enable 91 memcached_servers 92 memcached_select_timeout 93 memcached_backend 94 memcached_enable_compress 95 memcached_set_mode 96 memcached_object_expire 97 memcached_busy_lock 98 memcached_delayed 99 memcached_namespace 100 101 binary_directory 102 data_directory 103 images_directory 104 preview 105 106 tags_destinations 107 ); 108 } 109 110 sub AUTOLOAD { 111 my $self = shift; 112 my $attribute = $AUTOLOAD; 113 114 $attribute =~ s/.*:://; 115 return unless $attribute =~ /[^A-Z]/; # Отключаем методы типа DESTROY 116 117 if (!exists $self->{attributes}->{$attribute}) { 118 warn "Contenido Error (tags::State): Вызов метода, для которого не существует обрабатываемого свойства: ->$attribute()\n"; 119 return; 120 } 121 122 $self->{$attribute} = shift @_ if $#_>=0; 123 $self->{$attribute}; 124 } 125 126 1; -
utf8/plugins/tags/lib/tags/Tag.pm
1 package tags::Tag; 2 3 use base 'Contenido::Document'; 4 use Contenido::Globals; 5 6 sub extra_properties 7 { 8 return ( 9 { 'attr' => 'name', 'rusname' => 'Название тега', shortname => 'Тег' }, 10 ) 11 } 12 13 14 sub class_name 15 { 16 return 'Тег'; 17 } 18 19 sub class_description 20 { 21 return 'Тег'; 22 } 23 24 sub class_table 25 { 26 return 'tags::SQL::TagsTable'; 27 } 28 29 sub search_fields { 30 return ('name'); 31 } 32 33 sub pre_store 34 { 35 my $self = shift; 36 37 my $default_section = $project->s_alias->{tags} if ref $project->s_alias eq 'HASH' && exists $project->s_alias->{tags}; 38 $self->sections( $default_section ) if $default_section; 39 40 return 1; 41 } 42 43 44 1; -
utf8/plugins/tags/sql/TOAST/tags.sql
1 create table tags 2 ( 3 id integer not null primary key default nextval('public.documents_id_seq'::text), 4 ctime timestamp not null default now(), 5 mtime timestamp not null default now(), 6 class text not null, 7 status smallint not null default 0, 8 sections integer, 9 name text, 10 alias text, 11 data text 12 ); 13 create index tags_name on tags (name); 14 create index tags_alias on tags (alias) WHERE alias IS NOT NULL AND alias != ''; -
utf8/plugins/tags/sql/TOAST/tags_cloud.sql
1 create table tags_cloud 2 ( 3 id integer not null primary key default nextval('public.documents_id_seq'::text), 4 class text not null, 5 ctime timestamp not null default now(), 6 mtime timestamp not null default now(), 7 status smallint not null default 1, 8 source_id integer not null, 9 source_class text not null default 'tags::Tag', 10 dest_id integer not null, 11 dest_class text not null, 12 data text 13 ); 14 create index tags_cloud_source on tags_cloud (source_id); 15 create index tags_cloud_dest on tags_cloud (dest_id);