package events; use strict; use warnings; no warnings 'redefine'; use Data::Dumper; $Data::Dumper::Sortkeys=1; use MIME::Base64(); use Encode(); use Storable 'dclone'; use DBI(); use template(); use config(); use time(); use db(); use markup(); use log(); use project(); use studios(); our @EXPORT_OK = qw( init get_cached_or_render get modify_results get_query render get_running_event_id delete check_params configure_cache get_duration calc_dates get_keys add_recordings ); sub init { } sub get_cached_or_render($$$) { my ($response, $config, $request) = @_; my $params = $request->{params}->{checked}; my $results = events::get( $config, $request ); events::render( $response, $config, $request, $results ); return $response; } sub get_prev{ my ($config, $event) = @_; my $params = { till_date => time::check_date($event->{start}), till_time => time::check_time($event->{start}), archive => 'all', order => 'desc', limit => 1, exclude_locations => 1, exclude_projects => 1, }; my $request = { url => $ENV{QUERY_STRING}, params => { original => $params, checked => events::check_params( $config, $params ), } }; $request->{params}->{checked}->{stop_nav} = 1; my $results = events::get( $config, $request ); return $results->[0]; } sub get_next{ my ($config, $event) = @_; my $params = { from_date => time::check_date($event->{end}), from_time => time::check_time($event->{end}), archive => 'all', order => 'asc', limit => 1, exclude_locations => 1, exclude_projects => 1, }; my $request = { url => $ENV{QUERY_STRING}, params => { original => $params, checked => events::check_params( $config, $params ), }, }; $request->{params}->{checked}->{stop_nav} = 1; my $results = events::get( $config, $request ); return $results->[0]; } sub get($$); sub get($$) { my ($config, $request) = @_; my $dbh = db::connect( $config, $request ); ( my $query, my $bind_values ) = events::get_query( $dbh, $config, $request ); my $results = db::get( $dbh, $$query, $bind_values ); $results = events::add_recordings($dbh, $config, $request, $results) if $request->{params}->{checked}->{all_recordings}; $results = events::modify_results( $dbh, $config, $request, $results ); # get prev and next event if ( @$results==1 and !$request->{params}->{checked}->{stop_nav} #< prevent recursion! and my $event_id = $request->{params}->{original}->{event_id} ){ my $event = $results->[0]; $event->{prev_event_id} = (get_prev($config, $event)//{})->{event_id}; $event->{next_event_id} = (get_next($config, $event)//{})->{event_id}; } return $results; } sub modify_results ($$$$) { my ($dbh, $config, $request, $results) = @_; my $params = $request->{params}->{checked}; my $running_event_id = 0; my $projects = {}; my $studios = {}; my $time_diff = ''; if ( scalar @$results > 0 ) { $results->[0]->{__first__} = 1; $results->[-1]->{__last__} = 1; $running_event_id = events::get_running_event_id($dbh); } if ( ( defined $params->{template} ) && ( $params->{template} =~ /\.xml/ ) ) { $time_diff = time::utc_offset( $config->{date}->{time_zone} ); $time_diff =~ s/(\d\d)(\d\d)/$1\:$2/g; } my $previous_result = { start_date => '' }; my $counter = 1; for my $result (@$results) { if ( defined $params->{template} ) { if ( $params->{template} =~ /\.ics$/ ) { $result->{content_ical} = markup::plain_to_ical( $result->{content} ); $result->{title_ical} = markup::plain_to_ical( $result->{title} ); $result->{user_title_ical} = markup::plain_to_ical( $result->{user_title} ); $result->{excerpt_ical} = markup::plain_to_ical( $result->{excerpt} ); $result->{user_excerpt_ical} = markup::plain_to_ical( $result->{user_excerpt} ); $result->{series_name} = markup::plain_to_ical( $result->{series_name} ); $result->{created_at} =~ s/ /T/gi; $result->{created_at} =~ s/[\:\-]//gi; $result->{modified_at} =~ s/ /T/gi; $result->{modified_at} =~ s/[\:\-]//gi; } elsif ( $params->{template} =~ /\.atom\.xml/ ) { $result->{excerpt} = '' unless defined( $result->{excerpt} ); $result->{excerpt} = "lass dich ueberraschen" if ( $result->{excerpt} eq '' ); # $result->{excerpt} =markup::plain_to_xml($result->{excerpt}); # $result->{title} =markup::plain_to_xml($result->{title}); # $result->{series_name} =markup::plain_to_xml($result->{series_name}); # $result->{program} =markup::plain_to_xml($result->{program}); $result->{created_at} =~ s/ /T/gi; $result->{created_at} .= $time_diff; $result->{modified_at} =~ s/ /T/gi; $result->{modified_at} .= $time_diff; } elsif ( $params->{template} =~ /\.rss\.xml/ ) { $result->{excerpt} = '' unless defined( $result->{excerpt} ); $result->{excerpt} = "lass dich ueberraschen" if ( $result->{excerpt} eq '' ); $result->{modified_at} = time::datetime_to_rfc822( $result->{modified_at} ); if ( $result->{created_at} =~ /[1-9]/ ) { $result->{created_at} = time::datetime_to_rfc822( $result->{created_at} ); } else { $result->{created_at} = $result->{modified_at}; } } } $result->{series_name} ||= ''; $result->{series_name} = '' if $result->{series_name} eq '_single_'; $result->{rerun} = '' unless defined $result->{rerun}; $result->{title} = '' unless defined $result->{title}; if ( $result->{title} =~ /\#(\d+)([a-z])?\s*$/ ) { $result->{episode} = $1 unless defined $result->{episode}; $result->{rerun} = $2 || '' unless ( $result->{rerun} =~ /\d/ ); $result->{title} =~ s/\#\d+[a-z]?\s*$//; $result->{title} =~ s/\s+$//; } $result->{rerun} = '' if ( $result->{rerun} eq '0' ); if ( ( defined $result->{recurrence_count} ) && ( $result->{recurrence_count} > 0 ) ) { $result->{recurrence_count_alpha} = markup::base26( $result->{recurrence_count} + 1 ); $result->{recurrence_id} = $result->{recurrence}; } else { $result->{recurrence_count_alpha} = ''; $result->{recurrence_count} = ''; } # set title keys my $keys = get_keys($result); for my $key ( keys %$keys ) { $result->{$key} = $keys->{$key}; } $result = calc_dates( $config, $result, $params, $previous_result, $time_diff ); get_listen_key($config, $result) unless $params->{set_no_listen_keys}; $result->{event_uri} = ''; if ( ( defined $result->{program} ) && ( $result->{program} ne '' ) ) { $result->{event_uri} .= $result->{program}; $result->{event_uri} .= '-' if ( ( $result->{series_name} ne '' ) || ( $result->{title} ne '' ) ); } if ( ($result->{series_name}//'') ne '' ) { $result->{event_uri} .= $result->{series_name}; $result->{event_uri} .= '-' if ( $result->{title} ne '' ); } $result->{event_uri} .= $result->{title} if length $result->{title}; $result->{event_uri} =~ s/\#/Nr./g; $result->{event_uri} =~ s/\&/und/g; $result->{event_uri} =~ s/\//\%2f/g; $result->{event_uri} =~ s/[?]//g; $result->{rds_title} = $result->{event_uri}; $result->{rds_title} =~ s/[^a-zA-Z0-9\-]/\_/gi; $result->{rds_title} =~ s/\_{2,99}/\_/gi; $result->{rds_title} = substr( $result->{rds_title}, 0, 63 ); #$result->{event_id}=$result->{id}; $result->{base_url} = $request->{base_url}; $result->{base_domain} = $config->{locations}->{base_domain}; $result->{static_files_url} = $config->{locations}->{static_files_url}; $result->{source_base_url} = $config->{locations}->{source_base_url}; $result->{local_base_url} = $config->{locations}->{local_base_url}; $result->{widget_render_url}= $config->{locations}->{widget_render_url}; $result->{is_running} = 1 if $running_event_id && $result->{event_id} && $running_event_id eq $result->{event_id}; if (defined $result->{comment_count}){ $result->{one_comment} = 1 if ( $result->{comment_count} == 1 ); $result->{no_comment} = 1 if ( $result->{comment_count} == 0 ); } { my $url = $config->{locations}->{local_media_url} // ''; my $image = $result->{image}; my $conf = $config->{locations}; my $basic_url = "$url/images/"; if ( defined $result->{image} ) { $result->{thumb_url} = ($conf->{thumbs_url} // $basic_url) . $image; $result->{icon_url} = ($conf->{icons_url} // $basic_url) . $image; $result->{image_url} = ($conf->{images_url} // $basic_url) . $image; } if ( defined $result->{series_image} ) { $result->{series_thumb_url} = ($conf->{thumbs_url} // $basic_url) . $image; $result->{series_icon_url} = ($conf->{icons_url} // $basic_url) . $image; $result->{series_image_url} = ($conf->{images_url} // $basic_url) . $image; } } $result->{location_css} = $result->{location} || ''; $result->{location_css} = lc( $result->{location_css} ); $result->{location_css} =~ s/\.//g; $result->{location_css} =~ s/\s//g; $result->{ 'location_label_' . $result->{location_css} } = 1; # add project by name my $project_name = $result->{project}; if ( defined $project_name ) { #print STDERR "found project:$project_name\n"; unless ( defined $projects->{$project_name} ) { my $results = project::get( $config, { name => $project_name } ); $projects->{$project_name} = $results->[0] || {}; } my $project = $projects->{$project_name}; for my $key ( keys %$project ) { $result->{ 'project_' . $key } = $project->{$key}; } } else { printf STDERR "events::get - unknown project for event %s\n", $result->{id} // "undef"; } #if project_id is set add columns from project (cached) my $project_id = $result->{project_id}; if ( defined $project_id ) { unless ( defined $projects->{$project_id} ) { my $results = project::get( $config, { project_id => $project_id } ); $projects->{$project_id} = $results->[0] || {}; } my $project = $projects->{$project_id}; for my $key ( keys %$project ) { $result->{ 'project_' . $key } = $project->{$key}; } } #if studio_id is set add columns from studio (cached) my $studio_id = $result->{studio_id}; if ( defined $studio_id ) { unless ( defined $studios->{$studio_id} ) { my $results = studios::get( $config, { studio_id => $studio_id } ); $studios->{$studio_id} = $results->[0] || {}; } my $studio = $studios->{$studio_id}; for my $key ( keys %$studio ) { $result->{ 'studio_' . $key } = $studio->{$key}; } } for my $name ( keys %{ $config->{mapping}->{events} } ) { my $val = ''; if ( ( defined $name ) && ( defined $config->{mapping}->{events}->{$name} ) && ( defined $result->{$name} ) ) { $val = $config->{mapping}->{events}->{$name}->{ $result->{$name} } || ''; $result->{ $name . '_mapped' } = $val if ( $val ne '' ); } } $previous_result = $result; $result->{ 'counter_' . $counter } = 1; $counter++; if ( ( defined $params->{template} ) && ( $params->{template} =~ /(list|details)/ ) ) { if ( ( defined $result->{excerpt} ) && ( length( $result->{excerpt} ) > 250 ) ) { $result->{excerpt} = substr( $result->{excerpt}, 0, 250 ) . '...'; } if ( ( defined $result->{user_excerpt} ) && ( length( $result->{user_excerpt} ) > 250 ) ) { $result->{user_excerpt} = substr( $result->{user_excerpt}, 0, 250 ) . '...'; } } #build content if ( ( defined $params->{template} ) && ( $params->{template} =~ /\.html/ ) ) { $result->{html_content} = events::format($result, 'content') if defined $result->{content}; $result->{html_topic} = events::format($result, 'topic') if defined $result->{topic}; } #detect if images are in content or topic field my $image_in_text = 0; $image_in_text = 1 if ( defined $result->{content} ) && ( $result->{content} =~ /{topic} ) && ( $result->{topic} =~ /{no_image_in_text} = 1 if $image_in_text == 0; if ( ( defined $params->{template} ) && ( ( $params->{template} =~ /event_perl\.txt$/ ) || ( $params->{template} =~ /event_file_export\.txt$/ ) ) ) { for my $key ( keys %$result ) { $result->{$key} =~ s/\|/\\\|/g if defined $result->{$key}; } # $result->{content}='no'; } } # end for results add_recurrence_dates( $config, $results ); return $results; } sub format { my ($event, $field) = @_; if (($event->{content_format}//'') eq 'markdown'){ $event->{$field} = markup::markdown_to_html( $event->{$field} ); } else { $event->{$field} = markup::fix_line_ends( $event->{$field} ); $event->{$field} = markup::creole_to_html( $event->{$field} ); } return $event->{$field}; } sub add_recurrence_dates { my ($config, $results) = @_; # get unique list of recurrence ids from results my $recurrence_dates = {}; for my $result (@$results) { next unless defined $result->{recurrence}; next if $result->{recurrence} == 0; $recurrence_dates->{ $result->{recurrence} } = 0; } my @event_ids = keys %$recurrence_dates; return if @event_ids == 0; # query start date of recurrences my $conditions = []; my $bind_values = []; for my $id (@event_ids) { push @$conditions, '?'; push @$bind_values, $id; } $conditions = join( ',', @$conditions ); my $query = qq{ select id event_id, start from calcms_events where id in ($conditions) }; my $dbh = db::connect($config); my $events = db::get( $dbh, $query, $bind_values ); # store start dates by recurrence id for my $event (@$events) { $recurrence_dates->{ $event->{event_id} } = $event->{start}; } # set start dates to results my $language = $config->{date}->{language} || 'en'; for my $result (@$results) { next unless defined $result->{recurrence}; next if $result->{recurrence} == 0; my $rdate = $recurrence_dates->{ $result->{recurrence} }; if ($rdate){ $result->{recurrence_date} = $rdate; $result->{recurrence_date_name} = time::date_format( $config, $rdate, $language ); ( $result->{recurrence_time_name} ) = $rdate =~ m/(\d\d\:\d\d)\:\d\d/ ; my $ymd = time::date_to_array($rdate); my $weekdayIndex = time::weekday( $ymd->[0], $ymd->[1], $ymd->[2] ); $result->{recurrence_weekday_name} = time::getWeekdayNames($language)->[$weekdayIndex]; $result->{recurrence_weekday_short_name} = time::getWeekdayNamesShort($language)->[$weekdayIndex]; } } } sub calc_dates { my ($config, $result, $params, $previous_result, $time_diff) = @_; $params ||= {}; $previous_result ||= {}; $time_diff ||= ''; my $language = $config->{date}->{language} || 'en'; $result->{utc_offset} = $time_diff; $result->{time_zone} = $config->{date}->{time_zone}; $result->{start_datetime} = $result->{start} =~ s/ /T/r; $result->{end_datetime} = $result->{end} =~ s/ /T/r; $result->{dtstart} = $result->{start_datetime} =~ s/[:\-]//rg; $result->{dtend} = $result->{end_datetime} =~ s/[:\-]//gr; if ($result->{start_datetime} =~ /(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})/) { @{$result}{qw(start_year start_month start_day start_hour start_minute)} = ($1, $2, $3, $4, $5); } $result->{day} = time::datetime_to_array($result->{start})->[3] < 6 ? time::add_days_to_date($result->{start}, -1) : time::datetime_to_date($result->{start}) unless defined $result->{day}; $result->{start_date} ||= time::datetime_to_date($result->{start}); $result->{end_date} ||= time::datetime_to_date($result->{end}); $result->{start_utc_epoch} = time::datetime_to_utc($result->{start_datetime}, $config->{date}->{time_zone}); $result->{start_datetime_utc} = time::datetime_to_utc_datetime($result->{start_datetime}, $config->{date}->{time_zone}); $result->{end_utc_epoch} = time::datetime_to_utc($result->{end_datetime}, $config->{date}->{time_zone}); $result->{end_datetime_utc} = time::datetime_to_utc_datetime($result->{end_datetime}, $config->{date}->{time_zone}); if (defined $previous_result && defined $previous_result->{start_date} && $result->{start_date} ne $previous_result->{start_date}) { $result->{is_first_of_day} = 1; $previous_result->{is_last_of_day} = 1; } $result->{start_date_name} = time::date_format($config, $result->{start_date}, $language); $result->{end_date_name} = time::date_format($config, $result->{end_date}, $language); $result->{start_time} = $result->{start_time_name} = $1 if $result->{start} =~ /(\d{2}:\d{2}):\d{2}/; $result->{end_time} = $result->{end_time_name} = $1 if $result->{end} =~ /(\d{2}:\d{2}):\d{2}/; if (defined $result->{weekday}) { my $weekdayIndex = time::getWeekdayIndex($result->{weekday}) || 0; $result->{weekday_name} = time::getWeekdayNames($language)->[$weekdayIndex]; $result->{weekday_short_name} = time::getWeekdayNamesShort($language)->[$weekdayIndex]; } return $result; } sub get_listen_key($$){ my ($config, $event) =@_; my $time_zone = $config->{date}->{time_zone}; my $start = time::datetime_to_utc( $event->{start_datetime}, $time_zone ); my $now = time::datetime_to_utc( time::time_to_datetime( time() ), $time_zone); my $over_since = $now-$start; return if $over_since < 0; return if $over_since > 7*24*60*60; my $archive_dir = $config->{locations}->{local_archive_dir}; my $archive_url = $config->{locations}->{listen_url}; return $event->{listen_url} = $archive_url . '/' . $event->{listen_key} if defined $event->{listen_key} && -l $archive_dir .'/'. $event->{listen_key}; set_listen_key($config, $event) unless $event->{listen_key}; } sub set_listen_key{ my ($config, $event) =@_; my $archive_dir = $config->{locations}->{local_archive_dir}; my $archive_url = $config->{locations}->{listen_url}; my $datetime = $event->{start_datetime}; if ( $datetime =~ /(\d\d\d\d\-\d\d\-\d\d)[ T](\d\d)\:(\d\d)/ ) { $datetime = $1 . '\ ' . $2 . '_' . $3; } else { print STDERR "update_recording_link: no valid datetime found $datetime\n"; return; } my @files = glob( $archive_dir . '/' . $datetime . '*.mp3' ); return if @files <= 0; my $key = int( rand(99999999999999999) ); $key = MIME::Base64::encode_base64($key); $key =~ s/[^a-zA-Z0-9]//g; $key .='.mp3'; my $audio_file = Encode::decode( "UTF-8", $files[0] ); my $link = $archive_dir . '/' . $key; symlink $audio_file, $link or die "cannot create $link, $!"; $event->{listen_url} = $archive_url . '/' . $key; $event->{listen_key} = $key; return undef unless defined $event->{event_id}; return undef unless defined $event->{listen_key}; my $bindValues = [ $event->{listen_key}, $event->{event_id} ]; my $query = qq{ update calcms_events set listen_key=? where id=?; }; my $dbh = db::connect($config); my $recordings = db::put( $dbh, $query, $bindValues ); } sub set_upload_status($$){ my ($config, $event) = @_; for ('event_id', 'upload_status') { return undef unless defined $event->{$_} }; my $bindValues = [ $event->{upload_status}, $event->{event_id}, $event->{upload_status} ]; my $query = qq{ update calcms_events set upload_status=? where id=? and upload_status!=?; }; my $dbh = db::connect($config); my $recordings = db::put( $dbh, $query, $bindValues ); } sub add_recordings($$$$) { my ($dbh, $config, $request, $events) = @_; return $events unless defined $events; my $eventsById = { map { $_->{event_id} => $_ } @$events }; my $qms = join ', ', map { '?' } @$events; my $bindValues = [map {$_->{event_id}} @$events]; my $query = qq{ select * from calcms_audio_recordings where event_id in ($qms) order by created_at; }; $dbh = db::connect($config) unless defined $dbh; my $recordings = db::get( $dbh, $query, $bindValues ); push @{ $eventsById->{$_->{event_id}}->{recordings} }, $_ for @$recordings; return $events; } sub getDateQueryConditions ($$$) { my ($config, $params, $bind_values) = @_; # conditions by date my $date_conds = []; #date, today, tomorrow, yesterday my $date = ''; $date = time::date_cond( $params->{date} ) if $params->{date} ne ''; my $from_date = ''; $from_date = time::date_cond( $params->{from_date} ) if $params->{from_date} ne ''; my $till_date = ''; $till_date = time::date_cond( $params->{till_date} ) if $params->{till_date} ne ''; my $from_time = ''; $from_time = time::time_cond( $params->{from_time} ) if $params->{from_time} ne ''; my $till_time = ''; $till_time = time::time_cond( $params->{till_time} ) if $params->{till_time} ne ''; my $time = $params->{time}; $time = '' unless defined $time; my $date_range_include = $params->{date_range_include}; my $day_starting_hour = $config->{date}->{day_starting_hour}; if ( $date eq 'today' ) { my $date = time::get_event_date($config); push @$date_conds, ' ( start_date = ? ) '; push @$bind_values, $date; return $date_conds; } # given date my $start = time::datetime_cond( $date . 'T00:00:00' ); if ( $start ne '' ) { $start = time::add_hours_to_datetime( $start, $day_starting_hour ); my $end = time::add_hours_to_datetime( $start, 24 ); if ( $date_range_include eq '1' ) { push @$date_conds, ' end > ? '; push @$bind_values, $start; } else { push @$date_conds, ' start >= ? '; push @$bind_values, $start; } push @$date_conds, ' start < ? '; push @$bind_values, $end; return $date_conds; } if ( $time eq 'now' ) { push @$date_conds, qq{ ( ( unix_timestamp(end) > unix_timestamp(now() ) ) and ( unix_timestamp(start) <= unix_timestamp(now() ) ) ) }; return $date_conds; } if ( $time eq 'future' ) { push @$date_conds, qq{ ( ( unix_timestamp(end) > unix_timestamp(now() ) ) and ( unix_timestamp(end) - unix_timestamp(now() ) ) < 7*24*3600 ) }; return $date_conds; } #from_date and from_time is defined if ( ( $from_date ne '' ) && ( $from_time ne '' ) ) { my $datetime = time::datetime_cond( $from_date . 'T' . $from_time ); if ( $datetime ne '' ) { if ( $date_range_include eq '1' ) { push @$date_conds, ' end > ? '; push @$bind_values, $datetime; $from_date = ''; } else { push @$date_conds, ' start >= ? '; push @$bind_values, $datetime; $from_date = ''; } } } #till_date and till_time is defined if ( ( $till_date ne '' ) && ( $till_time ne '' ) ) { my $datetime = time::datetime_cond( $till_date . 'T' . $till_time ); if ( $datetime ne '' ) { push @$date_conds, ' start < ? '; push @$bind_values, $datetime; $till_date = ''; } } # after start of daily broadcast if ( ( $from_date ne '' ) && ( $from_time eq '' ) ) { my $start = time::datetime_cond( $from_date . 'T00:00:00' ); $start = time::add_hours_to_datetime( $start, $day_starting_hour ); if ( $date_range_include eq '1' ) { # end is after start push @$date_conds, ' ( end >= ? )'; push @$bind_values, $start; } else { push @$date_conds, ' ( start >= ? ) '; push @$bind_values, $start; } } # before end of daily broadcast if ( ( $till_date ne '' ) && ( $till_time eq '' ) ) { my $end = time::datetime_cond( $till_date . 'T00:00:00' ); $end = time::add_hours_to_datetime( $end, $day_starting_hour ); if ( $date_range_include eq '1' ) { # start is before end push @$date_conds, ' ( start <= ? )'; push @$bind_values, $end; } else { push @$date_conds, ' ( end <= ? ) '; push @$bind_values, $end; } } if ( $params->{weekday} ne '' ) { my $weekday = $params->{weekday}; $weekday += 1; $weekday -= 7 if ( $weekday > 7 ); push @$date_conds, ' (dayofweek(start)= ?) '; push @$bind_values, $weekday; } if ( $params->{last_days} ) { my $d = int $params->{last_days}; push @$date_conds, qq{ ( end between date_sub(now(),INTERVAL $d DAY) and now() ) }; } elsif ( $params->{archive} eq 'past' ) { my $date = time::get_event_date($config); if ( $date ne '' ) { push @$date_conds, ' ( start < ? ) '; push @$bind_values, $date; } } elsif ( $params->{archive} eq 'future' ) { my $date = time::get_event_date($config); if ( $date ne '' ) { push @$date_conds, ' ( end >= ? ) '; push @$bind_values, $date; } } return $date_conds; } # if "all_recordings" is set in params, all event recordings will be included # if "active_recording" is set in params, recordings date and path will be included sub get_query($$$) { my ($dbh, $config, $request) = @_; my $params = $request->{params}->{checked}; $params->{all_recordings} //= ''; $params->{active_recording} //= ''; $params->{only_active_recording} //= ''; my $bind_values = []; my $where_cond = []; my $order_cond = ''; my $limit_cond = ''; if ( $params->{event_id} ne '' ) { # conditions by event id push @$where_cond, 'e.id=?'; $bind_values = [ $params->{event_id} ]; #filter by published, default=1 to see published only, set published='all' to see all my $published = $params->{published} || '1'; if ( ( $published eq '0' ) || ( $published eq '1' ) ) { push @$where_cond, 'published=?'; push @$bind_values, $published; } my $draft = $params->{draft} || '0'; if ( ( $draft eq '0' ) || ( $draft eq '1' ) ) { push @$where_cond, 'draft=?'; push @$bind_values, $draft; } } else { my $date_conds = getDateQueryConditions( $config, $params, $bind_values ); my $date_cond = join " and ", @$date_conds; push @$where_cond, $date_cond if ( $date_cond ne '' ); } # location my $location_cond = ''; if ( $params->{location} ne '' ) { my $location = ( split( /\,/, $params->{location} ) )[0]; $location =~ s/[^a-zA-Z0-9\-\_]/%/g; $location =~ s/%{2,99}/%/g; if ( $location ne '' ) { $location_cond = ' location like ? '; push @$bind_values, $location; } } # exclude location my $exclude_location_cond = ''; if ( $params->{exclude_locations} eq '1' ) { if ( $params->{locations_to_exclude} ne '' ) { my @locations_to_exclude = split( /,/, $params->{locations_to_exclude} ); $exclude_location_cond = 'location not in (' . join( ",", map { '?' } @locations_to_exclude ) . ')'; for my $location (@locations_to_exclude) { $location =~ s/^\s+//g; $location =~ s/\s+$//g; push @$bind_values, $location; } } } # exclude project my $exclude_project_cond = ''; if ( $params->{exclude_projects} eq '1' ) { if ( $params->{projects_to_exclude} ne '' ) { my @projects_to_exclude = split( /,/, $params->{projects_to_exclude} ); $exclude_project_cond = 'project not in (' . join( ",", map { '?' } @projects_to_exclude ) . ')'; for my $project (@projects_to_exclude) { $project =~ s/^\s+//g; $project =~ s/\s+$//g; push @$bind_values, $project; } } } my $series_name_cond = ''; if ( ( defined $params->{series_name} ) && ( $params->{series_name} ne '' ) ) { my $series_name = ( split( /\,/, $params->{series_name} ) )[0]; $series_name =~ s/[^a-zA-Z0-9]/%/g; $series_name =~ s/%{2,99}/%/g; if ( $series_name ne '' ) { $series_name_cond = ' series_name like ? '; push @$bind_values, $series_name; } } #filter for tags my $tag_cond = ''; if ( ( defined $params->{tag} ) && ( $params->{tag} ne '' ) ) { my @tags = ( split( /\,/, $params->{tag} ) ); if ( scalar @tags > 0 ) { my $tags = join ",", ( map { '?' } @tags ); for my $tag (@tags) { push @$bind_values, $tag; } $tag_cond = qq{ id in( select event_id from calcms_tags where name in($tags) ) }; } } $tag_cond = ''; my $title_cond = ''; if ( ( defined $params->{title} ) && ( $params->{title} ne '' ) ) { my $title = ( split( /\,/, $params->{title} ) )[0]; $title =~ s/[^a-zA-Z0-9]/%/g; $title =~ s/%{2,99}/%/g; $title =~ s/^\%//; $title =~ s/\%$//; $title = '%' . $title . '%'; if ( $title ne '' ) { $title_cond = ' title like ? '; push @$bind_values, $title; } } my $search_cond = ''; if ( ( defined $params->{search} ) && ( $params->{search} ne '' ) ) { my $search = lc $params->{search}; $search =~ s/(?=[\\%_])/\\/g; $search =~ s/^[\%\s]+//; $search =~ s/[\%\s]+$//; if ( $search ne '' ) { $search = '%' . $search . '%'; my @attr = ( 'title', 'series_name', 'excerpt', 'content', 'topic' ); $search_cond = "(" . join( " or ", map { 'lower(' . $_ . ') like ?' } @attr ) . ")"; for my $attr (@attr) { push @$bind_values, $search; } } } my $project_cond = ''; my $project = undef; $project = $params->{project} if ( defined $params->{project} ) && ( $params->{project} ne '' ); my $project_name = ''; $project_name = $project->{name} if ( defined $project ) && ( defined $project->{name} ) && ( $project->{name} ne '' ); if ( ( $project_name ne '' ) && ( $project_name ne 'all' ) ) { $project_cond = '(project=?)'; push @$bind_values, $project_name; } #filter by published, default =1, set to 'all' to see all my $published_cond = ''; my $published = $params->{published} || '1'; if ( ( $published eq '0' ) || ( $published eq '1' ) ) { $published_cond = 'published=?'; push @$bind_values, $published; } #filter by draft, default =1, set to 'all' to see all my $draft_cond = ''; my $draft = $params->{draft} || '0'; if ( ( $draft eq '0' ) || ( $draft eq '1' ) ) { $draft_cond = 'draft=?'; push @$bind_values, $draft; } my $disable_event_sync_cond = ''; my $disable_event_sync = $params->{disable_event_sync} || ''; if ( ( $disable_event_sync eq '0' ) || ( $disable_event_sync eq '1' ) ) { $disable_event_sync_cond = 'disable_event_sync=?'; push @$bind_values, $disable_event_sync; } #print STDERR $disable_event_sync_cond." ".$bind_values->[-1]."\n"; #combine date, location, series_name, tag, search and project push @$where_cond, $location_cond if ( $location_cond =~ /\S/ ); push @$where_cond, $exclude_location_cond if ( $exclude_location_cond =~ /\S/ ); push @$where_cond, $exclude_project_cond if ( $exclude_project_cond =~ /\S/ ); push @$where_cond, $series_name_cond if ( $series_name_cond =~ /\S/ ); push @$where_cond, $tag_cond if ( $tag_cond =~ /\S/ ); push @$where_cond, $title_cond if ( $title_cond =~ /\S/ ); push @$where_cond, $search_cond if ( $search_cond =~ /\S/ ); push @$where_cond, $project_cond if ( $project_cond =~ /\S/ ); push @$where_cond, $published_cond if ( $published_cond =~ /\S/ ); push @$where_cond, $draft_cond if ( $draft_cond =~ /\S/ ); push @$where_cond, $disable_event_sync_cond if ( $disable_event_sync_cond ne '' ); #order is forced if ( $params->{order} eq 'asc' ) { $order_cond = 'order by start'; } elsif ( $params->{order} eq 'desc' ) { $order_cond = 'order by start desc'; } else { #derivate order from archive flag if ( $params->{archive} eq 'past' ) { $order_cond = 'order by start desc'; } else { $order_cond = 'order by start'; } } if ( ( defined $params->{limit} ne '' ) && ( $params->{limit} ne '' ) ) { $limit_cond = 'limit ' . $params->{limit}; } my $query = qq{ select date(e.start) start_date ,date(e.end) end_date ,weekday(e.start) weekday ,weekofyear(e.start) week_of_year ,dayofyear(e.start) day_of_year ,e.start_date day ,e.id event_id ,e.start ,e.end ,TIMEDIFF(e.end,e.start) duration ,e.program ,e.series_name ,e.title ,e.modified_at ,e.created_at ,e.modified_by ,e.comment_count ,e.image ,e.image_label ,e.series_image ,e.series_image_label ,e.reference ,e.recurrence ,e.recurrence_count ,e.podcast_url ,e.archive_url ,e.media_url ,e.status ,e.location ,e.project ,e.user_title ,e.user_excerpt ,e.published ,e.draft ,e.playout ,e.archived ,e.rerun ,e.live ,e.disable_event_sync ,e.episode ,e.listen_key ,e.upload_status ,e.content_format }; my $template = $params->{template} || ''; $query .= ',e.excerpt' unless ( $template =~ /menu/ ); # $query.=',e.project' unless ($template=~/menu/ || $template=~/list/); my $get = $params->{get} || ''; unless ( $get eq 'no_content' ) { unless ( $template =~ /menu/ || $template =~ /list/ ) { $query .= ', e.content, e.topic, e.html_content, e.html_topic'; } } # add project id and series id if ( ( $params->{project_id} ne '' ) || ( $params->{studio_id} ne '' ) ) { if ( $params->{project_id} ne '' ) { push @$where_cond, 'se.project_id=?'; push @$bind_values, $params->{project_id}; $query .= ', se.project_id'; } if ( $params->{studio_id} ne '' ) { push @$where_cond, 'se.studio_id=?'; push @$bind_values, $params->{studio_id}; $query .= ', se.studio_id'; } #push @$where_cond, 'se.event_id=e.id'; } # add recordings field and conditions if ( $params->{active_recording} || $params->{only_active_recording} ) { $query .= ', ar.path'; $query .= ', ar.size'; $query .= ', ar.created_by uploaded_by'; $query .= ', ar.modified_at uploaded_at'; } $query .= "\n from"; # add tables if ( ( $params->{project_id} ne '' ) || ( $params->{studio_id} ne '' ) ) { # prepent series_events $query .= "\n calcms_series_events se inner join calcms_events e on se.event_id=e.id"; } else { $query .= "\n calcms_events e"; } # add recordings table if ( $params->{active_recording} || $params->{only_active_recording}) { my $type = $params->{only_active_recording} ? 'inner' : 'left'; $query .= "\n $type join calcms_audio_recordings ar on e.id=ar.event_id and ar.active=1"; } if ( scalar @$where_cond > 0 ) { $query .= "\nwhere " . join( ' and ', @$where_cond ); } $query .= "\n" . $order_cond if ( $order_cond ne '' ); $query .= "\n" . $limit_cond if ( $limit_cond ne '' ); return ( \$query, $bind_values ); } sub render($$$$;$) { my ($response, $config, $request, $results, $root_params) = @_; my $params = $request->{params}->{checked}; if ( ref($root_params) eq 'HASH' ) { for my $param ( keys %$root_params ) { $params->{$param} = $root_params->{$param}; } } my %tparams = %$params; my $tparams = \%tparams; $tparams->{events} = $results; if ( scalar @$results > 0 ) { my $result = $results->[0]; $tparams->{event_id} = $result->{event_id}; $tparams->{event_dtstart} = $result->{dtstart}; $tparams->{first_date} = $results->[0]->{start_date}; $tparams->{last_date} = $results->[-1]->{start_date}; } # $tparams->{print} =1 if ($params->{print} eq '1'); $tparams->{base_url} = $config->{locations}->{base_url}; $tparams->{base_domain} = $config->{locations}->{base_domain}; $tparams->{local_base_url} = $config->{locations}->{local_base_url}; $tparams->{widget_render_url} = $config->{locations}->{widget_render_url}; $tparams->{modified_at} = time::time_to_datetime( time() ); if ( ( defined $params->{template} ) && ( $params->{template} =~ /(\.xml)/ ) ) { $tparams->{modified_at_datetime_utc} = time::datetime_to_utc_datetime( $tparams->{modified_at}, $config->{date}->{time_zone} ); } #$tparams->{tags} = $tags; if ( scalar @$results == 0 ) { if ( ( $params->{search} ne '' ) || ( $params->{series_name} ne '' ) ) { $tparams->{no_search_result} = '1'; } else { $tparams->{no_result} = '1'; } } else { if ( ( !defined $params->{event_id} ) || ( $params->{event_id} eq '' ) ) { $tparams->{event_count} = scalar @$results . ''; $tparams->{first_of_list} = $results->[0]->{event_id}; } my $start = $results->[0]->{start_datetime} || ''; if ( $start =~ /(\d{4}\-\d{2})/ ) { $tparams->{month} = $1; } } my $time_diff = time::utc_offset( $config->{date}->{time_zone} ); $time_diff =~ s/(\d\d)(\d\d)/$1\:$2/g; $tparams->{time_zone} = $config->{date}->{time_zone}; $tparams->{utc_offset} = $time_diff; if ( $params->{template} =~ /\.atom\.xml/ ) { $tparams->{modified_at} =~ s/ /T/gi; $tparams->{modified_at} .= $time_diff; } elsif ( $params->{template} =~ /\.rss\.xml/ ) { $tparams->{modified_at} = time::datetime_to_rfc822( $tparams->{modified_at} ); } elsif ( $params->{template} =~ /\.txt/ ) { $tparams->{modified_at_utc} = time::datetime_to_utc( $tparams->{modified_at}, $config->{date}->{time_zone} ); } my $project = $params->{default_project}; foreach my $key ( keys %$project ) { $tparams->{ 'project_' . $key } = $project->{$key}; } $tparams->{ 'project_' . $project->{name} } = 1 if ( $project->{name} ne '' ); $tparams->{controllers} = $config->{controllers}; $tparams->{hide_event_images} = 1 if ( defined $config->{permissions}->{hide_event_images} ) && ( $config->{permissions}->{hide_event_images} == 1 ); for my $attr (qw(no_result events_title events_description)){ $tparams->{$attr} = $config->{$attr}; } template::process( $config, $_[0], $params->{template}, $tparams ); return $_[0]; } sub get_running_event_id($) { my ($dbh) = @_; my $query = qq{ select id event_id, start, title from calcms_events where ( ( unix_timestamp(start) <= unix_timestamp(now() ) ) and ( unix_timestamp(end) > unix_timestamp(now() ) ) and ( unix_timestamp(end) - unix_timestamp(now() ) ) < 24*3600 ) order by start limit 1 }; my $running_events = db::get( $dbh, $query ); my @running_events = @$running_events; return $running_events->[0]->{event_id} if ( scalar @running_events > 0 ); return 0; } # add filters to query sub setDefaultEventConditions ($$$$) { my ($config, $conditions, $bind_values, $options) = @_; $options = {} unless defined $options; # exclude projects if ( ( defined $options->{exclude_projects} ) && ( $options->{exclude_projects} == 1 ) && ( defined $config->{filter} ) && ( defined $config->{filter}->{projects_to_exclude} ) ) { my @projects_to_exclude = split( /,/, $config->{filter}->{projects_to_exclude} ); push @$conditions, 'project not in (' . join( ",", map { '?' } @projects_to_exclude ) . ')'; for my $project (@projects_to_exclude) { push @$bind_values, $project; } } # exclude locations if ( ( defined $options->{exclude_locations} ) && ( $options->{exclude_locations} == 1 ) && ( defined $config->{filter} ) && ( defined $config->{filter}->{locations_to_exclude} ) ) { my @locations_to_exclude = split( /,/, $config->{filter}->{locations_to_exclude} ); push @$conditions, 'location not in (' . join( ",", map { '?' } @locations_to_exclude ) . ')'; for my $location (@locations_to_exclude) { push @$bind_values, $location; } } } # for local use only or add support for exclude_projects and exclude_locations sub getEventById ($$$$) { my ($dbh, $config, $event_id, $options) = @_; $dbh = db::connect($config) unless defined $dbh; my $conditions = []; my $bind_values = []; push @$conditions, "id=?"; push @$bind_values, $event_id; setDefaultEventConditions( $config, $conditions, $bind_values, $options ); $conditions = join( ' and ', @$conditions ); my $query = qq{ select * from calcms_events where $conditions }; my $events = db::get( $dbh, $query, $bind_values ); return $events; } sub get_next_event_of_series ($$$) { my ($dbh, $config, $options) = @_; my $eventId = $options->{event_id}; return undef unless defined $eventId; $dbh = db::connect($config) unless defined $dbh; my $events = getEventById( $dbh, $config, $eventId, $options ); return undef unless scalar(@$events) == 1; my $event = $events->[0]; my $conditions = []; my $bind_values = []; push @$conditions, "start>?"; push @$bind_values, $event->{start}; push @$conditions, "series_name=?"; push @$bind_values, $event->{series_name}; setDefaultEventConditions( $config, $conditions, $bind_values, $options ); $conditions = join( ' and ', @$conditions ); my $query = qq{ select id from calcms_events where $conditions order by start limit 1 }; $events = db::get( $dbh, $query, $bind_values ); return undef unless scalar @$events == 1; return $events->[0]->{id}; } sub get_previous_event_of_series($$$) { my ($dbh, $config, $options) = @_; my $eventId = $options->{event_id}; return undef unless defined $eventId; $dbh = db::connect($config) unless defined $dbh; my $events = getEventById( $dbh, $config, $eventId, $options ); return undef unless scalar(@$events) == 1; my $event = $events->[0]; my $conditions = []; my $bind_values = []; push @$conditions, "start{start}; push @$conditions, "series_name=?"; push @$bind_values, $event->{series_name}; setDefaultEventConditions( $config, $conditions, $bind_values, $options ); $conditions = join( ' and ', @$conditions ); my $query = qq{ select id from calcms_events where $conditions order by start desc limit 1 }; $events = db::get( $dbh, $query, $bind_values ); return undef unless scalar(@$events) == 1; return $events->[0]->{id}; } # used by calendar sub get_by_date_range ($$$$$) { my ($dbh, $config, $start_date, $end_date, $options) = @_; my $day_starting_hour = $config->{date}->{day_starting_hour}; my $start = time::datetime_cond( $start_date . 'T00:00:00' ); $start = time::add_hours_to_datetime( $start, $day_starting_hour ); my $end = time::datetime_cond( $end_date . 'T00:00:00' ); $end = time::add_hours_to_datetime( $end, $day_starting_hour ); my $conditions = []; push @$conditions, 'published = 1'; push @$conditions, 'start between ? and ?'; my $bind_values = [ $start, $end ]; setDefaultEventConditions( $config, $conditions, $bind_values, $options ); $conditions = join( ' and ', @$conditions ); my $select = qq{distinct date(start) 'start_date'}; $select = qq{distinct date(DATE_SUB(start, INTERVAL $day_starting_hour HOUR)) 'start_date'} if defined $day_starting_hour; my $query = qq{ select $select from calcms_events where $conditions }; my $events = db::get( $dbh, $query, $bind_values ); return $events; } sub get_by_image ($$$) { my ($dbh, $config, $filename) = @_; my $query = qq{ select * from calcms_events where content like ? order by start desc limit 1 }; my $bind_values = [ '%' . $filename . '%' ]; my $events = db::get( $dbh, $query, $bind_values ); return undef if scalar @$events == 0; return $events->[0]; } # deleting an event is currently disabled sub delete ($$$) { return; my ($request, $config, $event_id) = @_; my $params = $request->{params}->{checked}; my $dbh = db::connect($config); my $query = 'delete from calcms_events where id=?'; db::put( $dbh, $query, [$event_id] ); $query = 'delete from calcms_categories where id=?'; db::put( $dbh, $query, [$event_id] ); $query = 'delete from calcms_tags where id=?'; db::put( $dbh, $query, [$event_id] ); $query = 'delete from calcms_series_events where event_id=?'; db::put( $dbh, $query, [$event_id] ); } sub get_duration ($$) { my ($config, $event) = @_; my $timezone = $config->{date}->{time_zone}; my $start = time::get_datetime( $event->{start}, $timezone ); my $end = time::get_datetime( $event->{end}, $timezone ); #my $seconds = $end->subtract($start)->in_units("minutes"); #return $seconds; return undef unless defined $start; return undef unless defined $end; my $duration = $end->epoch() - $start->epoch(); #print STDERR "duration=$duration, end=".$end->datetime()." start=".$start->datetime()."\n"; return $duration / 60; } sub check_params ($$) { my ($config, $params) = @_; #define running at my $running_at = $params->{running_at} || ''; if ( ( defined $running_at ) && ( $running_at ne '' ) ) { my $run_date = time::check_date($running_at); my $run_time = time::check_time($running_at); if ( ( $run_date ne '' ) && ( $run_time ne '' ) ) { $params->{till_date} = $run_date; $params->{till_time} = $run_time; $params->{order} = 'asc'; $params->{limit} = 1; $params->{archive} = 'all'; } } #set time my $time = time::check_time( $params->{time} ); my $from_time = time::check_time( $params->{from_time} ); my $till_time = time::check_time( $params->{till_time} ); #set date my $date = ''; my $from_date = time::check_date( $params->{from_date} ); my $till_date = time::check_date( $params->{till_date} ); if ( ( $from_date eq '' ) && ( $till_date eq '' ) ) { $date = time::check_date( $params->{date} ); } #set date interval (including) my $date_range_include = 0; $date_range_include = 1 if ( defined $params->{date_range_include} ) && ( $params->{date_range_include} eq '1' ); my $order = ''; if ( defined $params->{order} ) { $order = 'desc' if ( $params->{order} eq 'desc' ); $order = 'asc' if ( $params->{order} eq 'asc' ); } my $weekday = $params->{weekday} || ''; if ( ( defined $weekday ) && ( $weekday ne '' ) ) { if ( $weekday =~ /\d/ ) { $weekday = int($weekday); log::error( $config, 'invalid weekday' ) if ( $weekday < 1 || $weekday > 7 ); } else { log::error( $config, 'invalid weekday' ); } } my $tag = $params->{tag} || ''; if ( ( defined $tag ) && ( $tag ne '' ) ) { log::error( $config, "invalid tag" ) if ( $tag =~ /\s/ ); log::error( $config, "invalid tag" ) if ( $tag =~ /\;/ ); $tag =~ s/\'//gi; } my $series_name = $params->{series_name} || ''; if ( ( defined $series_name ) && ( $series_name ne '' ) ) { log::error( $config, "invalid series_name" ) if ( $series_name =~ /\;/ ); $series_name =~ s/^\s+//gi; $series_name =~ s/\s+$//gi; $series_name =~ s/\'//gi; } my $title = $params->{title} || ''; if ( ( defined $title ) && ( $title ne '' ) ) { log::error( $config, "invalid title" ) if ( $title =~ /\;/ ); $title =~ s/^\s+//gi; $title =~ s/\s+$//gi; $title =~ s/\'//gi; } my $location = $params->{location} || ''; if ( ( defined $location ) && ( $location ne '' ) ) { log::error( $config, "invalid location" ) if ( $location =~ /\;/ ); $location =~ s/^\s+//gi; $location =~ s/\s+$//gi; $location =~ s/\'//gi; } #if no location is set, use exclude location filter from default config my $locations_to_exclude = ''; if ( ( $location eq '' ) && ( defined $config->{filter} ) && ( defined $config->{filter}->{locations_to_exclude} ) ) { $locations_to_exclude = $config->{filter}->{locations_to_exclude} || ''; $locations_to_exclude =~ s/\s+/ /g; } my $projects_to_exclude = ''; if ( ( defined $config->{filter} ) && ( defined $config->{filter}->{projects_to_exclude} ) ) { $projects_to_exclude = $config->{filter}->{projects_to_exclude} || ''; $projects_to_exclude =~ s/\s+/ /g; } #enable exclude locations filter my $exclude_locations = 0; $exclude_locations = 1 if ( defined $params->{exclude_locations} ) && ( $params->{exclude_locations} eq '1' ); my $exclude_projects = 0; $exclude_projects = 1 if ( defined $params->{exclude_projects} ) && ( $params->{exclude_projects} eq '1' ); my $exclude_event_images = 0; $exclude_event_images = 1 if ( defined $params->{exclude_event_images} ) && ( $params->{exclude_event_images} eq '1' ); #show future events by default my $archive = 'future'; if ( defined $params->{archive} ) { $archive = 'all' if ( $params->{archive} eq 'all' ); $archive = 'past' if ( $params->{archive} eq 'gone' ); $archive = 'future' if ( $params->{archive} eq 'coming' ); } my $last_days = defined $params->{last_days} ? int($params->{last_days}) : 0; my $disable_event_sync = ''; if ( ( defined $params->{disable_event_sync} ) && ( $params->{disable_event_sync} =~ /([01])/ ) ) { $disable_event_sync = $1; } #show all on defined timespans if ( ( $from_date ne '' ) && ( $till_date ne '' ) ) { $archive = 'all'; } my $event_id = $params->{event_id} || ''; if ( ( defined $event_id ) && ( $event_id ne '' ) ) { if ( $event_id =~ /(\d+)/ ) { $event_id = $1; } else { log::error( $config, "invalid event_id" ); } } my $get = 'all'; $get = 'no_content' if ( defined $params->{get} ) && ( $params->{get} eq 'no_content' ); my $search = $params->{search} || ''; if ( ( defined $search ) && ( $search ne '' ) ) { $search = substr( $search, 0, 100 ); $search =~ s/^\s+//gi; $search =~ s/\s+$//gi; } #print STDERR $params->{template}."\n"; my $template = '.html'; if ( ($params->{template}//'') eq 'no' ) { $template = 'no'; } elsif ( ($params->{template}//'') eq 'html' ) { $template = 'html'; } else { $template = template::check( $config, $params->{template}, 'event_list.html' ); } my $limit_config = $config->{permissions}->{result_limit} || 100; my $limit = $params->{limit} || $limit_config; log::error( $config, 'invalid limit!' ) if ( $limit =~ /\D/ ); $limit = $limit_config if ( $limit_config < $limit ); #read project from configuration file my $project_name = $config->{project} || ''; log::error( $config, 'no default project configured' ) if ( $project_name eq '' ); #get default project my $default_project = undef; my $projects = project::get( $config, { name => $project_name } ); log::error( $config, "no configuration found for project '$project_name'" ) unless ( scalar(@$projects) == 1 ); $default_project = $projects->[0]; # get project from parameter (by name) my $project = ''; if ( ( defined $params->{project} ) && ( $params->{project} =~ /\w+/ ) && ( $params->{project} ne 'all' ) ) { my $project_name = $params->{project}; my $projects = project::get( $config, { name => $project_name } ); log::error( $config, 'invalid project ' . $project_name ) unless scalar(@$projects) == 1; $project = $projects->[0]; } $project_name = $params->{project_name} || ''; my $studio_name = $params->{studio_name} || ''; my $project_id = $params->{project_id} || ''; my $studio_id = $params->{studio_id} || ''; my $json_callback = $params->{json_callback} || ''; if ( $json_callback ne '' ) { $json_callback =~ s/[^a-zA-Z0-9\_]//g; } # use relative links my $extern = 0; $extern = 1 if ( defined $params->{extern} ) && ( $params->{extern} eq '1' ); my $all_recordings = $params->{all_recordings}; my $active_recording = $params->{active_recording} // ''; my $only_active_recording = $params->{only_active_recording} // ''; my $set_no_listen_keys = !($active_recording or $only_active_recording); my $checked = { date => $date, time => $time, from_date => $from_date, till_date => $till_date, date_range_include => $date_range_include, from_time => $from_time, till_time => $till_time, weekday => $weekday, limit => $limit, template => $template, location => $location, series_name => $series_name, tag => $tag, title => $title, event_id => $event_id, search => $search, archive => $archive, last_days => $last_days, order => $order, project => $project, default_project => $default_project, project_name => $project_name, project_id => $project_id, studio_name => $studio_name, studio_id => $studio_id, json_callback => $json_callback, get => $get, locations_to_exclude => $locations_to_exclude, projects_to_exclude => $projects_to_exclude, exclude_locations => $exclude_locations, exclude_projects => $exclude_projects, exclude_event_images => $exclude_event_images, disable_event_sync => $disable_event_sync, extern => $extern, all_recordings => $all_recordings, active_recording => $active_recording, only_active_recordings => $only_active_recording, set_no_listen_keys => $set_no_listen_keys, ro => ($params->{ro}//'') ? 1 : 0 }; return $checked; } sub l($){ my ($word) = @_; return length $word ? $word : (); } sub get_keys($) { my ($event) = @_; #my $program = $event->{program} || ''; my $series_name = $event->{series_name} || ''; my $title = $event->{title} || ''; my $user_title = $event->{user_title} || ''; my $episode = $event->{episode} || ''; my $recurrence_count_alpha = $event->{recurrence_count_alpha} || ''; # ": <user-title>" my $tkey = join (': ', (l($title), l($user_title))); # episode "#123c" my $ekey = join '', ( (length $episode) ? '#'.$episode : '', $recurrence_count_alpha ); # "<title> <episode>" my $te = join " ", (l($tkey), l($ekey)); # separation between <series> and <title> my $stkey = ( length($series_name) and length($te) ) ? ' - ' : ''; return { skey => $series_name, stkey => $stkey, tkey => $tkey, ekey => $ekey, full_title => $series_name . $stkey . $te, full_title_no_series => $te, }; } #do not delete last line! 1;