App-DrivePlayer

 view release on metacpan or  search on metacpan

lib/App/DrivePlayer/DB.pm  view on Meta::CPAN

    my %cond = ( metadata_fetched => 0 );
    my %attr = ( order_by => \@TRACK_ORDER );
    if (defined $scan_folder_id) {
        $cond{'folder.scan_folder_id'} = $scan_folder_id;
        $attr{join} = 'folder';
    }
    return map { _row_to_hash($_) }
        $self->_rs('Track')->search(\%cond, \%attr)->all;
}

sub mark_metadata_fetched {
    my ($self, $id) = @_;
    my $row = $self->_rs('Track')->find($id) or return;
    $row->update({ metadata_fetched => 1 });
}

sub reset_metadata_fetched {
    my ($self) = @_;
    $self->_rs('Track')->update_all({ metadata_fetched => 0 });
}

sub reset_metadata_fetched_incomplete {
    my ($self) = @_;
    $self->_rs('Track')->search({
        metadata_fetched => 1,
        -or => [
            genre  => undef,
            genre  => '',
            artist => undef,
            artist => '',
            album  => undef,
            album  => '',
            year   => undef,
        ],
    })->update_all({ metadata_fetched => 0 });
}

sub clear_scan_folder_tracks {
    my ($self, $scan_folder_id) = @_;
    # Collect folder IDs, then bulk-delete tracks and folders.
    # (Relies on foreign_keys=ON cascade for correctness; explicit here for speed.)
    my @folder_ids = $self->_rs('Folder')
        ->search({ scan_folder_id => $scan_folder_id })
        ->get_column('id')->all;

    if (@folder_ids) {
        $self->_rs('Track')->search({ folder_id => \@folder_ids })->delete;
    }
    $self->_rs('Folder')->search({ scan_folder_id => $scan_folder_id })->delete;
}

sub count_unseen_tracks {
    my ($self, $scan_folder_id, $seen) = @_;
    my @keep = keys %$seen;
    my @folder_ids = $self->_rs('Folder')
        ->search({ scan_folder_id => $scan_folder_id })
        ->get_column('id')->all;
    return 0 unless @folder_ids;
    return $self->_rs('Track')->search({
        folder_id => { -in  => \@folder_ids },
        (@keep ? (drive_id => { -not_in => \@keep }) : ()),
    })->count;
}

sub remove_unseen_tracks {
    my ($self, $scan_folder_id, $seen) = @_;
    my @keep = keys %$seen;
    my @folder_ids = $self->_rs('Folder')
        ->search({ scan_folder_id => $scan_folder_id })
        ->get_column('id')->all;
    return 0 unless @folder_ids;
    return $self->_rs('Track')->search({
        folder_id => { -in  => \@folder_ids },
        (@keep ? (drive_id => { -not_in => \@keep }) : ()),
    })->delete;
}

sub remove_unseen_folders {
    my ($self, $scan_folder_id, $seen) = @_;
    my @keep = keys %$seen;
    return $self->_rs('Folder')->search({
        scan_folder_id => $scan_folder_id,
        (@keep ? (drive_id => { -not_in => \@keep }) : ()),
    })->delete;
}

1;

__END__

=head1 NAME

App::DrivePlayer::DB - SQLite database facade for the DrivePlayer library

=head1 SYNOPSIS

  use App::DrivePlayer::DB;

  my $db = App::DrivePlayer::DB->new(path => '/path/to/music.db');

  # Scan-folder management
  my $sf = $db->upsert_scan_folder($drive_id, 'My Music');
  my @sfs = $db->all_scan_folders;
  $db->delete_scan_folder($drive_id);   # cascades to folders + tracks

  # Track queries
  my @tracks = $db->all_tracks;
  my @tracks = $db->search_tracks('zeppelin');
  my @tracks = $db->tracks_by_artist('Queen');
  my @tracks = $db->tracks_by_album('Led Zeppelin IV');
  my $track  = $db->get_track_by_drive_id($drive_id);
  my $track  = $db->get_track($id);

  my @artists = $db->all_artists;
  my @albums  = $db->all_albums;
  my $count   = $db->track_count;

=head1 DESCRIPTION

A thin L<Moo> facade over a L<App::DrivePlayer::Schema> (L<DBIx::Class>) schema.
Handles database creation on first use and exposes a simple hashref-based
API so the rest of the application never touches DBIx::Class directly.

All query methods return plain hashrefs (or lists of hashrefs), never
DBIx::Class row objects.

=head1 ATTRIBUTES

=head2 path

  is: ro, isa: Str, required: 1

Filesystem path to the SQLite database file.  The parent directory is
created automatically if it does not exist.

=head2 schema

  is: lazy, isa: App::DrivePlayer::Schema

The underlying DBIx::Class schema object.  Built automatically on first
access; the database file and tables are created at that point if needed.

=head1 METHODS



( run in 0.916 second using v1.01-cache-2.11-cpan-39bf76dae61 )