The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.
package Yote::Util::Tag;
use strict;
use warnings;

use vars qw($VERSION);
$VERSION = '0.01';

#
# The tagging represents a namespace of tags to items.
#
#  Use
#    my $tagger = new Yote::Util::Tag();
#    $tagger->_add_tag( 'foo', $obj1, $obj2, $obj3 );
#

use base 'Yote::Obj';

sub _init {
    my $self = shift;
    $self->set_tag_to_items( {} );
    $self->set_item_to_tags( {} );
} #_init

#
# Returns list of items that have that tag.
#
sub _items_for_tag {
    my( $self, $tag, $paginate_start, $paginate_length ) = @_;
    return $self->paginate_hash( $self->{DATA}{ tag_to_items }, $paginate_length, $paginate_start );
} #_items_for_tag


#
# Returns list of items best associated with the tags.
#
sub _items_for_tags {

    my( $self, $args, $paginate_start, $paginate_length ) = @_;

    my $tags = $args->{tags};
    my $exclude = $args->{exclude_tags};

    my( %res, %scores );

    for my $tag (@$tags) {
	my $items = $self->_items_for_tag( $tag );
	for my $item ( @$items ) {
	    if( $exclude ) {
		next if grep { $self->_has_tag( $item, $_ ) } @$exclude;
	    } #if exclude
	    $res{$item} = $item;
	    $scores{$item}++;
	} #each item
    } #each tag
    my @res = sort { $scores{$b} <=> $scores{$a} } values %res;
    if( $paginate_length ) { 
	$paginate_start ||= 0;
	return [ @res[$paginate_start..($paginate_length+$paginate_start)] ];
    }
    return \@res;
} #_items_for_tags

sub _has_tag {
    my( $self, $tag ) = @_;
    return $self->_hash_has_key( 'item_to_tags', $tag );
} #_has_tag

#
# Ads the tag to the items in the list.
#
sub _add_tag {
    my( $self, $tag, @items ) = @_;

    for my $item (@items) {
	$self->_hash_insert( 'tag_to_items', $tag, $item );
	$self->_hash_insert( 'item_to_tags', $item->{ID}, $tag );
    }
} #_add_tag

#
# Removes the tag to the items in the list.
#
sub _remove_tag {
    my( $self, $tag, @items ) = @_;
    for my $item (@items) {
	my $hash = $self->_hash_fetch( 'item_to_tags', $item->{ID} );
	delete $hash->{ $tag };
    }
    $self->_hash_delete( 'tag_to_items', $tag );
} #_remove_tag

1;

__END__

=head1 AUTHOR

Eric Wolf

=head1 LICENSE AND COPYRIGHT

Copyright (C) 2011 Eric Wolf

This module is free software; it can be used under the same terms as perl
itself.

=cut