episodes can be checked and fixed. On checking errors and warnings are displayed. Once only warnings exist, episodes can be fixed.
1341 lines
40 KiB
Perl
1341 lines
40 KiB
Perl
package series;
|
|
|
|
use strict;
|
|
use warnings;
|
|
no warnings 'redefine';
|
|
|
|
use Data::Dumper;
|
|
|
|
use events();
|
|
use images();
|
|
|
|
use base 'Exporter';
|
|
our @EXPORT_OK = qw(
|
|
get_columns get insert update delete
|
|
get_users add_user remove_user
|
|
get_events get_event get_next_episode search_events
|
|
get_event_age is_event_older_than_days
|
|
get_images
|
|
assign_event unassign_event
|
|
add_series_ids_to_events set_event_ids
|
|
can_user_update_events can_user_create_events
|
|
is_series_assigned_to_user is_event_assigned_to_user
|
|
update_recurring_events update_recurring_event
|
|
);
|
|
|
|
#TODO: remove studio_id
|
|
#TODO: get project_id, studio_id by join with project_series
|
|
|
|
sub debug;
|
|
|
|
# get series columns
|
|
sub get_columns ($) {
|
|
my $config = shift;
|
|
|
|
my $dbh = db::connect($config);
|
|
my $cols = db::get_columns( $dbh, 'calcms_series' );
|
|
my $columns = {};
|
|
for my $col (@$cols) {
|
|
$columns->{$col} = 1;
|
|
}
|
|
return $columns;
|
|
}
|
|
|
|
# get series content
|
|
sub get ($$) {
|
|
my $config = shift;
|
|
my $condition = shift;
|
|
|
|
my @conditions = ();
|
|
my @bind_values = ();
|
|
|
|
if ( ( defined $condition->{series_id} ) && ( $condition->{series_id} ne '' ) ) {
|
|
push @conditions, 'id=?';
|
|
push @bind_values, $condition->{series_id};
|
|
}
|
|
|
|
if ( defined $condition->{series_name} ) {
|
|
push @conditions, 'series_name=?';
|
|
push @bind_values, $condition->{series_name};
|
|
}
|
|
|
|
if ( defined $condition->{title} ) {
|
|
push @conditions, 'title=?';
|
|
push @bind_values, $condition->{title};
|
|
}
|
|
|
|
if ( ( defined $condition->{has_single_events} ) && ( $condition->{has_single_events} ne '' ) ) {
|
|
push @conditions, 'has_single_events=?';
|
|
push @bind_values, $condition->{has_single_events};
|
|
}
|
|
|
|
my $search_cond = '';
|
|
if ( ( defined $condition->{search} ) && ( $condition->{search} ne '' ) ) {
|
|
my $search = lc $condition->{search};
|
|
$search =~ s/[^a-z0-9\_\.\-\:\!öäüßÖÄÜ \&]/%/;
|
|
$search =~ s/\%+/\%/;
|
|
$search =~ s/^[\%\s]+//;
|
|
$search =~ s/[\%\s]+$//;
|
|
if ( $search ne '' ) {
|
|
$search = '%' . $search . '%';
|
|
my @attr = ( 'title', 'series_name', 'excerpt', 'category', 'content' );
|
|
push @conditions, "(" . join( " or ", map { 'lower(' . $_ . ') like ?' } @attr ) . ")";
|
|
for my $attr (@attr) {
|
|
push @bind_values, $search;
|
|
}
|
|
}
|
|
}
|
|
|
|
my $query = '';
|
|
my $conditions = '';
|
|
|
|
if ( ( defined $condition->{project_id} ) || ( defined $condition->{studio_id} ) ) {
|
|
if ( ( defined $condition->{project_id} ) && ( $condition->{project_id} ne '' ) ) {
|
|
push @conditions, 'ps.project_id=?';
|
|
push @bind_values, $condition->{project_id};
|
|
}
|
|
|
|
if ( ( defined $condition->{studio_id} ) && ( $condition->{studio_id} ne '' ) ) {
|
|
push @conditions, 'ps.studio_id=?';
|
|
push @bind_values, $condition->{studio_id};
|
|
}
|
|
push @conditions, 'ps.series_id=s.id';
|
|
$conditions = " where " . join( " and ", @conditions ) if ( @conditions > 0 );
|
|
$query = qq{
|
|
select *
|
|
from calcms_series s, calcms_project_series ps
|
|
$conditions
|
|
order by has_single_events desc, series_name, title
|
|
};
|
|
} else {
|
|
|
|
# simple query
|
|
$conditions = " where " . join( " and ", @conditions ) if ( @conditions > 0 );
|
|
$query = qq{
|
|
select *
|
|
from calcms_series
|
|
$conditions
|
|
order by has_single_events desc, series_name, title
|
|
};
|
|
}
|
|
|
|
my $dbh = db::connect($config);
|
|
my $series = db::get( $dbh, $query, \@bind_values );
|
|
|
|
#print STDERR Dumper(time());
|
|
for my $serie (@$series) {
|
|
$serie->{series_id} = $serie->{id};
|
|
delete $serie->{id};
|
|
}
|
|
|
|
#print STDERR Dumper($series);
|
|
return $series;
|
|
}
|
|
|
|
# insert series
|
|
sub insert ($$) {
|
|
my $config = shift;
|
|
my $series = shift;
|
|
|
|
#print STDERR Dumper($series);
|
|
return undef unless defined $series->{project_id};
|
|
return undef unless defined $series->{studio_id};
|
|
|
|
my $project_id = $series->{project_id};
|
|
my $studio_id = $series->{studio_id};
|
|
|
|
my $columns = series::get_columns($config);
|
|
|
|
my $entry = {};
|
|
for my $column ( keys %$columns ) {
|
|
$entry->{$column} = $series->{$column} if defined $series->{$column};
|
|
}
|
|
$entry->{image} = images::normalizeName( $entry->{image} ) if defined $entry->{image};
|
|
|
|
$entry->{created_at} = time::time_to_datetime( time() );
|
|
$entry->{modified_at} = time::time_to_datetime( time() );
|
|
|
|
#print STDERR Dumper($entry);
|
|
|
|
my $dbh = db::connect($config);
|
|
my $series_id = db::insert( $dbh, 'calcms_series', $entry );
|
|
|
|
return undef unless defined $series_id;
|
|
|
|
my $result = project::assign_series(
|
|
$config,
|
|
{
|
|
project_id => $project_id,
|
|
studio_id => $studio_id,
|
|
series_id => $series_id
|
|
}
|
|
);
|
|
return undef unless defined $result;
|
|
return $series_id;
|
|
}
|
|
|
|
# update series
|
|
sub update ($$) {
|
|
my $config = shift;
|
|
my $series = shift;
|
|
|
|
return undef unless defined $series->{project_id};
|
|
return undef unless defined $series->{studio_id};
|
|
return undef unless defined $series->{series_id};
|
|
|
|
my $columns = series::get_columns($config);
|
|
|
|
my $entry = {};
|
|
for my $column ( keys %$columns ) {
|
|
$entry->{$column} = $series->{$column} if defined $series->{$column};
|
|
}
|
|
$entry->{image} = images::normalizeName( $entry->{image} ) if defined $entry->{image};
|
|
$entry->{id} = $series->{series_id};
|
|
$entry->{modified_at} = time::time_to_datetime( time() );
|
|
|
|
my $values = join( ",", map { $_ . '=?' } ( keys %$entry ) );
|
|
my @bind_values = map { $entry->{$_} } ( keys %$entry );
|
|
push @bind_values, $entry->{id};
|
|
|
|
my $query = qq{
|
|
update calcms_series
|
|
set $values
|
|
where id=?
|
|
};
|
|
|
|
#print STDERR Dumper($query).Dumper(\@bind_values);
|
|
|
|
my $dbh = db::connect($config);
|
|
return db::put( $dbh, $query, \@bind_values );
|
|
}
|
|
|
|
# delete series, its schedules and series dates
|
|
# unassign its users and events
|
|
sub delete($$) {
|
|
my $config = shift;
|
|
my $series = shift;
|
|
|
|
return undef unless defined $series->{project_id};
|
|
return undef unless defined $series->{studio_id};
|
|
return undef unless defined $series->{series_id};
|
|
|
|
my $project_id = $series->{project_id};
|
|
my $studio_id = $series->{studio_id};
|
|
my $series_id = $series->{series_id};
|
|
|
|
unless ( project::is_series_assigned( $config, $series ) == 1 ) {
|
|
print STDERR "series is not assigned to project $project_id and studio $studio_id\n";
|
|
return undef;
|
|
}
|
|
|
|
my $query = undef;
|
|
my $bind_values = undef;
|
|
my $dbh = db::connect($config);
|
|
|
|
$bind_values = [ $project_id, $studio_id, $series_id ];
|
|
|
|
#delete schedules
|
|
$query = qq{
|
|
delete from calcms_series_schedule
|
|
where project_id=? and studio_id=? and series_id=?
|
|
};
|
|
db::put( $dbh, $query, $bind_values );
|
|
|
|
#delete series dates
|
|
$query = qq{
|
|
delete from calcms_series_dates
|
|
where project_id=? and studio_id=? and series_id=?
|
|
};
|
|
db::put( $dbh, $query, $bind_values );
|
|
|
|
#unassign users
|
|
series::remove_user(
|
|
$config,
|
|
{
|
|
project_id => $project_id,
|
|
studio_id => $studio_id,
|
|
series_id => $series_id
|
|
}
|
|
);
|
|
|
|
#unassign events
|
|
$bind_values = [ $project_id, $studio_id, $series_id ];
|
|
$query = qq{
|
|
delete from calcms_series_events
|
|
where project_id=? and studio_id=? and series_id=?
|
|
};
|
|
|
|
#print '<pre>$query'.$query.Dumper($bind_values).'</pre>';
|
|
db::put( $dbh, $query, $bind_values );
|
|
|
|
project::unassign_series(
|
|
$config,
|
|
{
|
|
project_id => $project_id,
|
|
studio_id => $studio_id,
|
|
series_id => $series_id
|
|
}
|
|
);
|
|
|
|
#delete series
|
|
|
|
my $series_assignments = project::get_series_assignments(
|
|
$config,
|
|
{
|
|
series_id => $series_id
|
|
}
|
|
);
|
|
if ( scalar @$series_assignments > 1 ) {
|
|
print STDERR "do not delete series, due to assigned to other project or studio";
|
|
return;
|
|
}
|
|
|
|
$bind_values = [$series_id];
|
|
$query = qq{
|
|
delete from calcms_series
|
|
where id=?
|
|
};
|
|
|
|
#print STDERR $query.$query.Dumper($bind_values);
|
|
db::put( $dbh, $query, $bind_values );
|
|
}
|
|
|
|
# get users directly assigned to project, studio, series (editors)
|
|
sub get_users ($$) {
|
|
my $config = shift;
|
|
my $condition = shift;
|
|
|
|
my @conditions = ();
|
|
my @bind_values = ();
|
|
|
|
if ( ( defined $condition->{project_id} ) && ( $condition->{project_id} ne '' ) ) {
|
|
push @conditions, 'us.project_id=?';
|
|
push @bind_values, $condition->{project_id};
|
|
}
|
|
|
|
if ( ( defined $condition->{studio_id} ) && ( $condition->{studio_id} ne '' ) ) {
|
|
push @conditions, 'us.studio_id=?';
|
|
push @bind_values, $condition->{studio_id};
|
|
}
|
|
|
|
if ( ( defined $condition->{series_id} ) && ( $condition->{series_id} ne '' ) ) {
|
|
push @conditions, 'us.series_id=?';
|
|
push @bind_values, $condition->{series_id};
|
|
}
|
|
|
|
if ( ( defined $condition->{name} ) && ( $condition->{name} ne '' ) ) {
|
|
push @conditions, 'u.name=?';
|
|
push @bind_values, $condition->{name};
|
|
}
|
|
|
|
my $conditions = '';
|
|
$conditions = " and " . join( " and ", @conditions ) if ( @conditions > 0 );
|
|
|
|
my $query = qq{
|
|
select u.id, u.name, u.full_name, u.email, us.modified_by, us.modified_at
|
|
from calcms_users u, calcms_user_series us
|
|
where us.user_id=u.id
|
|
$conditions
|
|
};
|
|
|
|
#print STDERR $query." ".Dumper(\@bind_values)."\n";
|
|
my $dbh = db::connect($config);
|
|
my $result = db::get( $dbh, $query, \@bind_values );
|
|
|
|
#print STDERR $query." ".Dumper($result)."\n";
|
|
return $result;
|
|
}
|
|
|
|
# assign user to series
|
|
sub add_user ($$) {
|
|
my $config = shift;
|
|
my $entry = shift;
|
|
|
|
return unless defined $entry->{project_id};
|
|
return unless defined $entry->{studio_id};
|
|
return unless defined $entry->{series_id};
|
|
return unless defined $entry->{user_id};
|
|
return unless defined $entry->{user};
|
|
|
|
my $query = qq{
|
|
select id
|
|
from calcms_user_series
|
|
where project_id=? and studio_id=? and series_id=? and user_id=?
|
|
};
|
|
my $bind_values = [ $entry->{project_id}, $entry->{studio_id}, $entry->{series_id}, $entry->{user_id} ];
|
|
|
|
my $dbh = db::connect($config);
|
|
my $results = db::get( $dbh, $query, $bind_values );
|
|
return unless scalar @$results == 0;
|
|
|
|
$query = qq{
|
|
insert calcms_user_series
|
|
set project_id=?, studio_id=?, series_id=?, user_id=?, modified_by=?, modified_at=now()
|
|
};
|
|
$bind_values =
|
|
[ $entry->{project_id}, $entry->{studio_id}, $entry->{series_id}, $entry->{user_id}, $entry->{user} ];
|
|
db::put( $dbh, $query, $bind_values );
|
|
}
|
|
|
|
# remove user(s) from series.
|
|
sub remove_user ($$) {
|
|
my $config = shift;
|
|
my $condition = shift;
|
|
|
|
return unless ( defined $condition->{project_id} );
|
|
return unless ( defined $condition->{studio_id} );
|
|
return unless ( defined $condition->{series_id} );
|
|
|
|
my @conditions = ();
|
|
my @bind_values = ();
|
|
|
|
if ( ( defined $condition->{project_id} ) && ( $condition->{project_id} ne '' ) ) {
|
|
push @conditions, 'project_id=?';
|
|
push @bind_values, $condition->{project_id};
|
|
}
|
|
|
|
if ( ( defined $condition->{studio_id} ) && ( $condition->{studio_id} ne '' ) ) {
|
|
push @conditions, 'studio_id=?';
|
|
push @bind_values, $condition->{studio_id};
|
|
}
|
|
|
|
if ( ( defined $condition->{series_id} ) && ( $condition->{series_id} ne '' ) ) {
|
|
push @conditions, 'series_id=?';
|
|
push @bind_values, $condition->{series_id};
|
|
}
|
|
|
|
if ( ( defined $condition->{user_id} ) && ( $condition->{user_id} ne '' ) ) {
|
|
push @conditions, 'user_id=?';
|
|
push @bind_values, $condition->{user_id};
|
|
}
|
|
|
|
my $conditions = '';
|
|
$conditions = join( " and ", @conditions ) if ( @conditions > 0 );
|
|
|
|
my $query = qq{
|
|
delete from calcms_user_series
|
|
where $conditions
|
|
};
|
|
my $dbh = db::connect($config);
|
|
db::put( $dbh, $query, \@bind_values );
|
|
}
|
|
|
|
#search events by series_name and title (for events not assigned yet)
|
|
#TODO: add location
|
|
sub search_events ($$$) {
|
|
my $config = shift;
|
|
my $request = shift;
|
|
my $options = shift;
|
|
|
|
my $series_name = $options->{series_name} || '';
|
|
my $title = $options->{title} || '';
|
|
return undef if ( $series_name eq '' ) && ( $title eq '' );
|
|
|
|
$series_name =~ s/[^a-zA-Z0-9 \-]+/\?/g;
|
|
$title =~ s/[^a-zA-Z0-9 \-]+/\?/g;
|
|
|
|
$series_name =~ s/\?+/\?/g;
|
|
$title =~ s/\?+/\?/g;
|
|
|
|
my $params = {
|
|
series_name => $series_name,
|
|
title => $title,
|
|
template => 'no'
|
|
};
|
|
if ( defined $options ) {
|
|
$params->{from_date} = $options->{from_date} if ( defined $options->{from_date} );
|
|
$params->{till_date} = $options->{till_date} if ( defined $options->{till_date} );
|
|
$params->{location} = $options->{location} if ( defined $options->{location} );
|
|
$params->{limit} = $options->{limit} if ( defined $options->{limit} );
|
|
$params->{archive} = $options->{archive} if ( defined $options->{archive} );
|
|
$params->{get} = $options->{get} if ( defined $options->{get} );
|
|
}
|
|
|
|
my $checked_params = events::check_params( $config, $params );
|
|
|
|
#print STDERR '<pre>'.Dumper($checked_params).'</pre>';
|
|
my $request2 = {
|
|
params => {
|
|
checked => $checked_params
|
|
},
|
|
config => $request->{config},
|
|
permissions => $request->{permissions}
|
|
};
|
|
|
|
#my $debug=1;
|
|
#print STDERR Dumper($request2->{params});
|
|
my $events = events::get( $config, $request2 );
|
|
|
|
#print Dumper($events);
|
|
return $events;
|
|
}
|
|
|
|
#get events (only assigned ones) by project_id,studio_id,series_id,
|
|
sub get_events ($$) {
|
|
my $config = shift;
|
|
my $options = shift;
|
|
|
|
#print STDERR Dumper($options);
|
|
return [] if defined( $options->{series_id} ) && ( $options->{series_id} <= 0 );
|
|
|
|
my @conditions = ();
|
|
my @bind_values = ();
|
|
|
|
if ( defined $options->{project_id} ) {
|
|
push @conditions, 'se.project_id = ?';
|
|
push @bind_values, $options->{project_id};
|
|
}
|
|
if ( defined $options->{studio_id} ) {
|
|
push @conditions, 'se.studio_id = ?';
|
|
push @bind_values, $options->{studio_id};
|
|
}
|
|
if ( ( defined $options->{series_id} ) && ( $options->{series_id} =~ /(\d+)/ ) ) {
|
|
push @bind_values, $1;
|
|
push @conditions, 'se.series_id = ?';
|
|
}
|
|
|
|
if ( defined $options->{event_id} ) {
|
|
push @bind_values, $options->{event_id};
|
|
push @conditions, 'e.id = ?';
|
|
}
|
|
|
|
if ( ( defined $options->{from_date} ) && ( $options->{from_date} =~ /(\d\d\d\d\-\d\d\-\d\d)/ ) ) {
|
|
push @bind_values, $1;
|
|
push @conditions, 'e.start_date >= ?';
|
|
}
|
|
if ( ( defined $options->{till_date} ) && ( $options->{till_date} =~ /(\d\d\d\d\-\d\d\-\d\d)/ ) ) {
|
|
push @bind_values, $1;
|
|
push @conditions, 'e.start_date <= ?';
|
|
}
|
|
if ( defined $options->{location} ) {
|
|
push @conditions, 'e.location = ?';
|
|
push @bind_values, $options->{location};
|
|
}
|
|
|
|
if ( defined $options->{draft} ) {
|
|
push @conditions, 'e.draft = ?';
|
|
push @bind_values, $options->{draft};
|
|
}
|
|
|
|
my $conditions = '';
|
|
if ( @conditions > 0 ) {
|
|
$conditions = ' and ' . join( ' and ', @conditions );
|
|
}
|
|
|
|
my $limit = '';
|
|
if ( ( defined $options->{limit} ) && ( $limit =~ /(\d+)/ ) ) {
|
|
$limit = 'limit ' . $1;
|
|
}
|
|
|
|
my $query = qq{
|
|
select *
|
|
,date(start) start_date
|
|
,date(end) end_date
|
|
,weekday(start) weekday
|
|
,weekofyear(start) week_of_year
|
|
,dayofyear(start) day_of_year
|
|
,start_date day
|
|
,id event_id
|
|
,location location
|
|
from calcms_series_events se, calcms_events e
|
|
where se.event_id = e.id
|
|
$conditions
|
|
order by start_date desc
|
|
$limit
|
|
};
|
|
|
|
#print STDERR '<pre>'.$query.Dumper(\@bind_values).'</pre>';
|
|
|
|
my $dbh = db::connect($config);
|
|
my $results = db::get( $dbh, $query, \@bind_values );
|
|
|
|
#print STDERR Dumper($results);
|
|
|
|
$results = events::modify_results(
|
|
$dbh, $config,
|
|
{
|
|
base_url => '',
|
|
params => {
|
|
checked => {
|
|
template => ''
|
|
}
|
|
}
|
|
},
|
|
$results
|
|
);
|
|
|
|
#add studio id to events
|
|
my $studios = studios::get( $config, $options );
|
|
|
|
my $studio_id_by_location = {};
|
|
for my $studio (@$studios) {
|
|
$studio_id_by_location->{ $studio->{location} } = $studio->{id};
|
|
}
|
|
for my $result (@$results) {
|
|
$result->{studio_id} = $studio_id_by_location->{ $result->{location} };
|
|
}
|
|
|
|
#print STDERR Dumper($results);
|
|
return $results;
|
|
}
|
|
|
|
# load event given by studio_id, series_id and event_id
|
|
# helper for gui - errors are written to gui output
|
|
# return undef on error
|
|
sub get_event ($$) {
|
|
my $config = shift;
|
|
my $options = shift;
|
|
|
|
my $project_id = $options->{project_id} || '';
|
|
my $studio_id = $options->{studio_id} || '';
|
|
my $series_id = $options->{series_id} || '';
|
|
my $event_id = $options->{event_id} || '';
|
|
my $draft = $options->{draft} || '';
|
|
|
|
unless ( defined $options->{allow_any} ) {
|
|
if ( $project_id eq '' ) {
|
|
uac::print_error("missing project_id");
|
|
return undef;
|
|
}
|
|
if ( $studio_id eq '' ) {
|
|
uac::print_error("missing studio_id");
|
|
return undef;
|
|
}
|
|
if ( $series_id eq '' ) {
|
|
uac::print_error("missing series_id");
|
|
return undef;
|
|
}
|
|
}
|
|
|
|
if ( $event_id eq '' ) {
|
|
uac::print_error("missing event_id");
|
|
return undef;
|
|
}
|
|
|
|
my $queryOptions = {};
|
|
$queryOptions->{project_id} = $project_id if $project_id ne '';
|
|
$queryOptions->{studio_id} = $studio_id if $studio_id ne '';
|
|
$queryOptions->{series_id} = $series_id if $series_id ne '';
|
|
$queryOptions->{event_id} = $event_id if $event_id ne '';
|
|
$queryOptions->{draft} = $draft if $draft ne '';
|
|
|
|
my $events = series::get_events( $config, $queryOptions );
|
|
|
|
unless ( defined $events ) {
|
|
uac::print_error("error on loading event");
|
|
return undef;
|
|
}
|
|
|
|
if ( scalar(@$events) == 0 ) {
|
|
uac::print_error("event not found");
|
|
return undef;
|
|
}
|
|
|
|
if ( scalar(@$events) > 1 ) {
|
|
print STDERR q{multiple assignments found for }
|
|
. q{project_id=}
|
|
. $options->{project_id}
|
|
. q{, studio_id=}
|
|
. $options->{studio_id}
|
|
. q{, series_id=}
|
|
. $options->{series_id}
|
|
. q{, event_id=}
|
|
. $options->{event_id} . "\n";
|
|
}
|
|
my $event = $events->[0];
|
|
return $event;
|
|
}
|
|
|
|
# get name and title of series and age in days ('days_over')
|
|
sub get_event_age($$) {
|
|
my $config = shift;
|
|
my $options = shift;
|
|
|
|
#print STDERR Dumper($options);
|
|
return undef unless defined $options->{project_id};
|
|
return undef unless defined $options->{studio_id};
|
|
|
|
my @conditions = ();
|
|
my @bind_values = ();
|
|
|
|
if ( ( defined $options->{project_id} ) && ( $options->{project_id} =~ /(\d+)/ ) ) {
|
|
push @bind_values, $1;
|
|
push @conditions, 'ps.project_id = ?';
|
|
}
|
|
|
|
if ( ( defined $options->{studio_id} ) && ( $options->{studio_id} =~ /(\d+)/ ) ) {
|
|
push @bind_values, $1;
|
|
push @conditions, 'ps.studio_id = ?';
|
|
}
|
|
|
|
if ( ( defined $options->{series_id} ) && ( $options->{series_id} =~ /(\d+)/ ) ) {
|
|
push @bind_values, $1;
|
|
push @conditions, 's.id = ?';
|
|
}
|
|
|
|
if ( ( defined $options->{event_id} ) && ( $options->{event_id} =~ /(\d+)/ ) ) {
|
|
push @bind_values, $1;
|
|
push @conditions, 'e.id = ?';
|
|
}
|
|
|
|
my $conditions = '';
|
|
if ( @conditions > 0 ) {
|
|
$conditions = join( ' and ', @conditions );
|
|
}
|
|
my $query = qq{
|
|
select s.id series_id, s.series_name, s.title, s.has_single_events has_single_events, (to_days(now())-to_days(max(e.start))) days_over
|
|
from calcms_project_series ps
|
|
left join calcms_series s on ps.series_id=s.id
|
|
left join calcms_series_events se on s.id=se.series_id
|
|
left join calcms_events e on e.id=se.event_id
|
|
where $conditions
|
|
group by s.id
|
|
order by has_single_events desc, days_over
|
|
};
|
|
|
|
#print STDERR $query." ".Dumper(\@bind_values);
|
|
my $dbh = db::connect($config);
|
|
my $results = db::get( $dbh, $query, \@bind_values );
|
|
|
|
for my $result (@$results) {
|
|
$result->{days_over} = 0 unless defined $result->{days_over};
|
|
}
|
|
return $results;
|
|
}
|
|
|
|
# is event older than max_age days
|
|
sub is_event_older_than_days ($$) {
|
|
my $config = shift;
|
|
my $options = shift;
|
|
|
|
#print STDERR Dumper($options);
|
|
|
|
return 1 unless defined $options->{project_id};
|
|
return 1 unless defined $options->{studio_id};
|
|
return 1 unless defined $options->{series_id};
|
|
return 1 unless defined $options->{event_id};
|
|
return 1 unless defined $options->{max_age};
|
|
|
|
my $events = series::get_event_age(
|
|
$config,
|
|
{
|
|
project_id => $options->{project_id},
|
|
studio_id => $options->{studio_id},
|
|
series_id => $options->{series_id},
|
|
event_id => $options->{event_id}
|
|
}
|
|
);
|
|
|
|
if ( scalar(@$events) == 0 ) {
|
|
print STDERR
|
|
"series_events::event_over_in_days: event $options->{event_id} is not assigned to project $options->{project_id}, studio $options->{studio_id}, series $options->{series_id}\n";
|
|
return 1;
|
|
}
|
|
my $event = $events->[0];
|
|
|
|
#print STDERR Dumper($event);
|
|
return 1 if $event->{days_over} > $options->{max_age};
|
|
return 0;
|
|
}
|
|
|
|
sub get_next_episode($$) {
|
|
my $config = shift;
|
|
my $options = shift;
|
|
|
|
return 0 unless defined $options->{project_id};
|
|
return 0 unless defined $options->{studio_id};
|
|
return 0 unless defined $options->{series_id};
|
|
|
|
#return if episodes should not be counted for this series
|
|
my $query = q{
|
|
select count_episodes
|
|
from calcms_series
|
|
where id=?
|
|
};
|
|
my $bind_values = [ $options->{series_id} ];
|
|
my $dbh = db::connect($config);
|
|
my $results = db::get( $dbh, $query, $bind_values );
|
|
return 0 if ( @$results != 1 );
|
|
return 0 if ( $results->[0]->{count_episodes} eq '0' );
|
|
|
|
#print STDERR Dumper($results);
|
|
|
|
#get all
|
|
$query = q{
|
|
select title,episode from calcms_events e, calcms_series_events se
|
|
where se.project_id=? and se.studio_id=? and se.series_id=? and se.event_id=e.id
|
|
};
|
|
$bind_values = [ $options->{project_id}, $options->{studio_id}, $options->{series_id} ];
|
|
$results = db::get( $dbh, $query, $bind_values );
|
|
|
|
my $max = 0;
|
|
for my $result (@$results) {
|
|
if ( $result->{title} =~ /\#(\d+)/ ) {
|
|
my $value = $1;
|
|
$max = $value if $value > $max;
|
|
}
|
|
next unless defined $result->{episode};
|
|
$max = $result->{episode} if $result->{episode} > $max;
|
|
}
|
|
return $max + 1;
|
|
}
|
|
|
|
sub get_images ($$) {
|
|
my $config = shift;
|
|
my $options = shift;
|
|
|
|
return undef unless defined $options->{project_id};
|
|
return undef unless defined $options->{studio_id};
|
|
return undef unless defined $options->{series_id};
|
|
|
|
#get images from all events of the series
|
|
my $dbh = db::connect($config);
|
|
my $events = series::get_events(
|
|
$config,
|
|
{
|
|
project_id => $options->{project_id},
|
|
studio_id => $options->{studio_id},
|
|
series_id => $options->{series_id}
|
|
}
|
|
);
|
|
my $images = {};
|
|
my $found = 0;
|
|
for my $event (@$events) {
|
|
my $image = $event->{image};
|
|
$image =~ s/.*\///;
|
|
$images->{$image} = 1;
|
|
$found++;
|
|
}
|
|
|
|
return undef if $found == 0;
|
|
|
|
# get all images from database
|
|
my @cond = ();
|
|
my $bind_values = [];
|
|
for my $image ( keys %$images ) {
|
|
push @cond, 'filename=?';
|
|
push @$bind_values, $image;
|
|
}
|
|
|
|
my $where = '';
|
|
if ( @cond > 0 ) {
|
|
$where = 'where ' . join( ' or ', @cond );
|
|
}
|
|
|
|
my $limit = '';
|
|
if ( ( defined $options->{limit} ) && ( $options->{limit} =~ /(\d+)/ ) ) {
|
|
$limit = ' limit ' . $1;
|
|
}
|
|
|
|
my $query = qq{
|
|
select *
|
|
from calcms_images
|
|
$where
|
|
order by created_at desc
|
|
$limit
|
|
};
|
|
|
|
#print STDERR Dumper($query).Dumper($bind_values);
|
|
my $results = db::get( $dbh, $query, $bind_values );
|
|
|
|
#print STDERR @$results."\n";
|
|
return $results;
|
|
}
|
|
|
|
#assign event to series
|
|
#TODO: manual assign needs to update automatic one
|
|
sub assign_event($$) {
|
|
my $config = shift;
|
|
my $entry = shift;
|
|
|
|
#print STDERR Dumper($entry);
|
|
return undef unless defined $entry->{project_id};
|
|
return undef unless defined $entry->{studio_id};
|
|
return undef unless defined $entry->{series_id};
|
|
return undef unless defined $entry->{event_id};
|
|
$entry->{manual} = 0 unless ( defined $entry->{manual} ) && ( $entry->{manual} eq '1' );
|
|
|
|
my $conditions = '';
|
|
$conditions = 'and manual=1' if $entry->{manual} eq '1';
|
|
|
|
my $query = qq{
|
|
select * from calcms_series_events
|
|
where project_id=? and studio_id=? and series_id=? and event_id=? $conditions
|
|
};
|
|
my $bind_values = [ $entry->{project_id}, $entry->{studio_id}, $entry->{series_id}, $entry->{event_id} ];
|
|
my $dbh = db::connect($config);
|
|
my $results = db::get( $dbh, $query, $bind_values );
|
|
|
|
if ( scalar @$results > 1 ) {
|
|
print STDERR
|
|
"multiple assignments of project_id=$entry->{project_id}, studio_id=$entry->{studio_id}, series_id=$entry->{series_id}, event_id=$entry->{event_id}\n";
|
|
return;
|
|
}
|
|
if ( scalar @$results == 1 ) {
|
|
print STDERR
|
|
"already assigned: project_id=$entry->{project_id}, studio_id=$entry->{studio_id}, series_id=$entry->{series_id}, event_id=$entry->{event_id}\n";
|
|
return;
|
|
}
|
|
|
|
$query = qq{
|
|
insert into calcms_series_events (project_id, studio_id, series_id, event_id, manual)
|
|
values (?,?,?,?,?)
|
|
};
|
|
$bind_values =
|
|
[ $entry->{project_id}, $entry->{studio_id}, $entry->{series_id}, $entry->{event_id}, $entry->{manual} ];
|
|
|
|
#print STDERR '<pre>'.$query.Dumper($bind_values).'</pre>';
|
|
return db::put( $dbh, $query, $bind_values );
|
|
}
|
|
|
|
#unassign event from series
|
|
sub unassign_event($$) {
|
|
my $config = shift;
|
|
my $entry = shift;
|
|
|
|
return unless defined $entry->{project_id};
|
|
return unless defined $entry->{studio_id};
|
|
return unless defined $entry->{series_id};
|
|
return unless defined $entry->{event_id};
|
|
|
|
my $conditions = '';
|
|
$conditions = 'and manual=1' if ( defined $entry->{manual} ) && ( $entry->{manual} eq '1' );
|
|
|
|
my $query = qq{
|
|
delete from calcms_series_events
|
|
where project_id=? and studio_id=? and series_id=? and event_id=?
|
|
$conditions
|
|
};
|
|
my $bind_values = [ $entry->{project_id}, $entry->{studio_id}, $entry->{series_id}, $entry->{event_id} ];
|
|
|
|
#print STDERR '<pre>'.$query.Dumper($bind_values).'</pre>';
|
|
my $dbh = db::connect($config);
|
|
return db::put( $dbh, $query, $bind_values );
|
|
}
|
|
|
|
# put series id to given events (for legacy handling)
|
|
# used by calendar
|
|
# TODO: optionally add project_id and studio_id to conditions
|
|
sub add_series_ids_to_events ($$) {
|
|
my $config = shift;
|
|
my $events = shift;
|
|
|
|
#get event ids from given events
|
|
my @event_ids = ();
|
|
for my $event (@$events) {
|
|
push @event_ids, $event->{event_id};
|
|
}
|
|
|
|
return if scalar @event_ids == 0;
|
|
|
|
my @bind_values = @event_ids;
|
|
my $event_ids = join( ',', map { '?' } @event_ids );
|
|
|
|
#query series ids
|
|
my $dbh = db::connect($config);
|
|
my $query = qq{
|
|
select project_id, studio_id, series_id, event_id
|
|
from calcms_series_events
|
|
where event_id in ($event_ids)
|
|
};
|
|
my $results = db::get( $dbh, $query, \@bind_values );
|
|
my @results = @$results;
|
|
return [] unless scalar @results > 0;
|
|
|
|
#build hash of series ids by event ids
|
|
my $assignments_by_event_id = {};
|
|
for my $entry (@$results) {
|
|
my $event_id = $entry->{event_id};
|
|
$assignments_by_event_id->{$event_id} = $entry;
|
|
}
|
|
|
|
#fill in ids into events
|
|
for my $event (@$events) {
|
|
my $event_id = $event->{event_id};
|
|
my $assignment = $assignments_by_event_id->{$event_id};
|
|
if ( defined $assignment ) {
|
|
$event->{project_id} = $assignment->{project_id};
|
|
$event->{studio_id} = $assignment->{studio_id};
|
|
$event->{series_id} = $assignment->{series_id};
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
# add event_ids to series and remove all event ids from series, not given event_ids
|
|
# for scan only, used at series
|
|
sub set_event_ids ($$$$$) {
|
|
my $config = shift;
|
|
my $project_id = shift;
|
|
my $studio_id = shift;
|
|
my $serie = shift;
|
|
my $event_ids = shift;
|
|
|
|
my $serie_id = $serie->{series_id};
|
|
return unless defined $project_id;
|
|
return unless defined $studio_id;
|
|
return unless defined $serie_id;
|
|
return unless defined $event_ids;
|
|
|
|
#make lookup table from events
|
|
my $event_id_hash = {};
|
|
for my $event_id (@$event_ids) {
|
|
$event_id_hash->{$event_id} = 1;
|
|
}
|
|
|
|
#get series_entries from db
|
|
#my $bind_names=join(',', (map { '?' } @$event_ids));
|
|
my $query = qq{
|
|
select event_id from calcms_series_events
|
|
where project_id=? and studio_id=? and series_id=?
|
|
};
|
|
my $bind_values = [ $project_id, $studio_id, $serie_id ];
|
|
|
|
my $dbh = db::connect($config);
|
|
my $results = db::get( $dbh, $query, $bind_values );
|
|
|
|
my $found = {};
|
|
|
|
#mark events found assigned to series
|
|
my $i = 1;
|
|
for my $event (@$results) {
|
|
|
|
#print "found event $i: $event->{event_id}\n";
|
|
$found->{ $event->{event_id} } = 1;
|
|
$i++;
|
|
}
|
|
|
|
#insert events from list, not found in db
|
|
for my $event_id (@$event_ids) {
|
|
|
|
#print "insert event_id $event_id\n";
|
|
series::assign_event(
|
|
$config,
|
|
{
|
|
project_id => $project_id,
|
|
studio_id => $studio_id,
|
|
series_id => $serie_id,
|
|
event_id => $event_id
|
|
}
|
|
) unless ( $found->{$event_id} );
|
|
}
|
|
|
|
#delete events found in db, but not in list
|
|
for my $event_id ( keys %$found ) {
|
|
|
|
#print "delete event_id $event_id\n";
|
|
series::unassign_event(
|
|
$config,
|
|
{
|
|
project_id => $project_id,
|
|
studio_id => $studio_id,
|
|
series_id => $serie_id,
|
|
event_id => $event_id,
|
|
manual => 0
|
|
}
|
|
) unless defined $event_id_hash->{$event_id};
|
|
}
|
|
|
|
}
|
|
|
|
# check if user allowed to update series events
|
|
# evaluate permissions and consider editors directly assigned to series
|
|
sub can_user_update_events ($$) {
|
|
my $request = shift;
|
|
my $options = shift;
|
|
|
|
my $config = $request->{config};
|
|
my $permissions = $request->{permissions};
|
|
|
|
return 0 unless defined $request->{user};
|
|
return 0 unless defined $options->{project_id};
|
|
return 0 unless defined $options->{studio_id};
|
|
return 0 unless defined $options->{series_id};
|
|
|
|
return 1 if ( defined $permissions->{update_event_of_others} ) && ( $permissions->{update_event_of_others} eq '1' );
|
|
return 1 if ( defined $permissions->{is_admin} ) && ( $permissions->{is_admin} eq '1' );
|
|
return 0 if $permissions->{update_event_of_series} ne '1';
|
|
|
|
return is_series_assigned_to_user( $request, $options );
|
|
}
|
|
|
|
# check if user allowed to create series events
|
|
# evaluate permissions and consider editors directly assigned to series
|
|
sub can_user_create_events ($$) {
|
|
my $request = shift;
|
|
my $options = shift;
|
|
|
|
my $config = $request->{config};
|
|
my $permissions = $request->{permissions};
|
|
|
|
return 0 unless defined $request->{user};
|
|
return 0 unless defined $options->{project_id};
|
|
return 0 unless defined $options->{studio_id};
|
|
return 0 unless defined $options->{series_id};
|
|
|
|
return 1 if ( defined $permissions->{create_event} ) && ( $permissions->{create_event} eq '1' );
|
|
return 1 if ( defined $permissions->{is_admin} ) && ( $permissions->{is_admin} eq '1' );
|
|
return 0 if $permissions->{create_event_of_series} ne '1';
|
|
|
|
return is_series_assigned_to_user( $request, $options );
|
|
}
|
|
|
|
sub is_series_assigned_to_user ($$) {
|
|
my $request = shift;
|
|
my $options = shift;
|
|
|
|
my $config = $request->{config};
|
|
my $permissions = $request->{permissions};
|
|
|
|
return 0 unless defined $options->{project_id};
|
|
return 0 unless defined $options->{studio_id};
|
|
return 0 unless defined $options->{series_id};
|
|
return 0 unless defined $request->{user};
|
|
|
|
my $series_users = series::get_users(
|
|
$config,
|
|
{
|
|
project_id => $options->{project_id},
|
|
studio_id => $options->{studio_id},
|
|
series_id => $options->{series_id},
|
|
name => $request->{user}
|
|
}
|
|
);
|
|
return 0 if scalar @$series_users == 0;
|
|
return 1;
|
|
}
|
|
|
|
# check if user is assigned to studio where location matchs to event
|
|
# return 1 on success or error text
|
|
sub is_event_assigned_to_user ($$) {
|
|
my $request = shift;
|
|
my $options = shift;
|
|
|
|
my $config = $request->{config};
|
|
|
|
return "missing user" unless defined $request->{user};
|
|
return "missing project_id" unless defined $options->{project_id};
|
|
return "missing studio_id" unless defined $options->{studio_id};
|
|
return "missing series_id" unless defined $options->{series_id};
|
|
return "missing event_id" unless defined $options->{event_id};
|
|
|
|
#check roles
|
|
my $user_studios = uac::get_studios_by_user(
|
|
$config,
|
|
{
|
|
project_id => $options->{project_id},
|
|
studio_id => $options->{studio_id},
|
|
user => $request->{user},
|
|
}
|
|
);
|
|
return "user is not assigned to studio" if scalar @$user_studios == 0;
|
|
my $studio = $user_studios->[0];
|
|
my $location = $studio->{location};
|
|
return "could not get studio location" if $location eq '';
|
|
|
|
#TODO: replace legacy support
|
|
my $events = series::get_events(
|
|
$config,
|
|
{
|
|
project_id => $options->{project_id},
|
|
studio_id => $options->{studio_id},
|
|
series_id => $options->{series_id},
|
|
event_id => $options->{event_id},
|
|
location => $location,
|
|
limit => 1
|
|
}
|
|
);
|
|
|
|
#print STDERR Dumper(@$events);
|
|
return
|
|
"no event found for"
|
|
. " project $options->{project_id},"
|
|
. " studio $options->{studio_id},"
|
|
. " location $location,"
|
|
. " series $options->{series_id}"
|
|
. " and event $options->{event_id}"
|
|
if scalar @$events == 0;
|
|
return 1;
|
|
}
|
|
|
|
sub get_rebuilt_episodes ($$) {
|
|
my $config = shift;
|
|
my $options = shift;
|
|
|
|
return "missing project_id" unless defined $options->{project_id};
|
|
return "missing studio_id" unless defined $options->{studio_id};
|
|
return "missing series_id" unless defined $options->{series_id};
|
|
|
|
# ignore project and studio as series can be used in multiple studios
|
|
my $events = series::get_events(
|
|
$config,
|
|
{
|
|
#project_id => $options->{project_id},
|
|
#studio_id => $options->{studio_id},
|
|
series_id => $options->{series_id},
|
|
draft => 0
|
|
}
|
|
);
|
|
@$events = sort { $a->{start} cmp $b->{start} } @$events;
|
|
|
|
my $events_by_episode = {};
|
|
for my $event (@$events) {
|
|
next unless $event->{episode};
|
|
push @{ $events_by_episode->{$event->{episode}} }, $event;
|
|
}
|
|
|
|
my $done={};
|
|
my $episode = $events->[0]->{episode} // 0;
|
|
$episode-=1;
|
|
|
|
for my $i (0..$#$events){
|
|
my $event = $events->[$i];
|
|
next if $done->{$event->{id}};
|
|
$episode++;
|
|
# increase episode for not set values
|
|
if ( ($event->{episode}//'') eq ''){
|
|
$event->{old_episode} = $event->{episode};
|
|
$event->{episode} = $episode;
|
|
next;
|
|
}
|
|
# set new value to all episodes with same value
|
|
for my $event2 (@{$events_by_episode->{$event->{episode}}}){
|
|
$event2->{old_episode} = $event2->{episode};
|
|
$event2->{episode} = $episode;
|
|
$done->{$event2->{id}}=1;
|
|
};
|
|
}
|
|
#print STDERR Dumper($events);
|
|
return $events;
|
|
}
|
|
|
|
# to find multiple recurrences this does not include the recurrence_count
|
|
# use events::get_key to add the recurrence
|
|
sub get_event_key ($) {
|
|
my $event = shift;
|
|
|
|
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 $key = '';
|
|
$key .= $series_name if $series_name ne '';
|
|
$key .= ' - ' if ( $series_name ne '' ) && ( $title ne '' );
|
|
$key .= $title if $title ne '';
|
|
$key .= ': ' if ( $title ne '' ) && ( $user_title ne '' );
|
|
$key .= $user_title if $user_title ne '';
|
|
$key .= ' #' . $episode if $episode ne '';
|
|
return $key;
|
|
}
|
|
|
|
sub update_recurring_events ($$) {
|
|
my $config = shift;
|
|
my $options = shift;
|
|
|
|
return "missing project_id" unless defined $options->{project_id};
|
|
return "missing studio_id" unless defined $options->{studio_id};
|
|
return "missing series_id" unless defined $options->{series_id};
|
|
return "missing event_id" unless defined $options->{event_id};
|
|
|
|
my $events = series::get_events(
|
|
$config,
|
|
{
|
|
#project_id => $options->{project_id},
|
|
#studio_id => $options->{studio_id},
|
|
series_id => $options->{series_id},
|
|
draft => 0
|
|
}
|
|
);
|
|
@$events = sort { $a->{start} cmp $b->{start} } @$events;
|
|
|
|
# store events with recurrences by key (series_name, title, user_title, episode)
|
|
my $events_by_key = {};
|
|
for my $event (@$events) {
|
|
my $key = get_event_key($event);
|
|
next unless $key =~ /\#\d+$/;
|
|
$event->{key} = $key;
|
|
push @{ $events_by_key->{$key} }, $event;
|
|
}
|
|
|
|
# handle all events with the same key
|
|
for my $key ( sort keys %$events_by_key ) {
|
|
my $events = $events_by_key->{$key};
|
|
next unless scalar @$events > 0;
|
|
|
|
if ( scalar @$events == 1 ) {
|
|
|
|
# one event found -> check if recurrence is to be removed
|
|
my $event = $events->[0];
|
|
next if $event->{recurrence} == 0;
|
|
next if $event->{recurrence_count} == 0;
|
|
$event->{recurrence} = 0;
|
|
$event->{recurrence_count} = 0;
|
|
$event->{rerun} = 0;
|
|
series::update_recurring_event( $config, $event );
|
|
|
|
} elsif ( scalar @$events > 1 ) {
|
|
|
|
# multiple events found with same key
|
|
# first event is the original
|
|
my $event = $events->[0];
|
|
my $originalId = $event->{event_id};
|
|
|
|
# succeeding events are reruns
|
|
for ( my $c = 1 ; $c < scalar(@$events) ; $c++ ) {
|
|
my $event = $events->[$c];
|
|
|
|
my $update = 0;
|
|
$update = 1 if $event->{recurrence} ne $originalId;
|
|
$update = 1 if $event->{rerun} ne '1';
|
|
$update = 1 if $event->{recurrence_count} ne $c;
|
|
next if $update == 0;
|
|
|
|
$event->{recurrence} = $originalId;
|
|
$event->{recurrence_count} = $c;
|
|
$event->{rerun} = 1;
|
|
series::update_recurring_event( $config, $event );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
sub update_recurring_event($$) {
|
|
my $config = shift;
|
|
my $event = shift;
|
|
|
|
return undef unless defined $event->{event_id};
|
|
return undef unless defined $event->{recurrence};
|
|
return undef unless defined $event->{recurrence_count};
|
|
return undef unless defined $event->{rerun};
|
|
|
|
return unless $event->{event_id} =~ /^\d+$/;
|
|
return unless $event->{recurrence} =~ /^\d+$/;
|
|
return unless $event->{recurrence_count} =~ /^\d+$/;
|
|
return unless $event->{rerun} =~ /^\d+$/;
|
|
|
|
my $bind_values = [];
|
|
push @$bind_values, $event->{recurrence};
|
|
push @$bind_values, $event->{recurrence_count};
|
|
push @$bind_values, $event->{rerun};
|
|
push @$bind_values, $event->{id};
|
|
|
|
my $update_sql = qq{
|
|
update calcms_events
|
|
set recurrence=?, recurrence_count=?, rerun=?
|
|
where id=?
|
|
};
|
|
|
|
my $dbh = db::connect($config);
|
|
db::put( $dbh, $update_sql, $bind_values );
|
|
}
|
|
|
|
sub error($) {
|
|
my $msg = shift;
|
|
print "ERROR: $msg<br/>\n";
|
|
}
|
|
|
|
#do not delete last line!
|
|
1;
|