package tag::Cloud; use base 'Contenido::Link'; use Contenido::Globals; use Data::Recursive::Encode; use Data::Dumper; use JSON::XS; sub class_name { return 'Тег к объекту'; } sub class_description { return 'Организация облака тегов'; } sub extra_properties { return ( ); } sub available_sources { return [ qw(tag::Tag) ]; } sub available_destinations { return $state->{tag}->tag_destinations; } sub class_table { return 'tag::SQL::TagsCloudTable'; } sub pre_store { my $self = shift; return 1; } sub post_store { my $self = shift; warn "Store tag cloud element\n" if $DEBUG; my $object = $keeper->get_document_by_id($self->dest_id, class => $self->dest_class ) if $self->dest_id && $self->dest_class; my $tag = $self->keeper->get_document_by_id($self->source_id, class => $self->source_class ) if $self->source_id && $self->source_class; if ( ref $object && ref $tag ) { my ($prop) = grep { $_->{type} eq 'tagset' } $object->structure; my $class = $object->class; my $is_extra = grep { ref $_ && $_->{attr} eq $name } $class->extra_properties ? 1 : 0; if ( ref $prop && !(exists $prop->{virtual} && $prop->{virtual}) ) { my $name = $prop->{attr}; my $struct; if ( ref $object->$name ) { $struct = $object->$name; } elsif ( $object->$name ) { $struct = JSON::XS->new->utf8->decode( $object->$name ); } if ( ref $struct eq 'ARRAY' && @$struct && !(grep { $_->{id} == $tag->id } @$struct) ) { push @$struct, { id => $tag->id, name => Encode::decode('utf-8', $tag->name) }; unless ( $is_extra ) { $struct = Encode::encode('utf-8', JSON::XS->new->encode( $struct )); } $object->$name( $struct ); $object->store; } } } else { warn "Tag Cloud update error: cloud_element_id=".$self->id.", no source or destination available\n"; } } sub post_delete { my $self = shift; my $object = $keeper->get_document_by_id($self->dest_id, class => $self->dest_class ) if $self->dest_id && $self->dest_class; my $tag = $self->keeper->get_document_by_id($self->source_id, class => $self->source_class ) if $self->source_id && $self->source_class; if ( ref $object && ref $tag ) { my ($prop) = grep { $_->{type} eq 'tagset' } $object->structure; my $class = $object->class; my $is_extra = grep { ref $_ && $_->{attr} eq $name } $class->extra_properties ? 1 : 0; if ( ref $prop && !(exists $prop->{virtual} && $prop->{virtual}) ) { my $name = $prop->{attr}; my $struct; if ( ref $object->$name ) { $struct = $object->$name; } elsif ( $object->$name ) { $struct = JSON::XS->new->utf8->decode( $object->$name ); } if ( ref $struct eq 'ARRAY' && @$struct && (grep { $_->{id} == $tag->id } @$struct) ) { @$struct = grep { $_->{id} != $tag->id } @$struct; unless ( $is_extra ) { $struct = Encode::encode('utf-8', JSON::XS->new->encode( $struct )); } $object->$name( $struct ); $object->store; } } } else { warn "Tag Cloud delete error: cloud_element_id=".$self->id.", no source or destination available\n"; } } 1;