package comments; use strict; use warnings; no warnings 'redefine'; use Data::Dumper; use db(); use config(); use markup(); use template(); use time(); #use base 'Exporter'; our @EXPORT_OK = qw(init get_cached_or_render get modify_results render configure_cache get_query get_by_event get_level get_events check insert set_lock_status set_news_status lock update_comment_count sort); sub init() { } sub get_cached_or_render($$$;$) { # my $response=$_[0]; my $config = $_[1]; my $request = $_[2]; my $mark_locked = $_[3]; my $params = $request->{params}->{checked}; $config->{app_name} = $config->{controllers}->{comments}; my $comment = $request->{params}->{checked}; my $filename = ''; my $results = comments::get( $config, $request ); if ( ( defined $mark_locked ) && ( $mark_locked eq 'mark_locked' ) ) { for my $result (@$results) { if ( $result->{lock_status} ne 'show' ) { $result->{author} = 'Zensur'; $result->{content} = 'Dieser Eintrag wurde gelöscht.'; } } } elsif ( ( defined $mark_locked ) && ( $mark_locked eq 'filter_locked' ) ) { my @results2 = (); for my $result (@$results) { push @results2, $result if ( $result->{lock_status} eq 'show' ); } $results = \@results2; } comments::modify_results( $results, $config, $request ); $results = comments::sort( $config, $results ) if ( $comment->{type} eq 'tree' ); if ( ( $params->{show_max} ne '' ) && ( $params->{limit} ne '' ) && ( $params->{show_max} < $params->{limit} ) ) { my @results2 = (); my $c = 0; for my $result (@$results) { push @results2, $result; $c++; last if ( $c >= $params->{show_max} ); } $results = \@results2; } comments::render( $_[0], $config, $request, $results ); } sub get($$) { my $config = shift; my $request = shift; my $params = $request->{params}->{checked}; my $dbh = db::connect( $config, $request ); ( my $query, my $bind_values ) = comments::get_query( $dbh, $config, $request ); my $results = db::get( $dbh, $$query, $bind_values ); return $results; } sub get_query($$$) { my $dbh = shift; my $config = shift; my $request = shift; my $params = $request->{params}->{checked}; my $event_id = undef; my $event_start = undef; my $from = 'calcms_comments c'; my $where = ''; my $limit = ''; my @conditions = (); my $bind_values = []; #exclude comments from config filter/locations_to_exclude if ( ( defined $config->{filter} ) && ( defined $config->{filter}->{locations_to_exclude} ) ) { my @locations_to_exclude = split( /[,\s]+/, $config->{filter}->{locations_to_exclude} ); my $locations_to_exclude = join( ', ', map { '?' } @locations_to_exclude ); $from .= ',calcms_events e'; push @conditions, 'e.id=c.event_id'; push @conditions, 'e.location not in (' . $locations_to_exclude . ')'; for my $location (@locations_to_exclude) { push @$bind_values, $location; } } if ( ( defined $params->{event_id} && $params->{event_id} ne '' ) && ( defined $params->{event_start} && $params->{event_start} ne '' ) ) { #$where =qq{ and (event_id=? or event_start=?) }; push @conditions, q{ (event_id=? or event_start=?) }; push @$bind_values, $params->{event_id}; push @$bind_values, $params->{event_start}; } my $sort_order = $params->{sort_order}; if ( $params->{limit} ne '' ) { $limit = 'limit ?'; push @$bind_values, $params->{limit}; } if ( @conditions > 0 ) { $where = 'where ' . join( ' and ', @conditions ); } my $dbcols = [ 'id', 'event_start', 'event_id', 'content', 'ip', 'author', 'email', 'lock_status', 'created_at', 'title', 'parent_id', 'level', 'news_status', 'project' ]; my $cols = join( ', ', map { 'c.' . $_ } @$dbcols ); my $query = qq{ select $cols from $from $where order by created_at $sort_order $limit }; return ( \$query, $bind_values ); } sub modify_results($$$) { my $results = $_[0]; my $config = $_[1]; my $request = $_[2]; my $params = $request->{params}->{checked}; my $time_diff = ''; if ( $params->{template} =~ /\.xml/ ) { $time_diff = time::utc_offset( $config->{date}->{time_zone} ); $time_diff =~ s/(\d\d)(\d\d)/$1\:$2/g; } my $language = $config->{date}->{language} || 'en'; for my $result (@$results) { $result->{allow}->{new_comments} = 1 if ( $params->{allow}->{new_comments} ); $result->{start_date_name} = time::date_format( $config, $result->{created_at}, $language ); $result->{start_time_name} = time::time_format( $result->{created_at} ); my $comment_limit = 100; if ( length( $result->{content} ) > $comment_limit ) { $result->{short_content} = substr( $result->{content}, 0, $comment_limit ) . '...'; } else { $result->{short_content} = $result->{content}; } $result->{base_url} = $config->{locations}->{base_url}; $result->{cache_base_url} = $config->{cache}->{base_url}; if ( $params->{template} =~ /\.xml/ ) { # $result->{content} =~s/(\[\[.*?\]\])//gi; # $result->{content} =markup::plain_to_xml($result->{content}); # $result->{content} =$result->{html_content}; $result->{content} = markup::html_to_plain( $result->{html_content} ); $result->{short_content} = markup::html_to_plain( $result->{short_content} ); $result->{excerpt} = "lass dich ueberraschen" if ( defined $result->{excerpt} ) && ( $result->{excerpt} eq '' ); $result->{excerpt} = markup::html_to_plain( $result->{excerpt} ); $result->{title} = markup::html_to_plain( $result->{title} ); $result->{series_name} = markup::html_to_plain( $result->{series_name} ); $result->{program} = markup::html_to_plain( $result->{program} ); if ( defined $result->{created_at} ) { $result->{created_at} =~ s/ /T/gi; $result->{created_at} .= $time_diff; } if ( defined $result->{modified_at} ) { $result->{modified_at} =~ s/ /T/gi; $result->{modified_at} .= $time_diff; } } } return $results; } sub render($$$$) { # my $response =$_[0]; my $config = $_[1]; my $request = $_[2]; my $results = $_[3]; my $params = $request->{params}->{checked}; my %template_parameters = %$params; my $template_parameters = \%template_parameters; $template_parameters->{comments} = $results; $template_parameters->{comment_count} = scalar(@$results) + 0; $template_parameters->{one_result} = 1 if ( $template_parameters->{comment_count} == 1 ); $template_parameters->{allow}->{new_comments} = 1 if ( $params->{allow}->{new_comments} ); $template_parameters->{event_id} = $params->{event_id}; $template_parameters->{event_start} = $params->{event_start}; $template_parameters->{server_cache} = $config->{cache}->{server_cache} if ( $config->{cache}->{server_cache} ); $template_parameters->{use_client_cache} = $config->{cache}->{use_client_cache} if ( $config->{cache}->{use_client_cache} ); $template_parameters->{controllers} = $config->{controllers}; template::process( $config, $_[0], $params->{template}, $template_parameters ); } #check if comment exists already sub check ($$$) { my $dbh = shift; my $config = shift; my $comment = shift; my $query = qq{ select id from calcms_comments where ( event_start=? or event_id=? ) and parent_id=? and author=? and ip=? and content=? }; my $bind_values = [ $comment->{event_start}, $comment->{event_id}, $comment->{parent_id}, $comment->{author}, $comment->{ip}, $comment->{content} ]; my $comments = db::get( $dbh, $query, $bind_values ); my @comments = @$comments; return 0 if scalar @comments > 0; return 1; } #used for insert sub get_level($$$) { my $dbh = shift; my $config = shift; my $comment = shift; my $parent_id = $comment->{parent_id}; return 0 unless defined $parent_id; if ( $parent_id =~ /(\d+)/ ) { $parent_id = $1; } return 0 unless $parent_id =~ /^\d+$/; return 0 if $parent_id == 0; #get level from parent node my $query = qq{ select level from calcms_comments where ( event_start=? or event_id=? ) and id=? limit 1 }; my $bind_values = [ $comment->{event_start}, $comment->{event_id}, $parent_id ]; my $comments = db::get( $dbh, $query, $bind_values ); my @comments = @$comments; if ( scalar @comments > 0 ) { return $comments->[0]->{level} + 1; } return 0; } sub get_by_event($$$) { my $dbh = shift; my $config = shift; my $request = $_[0]; my $params = $request->{params}->{checked}->{comment}; my $event_id = undef; my $search = undef; my $where = ''; my $limit = ''; my $bind_values = []; if ( $params->{event_id} ne '' ) { $where = qq{ event_id=? }; $bind_values = [ $params->{event_id} ]; } if ( ( defined $params->{search} ) && ( $params->{search} ne '' ) ) { $search = '%' . $params->{search} . '%'; $where = qq{ (content like ?) or (email like ?) or (author like ?) or (ip like ?)}; $bind_values = [ $search, $search, $search, $search ]; } my $sort_order = $params->{sort_order} || 'desc'; if ( ( defined $params->{limit} ) && ( $params->{limit} ne '' ) ) { $limit = 'limit ?'; push @$bind_values, $params->{limit}; } my $query = qq{ select * from calcms_comments where $where order by created_at $sort_order $limit }; my $comments = db::get( $dbh, $query, $bind_values ); return $comments; } sub get_by_time($$$) { my $dbh = shift; my $config = shift; my $comment = shift; my $where = ''; my $bind_values = []; if ( $comment->{age} ne '' ) { $where = qq{ where event_id in ( select distinct event_id from calcms_comments where ( unix_timestamp(now()) - ? < unix_timestamp(created_at) ) ) }; $bind_values = [ $comment->{age} * 3600, ]; } elsif ( ( $comment->{from} ne '' ) && ( $comment->{till} ne '' ) ) { $where = qq{ where event_id in ( select distinct event_id from calcms_comments where created_at >= ? and created_at <= ? ) }; $bind_values = [ $comment->{from}, $comment->{till} ]; } my $query = qq{ select * from calcms_comments $where order by event_id, id }; my $comments = db::get( $dbh, $query, $bind_values ); return $comments; } sub get_events($$$$) { my $dbh = shift; my $config = shift; my $request = shift; my $comments = shift; my $params = $request->{params}->{checked}->{comment}; #get event_ids from comments my $event_ids = { map { $_->{event_id} => 1 } @$comments }; my @keys = keys %{$event_ids}; #get events from comment's event ids return [] if ( scalar @keys ) == 0; #my $quoted_event_ids=join "," ,(map {$dbh->quote($_)}(@keys)); my @bind_values = @keys; my $event_id_values = join ",", ( map { '?' } ( @keys ) ); my $query = qq{ select id, start, program, series_name, title, excerpt from calcms_events where id in ($event_id_values) }; my $events = db::get( $dbh, $query, \@bind_values ); #build lookup table for events by id my $events_by_id = {}; for my $event (@$events) { $events_by_id->{ $event->{id} } = $event; $event->{max_comment_id} = 0; } #add unassigned events # for my $event_id (@keys){ # if ($events_by_id->{$event_id}eq''){ # my $event={ # title => "not assigned", # max_comment_id => 0 # # }; # push @$events,$event; # $events_by_id->{$event_id}=$event; # } # } for my $comment (@$comments) { my $event_id = $comment->{event_id}; my $event = $events_by_id->{$event_id}; next unless defined $event; $event->{comment_count}++; push @{ $event->{comments} }, $comment; # if ($params->{event_id}ne''); $event->{max_comment_id} = $comment->{id} if $comment->{id} > $event->{max_comment_id}; for my $name ( keys %{ $config->{controllers} } ) { $comment->{ "controller_" . $name } = $config->{controllers}->{$name} || ''; # $event->{"controller_$name"}=$config->{controllers}->{$name}; } } my @sorted_events = reverse sort { $a->{max_comment_id} <=> $b->{max_comment_id} } @$events; return \@sorted_events; } sub insert ($$$) { my $dbh = shift; my $config = shift; my $comment = shift; $comment->{level} = comments::get_level( $dbh, $config, $comment ); my $entry = { event_start => $comment->{event_start}, event_id => $comment->{event_id}, parent_id => $comment->{parent_id}, level => $comment->{level}, title => $comment->{title}, content => $comment->{content}, author => $comment->{author}, email => $comment->{email}, ip => $comment->{ip} }; my $comment_id = db::insert( $dbh, 'calcms_comments', $entry ); return $comment_id; } sub set_lock_status ($$$) { my $dbh = shift; my $config = shift; my $comment = shift; my $id = $comment->{id}; my $lock_status = $comment->{set_lock_status}; my $query = qq{ update calcms_comments set lock_status = ? where id = ? }; my $bind_values = [ $lock_status, $id ]; db::put( $dbh, $query, $bind_values ); $query = qq{ select event_id from calcms_comments where id=? }; $bind_values = [$id]; my $comments = db::get( $dbh, $query, $bind_values ); if ( scalar @$comments > 0 ) { $comment->{event_id} = $comments->[0]->{event_id}; update_comment_count( $dbh, $config, $comment ); } } sub set_news_status($$$) { my $dbh = shift; my $config = shift; my $comment = shift; my $id = $comment->{id}; my $news_status = $comment->{set_news_status}; my $query = qq{ update calcms_comments set news_status= ? where id = ? }; my $bind_values = [ $news_status, $id ]; db::put( $dbh, $query, $bind_values ); } sub update_comment_count ($$$) { my $dbh = shift; my $config = shift; my $comment = shift; my $query = qq{ select count(id) count from calcms_comments where lock_status='show' and event_id=? }; my $bind_values = [ $comment->{event_id} ]; my $comments = db::get( $dbh, $query, $bind_values ); my $count = 0; $count = $comments->[0]->{count} if scalar @$comments > 0; $query = qq{ update calcms_events set comment_count=? where id=? }; $bind_values = [ $count, $comment->{event_id} ]; db::put( $dbh, $query, $bind_values ); } sub sort_childs { my $node = shift; my $nodes = shift; my $sorted_nodes = shift; #push node into list of sorted nodes push @{$sorted_nodes}, $node; #return if node is leaf return $sorted_nodes unless defined $node->{childs}; #process child nodes for my $child ( @{ $node->{childs} } ) { $sorted_nodes = sort_childs( $child, $nodes, $sorted_nodes ); } return $sorted_nodes; } #precondition: results are presorted by creation date (by sql) sub sort($$) { my $config = shift; my $results = shift; #define parent nodes my $nodes = {}; for my $node (@$results) { $nodes->{ $node->{id} } = $node; } my @root_nodes = (); for my $node (@$results) { #fill childs into parent nodes push @{ $nodes->{ $node->{parent_id} }->{childs} }, $node; #define root nodes push @root_nodes, $node if ( $node->{level} == 0 ); } #sort root nodes from newest to oldest my $sorted_nodes = []; for my $node (@root_nodes) { #for my $node (reverse @root_nodes){ sort_childs( $node, $nodes, $sorted_nodes ); } return $sorted_nodes; } sub check_params ($$) { my $config = shift; my $params = shift; my $comment = {}; $comment->{event_start} = ''; if ( ( defined $params->{event_start} ) && ( $params->{event_start} =~ /(\d\d\d\d\-\d\d\-\d\d[T ]\d\d\:\d\d)(\:\d\d)?/ ) ) { $comment->{event_start} = $1; } $comment->{sort_order} = 'desc'; $comment->{limit} = ''; if ( ( defined $params->{limit} ) && ( $params->{limit} =~ /(\d+)/ ) ) { $comment->{limit} = $1; } $comment->{show_max} = ''; if ( ( defined $params->{show_max} ) && ( $params->{show_max} =~ /(\d+)/ ) ) { $comment->{show_max} = $1; } if ( ( defined $params->{sort_order} ) && ( $params->{sort_order} eq 'asc' ) ) { $comment->{sort_order} = 'asc'; } $comment->{event_id} = ''; if ( ( defined $params->{event_id} ) && ( $params->{event_id} =~ /(\d+)/ ) ) { $comment->{event_id} = $1; } if ( ( defined $params->{parent_id} ) && ( $params->{parent_id} =~ /(\d+)/ ) ) { $comment->{parent_id} = $1; } if ( ( defined $params->{type} ) && ( $params->{type} eq 'list' ) ) { $comment->{type} = 'list'; } else { $comment->{type} = 'tree'; } my $debug = $params->{debug} || ''; if ( $debug =~ /([a-z\_\,]+)/ ) { $comment->{debug} = $1; } log::error( $config, 'missing parameter a' ) if ( defined $params->{limit} ) && ( $comment->{limit} eq '' ); log::error( $config, 'missing parameter b' ) if ( defined $params->{event_id} ) && ( $comment->{event_id} eq '' ); log::error( $config, 'missing parameter c' ) if ( defined $params->{event_start} ) && ( $comment->{event_start} eq '' ); my $delta_days = 1; if ( $comment->{event_start} ne '' ) { my $today = time::datetime_to_array( time::time_to_datetime() ); my $date = time::datetime_to_array( $comment->{event_start} ); $delta_days = time::days_between( $today, $date ); } if ( ( $delta_days > $config->{permissions}->{no_new_comments_before} ) || ( $delta_days < -1 * $config->{permissions}->{no_new_comments_after} ) ) { $comment->{allow}->{new_comments} = 0; } else { $comment->{allow}->{new_comments} = 1; } $comment->{template} = template::check( $config, $params->{template}, 'comments.html' ); return $comment; } #do not delete last line! 1;