Revision 480 
  Date: 
  2015/03/03 12:14:40 
  Author: 
  ahitrov 
  Revision Log: 
  Tags plugin: initial import 
  Files: 
  
    
   
 
  
    Legend: 
    
        Added 
        Removed 
        Modified 
     
       
     
      utf8/plugins/tag/comps/contenido/components/inputs/tagset.msn 
      
        
           
        
          
              
           
         
                              
      
             1 
            % if ( $object->id ) {  
         
      
             2 
            <script type="text/javascript">  
         
      
             3 
            <!--  
         
      
             4 
            function <% $name %>_onAddTag(tag) {  
         
      
             5 
                    $.ajax({  
         
      
             6 
                            'url'   : '/contenido/tag/ajax/manage.html',  
         
      
             7 
                            'type'  : 'GET',  
         
      
             8 
                            'data'  : { 'action' : 'add', 'id' : <% $object->id %>, 'class' : '<% $object->class %>', 'tag' : tag },  
         
      
             9 
                            'dataType'      : 'json',  
         
      
             10 
                            'success'       : function( data ) {  
         
      
             11 
                                    if ( data.fallback ) {  
         
      
             12 
                                            alert('Не могу добавить тег ' + tag + '. Откат');  
         
      
             13 
                                            $('#<% $name%>_text').removeTag(tag);  
         
      
             14 
                                    }  
         
      
             15 
                            }  
         
      
             16 
                    });  
         
      
             17 
            }  
         
      
             18 
             
         
      
             19 
            function <% $name %>_onRemoveTag(tag) {  
         
      
             20 
                    $.ajax({  
         
      
             21 
                            'url'   : '/contenido/tag/ajax/manage.html',  
         
      
             22 
                            'type'  : 'GET',  
         
      
             23 
                            'data'  : { 'action' : 'remove', 'id' : <% $object->id %>, 'class' : '<% $object->class %>', 'tag' : tag },  
         
      
             24 
                            'dataType'      : 'json',  
         
      
             25 
                            'success'       : function( data ) {  
         
      
             26 
                                    if ( data.fallback ) {  
         
      
             27 
                                            alert('Не могу удалить тег ' + tag + '. Откат');  
         
      
             28 
                                            $('#<% $name%>_text').addTag(tag);  
         
      
             29 
                                    }  
         
      
             30 
                            }  
         
      
             31 
                    });  
         
      
             32 
            }  
         
      
             33 
             
         
      
             34 
            $(document).ready(function() {  
         
      
             35 
             
         
      
             36 
                $('#<% $name %>_text').tagsInput({  
         
      
             37 
            	'width'		: 'auto',  
         
      
             38 
            	'height'	: '60px',  
         
      
             39 
            	'minChars'	: 3,  
         
      
             40 
            	'autocomplete_url'	: '/contenido/tag/ajax/search.html?id=<% $object->id %>&class=<% $object->class %>',  
         
      
             41 
            	'onAddTag'	: <% $name %>_onAddTag,  
         
      
             42 
            	'onRemoveTag'	: <% $name %>_onRemoveTag,  
         
      
             43 
            	'defaultText'	: 'Добавьте тег'  
         
      
             44 
                });  
         
      
             45 
             
         
      
             46 
            %	if ( @tags ) {  
         
      
             47 
                $('#<% $name %>_text').importTags('<% join(',', map { $_->name } @tags) %>');  
         
      
             48 
            %	}  
         
      
             49 
             
         
      
             50 
            });  
         
      
             51 
            //-->  
         
      
             52 
            </script>  
         
      
             53 
            <div style="width:95%;">  
         
      
             54 
            <input type="text" name="<% $name %>" id="<% $name %>_text" placeholder="Tags" class="tm-input"/>  
         
      
             55 
            </div>  
         
      
             56 
            % } else {  
         
      
             57 
            <div style="width:95%; padding:10px; border:1px solid green; background:#f0fff0">  
         
      
             58 
            <div style="color:green">Ввод тегов возможен только после сохранения документа</div>  
         
      
             59 
            </div>  
         
      
             60 
            % }  
         
      
             61 
            <%once>  
         
      
             62 
             
         
      
             63 
                use Data::Recursive::Encode;  
         
      
             64 
                use JSON::XS;  
         
      
             65 
                my $json = JSON::XS->new->utf8;  
         
      
             66 
             
         
      
             67 
            </%once>  
         
      
             68 
            <%args>  
         
      
             69 
             
         
      
             70 
            	$object  
         
      
             71 
            	$name	=> undef  
         
      
             72 
            	$check	=> undef  
         
      
             73 
            	$prop	=> {}  
         
      
             74 
             
         
      
             75 
            </%args>  
         
      
             76 
            <%init>  
         
      
             77 
             
         
      
             78 
                my @tags;  
         
      
             79 
                if ( $object->id ) {  
         
      
             80 
            	@tags = $keeper->get_documents(  
         
      
             81 
            			class	=> 'tag::Tag',  
         
      
             82 
            			lclass	=> 'tag::Cloud',  
         
      
             83 
            			ldest	=> $object->id,  
         
      
             84 
            			ldestclass	=> $object->class,  
         
      
             85 
            		);  
         
      
             86 
                }  
         
      
             87 
                my $value;  
         
      
             88 
                unless ( $prop->{virtual} ) {  
         
      
             89 
            	if ( ref $object->$name ) {  
         
      
             90 
            		$value = $object->$name;  
         
      
             91 
            	} elsif ( $object->$name ) {  
         
      
             92 
            		$value = Data::Recursive::Encode->encode_utf8( $json->decode( $object->$name ) );  
         
      
             93 
            	}  
         
      
             94 
                }  
         
      
             95 
             
         
      
             96 
            </%init>  
          
   
      utf8/plugins/tag/comps/contenido/components/outputs/tagset.msn 
      
        
           
        
          
              
           
         
                              
      
             1 
            <%once>  
         
      
             2 
             
         
      
             3 
                 use JSON::XS;  
         
      
             4 
                 my $json = JSON::XS->new;  
         
      
             5 
             
         
      
             6 
            </%once>  
         
      
             7 
            <%args>  
         
      
             8 
             
         
      
             9 
            	$object => undef  
         
      
             10 
            	$name => undef  
         
      
             11 
            	$SETS => undef  
         
      
             12 
             
         
      
             13 
            </%args>  
         
      
             14 
            <%init>  
         
      
             15 
             
         
      
             16 
                return undef unless ref $SETS;  
         
      
             17 
                return undef unless $name;  
         
      
             18 
             
         
      
             19 
                return undef if $SETS->{$name} eq '';  
         
      
             20 
             
         
      
             21 
                warn "\nTAG Store:\n"		if $DEBUG;  
         
      
             22 
                warn Dumper $SETS->{$name}		if $DEBUG;  
         
      
             23 
             
         
      
             24 
                my ($prop) = grep { $_->{attr} eq $name } $object->structure;  
         
      
             25 
                return undef	if exists $prop->{virtual} && $prop->{virtual};  
         
      
             26 
                my $class = $object->class;  
         
      
             27 
                my $is_extra = grep { ref $_ && $_->{attr} eq $name } $class->extra_properties ? 1 : 0;  
         
      
             28 
             
         
      
             29 
                my $result;  
         
      
             30 
                my @tags;  
         
      
             31 
                if ( $object->id ) {  
         
      
             32 
            	@tags = $keeper->get_documents(  
         
      
             33 
            			class	=> 'tag::Tag',  
         
      
             34 
            			lclass	=> 'tag::Cloud',  
         
      
             35 
            			ldest	=> $object->id,  
         
      
             36 
            			ldestclass	=> $object->class,  
         
      
             37 
            		);  
         
      
             38 
            	if ( @tags ) {  
         
      
             39 
            		$result = [];  
         
      
             40 
            		foreach my $tag ( @tags ) {  
         
      
             41 
            			push @$result, { id => $tag->id, name => Encode::decode('utf-8', $tag->name) };  
         
      
             42 
            		}  
         
      
             43 
            	}  
         
      
             44 
            	unless ( $is_extra ) {  
         
      
             45 
            		$result = Encode::encode('utf-8', $json->encode( $result ));  
         
      
             46 
            	}  
         
      
             47 
            	warn Dumper $result		if $DEBUG;  
         
      
             48 
            	return $result;  
         
      
             49 
                } else {  
         
      
             50 
            	return undef;  
         
      
             51 
                }  
         
      
             52 
             
         
      
             53 
             
         
      
             54 
            </%init>  
          
   
      utf8/plugins/tag/comps/contenido/tag/ajax/manage.html 
      
        
           
        
          
              
           
         
                              
      
             1 
            <% $json %>  
         
      
             2 
            <%once>  
         
      
             3 
             
         
      
             4 
                use JSON::XS;  
         
      
             5 
             
         
      
             6 
            </%once>  
         
      
             7 
            <%args>  
         
      
             8 
             
         
      
             9 
            	$action	=> undef  
         
      
             10 
            	$id	=> undef  
         
      
             11 
            	$class	=> undef  
         
      
             12 
            	$tag	=> undef  
         
      
             13 
             
         
      
             14 
            </%args>  
         
      
             15 
            <%init>  
         
      
             16 
             
         
      
             17 
                my %result;  
         
      
             18 
                warn Dumper \%ARGS;  
         
      
             19 
                my $doc = $keeper->get_document_by_id( $id, class => $class );  
         
      
             20 
             
         
      
             21 
                if ( ref $doc && $ARGS{tag} ) {  
         
      
             22 
            	my @links = $keeper->get_links(  
         
      
             23 
            			class	=> 'tag::Cloud',  
         
      
             24 
            			dest_id	=> $id,  
         
      
             25 
            			dest_class	=> $class,  
         
      
             26 
            		);  
         
      
             27 
            	my @tags;  
         
      
             28 
            	if ( @links ) {  
         
      
             29 
            		my %ids = map { $_->source_id => 1 } @links;  
         
      
             30 
            		my @ids = keys %ids;  
         
      
             31 
            		@tags = $keeper->get_documents(  
         
      
             32 
            				id	=> \@ids,  
         
      
             33 
            				class	=> 'tag::Tag',  
         
      
             34 
            			)		if @ids;  
         
      
             35 
            	}  
         
      
             36 
            	my ($tobj) = $keeper->get_documents(  
         
      
             37 
            			class	=> 'tag::Tag',  
         
      
             38 
            			name	=> $ARGS{tag},  
         
      
             39 
            			ilike	=> 1,  
         
      
             40 
            			limit	=> 1,  
         
      
             41 
            		);  
         
      
             42 
            	if ( $action eq 'add'  ) {  
         
      
             43 
            		unless ( ref $tobj ) {  
         
      
             44 
            			$tobj = tag::Tag->new( $keeper );  
         
      
             45 
            			$tobj->name( $ARGS{tag} );  
         
      
             46 
            			$tobj->status( 1 );  
         
      
             47 
            			$tobj->store;  
         
      
             48 
            		}  
         
      
             49 
            		my $exists = (grep { $_->id == $tobj->id } @tags) ? 1 : 0;  
         
      
             50 
            		if ( ref $tobj && !$exists ) {  
         
      
             51 
            			my $link = tag::Cloud->new( $keeper );  
         
      
             52 
            			$link->source_id( $tobj->id );  
         
      
             53 
            			$link->source_class( $tobj->class );  
         
      
             54 
            			$link->dest_id( $id );  
         
      
             55 
            			$link->dest_class( $class );  
         
      
             56 
            			$link->status( 1 );  
         
      
             57 
            			$link->store;  
         
      
             58 
            		} else {  
         
      
             59 
            			$result{fallback} = 1;  
         
      
             60 
            		}  
         
      
             61 
            	} elsif ( $action eq 'remove' ) {  
         
      
             62 
            		if ( ref $tobj ) {  
         
      
             63 
            			my @delete = grep { $_->source_id == $tobj->id } @links;  
         
      
             64 
            			foreach my $obj ( @delete ) {  
         
      
             65 
            				$obj->delete;  
         
      
             66 
            			}  
         
      
             67 
            			my $count = $keeper->get_links(  
         
      
             68 
            					class	=> 'tag::Cloud',  
         
      
             69 
            					count	=> 1,  
         
      
             70 
            					source_id	=> $tobj->id,  
         
      
             71 
            				);  
         
      
             72 
            			$tobj->delete	unless $count;  
         
      
             73 
            		} else {  
         
      
             74 
            			$result{fallback} = 1;  
         
      
             75 
            		}  
         
      
             76 
            	}  
         
      
             77 
                }  
         
      
             78 
                $result{ok} = 1	unless exists $result{fallback};  
         
      
             79 
             
         
      
             80 
                my $json = encode_json \%result;  
         
      
             81 
             
         
      
             82 
            </%init>  
          
   
      utf8/plugins/tag/comps/contenido/tag/ajax/search.html 
      
        
           
        
          
              
           
         
                              
      
             1 
            <% $json %>  
         
      
             2 
            <%once>  
         
      
             3 
             
         
      
             4 
                use JSON::XS;  
         
      
             5 
             
         
      
             6 
            </%once>  
         
      
             7 
            <%args>  
         
      
             8 
             
         
      
             9 
            	$id	=> undef  
         
      
             10 
            	$class	=> undef  
         
      
             11 
            	$term	=> undef  
         
      
             12 
             
         
      
             13 
            </%args>  
         
      
             14 
            <%init>  
         
      
             15 
             
         
      
             16 
                warn Dumper \%ARGS		if $DEBUG;  
         
      
             17 
                return	if length( $ARGS{term} ) < 3;  
         
      
             18 
             
         
      
             19 
                my @links = $keeper->get_links(  
         
      
             20 
            			class	=> 'tag::Cloud',  
         
      
             21 
            			dest_class	=> $class,  
         
      
             22 
            			dest_id		=> $id,  
         
      
             23 
            	);  
         
      
             24 
                my %ex = map { $_->source_id => 1 } @links;  
         
      
             25 
                my @ex = keys %ex;  
         
      
             26 
             
         
      
             27 
                my @tags = $keeper->get_documents(  
         
      
             28 
            			@ex ? ( excludes => \@ex ) : (),  
         
      
             29 
            			class	=> 'tag::Tag',  
         
      
             30 
            			status	=> 1,  
         
      
             31 
            			name	=> '%'.$ARGS{term}.'%',  
         
      
             32 
            			ilike	=> 1,  
         
      
             33 
            			order_by	=> 'name',  
         
      
             34 
            	);  
         
      
             35 
                return	unless @tags;  
         
      
             36 
             
         
      
             37 
                my @result = map { {id => $_->id, label => Encode::decode('utf-8', $_->name), value => Encode::decode('utf-8', $_->name)} } @tags;  
         
      
             38 
             
         
      
             39 
                my $json = encode_json \@result;  
         
      
             40 
             
         
      
             41 
            </%init>  
          
   
      utf8/plugins/tag/comps/contenido/tag/autohandler 
      
        
           
        
          
              
           
         
                              
      
             1 
            <%init>  
         
      
             2 
             
         
      
             3 
             $r->content_type('text/html');  
         
      
             4 
             $m->call_next();  
         
      
             5 
             
         
      
             6 
            </%init>  
          
   
      utf8/plugins/tag/comps/contenido/tag/components/title_inc.msn 
      
        
           
        
          
              
           
         
                              
      
             1 
            <script language="javascript" type="text/javascript" src="/contenido/tag/i/js/jquery.tagsinput.js"></script>  
         
      
             2 
            <link href="/contenido/tag/i/js/jquery.tagsinput.css" rel="stylesheet" type="text/css">  
          
   
      utf8/plugins/tag/comps/contenido/tag/dhandler 
      
        
           
        
          
              
           
         
                              
      
             1 
            <& $call, %ARGS &>  
         
      
             2 
            <%init>  
         
      
             3 
             
         
      
             4 
              my $call;  
         
      
             5 
              if ( $r->uri eq '/contenido/tag/' ) {  
         
      
             6 
                    $call = 'index.html';  
         
      
             7 
              } else {  
         
      
             8 
                    &abort404;  
         
      
             9 
              }  
         
      
             10 
             
         
      
             11 
            </%init>  
          
   
      utf8/plugins/tag/comps/contenido/tag/i/js/jquery.tagsinput.css 
      
        
           
        
          
              
           
         
                              
      
             1 
            div.tagsinput { border:1px solid #CCC; background: #FFF; padding:5px; width:300px; height:100px; overflow-y: auto;}  
         
      
             2 
            div.tagsinput span.tag { border: 1px solid #a5d24a; -moz-border-radius:2px; -webkit-border-radius:2px; display: block; float: left; padding: 5px; text-decoration:none; background: #cde69c; color: #638421; margin-right: 5px; margin-bottom:5px;font-family: helvetica;  font-size:13px;}  
         
      
             3 
            div.tagsinput span.tag a { font-weight: bold; color: #82ad2b; text-decoration:none; font-size: 11px;  }   
         
      
             4 
            div.tagsinput input { width:100px; margin:0px; font-family: helvetica; font-size: 13px; border:1px solid transparent; padding:5px; background: transparent; color: #000; outline:0px;  margin-right:5px; margin-bottom:5px; }  
         
      
             5 
            div.tagsinput div { display:block; float: left; }   
         
      
             6 
            .tags_clear { clear: both; width: 100%; height: 0px; }  
         
      
             7 
            .not_valid {background: #FBD8DB !important; color: #90111A !important;}  
          
   
      utf8/plugins/tag/comps/contenido/tag/i/js/jquery.tagsinput.js 
      
        
           
        
          
              
           
         
                              
      
             1 
            /*  
         
      
             2 
             
         
      
             3 
            	jQuery Tags Input Plugin 1.3.3  
         
      
             4 
            	  
         
      
             5 
            	Copyright (c) 2011 XOXCO, Inc  
         
      
             6 
            	  
         
      
             7 
            	Documentation for this plugin lives here:  
         
      
             8 
            	http://xoxco.com/clickable/jquery-tags-input  
         
      
             9 
            	  
         
      
             10 
            	Licensed under the MIT license:  
         
      
             11 
            	http://www.opensource.org/licenses/mit-license.php  
         
      
             12 
             
         
      
             13 
            	ben@xoxco.com  
         
      
             14 
             
         
      
             15 
            */  
         
      
             16 
             
         
      
             17 
            (function($) {  
         
      
             18 
             
         
      
             19 
            	var delimiter = new Array();  
         
      
             20 
            	var tags_callbacks = new Array();  
         
      
             21 
            	$.fn.doAutosize = function(o){  
         
      
             22 
            	    var minWidth = $(this).data('minwidth'),  
         
      
             23 
            	        maxWidth = $(this).data('maxwidth'),  
         
      
             24 
            	        val = '',  
         
      
             25 
            	        input = $(this),  
         
      
             26 
            	        testSubject = $('#'+$(this).data('tester_id'));  
         
      
             27 
            	  
         
      
             28 
            	    if (val === (val = input.val())) {return;}  
         
      
             29 
            	  
         
      
             30 
            	    // Enter new content into testSubject  
         
      
             31 
            	    var escaped = val.replace(/&/g, '&').replace(/\s/g,' ').replace(/</g, '<').replace(/>/g, '>');  
         
      
             32 
            	    testSubject.html(escaped);  
         
      
             33 
            	    // Calculate new width + whether to change  
         
      
             34 
            	    var testerWidth = testSubject.width(),  
         
      
             35 
            	        newWidth = (testerWidth + o.comfortZone) >= minWidth ? testerWidth + o.comfortZone : minWidth,  
         
      
             36 
            	        currentWidth = input.width(),  
         
      
             37 
            	        isValidWidthChange = (newWidth < currentWidth && newWidth >= minWidth)  
         
      
             38 
            	                             || (newWidth > minWidth && newWidth < maxWidth);  
         
      
             39 
            	  
         
      
             40 
            	    // Animate width  
         
      
             41 
            	    if (isValidWidthChange) {  
         
      
             42 
            	        input.width(newWidth);  
         
      
             43 
            	    }  
         
      
             44 
             
         
      
             45 
             
         
      
             46 
              };  
         
      
             47 
              $.fn.resetAutosize = function(options){  
         
      
             48 
                // alert(JSON.stringify(options));  
         
      
             49 
                var minWidth =  $(this).data('minwidth') || options.minInputWidth || $(this).width(),  
         
      
             50 
                    maxWidth = $(this).data('maxwidth') || options.maxInputWidth || ($(this).closest('.tagsinput').width() - options.inputPadding),  
         
      
             51 
                    val = '',  
         
      
             52 
                    input = $(this),  
         
      
             53 
                    testSubject = $('<tester/>').css({  
         
      
             54 
                        position: 'absolute',  
         
      
             55 
                        top: -9999,  
         
      
             56 
                        left: -9999,  
         
      
             57 
                        width: 'auto',  
         
      
             58 
                        fontSize: input.css('fontSize'),  
         
      
             59 
                        fontFamily: input.css('fontFamily'),  
         
      
             60 
                        fontWeight: input.css('fontWeight'),  
         
      
             61 
                        letterSpacing: input.css('letterSpacing'),  
         
      
             62 
                        whiteSpace: 'nowrap'  
         
      
             63 
                    }),  
         
      
             64 
                    testerId = $(this).attr('id')+'_autosize_tester';  
         
      
             65 
                if(! $('#'+testerId).length > 0){  
         
      
             66 
                  testSubject.attr('id', testerId);  
         
      
             67 
                  testSubject.appendTo('body');  
         
      
             68 
                }  
         
      
             69 
             
         
      
             70 
                input.data('minwidth', minWidth);  
         
      
             71 
                input.data('maxwidth', maxWidth);  
         
      
             72 
                input.data('tester_id', testerId);  
         
      
             73 
                input.css('width', minWidth);  
         
      
             74 
              };  
         
      
             75 
                
         
      
             76 
            	$.fn.addTag = function(value,options) {  
         
      
             77 
            			options = jQuery.extend({focus:false,callback:true},options);  
         
      
             78 
            			this.each(function() {   
         
      
             79 
            				var id = $(this).attr('id');  
         
      
             80 
             
         
      
             81 
            				var tagslist = $(this).val().split(delimiter[id]);  
         
      
             82 
            				if (tagslist[0] == '') {   
         
      
             83 
            					tagslist = new Array();  
         
      
             84 
            				}  
         
      
             85 
             
         
      
             86 
            				value = jQuery.trim(value);  
         
      
             87 
            		  
         
      
             88 
            				if (options.unique) {  
         
      
             89 
            					var skipTag = $(this).tagExist(value);  
         
      
             90 
            					if(skipTag == true) {  
         
      
             91 
            					    //Marks fake input as not_valid to let styling it  
         
      
             92 
                				    $('#'+id+'_tag').addClass('not_valid');  
         
      
             93 
                				}  
         
      
             94 
            				} else {  
         
      
             95 
            					var skipTag = false;   
         
      
             96 
            				}  
         
      
             97 
            				  
         
      
             98 
            				if (value !='' && skipTag != true) {   
         
      
             99 
                                $('<span>').addClass('tag').append(  
         
      
             100 
                                    $('<span>').text(value).append('  '),  
         
      
             101 
                                    $('<a>', {  
         
      
             102 
                                        href  : '#',  
         
      
             103 
                                        title : 'Removing tag',  
         
      
             104 
                                        text  : 'x'  
         
      
             105 
                                    }).click(function () {  
         
      
             106 
                                        return $('#' + id).removeTag(escape(value));  
         
      
             107 
                                    })  
         
      
             108 
                                ).insertBefore('#' + id + '_addTag');  
         
      
             109 
             
         
      
             110 
            					tagslist.push(value);  
         
      
             111 
            				  
         
      
             112 
            					$('#'+id+'_tag').val('');  
         
      
             113 
            					if (options.focus) {  
         
      
             114 
            						$('#'+id+'_tag').focus();  
         
      
             115 
            					} else {		  
         
      
             116 
            						$('#'+id+'_tag').blur();  
         
      
             117 
            					}  
         
      
             118 
            					  
         
      
             119 
            					$.fn.tagsInput.updateTagsField(this,tagslist);  
         
      
             120 
            					  
         
      
             121 
            					if (options.callback && tags_callbacks[id] && tags_callbacks[id]['onAddTag']) {  
         
      
             122 
            						var f = tags_callbacks[id]['onAddTag'];  
         
      
             123 
            						f.call(this, value);  
         
      
             124 
            					}  
         
      
             125 
            					if(tags_callbacks[id] && tags_callbacks[id]['onChange'])  
         
      
             126 
            					{  
         
      
             127 
            						var i = tagslist.length;  
         
      
             128 
            						var f = tags_callbacks[id]['onChange'];  
         
      
             129 
            						f.call(this, $(this), tagslist[i-1]);  
         
      
             130 
            					}					  
         
      
             131 
            				}  
         
      
             132 
            		  
         
      
             133 
            			});		  
         
      
             134 
            			  
         
      
             135 
            			return false;  
         
      
             136 
            		};  
         
      
             137 
            		  
         
      
             138 
            	$.fn.removeTag = function(value) {   
         
      
             139 
            			value = unescape(value);  
         
      
             140 
            			this.each(function() {   
         
      
             141 
            				var id = $(this).attr('id');  
         
      
             142 
            	  
         
      
             143 
            				var old = $(this).val().split(delimiter[id]);  
         
      
             144 
            					  
         
      
             145 
            				$('#'+id+'_tagsinput .tag').remove();  
         
      
             146 
            				str = '';  
         
      
             147 
            				for (i=0; i< old.length; i++) {   
         
      
             148 
            					if (old[i]!=value) {   
         
      
             149 
            						str = str + delimiter[id] +old[i];  
         
      
             150 
            					}  
         
      
             151 
            				}  
         
      
             152 
            				  
         
      
             153 
            				$.fn.tagsInput.importTags(this,str);  
         
      
             154 
             
         
      
             155 
            				if (tags_callbacks[id] && tags_callbacks[id]['onRemoveTag']) {  
         
      
             156 
            					var f = tags_callbacks[id]['onRemoveTag'];  
         
      
             157 
            					f.call(this, value);  
         
      
             158 
            				}  
         
      
             159 
            			});  
         
      
             160 
            					  
         
      
             161 
            			return false;  
         
      
             162 
            		};  
         
      
             163 
            	  
         
      
             164 
            	$.fn.tagExist = function(val) {  
         
      
             165 
            		var id = $(this).attr('id');  
         
      
             166 
            		var tagslist = $(this).val().split(delimiter[id]);  
         
      
             167 
            		return (jQuery.inArray(val, tagslist) >= 0); //true when tag exists, false when not  
         
      
             168 
            	};  
         
      
             169 
            	  
         
      
             170 
            	// clear all existing tags and import new ones from a string  
         
      
             171 
            	$.fn.importTags = function(str) {  
         
      
             172 
                            id = $(this).attr('id');  
         
      
             173 
            		$('#'+id+'_tagsinput .tag').remove();  
         
      
             174 
            		$.fn.tagsInput.importTags(this,str);  
         
      
             175 
            	}  
         
      
             176 
            		  
         
      
             177 
            	$.fn.tagsInput = function(options) {   
         
      
             178 
                var settings = jQuery.extend({  
         
      
             179 
                  interactive:true,  
         
      
             180 
                  defaultText:'add a tag',  
         
      
             181 
                  minChars:0,  
         
      
             182 
                  width:'300px',  
         
      
             183 
                  height:'100px',  
         
      
             184 
                  autocomplete: {selectFirst: false },  
         
      
             185 
                  'hide':true,  
         
      
             186 
                  'delimiter':',',  
         
      
             187 
                  'unique':true,  
         
      
             188 
                  removeWithBackspace:true,  
         
      
             189 
                  placeholderColor:'#666666',  
         
      
             190 
                  autosize: true,  
         
      
             191 
                  comfortZone: 20,  
         
      
             192 
                  inputPadding: 6*2  
         
      
             193 
                },options);  
         
      
             194 
             
         
      
             195 
            		this.each(function() {   
         
      
             196 
            			if (settings.hide) {   
         
      
             197 
            				$(this).hide();				  
         
      
             198 
            			}  
         
      
             199 
            			var id = $(this).attr('id');  
         
      
             200 
            			if (!id || delimiter[$(this).attr('id')]) {  
         
      
             201 
            				id = $(this).attr('id', 'tags' + new Date().getTime()).attr('id');  
         
      
             202 
            			}  
         
      
             203 
            			  
         
      
             204 
            			var data = jQuery.extend({  
         
      
             205 
            				pid:id,  
         
      
             206 
            				real_input: '#'+id,  
         
      
             207 
            				holder: '#'+id+'_tagsinput',  
         
      
             208 
            				input_wrapper: '#'+id+'_addTag',  
         
      
             209 
            				fake_input: '#'+id+'_tag'  
         
      
             210 
            			},settings);  
         
      
             211 
            	  
         
      
             212 
            			delimiter[id] = data.delimiter;  
         
      
             213 
            			  
         
      
             214 
            			if (settings.onAddTag || settings.onRemoveTag || settings.onChange) {  
         
      
             215 
            				tags_callbacks[id] = new Array();  
         
      
             216 
            				tags_callbacks[id]['onAddTag'] = settings.onAddTag;  
         
      
             217 
            				tags_callbacks[id]['onRemoveTag'] = settings.onRemoveTag;  
         
      
             218 
            				tags_callbacks[id]['onChange'] = settings.onChange;  
         
      
             219 
            			}  
         
      
             220 
            	  
         
      
             221 
            			var markup = '<div id="'+id+'_tagsinput" class="tagsinput"><div id="'+id+'_addTag">';  
         
      
             222 
            			  
         
      
             223 
            			if (settings.interactive) {  
         
      
             224 
            				markup = markup + '<input id="'+id+'_tag" value="" data-default="'+settings.defaultText+'" />';  
         
      
             225 
            			}  
         
      
             226 
            			  
         
      
             227 
            			markup = markup + '</div><div class="tags_clear"></div></div>';  
         
      
             228 
            			  
         
      
             229 
            			$(markup).insertAfter(this);  
         
      
             230 
             
         
      
             231 
            			$(data.holder).css('width',settings.width);  
         
      
             232 
            			$(data.holder).css('min-height',settings.height);  
         
      
             233 
            			$(data.holder).css('height','100%');  
         
      
             234 
            	  
         
      
             235 
            			if ($(data.real_input).val()!='') {   
         
      
             236 
            				$.fn.tagsInput.importTags($(data.real_input),$(data.real_input).val());  
         
      
             237 
            			}		  
         
      
             238 
            			if (settings.interactive) {   
         
      
             239 
            				$(data.fake_input).val($(data.fake_input).attr('data-default'));  
         
      
             240 
            				$(data.fake_input).css('color',settings.placeholderColor);  
         
      
             241 
            		        $(data.fake_input).resetAutosize(settings);  
         
      
             242 
            		  
         
      
             243 
            				$(data.holder).bind('click',data,function(event) {  
         
      
             244 
            					$(event.data.fake_input).focus();  
         
      
             245 
            				});  
         
      
             246 
            			  
         
      
             247 
            				$(data.fake_input).bind('focus',data,function(event) {  
         
      
             248 
            					if ($(event.data.fake_input).val()==$(event.data.fake_input).attr('data-default')) {   
         
      
             249 
            						$(event.data.fake_input).val('');  
         
      
             250 
            					}  
         
      
             251 
            					$(event.data.fake_input).css('color','#000000');		  
         
      
             252 
            				});  
         
      
             253 
            						  
         
      
             254 
            				if (settings.autocomplete_url != undefined) {  
         
      
             255 
            					autocomplete_options = {source: settings.autocomplete_url};  
         
      
             256 
            					for (attrname in settings.autocomplete) {   
         
      
             257 
            						autocomplete_options[attrname] = settings.autocomplete[attrname];   
         
      
             258 
            					}  
         
      
             259 
            				  
         
      
             260 
            					if (jQuery.Autocompleter !== undefined) {  
         
      
             261 
            						$(data.fake_input).autocomplete(settings.autocomplete_url, settings.autocomplete);  
         
      
             262 
            						$(data.fake_input).bind('result',data,function(event,data,formatted) {  
         
      
             263 
            							if (data) {  
         
      
             264 
            								$('#'+id).addTag(data[0] + "",{focus:true,unique:(settings.unique)});  
         
      
             265 
            							}  
         
      
             266 
            					  	});  
         
      
             267 
            					} else if (jQuery.ui.autocomplete !== undefined) {  
         
      
             268 
            						$(data.fake_input).autocomplete(autocomplete_options);  
         
      
             269 
            						$(data.fake_input).bind('autocompleteselect',data,function(event,ui) {  
         
      
             270 
            							$(event.data.real_input).addTag(ui.item.value,{focus:true,unique:(settings.unique)});  
         
      
             271 
            							return false;  
         
      
             272 
            						});  
         
      
             273 
            					}  
         
      
             274 
            				  
         
      
             275 
            					  
         
      
             276 
            				} else {  
         
      
             277 
            						// if a user tabs out of the field, create a new tag  
         
      
             278 
            						// this is only available if autocomplete is not used.  
         
      
             279 
            						$(data.fake_input).bind('blur',data,function(event) {   
         
      
             280 
            							var d = $(this).attr('data-default');  
         
      
             281 
            							if ($(event.data.fake_input).val()!='' && $(event.data.fake_input).val()!=d) {   
         
      
             282 
            								if( (event.data.minChars <= $(event.data.fake_input).val().length) && (!event.data.maxChars || (event.data.maxChars >= $(event.data.fake_input).val().length)) )  
         
      
             283 
            									$(event.data.real_input).addTag($(event.data.fake_input).val(),{focus:true,unique:(settings.unique)});  
         
      
             284 
            							} else {  
         
      
             285 
            								$(event.data.fake_input).val($(event.data.fake_input).attr('data-default'));  
         
      
             286 
            								$(event.data.fake_input).css('color',settings.placeholderColor);  
         
      
             287 
            							}  
         
      
             288 
            							return false;  
         
      
             289 
            						});  
         
      
             290 
            				  
         
      
             291 
            				}  
         
      
             292 
            				// if user types a comma, create a new tag  
         
      
             293 
            				$(data.fake_input).bind('keypress',data,function(event) {  
         
      
             294 
            					if (event.which==event.data.delimiter.charCodeAt(0) || event.which==13 ) {  
         
      
             295 
            					    event.preventDefault();  
         
      
             296 
            						if( (event.data.minChars <= $(event.data.fake_input).val().length) && (!event.data.maxChars || (event.data.maxChars >= $(event.data.fake_input).val().length)) )  
         
      
             297 
            							$(event.data.real_input).addTag($(event.data.fake_input).val(),{focus:true,unique:(settings.unique)});  
         
      
             298 
            					  	$(event.data.fake_input).resetAutosize(settings);  
         
      
             299 
            						return false;  
         
      
             300 
            					} else if (event.data.autosize) {  
         
      
             301 
            			            $(event.data.fake_input).doAutosize(settings);  
         
      
             302 
                          
         
      
             303 
                      			}  
         
      
             304 
            				});  
         
      
             305 
            				//Delete last tag on backspace  
         
      
             306 
            				data.removeWithBackspace && $(data.fake_input).bind('keydown', function(event)  
         
      
             307 
            				{  
         
      
             308 
            					if(event.keyCode == 8 && $(this).val() == '')  
         
      
             309 
            					{  
         
      
             310 
            						 event.preventDefault();  
         
      
             311 
            						 var last_tag = $(this).closest('.tagsinput').find('.tag:last').text();  
         
      
             312 
            						 var id = $(this).attr('id').replace(/_tag$/, '');  
         
      
             313 
            						 last_tag = last_tag.replace(/[\s]+x$/, '');  
         
      
             314 
            						 $('#' + id).removeTag(escape(last_tag));  
         
      
             315 
            						 $(this).trigger('focus');  
         
      
             316 
            					}  
         
      
             317 
            				});  
         
      
             318 
            				$(data.fake_input).blur();  
         
      
             319 
            				  
         
      
             320 
            				//Removes the not_valid class when user changes the value of the fake input  
         
      
             321 
            				if(data.unique) {  
         
      
             322 
            				    $(data.fake_input).keydown(function(event){  
         
      
             323 
            				        if(event.keyCode == 8 || String.fromCharCode(event.which).match(/\w+|[áéíóúÁÉÍÓÚñÑ,/]+/)) {  
         
      
             324 
            				            $(this).removeClass('not_valid');  
         
      
             325 
            				        }  
         
      
             326 
            				    });  
         
      
             327 
            				}  
         
      
             328 
            			} // if settings.interactive  
         
      
             329 
            		});  
         
      
             330 
            			  
         
      
             331 
            		return this;  
         
      
             332 
            	  
         
      
             333 
            	};  
         
      
             334 
            	  
         
      
             335 
            	$.fn.tagsInput.updateTagsField = function(obj,tagslist) {   
         
      
             336 
            		var id = $(obj).attr('id');  
         
      
             337 
            		$(obj).val(tagslist.join(delimiter[id]));  
         
      
             338 
            	};  
         
      
             339 
            	  
         
      
             340 
            	$.fn.tagsInput.importTags = function(obj,val) {			  
         
      
             341 
            		$(obj).val('');  
         
      
             342 
            		var id = $(obj).attr('id');  
         
      
             343 
            		var tags = val.split(delimiter[id]);  
         
      
             344 
            		for (i=0; i<tags.length; i++) {   
         
      
             345 
            			$(obj).addTag(tags[i],{focus:false,callback:false});  
         
      
             346 
            		}  
         
      
             347 
            		if(tags_callbacks[id] && tags_callbacks[id]['onChange'])  
         
      
             348 
            		{  
         
      
             349 
            			var f = tags_callbacks[id]['onChange'];  
         
      
             350 
            			f.call(obj, obj, tags[i]);  
         
      
             351 
            		}  
         
      
             352 
            	};  
         
      
             353 
             
         
      
             354 
            })(jQuery);  
          
   
      utf8/plugins/tag/comps/contenido/tag/i/js/jquery.tagsinput.min.js 
      
        
           
        
          
              
           
         
                              
      
             1 
            (function(a){var b=new Array;var c=new Array;a.fn.doAutosize=function(b){var c=a(this).data("minwidth"),d=a(this).data("maxwidth"),e="",f=a(this),g=a("#"+a(this).data("tester_id"));if(e===(e=f.val())){return}var h=e.replace(/&/g,"&").replace(/\s/g," ").replace(/</g,"<").replace(/>/g,">");g.html(h);var i=g.width(),j=i+b.comfortZone>=c?i+b.comfortZone:c,k=f.width(),l=j<k&&j>=c||j>c&&j<d;if(l){f.width(j)}};a.fn.resetAutosize=function(b){var c=a(this).data("minwidth")||b.minInputWidth||a(this).width(),d=a(this).data("maxwidth")||b.maxInputWidth||a(this).closest(".tagsinput").width()-b.inputPadding,e="",f=a(this),g=a("<tester/>").css({position:"absolute",top:-9999,left:-9999,width:"auto",fontSize:f.css("fontSize"),fontFamily:f.css("fontFamily"),fontWeight:f.css("fontWeight"),letterSpacing:f.css("letterSpacing"),whiteSpace:"nowrap"}),h=a(this).attr("id")+"_autosize_tester";if(!a("#"+h).length>0){g.attr("id",h);g.appendTo("body")}f.data("minwidth",c);f.data("maxwidth",d);f.data("tester_id",h);f.css("width",c)};a.fn.addTag=function(d,e){e=jQuery.extend({focus:false,callback:true},e);this.each(function(){var f=a(this).attr("id");var g=a(this).val().split(b[f]);if(g[0]==""){g=new Array}d=jQuery.trim(d);if(e.unique){var h=a(g).tagExist(d);if(h==true){a("#"+f+"_tag").addClass("not_valid")}}else{var h=false}if(d!=""&&h!=true){a("<span>").addClass("tag").append(a("<span>").text(d).append("  "),a("<a>",{href:"#",title:"Removing tag",text:"x"}).click(function(){return a("#"+f).removeTag(escape(d))})).insertBefore("#"+f+"_addTag");g.push(d);a("#"+f+"_tag").val("");if(e.focus){a("#"+f+"_tag").focus()}else{a("#"+f+"_tag").blur()}a.fn.tagsInput.updateTagsField(this,g);if(e.callback&&c[f]&&c[f]["onAddTag"]){var i=c[f]["onAddTag"];i.call(this,d)}if(c[f]&&c[f]["onChange"]){var j=g.length;var i=c[f]["onChange"];i.call(this,a(this),g[j-1])}}});return false};a.fn.removeTag=function(d){d=unescape(d);this.each(function(){var e=a(this).attr("id");var f=a(this).val().split(b[e]);a("#"+e+"_tagsinput .tag").remove();str="";for(i=0;i<f.length;i++){if(f[i]!=d){str=str+b[e]+f[i]}}a.fn.tagsInput.importTags(this,str);if(c[e]&&c[e]["onRemoveTag"]){var g=c[e]["onRemoveTag"];g.call(this,d)}});return false};a.fn.tagExist=function(b){return jQuery.inArray(b,a(this))>=0};a.fn.importTags=function(b){id=a(this).attr("id");a("#"+id+"_tagsinput .tag").remove();a.fn.tagsInput.importTags(this,b)};a.fn.tagsInput=function(d){var e=jQuery.extend({interactive:true,defaultText:"add a tag",minChars:0,width:"300px",height:"100px",autocomplete:{selectFirst:false},hide:true,delimiter:",",unique:true,removeWithBackspace:true,placeholderColor:"#666666",autosize:true,comfortZone:20,inputPadding:6*2},d);this.each(function(){if(e.hide){a(this).hide()}var d=a(this).attr("id");if(!d||b[a(this).attr("id")]){d=a(this).attr("id","tags"+(new Date).getTime()).attr("id")}var f=jQuery.extend({pid:d,real_input:"#"+d,holder:"#"+d+"_tagsinput",input_wrapper:"#"+d+"_addTag",fake_input:"#"+d+"_tag"},e);b[d]=f.delimiter;if(e.onAddTag||e.onRemoveTag||e.onChange){c[d]=new Array;c[d]["onAddTag"]=e.onAddTag;c[d]["onRemoveTag"]=e.onRemoveTag;c[d]["onChange"]=e.onChange}var g='<div id="'+d+'_tagsinput" class="tagsinput"><div id="'+d+'_addTag">';if(e.interactive){g=g+'<input id="'+d+'_tag" value="" data-default="'+e.defaultText+'" />'}g=g+'</div><div class="tags_clear"></div></div>';a(g).insertAfter(this);a(f.holder).css("width",e.width);a(f.holder).css("height",e.height);if(a(f.real_input).val()!=""){a.fn.tagsInput.importTags(a(f.real_input),a(f.real_input).val())}if(e.interactive){a(f.fake_input).val(a(f.fake_input).attr("data-default"));a(f.fake_input).css("color",e.placeholderColor);a(f.fake_input).resetAutosize(e);a(f.holder).bind("click",f,function(b){a(b.data.fake_input).focus()});a(f.fake_input).bind("focus",f,function(b){if(a(b.data.fake_input).val()==a(b.data.fake_input).attr("data-default")){a(b.data.fake_input).val("")}a(b.data.fake_input).css("color","#000000")});if(e.autocomplete_url!=undefined){autocomplete_options={source:e.autocomplete_url};for(attrname in e.autocomplete){autocomplete_options[attrname]=e.autocomplete[attrname]}if(jQuery.Autocompleter!==undefined){a(f.fake_input).autocomplete(e.autocomplete_url,e.autocomplete);a(f.fake_input).bind("result",f,function(b,c,f){if(c){a("#"+d).addTag(c[0]+"",{focus:true,unique:e.unique})}})}else if(jQuery.ui.autocomplete!==undefined){a(f.fake_input).autocomplete(autocomplete_options);a(f.fake_input).bind("autocompleteselect",f,function(b,c){a(b.data.real_input).addTag(c.item.value,{focus:true,unique:e.unique});return false})}}else{a(f.fake_input).bind("blur",f,function(b){var c=a(this).attr("data-default");if(a(b.data.fake_input).val()!=""&&a(b.data.fake_input).val()!=c){if(b.data.minChars<=a(b.data.fake_input).val().length&&(!b.data.maxChars||b.data.maxChars>=a(b.data.fake_input).val().length))a(b.data.real_input).addTag(a(b.data.fake_input).val(),{focus:true,unique:e.unique})}else{a(b.data.fake_input).val(a(b.data.fake_input).attr("data-default"));a(b.data.fake_input).css("color",e.placeholderColor)}return false})}a(f.fake_input).bind("keypress",f,function(b){if(b.which==b.data.delimiter.charCodeAt(0)||b.which==13){b.preventDefault();if(b.data.minChars<=a(b.data.fake_input).val().length&&(!b.data.maxChars||b.data.maxChars>=a(b.data.fake_input).val().length))a(b.data.real_input).addTag(a(b.data.fake_input).val(),{focus:true,unique:e.unique});a(b.data.fake_input).resetAutosize(e);return false}else if(b.data.autosize){a(b.data.fake_input).doAutosize(e)}});f.removeWithBackspace&&a(f.fake_input).bind("keydown",function(b){if(b.keyCode==8&&a(this).val()==""){b.preventDefault();var c=a(this).closest(".tagsinput").find(".tag:last").text();var d=a(this).attr("id").replace(/_tag$/,"");c=c.replace(/[\s]+x$/,"");a("#"+d).removeTag(escape(c));a(this).trigger("focus")}});a(f.fake_input).blur();if(f.unique){a(f.fake_input).keydown(function(b){if(b.keyCode==8||String.fromCharCode(b.which).match(/\w+|[áéíóúÁÉÍÓÚñÑ,/]+/)){a(this).removeClass("not_valid")}})}}});return this};a.fn.tagsInput.updateTagsField=function(c,d){var e=a(c).attr("id");a(c).val(d.join(b[e]))};a.fn.tagsInput.importTags=function(d,e){a(d).val("");var f=a(d).attr("id");var g=e.split(b[f]);for(i=0;i<g.length;i++){a(d).addTag(g[i],{focus:false,callback:false})}if(c[f]&&c[f]["onChange"]){var h=c[f]["onChange"];h.call(d,d,g[i])}}})(jQuery);  
          
   
      utf8/plugins/tag/comps/contenido/tag/index.html 
      
        
           
        
          
              
           
         
                              
      
             1 
            <& "/contenido/components/header.msn" &>  
         
      
             2 
            <& "/contenido/components/naviline.msn" &>  
         
      
             3 
             
         
      
             4 
            <p>PLugin [tag]</p>  
         
      
             5 
             
         
      
             6 
            </body>  
         
      
             7 
            </html>  
          
   
      utf8/plugins/tag/config.proto 
      
        
           
        
          
              
           
         
                              
      
             1 
            #############################################################################  
         
      
             2 
            #  
         
      
             3 
            #  Параметры данного шаблона необходимо ВРУЧНУЮ добавить в config.mk проекта  
         
      
             4 
            #  и привести в соответствие с требованиями проекта  
         
      
             5 
            #  
         
      
             6 
            #############################################################################  
         
      
             7 
             
         
      
             8 
            PLUGINS +=                      tag  
         
      
             9 
             
         
      
             10 
            TAG_DEST =			<список через пробел классов тегируемых документов>  
         
      
             11 
            REWRITE +=			TAG_DEST  
          
   
      utf8/plugins/tag/lib/tag/Apache.pm 
      
        
           
        
          
              
           
         
                              
      
             1 
            package tag::Apache;  
         
      
             2 
             
         
      
             3 
            use strict;  
         
      
             4 
            use warnings 'all';  
         
      
             5 
             
         
      
             6 
            use tag::State;  
         
      
             7 
            use Contenido::Globals;  
         
      
             8 
             
         
      
             9 
             
         
      
             10 
            sub child_init {  
         
      
             11 
            	# встраиваем keeper плагина в keeper проекта  
         
      
             12 
            	$keeper->{tag} = tag::Keeper->new($state->tag);  
         
      
             13 
            }  
         
      
             14 
             
         
      
             15 
            sub request_init {  
         
      
             16 
            }  
         
      
             17 
             
         
      
             18 
            sub child_exit {  
         
      
             19 
            }  
         
      
             20 
             
         
      
             21 
            1;  
          
   
      utf8/plugins/tag/lib/tag/Cloud.pm 
      
        
           
        
          
              
           
         
                              
      
             1 
            package tag::Cloud;  
         
      
             2 
             
         
      
             3 
            use base 'Contenido::Link';  
         
      
             4 
            use Contenido::Globals;  
         
      
             5 
            use Data::Recursive::Encode;  
         
      
             6 
            use Data::Dumper;  
         
      
             7 
            use JSON::XS;  
         
      
             8 
             
         
      
             9 
            sub class_name  
         
      
             10 
            {  
         
      
             11 
            	return 'Тег к объекту';  
         
      
             12 
            }  
         
      
             13 
             
         
      
             14 
            sub class_description  
         
      
             15 
            {  
         
      
             16 
            	return 'Организация облака тегов';  
         
      
             17 
            }  
         
      
             18 
             
         
      
             19 
            sub extra_properties  
         
      
             20 
            {  
         
      
             21 
            	return (  
         
      
             22 
            	);  
         
      
             23 
            }  
         
      
             24 
             
         
      
             25 
            sub available_sources  
         
      
             26 
            {  
         
      
             27 
            	return [ qw(tag::Tag) ];  
         
      
             28 
            }  
         
      
             29 
             
         
      
             30 
            sub available_destinations  
         
      
             31 
            {  
         
      
             32 
            	return $state->{tag}->tag_destinations;  
         
      
             33 
            }  
         
      
             34 
             
         
      
             35 
            sub class_table  
         
      
             36 
            {  
         
      
             37 
            	return 'tag::SQL::TagsCloudTable';  
         
      
             38 
            }  
         
      
             39 
             
         
      
             40 
            sub pre_store  
         
      
             41 
            {  
         
      
             42 
            	my $self = shift;  
         
      
             43 
             
         
      
             44 
            	return 1;  
         
      
             45 
            }  
         
      
             46 
             
         
      
             47 
            sub post_store  
         
      
             48 
            {  
         
      
             49 
            	my $self = shift;  
         
      
             50 
            	warn "Store tag cloud element\n"	if $DEBUG;  
         
      
             51 
            	my $object = $keeper->get_document_by_id($self->dest_id, class => $self->dest_class )		if $self->dest_id && $self->dest_class;  
         
      
             52 
            	my $tag = $self->keeper->get_document_by_id($self->source_id, class => $self->source_class )	if $self->source_id && $self->source_class;  
         
      
             53 
            	if ( ref $object && ref $tag ) {  
         
      
             54 
            		my ($prop) = grep { $_->{type} eq 'tagset' } $object->structure;  
         
      
             55 
            		my $class = $object->class;  
         
      
             56 
            		my $is_extra = grep { ref $_ && $_->{attr} eq $name } $class->extra_properties ? 1 : 0;  
         
      
             57 
            		if ( ref $prop && !(exists $prop->{virtual} && $prop->{virtual}) ) {  
         
      
             58 
            			my $name = $prop->{attr};  
         
      
             59 
            			my $struct;  
         
      
             60 
            			if ( ref $object->$name ) {  
         
      
             61 
            				$struct = $object->$name;  
         
      
             62 
            			} elsif ( $object->$name ) {  
         
      
             63 
            				$struct = JSON::XS->new->utf8->decode( $object->$name );  
         
      
             64 
            			}  
         
      
             65 
            			if ( ref $struct eq 'ARRAY' && @$struct && !(grep { $_->{id} == $tag->id } @$struct) ) {  
         
      
             66 
            				push @$struct, { id => $tag->id, name => Encode::decode('utf-8', $tag->name) };  
         
      
             67 
            				unless ( $is_extra ) {  
         
      
             68 
            					$struct = Encode::encode('utf-8', JSON::XS->new->encode( $struct ));  
         
      
             69 
            				}  
         
      
             70 
            				$object->$name( $struct );  
         
      
             71 
            				$object->store;  
         
      
             72 
            			}  
         
      
             73 
            		}  
         
      
             74 
            	} else {  
         
      
             75 
            		warn "Tag Cloud update error: cloud_element_id=".$self->id.", no source or destination available\n";  
         
      
             76 
            	}  
         
      
             77 
            }  
         
      
             78 
             
         
      
             79 
            sub post_delete  
         
      
             80 
            {  
         
      
             81 
            	my $self = shift;  
         
      
             82 
            	my $object = $keeper->get_document_by_id($self->dest_id, class => $self->dest_class )		if $self->dest_id && $self->dest_class;  
         
      
             83 
            	my $tag = $self->keeper->get_document_by_id($self->source_id, class => $self->source_class )	if $self->source_id && $self->source_class;  
         
      
             84 
            	if ( ref $object && ref $tag ) {  
         
      
             85 
            		my ($prop) = grep { $_->{type} eq 'tagset' } $object->structure;  
         
      
             86 
            		my $class = $object->class;  
         
      
             87 
            		my $is_extra = grep { ref $_ && $_->{attr} eq $name } $class->extra_properties ? 1 : 0;  
         
      
             88 
            		if ( ref $prop && !(exists $prop->{virtual} && $prop->{virtual}) ) {  
         
      
             89 
            			my $name = $prop->{attr};  
         
      
             90 
            			my $struct;  
         
      
             91 
            			if ( ref $object->$name ) {  
         
      
             92 
            				$struct = $object->$name;  
         
      
             93 
            			} elsif ( $object->$name ) {  
         
      
             94 
            				$struct = JSON::XS->new->utf8->decode( $object->$name );  
         
      
             95 
            			}  
         
      
             96 
            			if ( ref $struct eq 'ARRAY' && @$struct && (grep { $_->{id} == $tag->id } @$struct) ) {  
         
      
             97 
            				@$struct = grep { $_->{id} != $tag->id } @$struct;  
         
      
             98 
            				unless ( $is_extra ) {  
         
      
             99 
            					$struct = Encode::encode('utf-8', JSON::XS->new->encode( $struct ));  
         
      
             100 
            				}  
         
      
             101 
            				$object->$name( $struct );  
         
      
             102 
            				$object->store;  
         
      
             103 
            			}  
         
      
             104 
            		}  
         
      
             105 
            	} else {  
         
      
             106 
            		warn "Tag Cloud delete error: cloud_element_id=".$self->id.", no source or destination available\n";  
         
      
             107 
            	}  
         
      
             108 
            }  
         
      
             109 
             
         
      
             110 
            1;  
          
   
      utf8/plugins/tag/lib/tag/Init.pm 
      
        
           
        
          
              
           
         
                              
      
             1 
            package tag::Init;  
         
      
             2 
             
         
      
             3 
            use strict;  
         
      
             4 
            use warnings 'all';  
         
      
             5 
             
         
      
             6 
            use Contenido::Globals;  
         
      
             7 
            use tag::Apache;  
         
      
             8 
            use tag::Keeper;  
         
      
             9 
            use tag::Section;  
         
      
             10 
            use tag::Tag;  
         
      
             11 
            use tag::Cloud;  
         
      
             12 
            use tag::SQL::TagsCloudTable;  
         
      
             13 
            use tag::SQL::TagsTable;  
         
      
             14 
             
         
      
             15 
            # загрузка всех необходимых плагину классов  
         
      
             16 
            # tag::SQL::SomeTable  
         
      
             17 
            # tag::SomeClass  
         
      
             18 
            Contenido::Init::load_classes(qw(  
         
      
             19 
            		tag::Section  
         
      
             20 
            		tag::Tag  
         
      
             21 
            		tag::Cloud  
         
      
             22 
            		tag::SQL::TagsCloudTable  
         
      
             23 
            		tag::SQL::TagsTable  
         
      
             24 
            	));  
         
      
             25 
             
         
      
             26 
            sub init {  
         
      
             27 
            	push @{ $state->{'available_documents'} },  
         
      
             28 
            		qw (  
         
      
             29 
            			tag::Tag  
         
      
             30 
            		);  
         
      
             31 
            	push @{ $state->{'available_sections'} },  
         
      
             32 
            		qw (  
         
      
             33 
            			tag::Section  
         
      
             34 
            		);  
         
      
             35 
            	push @{ $state->{'available_links'} },  
         
      
             36 
            		qw (  
         
      
             37 
            			tag::Cloud  
         
      
             38 
            		);  
         
      
             39 
            	0;  
         
      
             40 
            }  
         
      
             41 
             
         
      
             42 
            1;  
          
   
      utf8/plugins/tag/lib/tag/Keeper.pm 
      
        
           
        
          
              
           
         
                              
      
             1 
            package tag::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/tag/lib/tag/Section.pm 
      
        
           
        
          
              
           
         
                              
      
             1 
            package tag::Section;  
         
      
             2 
             
         
      
             3 
            use base 'Contenido::Section';  
         
      
             4 
             
         
      
             5 
            sub extra_properties  
         
      
             6 
            {  
         
      
             7 
            	return (  
         
      
             8 
            		{ 'attr' => 'default_document_class',			'default' => 'tag::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/tag/lib/tag/SQL/TagsCloudTable.pm 
      
        
           
        
          
              
           
         
                              
      
             1 
            package tag::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/tag/lib/tag/SQL/TagsTable.pm 
      
        
           
        
          
              
           
         
                              
      
             1 
            package tag::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/tag/lib/tag/State.pm.proto 
      
        
           
        
          
              
           
         
                              
      
             1 
            package tag::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_tag|';  
         
      
             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->{tag_destinations} =	[qw(@TAG_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 
            		tag_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 (tag::State): Вызов метода, для которого не существует обрабатываемого свойства: ->$attribute()\n";  
         
      
             119 
            		return;  
         
      
             120 
            	}  
         
      
             121 
             
         
      
             122 
            	$self->{$attribute} = shift @_ if $#_>=0;  
         
      
             123 
            	$self->{$attribute};  
         
      
             124 
            }  
         
      
             125 
             
         
      
             126 
            1;  
          
   
      utf8/plugins/tag/lib/tag/Tag.pm 
      
        
           
        
          
              
           
         
                              
      
             1 
            package tag::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 'tag::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 
            sub post_delete  
         
      
             44 
            {  
         
      
             45 
            	my $self = shift;  
         
      
             46 
             
         
      
             47 
            	my $links = $self->keeper->get_links(  
         
      
             48 
            			class   => 'tag::Cloud',  
         
      
             49 
            			source_id       => $self->id,  
         
      
             50 
            			return_mode	=> 'array_ref',  
         
      
             51 
            		);  
         
      
             52 
            	if ( ref $links eq 'ARRAY' &&  @$links ) {  
         
      
             53 
            		foreach my $link ( @$links ) {  
         
      
             54 
            			$link->delete;  
         
      
             55 
            		}  
         
      
             56 
            	}  
         
      
             57 
            }  
         
      
             58 
             
         
      
             59 
            1;  
          
   
      utf8/plugins/tag/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/tag/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);  
          
     
 
 
      
    
Небольшая справка по веткам 
cnddist  – контейнер, в котором хранятся все дистрибутивы всех библиотек и программных пакетов, которые использовались при построении различных версий Contenido. Если какой-то библиотеки в данном хранилище нет, инсталлятор сделает попытку "подтянуть" ее с веба (например, с CPAN). Если библиотека слишком старая, есть очень большая вероятность, что ее там уже нет. Поэтому мы храним весь хлам от всех сборок. Если какой-то дистрибутив вдруг отсутствует в cnddist - напишите нам, мы положим его туда.
koi8  – отмирающая ветка, чей код, выдача и все внутренние библиотеки заточены на кодировку KOI8-R. Вносятся только те дополнения, которые касаются внешнего вида и функционала админки, баги ядра, обязательные обновления портов и мелочи, которые легко скопипастить. В дальнейшем планируется полная остановка поддержки по данной ветке.
utf8  – актуальная ветка, заточенная под UTF-8.
Внутри каждой ветки: core  – исходники ядра; install  – скрипт установки инсталляции; plugins  – плагины; samples  – "готовые к употреблению" проекты, которые можно поставить, запустить и посмотреть, как они работают.