|
|
- =pod
-
- =head1 NAME
-
- App::Pieces - some utility functions for bookmarking and interlinking things
-
- =head1 SYNOPSIS
-
- tk tk tk
-
- =head1 INSTALLING
-
- $ perl Build.PL
- $ ./Build
- $ ./Build install
-
- =head1 DESCRIPTION
-
- tk tk tk
-
- =cut
-
- package App::Pieces;
-
- use strict;
- use warnings;
- use 5.10.0;
-
- use base qw(Exporter);
- our @EXPORT_OK = qw();
-
- our ($VERSION) = '0.0.1';
-
- use Carp;
- use DBI;
- use File::Basename;
- use File::HomeDir;
- use File::Spec;
- use URI;
-
- my %default = (
- dbfile => File::Spec->catfile(File::HomeDir->my_home, 'pieces.db')
- );
-
- =head1 SUBROUTINES
-
- =over
-
- =item new(%params)
-
- Get a new Pieces object with the specified parameters set.
-
- =cut
-
- sub new {
- my $class = shift;
- my %params = @_;
-
- my %copy_of_default = %default;
- my $self = \%copy_of_default;
- bless $self, $class;
-
- # Configure from passed-in values, overwriting defaults:
- for my $p (keys %params) {
- $self->{$p} = $params{$p};
- }
-
- $self->{dbh} = $self->get_dbh();
-
- return $self;
- }
-
- =item get_dbh()
-
- Get database handle for default pieces database, stored in F<~/pieces.db>.
-
- Creates a new database with the correct schema if one doesn't already exist.
-
- =cut
-
- sub get_dbh {
- my ($self) = shift;
- my $dbfile = $self->{dbfile};
-
- my $init_new = 0;
- $init_new = 1 unless -f $dbfile;
-
- my $dbh = DBI->connect("dbi:SQLite:dbname=$dbfile", "", "");
-
- $self->create_pieces_db($dbh) if $init_new;
-
- return $dbh;
- }
-
- =item create_pieces_db($dbh)
-
- Create new pieces tables.
-
- =cut
-
- sub create_pieces_db {
- my ($self) = shift;
- my ($dbh) = @_;
-
- # We'll stash what version of pieces created the schema, and when:
- $dbh->do(qq{
- CREATE TABLE schema_version (
- id integer primary key,
- version text DEFAULT '$VERSION',
- created text DEFAULT CURRENT_TIMESTAMP
- );
- });
-
- $dbh->do(q{ INSERT INTO schema_version DEFAULT VALUES; });
-
- $dbh->do(q{
- CREATE TABLE pieces (
- id integer primary key,
- address text,
- created text,
- modified text
- );
- });
-
-
- $dbh->do(q{
- CREATE TABLE links (
- id integer primary key,
- from_piece integer,
- to_piece integer,
- description text,
- created text
- );
- });
-
- $dbh->do(q{
- CREATE TABLE groups (
- id integer primary key,
- name text,
- description text,
- created text,
- modifed text
- );
- });
- }
-
- =item add(@addresses)
-
- Add one or more addresses to the pieces db.
-
- =cut
-
- sub add {
- my ($self) = shift;
- my (@addresses) = @_;
-
- # Filter out any paths that have already been marked:
- # XXX: This is gonna get pretty silly with thousands of entries to read every
- # time.
- my %addressmap = map { $_ => 1 } @addresses;
- $self->each_address(sub {
- my ($existing_addy) = @_;
- if ($addressmap{ $existing_addy }) {
- delete $addressmap{ $existing_addy };
- }
- });
-
- my $sth = $self->{dbh}->prepare(q{
- INSERT INTO pieces (address, created) VALUES (?, datetime('now'))
- });
-
- my @ids;
- foreach my $addy (keys %addressmap) {
- $sth->execute($addy);
-
- # The empty strings passed to last_insert_id() should just leave it
- # getting the last insert for the dbh:
- push @ids, $self->{dbh}->last_insert_id('', '', '', '');
- }
-
- return @ids;
- }
-
- sub get {
- my ($self) = shift;
- my ($addy) = @_;
-
- my $find_sth = $self->{dbh}->prepare(q{
- SELECT id FROM pieces WHERE address = ?;
- });
-
- my ($id) = $self->{dbh}->selectrow_array($find_sth, {}, $addy);
-
- return $id;
- }
-
- sub get_or_add {
- my ($self) = shift;
- my ($addy) = @_;
-
- my $id = $self->get($addy);
-
- # If we didn't find an existing piece, add it and get its id
- if (! defined $id) {
- ($id) = $self->add($addy);
- }
-
- return $id;
- }
-
- sub add_link {
- my ($self) = shift;
- my ($from, $to) = @_;
-
- my $from_id = $self->get_or_add($from);
- my $to_id = $self->get_or_add($to);
-
- my $sth = $self->{dbh}->prepare(q{
- INSERT INTO links (from_piece, to_piece, created) VALUES (?, ?, datetime('now'))
- });
-
- $sth->execute($from_id, $to_id);
- }
-
- =item remove(@paths)
-
- Remove all given paths from the mark list.
-
- =cut
-
- sub remove {
- my ($self) = shift;
- my (@addresses) = @_;
-
- my $sth = $self->{dbh}->prepare(q{
- DELETE FROM pieces WHERE address = ?;
- });
-
- foreach my $addy (@addresses) {
- $sth->execute($addy);
- }
- }
-
- =item each_address($func)
-
- Run an anonymous function against each item in the pieces list.
-
- Expects a sub which takes a path string.
-
- =cut
-
- sub each_address {
- my ($self) = shift;
- my ($func) = @_;
-
- my $sth = $self->{dbh}->prepare(q{
- SELECT DISTINCT(address) as address FROM pieces ORDER BY created;
- });
-
- $sth->execute();
-
- while (my $data = $sth->fetchrow_hashref()) {
- $func->($data->{address});
- }
- }
-
- sub foreach_row {
- my ($self) = shift;
- my ($query, $func) = @_;
-
- my $sth = $self->{dbh}->prepare($query);
- $sth->execute();
-
- while (my $data = $sth->fetchrow_hashref()) {
- $func->($data);
- }
- }
-
- =back
-
- =head1 AUTHOR
-
- Copyright 2018 Brennen Bearnes
-
- pieces is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- =cut
-
- 1;
|