forked from HPR/hpr-tools
		
	Moved project directories and files to an empty local repo
This commit is contained in:
		
							
								
								
									
										832
									
								
								Database/edit_episode
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										832
									
								
								Database/edit_episode
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,832 @@ | ||||
| #!/usr/bin/env perl | ||||
| #=============================================================================== | ||||
| # | ||||
| #         FILE: edit_episode | ||||
| # | ||||
| #        USAGE: ./edit_episode [-h] [-debug=N] [-config=FILE] [-[no]update] | ||||
| #                       [-[no]title] [-[no]summary] [-[no]tags] [-[no]notes] | ||||
| #                       [-[no]ctitle] [-[no]ctext] [-cnumber=N] shownumber | ||||
| # | ||||
| #  DESCRIPTION: A simple command-line editor for the HPR database | ||||
| # | ||||
| #      OPTIONS: --- | ||||
| # REQUIREMENTS: --- | ||||
| #         BUGS: --- | ||||
| #        NOTES: Had to revert to MySQL due to a problem with DBD::MariaDB | ||||
| #       AUTHOR: Dave Morriss (djm), Dave.Morriss@gmail.com | ||||
| #      VERSION: 0.1.3 | ||||
| #      CREATED: 2015-06-17 23:17:50 | ||||
| #     REVISION: 2022-02-16 20:07:45 | ||||
| # | ||||
| #=============================================================================== | ||||
|  | ||||
| use 5.010; | ||||
| use strict; | ||||
| use warnings; | ||||
| use utf8; | ||||
|  | ||||
| use Getopt::Long; | ||||
| use Pod::Usage; | ||||
|  | ||||
| use Config::General; | ||||
| use File::Temp; | ||||
| use File::Slurper qw{ read_text }; | ||||
| use SQL::Abstract; | ||||
| use DBI; | ||||
|  | ||||
| use Data::Dumper; | ||||
|  | ||||
| # | ||||
| # Version number (manually incremented) | ||||
| # | ||||
| our $VERSION = '0.1.3'; | ||||
|  | ||||
| # | ||||
| # Script and directory names | ||||
| # | ||||
| ( my $PROG = $0 ) =~ s|.*/||mx; | ||||
| ( my $DIR  = $0 ) =~ s|/?[^/]*$||mx; | ||||
| $DIR = '.' unless $DIR; | ||||
|  | ||||
| #------------------------------------------------------------------------------- | ||||
| # Declarations | ||||
| #------------------------------------------------------------------------------- | ||||
| # | ||||
| # Constants and other declarations | ||||
| # | ||||
| my $basedir    = "$ENV{HOME}/HPR/Database"; | ||||
| my $configfile = "$basedir/.hpr_db.cfg"; | ||||
|  | ||||
| # | ||||
| # Declarations | ||||
| # | ||||
| my ( $dbh, $sth1, $h1, $rc ); | ||||
| my (%changes); | ||||
|  | ||||
| # | ||||
| # Enable Unicode mode | ||||
| # | ||||
| binmode STDOUT, ":encoding(UTF-8)"; | ||||
| binmode STDERR, ":encoding(UTF-8)"; | ||||
|  | ||||
| # | ||||
| # Options and arguments | ||||
| # | ||||
| my %options; | ||||
| Options( \%options ); | ||||
|  | ||||
| # | ||||
| # Default help | ||||
| # | ||||
| pod2usage( -msg => "Version $VERSION\n", -exitval => 1 ) | ||||
|     if ( $options{'help'} ); | ||||
|  | ||||
| # | ||||
| # Collect options | ||||
| # | ||||
| my $DEBUG = ( $options{'debug'} ? $options{'debug'} : 0 ); | ||||
|  | ||||
| my $cfgfile | ||||
|     = ( defined( $options{config} ) ? $options{config} : $configfile ); | ||||
|  | ||||
| my $updatedb = ( defined( $options{'updatedb'} ) ? $options{'updatedb'} : 0 ); | ||||
|  | ||||
| my $title   = ( defined( $options{'title'} )   ? $options{'title'}   : 0 ); | ||||
| my $summary = ( defined( $options{'summary'} ) ? $options{'summary'} : 0 ); | ||||
| my $tags    = ( defined( $options{'tags'} )    ? $options{'tags'}    : 0 ); | ||||
| my $notes   = ( defined( $options{'notes'} )   ? $options{'notes'}   : 0 ); | ||||
| my $ctitle  = ( defined( $options{'ctitle'} )  ? $options{'ctitle'}  : 0 ); | ||||
| my $ctext   = ( defined( $options{'ctext'} )   ? $options{'ctext'}   : 0 ); | ||||
| my $cnumber = $options{'cnumber'}; | ||||
|  | ||||
| die "Select one of -title, -summary, -tags, -notes, -ctitle and -ctext\n" | ||||
|     unless ( $title || $summary || $tags || $notes || $ctitle || $ctext ); | ||||
|  | ||||
| die "Needs a comment number (-cnumber=N)\n" | ||||
|     if ( ( $ctitle || $ctext ) && ( !$cnumber ) ); | ||||
|  | ||||
| # | ||||
| # Get the arg | ||||
| # | ||||
| my $show = shift; | ||||
| pod2usage( -msg => "Specify the show number\n", -exitval => 1 ) unless $show; | ||||
|  | ||||
| # | ||||
| # Sanity check | ||||
| # | ||||
| die "Unable to find $cfgfile\n" unless ( -e $cfgfile ); | ||||
|  | ||||
| # | ||||
| # Load configuration data | ||||
| # | ||||
| my $conf = new Config::General( | ||||
|     -ConfigFile      => $cfgfile, | ||||
|     -InterPolateVars => 1, | ||||
|     -ExtendedAccess  => 1 | ||||
| ); | ||||
| my %config = $conf->getall(); | ||||
|  | ||||
| # | ||||
| # Connect to the database | ||||
| # | ||||
| my $dbhost = $config{database}->{host} // '127.0.0.1'; | ||||
| my $dbport = $config{database}->{port} // 3306; | ||||
| my $dbname = $config{database}->{name}; | ||||
| my $dbuser = $config{database}->{user}; | ||||
| my $dbpwd  = $config{database}->{password}; | ||||
|  | ||||
| #$dbh = DBI->connect( "DBI:MariaDB:database=$dbname;host=$dbhost;port=$dbport", | ||||
| #    $dbuser, $dbpwd, { AutoCommit => 1 } ) | ||||
| #    or die $DBI::errstr; | ||||
|  | ||||
| $dbh = DBI->connect( "dbi:mysql:database=$dbname;host=$dbhost;port=$dbport", | ||||
|     $dbuser, $dbpwd, { AutoCommit => 1 } ) | ||||
|     or die $DBI::errstr; | ||||
|  | ||||
| # | ||||
| # Enable client-side UTF8 | ||||
| # | ||||
| $dbh->{mysql_enable_utf8} = 1; | ||||
|  | ||||
| # | ||||
| # Prepare to read the database for the selected episode and count the number | ||||
| # of comments it has in case we need to know later. | ||||
| # | ||||
| $sth1 = $dbh->prepare(q{ | ||||
|     SELECT | ||||
|         e.*, count(c.id) as comment_count | ||||
|     FROM eps e | ||||
|     LEFT JOIN comments c ON e.id = c.eps_id | ||||
|     GROUP BY e.id | ||||
|     HAVING e.id = ? | ||||
| }); | ||||
| $sth1->execute($show); | ||||
| if ( $dbh->err ) { | ||||
|     warn $dbh->errstr; | ||||
| } | ||||
|  | ||||
| # | ||||
| # Did we find the episode? | ||||
| # | ||||
| if ( $h1 = $sth1->fetchrow_hashref ) { | ||||
|     # | ||||
|     # Found, so do the episode details need changing? | ||||
|     # | ||||
|     if ( $title || $summary || $tags || $notes ) { | ||||
|         change_episode( $dbh, $h1, $show, $updatedb, $title, $summary, $tags, | ||||
|             $notes ); | ||||
|     } | ||||
|  | ||||
|     # | ||||
|     # Are we to change comment details? | ||||
|     # | ||||
|     if ( $ctitle || $ctext ) { | ||||
|         if ( $h1->{comment_count} > 0 ) { | ||||
|             change_comment( $dbh, $h1, $show, $cnumber, $updatedb, $ctitle, | ||||
|                 $ctext ); | ||||
|         } | ||||
|         else { | ||||
|             print "This show has no comments\n"; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| else { | ||||
|     print "Unable to find show number $show\n"; | ||||
| } | ||||
|  | ||||
| #$dbh->disconnect; | ||||
|  | ||||
| exit; | ||||
|  | ||||
| #===  FUNCTION  ================================================================ | ||||
| #         NAME: change_episode | ||||
| #      PURPOSE: Make changes to a row in the 'eps' table for a show | ||||
| #   PARAMETERS: $dbh            open handle of the MySQL database | ||||
| #               $h              handle of the query that returned the episode | ||||
| #                               record and comment count | ||||
| #               $show           show number being updated | ||||
| #               $updatedb       Boolean; true when changes are to be made | ||||
| #               $title          Boolean; true when the episode title is to be | ||||
| #                               changed | ||||
| #               $summary        Boolean; true when the episode summary is to be | ||||
| #                               changed | ||||
| #               $tags           Boolean; true when the episode tags are to be | ||||
| #                               changed | ||||
| #               $notes          Boolean; true when the episode notes are to be | ||||
| #                               changed | ||||
| #      RETURNS: Nothing | ||||
| #  DESCRIPTION: The episode has been found in the database. The requested | ||||
| #               changes are applied. If after comparing old with new changes | ||||
| #               are found they are applied, otherwise nothing is done. | ||||
| #       THROWS: No exceptions | ||||
| #     COMMENTS: None | ||||
| #     SEE ALSO: N/A | ||||
| #=============================================================================== | ||||
| sub change_episode { | ||||
|     my ( $dbh, $h, $show, $updatedb, $title, $summary, $tags, $notes ) = @_; | ||||
|  | ||||
|     my (%changes); | ||||
|  | ||||
|     #<<< [perltidy messes up the following] | ||||
|     if ($title) { | ||||
|         $changes{title} = check_field( 'title', | ||||
|             scalar( run_editor( $h->{title} ) ), 100, qr{(\n)} ); | ||||
|     } | ||||
|     if ($summary) { | ||||
|         $changes{summary} = check_field( 'summary', | ||||
|             scalar( run_editor( $h->{summary} ) ), 100, qr{(\n)} ); | ||||
|     } | ||||
|     if ($tags) { | ||||
|         $changes{tags} = check_field( 'tags', | ||||
|             scalar( run_editor( $h->{tags} ) ), 200, qr{(\n)} ); | ||||
|     } | ||||
|     if ($notes) { | ||||
|         $changes{notes} = run_editor( $h->{notes}, ['+set filetype=html'] ); | ||||
|     } | ||||
|     #>>> | ||||
|     print Dumper( \%changes ), "\n" if ( $DEBUG > 2 ); | ||||
|  | ||||
|     # | ||||
|     # Are we updating the database then? | ||||
|     # | ||||
|     if ($updatedb) { | ||||
|         # | ||||
|         # Was anything edited? | ||||
|         # | ||||
|         if (%changes) { | ||||
|             # | ||||
|             # Did the edits do anything? If not delete the element from the | ||||
|             # hash since there's no point writing it to the database | ||||
|             # | ||||
|             for my $key ( keys(%changes) ) { | ||||
|                 if ( $changes{$key} eq $h->{$key} ) { | ||||
|                     print "No change made to $key, ignored\n"; | ||||
|                     delete( $changes{$key} ); | ||||
|                 } | ||||
|             } | ||||
|             print Dumper( \%changes ), "\n" if ( $DEBUG > 2 ); | ||||
|         } | ||||
|  | ||||
|         # | ||||
|         # If there's anything left apply the changes | ||||
|         # | ||||
|         if (%changes) { | ||||
|             # | ||||
|             # Go into transaction mode here so we can fail safely | ||||
|             # | ||||
|             $rc = $dbh->begin_work or die $dbh->errstr; | ||||
|  | ||||
|             my $sql = SQL::Abstract->new; | ||||
|             my %where = ( id => $show ); | ||||
|             my ( $stmt, @bind ) = $sql->update( 'eps', \%changes, \%where ); | ||||
|  | ||||
|             my $sth = $dbh->prepare($stmt); | ||||
|             my $rv  = $sth->execute(@bind); | ||||
|  | ||||
|             # | ||||
|             # Respond to any error by rolling back | ||||
|             # | ||||
|             if ( $dbh->err ) { | ||||
|                 warn $dbh->errstr; | ||||
|                 eval { $dbh->rollback }; | ||||
|                 $rv = 0; | ||||
|             } | ||||
|             else { | ||||
|                 $dbh->commit; | ||||
|             } | ||||
|             $rv = 0 if ( $rv eq '0E0' ); | ||||
|  | ||||
|             # | ||||
|             # Report the update | ||||
|             # | ||||
|             if ($rv) { | ||||
|                 my $ccount = scalar( keys(%changes) ); | ||||
|                 printf "Updated database (%d %s to the eps row)\n", | ||||
|                     $ccount, _plural( 'change', $ccount ); | ||||
|             } | ||||
|             else { | ||||
|                 print "Episode not updated due to error\n"; | ||||
|             } | ||||
|  | ||||
|         } | ||||
|         else { | ||||
|             # | ||||
|             # No changes were found | ||||
|             # | ||||
|             print "There was nothing to do\n"; | ||||
|         } | ||||
|     } | ||||
|     else { | ||||
|         print "Option -noupdatedb chosen database not updated\n"; | ||||
|     } | ||||
|  | ||||
|     return; | ||||
| } | ||||
|  | ||||
| #===  FUNCTION  ================================================================ | ||||
| #         NAME: change_comment | ||||
| #      PURPOSE: Make changes to a comment relating to a show | ||||
| #   PARAMETERS: $dbh            open handle of the MySQL database | ||||
| #               $h              handle of the query that returned the episode | ||||
| #                               record and comment count | ||||
| #               $show           show number being updated | ||||
| #               $cnumber        comment number within show | ||||
| #               $updatedb       Boolean; true when changes are to be made | ||||
| #               $ctitle         Boolean; true when the comment title is to be | ||||
| #                               changed | ||||
| #               $ctext          Boolean; true when the comment text is to be | ||||
| #                               changed | ||||
| #      RETURNS: Nothing | ||||
| #  DESCRIPTION: The episode has been found in the database and the number of | ||||
| #               comments determined. We know there are more than zero comments | ||||
| #               otherwise this routine woulkd not have been called. We check | ||||
| #               that the requested comment number is in range here (if could | ||||
| #               have been done before invocation). We query the target comment | ||||
| #               and modify one or both of the requested fields. If, after | ||||
| #               comparing old with new, changes are found, they are applied, | ||||
| #               otherwise nothing is done. | ||||
| #       THROWS: No exceptions | ||||
| #     COMMENTS: None | ||||
| #     SEE ALSO: N/A | ||||
| #=============================================================================== | ||||
| sub change_comment { | ||||
|     my ( $dbh, $h, $show, $cnumber, $updatedb, $ctitle, $ctext ) = @_; | ||||
|  | ||||
|     my ( $sth1, $h1 ); | ||||
|     my (%changes); | ||||
|  | ||||
|     if ( $cnumber <= $h->{comment_count} ) { | ||||
|         # | ||||
|         # Get the requested comment | ||||
|         # | ||||
|         $sth1 = $dbh->prepare( | ||||
|             q{ | ||||
|                 SELECT * | ||||
|                 FROM comments | ||||
|                 WHERE eps_id = ? | ||||
|                 ORDER BY comment_timestamp | ||||
|                 LIMIT 1 | ||||
|                 OFFSET ? | ||||
|             } | ||||
|         ); | ||||
|         $sth1->execute( $show, $cnumber - 1 ); | ||||
|         if ( $dbh->err ) { | ||||
|             warn $dbh->errstr; | ||||
|         } | ||||
|  | ||||
|         # | ||||
|         # If found perform changes, otherwise it wasn't found (not sure how | ||||
|         # that's possible but you never know) | ||||
|         # | ||||
|         if ( $h1 = $sth1->fetchrow_hashref ) { | ||||
|             if ($ctitle) { | ||||
|                 $changes{comment_title} = run_editor( $h1->{comment_title} ); | ||||
|             } | ||||
|             if ($ctext) { | ||||
|                 $changes{comment_text} = run_editor( $h1->{comment_text} ); | ||||
|             } | ||||
|             print Dumper( \%changes ), "\n" if ( $DEBUG > 2 ); | ||||
|  | ||||
|             # | ||||
|             # Are we updating the database then? | ||||
|             # | ||||
|             if ($updatedb) { | ||||
|                 # | ||||
|                 # Was anything edited? | ||||
|                 # | ||||
|                 if (%changes) { | ||||
|                     # | ||||
|                     # Did the edits do anything? If not delete the element from the | ||||
|                     # hash since there's no point writing it to the database | ||||
|                     # | ||||
|                     for my $key ( keys(%changes) ) { | ||||
|                         if ( $changes{$key} eq $h1->{$key} ) { | ||||
|                             print "No change made to $key, ignored\n"; | ||||
|                             delete( $changes{$key} ); | ||||
|                         } | ||||
|                     } | ||||
|                     print Dumper( \%changes ), "\n" if ( $DEBUG > 2 ); | ||||
|                 } | ||||
|  | ||||
|                 # | ||||
|                 # If there's anything left apply the changes | ||||
|                 # | ||||
|                 if (%changes) { | ||||
|                     # | ||||
|                     # Go into transaction mode here so we can fail safely | ||||
|                     # | ||||
|                     $rc = $dbh->begin_work or die $dbh->errstr; | ||||
|  | ||||
|                     my $sql = SQL::Abstract->new; | ||||
|                     my %where = ( id => $h1->{id} ); | ||||
|                     my ( $stmt, @bind ) | ||||
|                         = $sql->update( 'comments', \%changes, \%where ); | ||||
|  | ||||
|                     my $sth = $dbh->prepare($stmt); | ||||
|                     my $rv  = $sth->execute(@bind); | ||||
|  | ||||
|                     # | ||||
|                     # Respond to any error by rolling back | ||||
|                     # | ||||
|                     if ( $dbh->err ) { | ||||
|                         warn $dbh->errstr; | ||||
|                         eval { $dbh->rollback }; | ||||
|                         $rv = 0; | ||||
|                     } | ||||
|                     else { | ||||
|                         $dbh->commit; | ||||
|                     } | ||||
|                     $rv = 0 if ( $rv eq '0E0' ); | ||||
|  | ||||
|                     # | ||||
|                     # Report the update | ||||
|                     # | ||||
|                     if ($rv) { | ||||
|                         my $ccount = scalar(keys(%changes)); | ||||
|                         printf "Updated database (%d %s to the comments row)\n", | ||||
|                             $ccount, _plural( 'change', $ccount ); | ||||
|                     } | ||||
|                     else { | ||||
|                         print "Comment not updated due to error\n"; | ||||
|                     } | ||||
|  | ||||
|                 } | ||||
|                 else { | ||||
|                     print "There was nothing to do\n"; | ||||
|                 } | ||||
|             } | ||||
|             else { | ||||
|                 print "Option -noupdatedb chosen database not updated\n"; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     else { | ||||
|         print "Requested comment is out of range\n"; | ||||
|     } | ||||
|  | ||||
|     return; | ||||
| } | ||||
|  | ||||
| #===  FUNCTION  ================================================================ | ||||
| #         NAME: run_editor | ||||
| #      PURPOSE: Run an interactive vim editor on a string | ||||
| #   PARAMETERS: $string         String to edit | ||||
| #               $options        An arrayref containing options for vim | ||||
| #                               (optional) Example '+set paste'. Each option | ||||
| #                               (such as '-c startinsert') needs to be | ||||
| #                               a separate array element. | ||||
| #      RETURNS: Edited string | ||||
| #  DESCRIPTION: Makes a temporary file with File::Temp ensuring that the file | ||||
| #               is in utf8 mode. Writes the edit string to the file and invokes | ||||
| #               the 'vim' editor on it. The resulting file is then read back | ||||
| #               into a string and returned to the caller, again taking care to | ||||
| #               retain utf8 mode. | ||||
| #       THROWS: No exceptions | ||||
| #     COMMENTS: File::Slurp and UTF-8 don't go well together. Moved to | ||||
| #               File::Slurper instead | ||||
| #     SEE ALSO: N/A | ||||
| #=============================================================================== | ||||
| sub run_editor { | ||||
|     my ( $string, $options ) = @_; | ||||
|  | ||||
|     # | ||||
|     # Build an arguments array for 'system' | ||||
|     # | ||||
|     my @args; | ||||
|     push( @args, @$options ) if $options; | ||||
|  | ||||
|     # | ||||
|     # Make a temporary file | ||||
|     # | ||||
|     my $tfh = File::Temp->new; | ||||
|     binmode $tfh, ":encoding(UTF-8)"; | ||||
|     my $tfn = $tfh->filename; | ||||
|     print $tfh $string if $string; | ||||
|     $tfh->close; | ||||
|  | ||||
|     # | ||||
|     # Add the filename to the arguments | ||||
|     # | ||||
|     push( @args, $tfn ); | ||||
|  | ||||
|     die "Edit failed\n" | ||||
|         unless ( system( ( 'vim', @args ) ) == 0 ); | ||||
|  | ||||
|     return read_text($tfn); | ||||
| } | ||||
|  | ||||
| #===  FUNCTION  ================================================================ | ||||
| #         NAME: check_field | ||||
| #      PURPOSE: Checks the a field is not too long and doesn't contain certain | ||||
| #               characters | ||||
| #   PARAMETERS: $name           name of field | ||||
| #               $field          string to be checked | ||||
| #               $maxlen         maximum string length | ||||
| #               $regex          regex containing illegal characters to be removed | ||||
| #      RETURNS: The input string truncated and with any illegal characters | ||||
| #               removed. | ||||
| #  DESCRIPTION: Runs a substitution on the string then truncates the result if | ||||
| #               it is too long. | ||||
| #       THROWS: No exceptions | ||||
| #     COMMENTS: None | ||||
| #     SEE ALSO: N/A | ||||
| #=============================================================================== | ||||
| sub check_field { | ||||
|     my ( $name, $field, $maxlen, $regex ) = @_; | ||||
|  | ||||
|     return unless $field; | ||||
|  | ||||
|     $field =~ s/$regex//g; | ||||
|     if ( length($field) > $maxlen ) { | ||||
|         warn "Field '$name' too long (" | ||||
|             . length($field) | ||||
|             . "); truncated to " | ||||
|             . $maxlen . "\n"; | ||||
|         $field = substr( $field, 0, $maxlen ); | ||||
|     } | ||||
|     return $field; | ||||
| } | ||||
|  | ||||
| #===  FUNCTION  ================================================================ | ||||
| #         NAME: _plural | ||||
| #      PURPOSE: Add an 's' to a word depending on a number | ||||
| #   PARAMETERS: $word           word to pluralise | ||||
| #               $count          number being used in message | ||||
| #      RETURNS: The word in a plural form or not | ||||
| #  DESCRIPTION: Just hides the expression that adds an 's' or not behind | ||||
| #               a function call | ||||
| #       THROWS: No exceptions | ||||
| #     COMMENTS: None | ||||
| #     SEE ALSO: N/A | ||||
| #=============================================================================== | ||||
| sub _plural { | ||||
|     my ( $word, $count ) = @_; | ||||
|  | ||||
|     return $word . ( abs($count) != 1 ? 's' : '' ); | ||||
| } | ||||
|  | ||||
| #===  FUNCTION  ================================================================ | ||||
| #         NAME: Options | ||||
| #      PURPOSE: Processes command-line options | ||||
| #   PARAMETERS: $optref     Hash reference to hold the options | ||||
| #      RETURNS: Undef | ||||
| #  DESCRIPTION: | ||||
| #       THROWS: no exceptions | ||||
| #     COMMENTS: none | ||||
| #     SEE ALSO: n/a | ||||
| #=============================================================================== | ||||
| sub Options { | ||||
|     my ($optref) = @_; | ||||
|  | ||||
|     my @options = ( | ||||
|         "help",     "debug=i", "config=s", "updatedb!", "title!", | ||||
|         "summary!", "tags!",   "notes!", "ctitle!", "ctext!", "cnumber=i", | ||||
|     ); | ||||
|  | ||||
|     if ( !GetOptions( $optref, @options ) ) { | ||||
|         pod2usage( -msg => "Version $VERSION\n", -exitval => 1 ); | ||||
|     } | ||||
|  | ||||
|     return; | ||||
| } | ||||
|  | ||||
| __END__ | ||||
|  | ||||
| #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||||
| #  Application Documentation | ||||
| #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||||
| #{{{ | ||||
|  | ||||
| =head1 NAME | ||||
|  | ||||
| edit_episode - edit one or more fields in the database for a given HPR show | ||||
|  | ||||
| =head1 VERSION | ||||
|  | ||||
| This documentation refers to edit_episode version 0.1.3 | ||||
|  | ||||
|  | ||||
| =head1 USAGE | ||||
|  | ||||
|     edit_episode [-help] [-debug=N] [-config=FILE] [-[no]updatedb] [-[no]title] | ||||
|         [-[no]summary] [-[no]tags] [-[no]notes] [-[no]ctitle] [-[no]ctext] | ||||
|         [-cnumber=N] shownumber | ||||
|  | ||||
|     edit_episode -updatedb -title 1234 | ||||
|     edit_episode -updatedb -title -summary 2000 | ||||
|     edit_episode -updatedb -tags 2050 | ||||
|     edit_episode -updatedb -notes 2045 | ||||
|     edit_episode -updatedb -ctext -cnumber=1 2813 | ||||
|  | ||||
|  | ||||
| =head1 REQUIRED ARGUMENTS | ||||
|  | ||||
| =over 4 | ||||
|  | ||||
| =item B<shownumber> | ||||
|  | ||||
| The script must be provided with a single show number to operate on. | ||||
|  | ||||
| =back | ||||
|  | ||||
| =head1 OPTIONS | ||||
|  | ||||
| =over 4 | ||||
|  | ||||
| =item B<-[no]updatedb> | ||||
|  | ||||
| This option is required to make the script apply any changes that are made to | ||||
| the database. By default no updates are applied (B<-noupdatedb>). | ||||
|  | ||||
| =item B<-[no]title> | ||||
|  | ||||
| This option, if given (as B<-title>) indicates that the 'title' field of the | ||||
| row for the selected episode is to be edited. The Vim editor is invoked to | ||||
| make changes. The default is B<-notitle> meaning that this field is not to be | ||||
| edited. | ||||
|  | ||||
| =item B<-[no]summary> | ||||
|  | ||||
| This option, if given (as B<-summary>) indicates that the 'summary' field of the | ||||
| row for the selected episode is to be edited. The Vim editor is invoked to | ||||
| make changes. The default is B<-nosummary> meaning that this field is not to be | ||||
| edited. | ||||
|  | ||||
| =item B<-[no]tags> | ||||
|  | ||||
| This option, if given (as B<-tags>) indicates that the 'tags' field of the | ||||
| row for the selected episode is to be edited. The Vim editor is invoked to | ||||
| make changes. The default is B<-notags> meaning that this field is not to be | ||||
| edited. | ||||
|  | ||||
| =item B<-[no]notes> | ||||
|  | ||||
| This option, if given (as B<-notes>) indicates that the 'notes' field of the | ||||
| row for the selected episode is to be edited. The Vim editor is invoked to | ||||
| make changes. The default is B<-nonotes> meaning that this field is not to be | ||||
| edited. | ||||
|  | ||||
| =item B<-[no]ctitle> | ||||
|  | ||||
| This option, if given (as B<-ctitle>) indicates that the 'title' field of the | ||||
| row for the selected comment is to be edited. The Vim editor is invoked to | ||||
| make changes. The default is B<-noctitle> meaning that this field is not to be | ||||
| edited. | ||||
|  | ||||
| =item B<-[no]ctext> | ||||
|  | ||||
| This option, if given (as B<-ctext>) indicates that the 'comment_text' field | ||||
| of the row for the selected comment is to be edited. The Vim editor is invoked | ||||
| to make changes. The default is B<-noctext> meaning that this field is not to | ||||
| be edited. | ||||
|  | ||||
| =item B<-cnumber=N> | ||||
|  | ||||
| If comment fields are being edited then a comment index is required. The | ||||
| comments are numbered starting from 1 and are sorted in the submission | ||||
| timestamp order. This number must be in the range 1..N where I<N> is the | ||||
| number of comments on this particular show. | ||||
|  | ||||
| =item B<-config=FILE> | ||||
|  | ||||
| This option allows an alternative configuration file to be used. This file | ||||
| defines the location of the database, its port, its name and the username and | ||||
| password to be used to access it. This feature was added to allow the script | ||||
| to access alternative databases or the live database over an SSH tunnel. | ||||
|  | ||||
| See the CONFIGURATION AND ENVIRONMENT section below for the file format. | ||||
|  | ||||
| If the option is omitted the default file is used: B<.hpr_db.cfg> | ||||
|  | ||||
| =back | ||||
|  | ||||
| At least one of the options B<-title>, B<-summary>, B<-tags> and B<-notes> | ||||
| must be provided otherwise the script will abort with an error. | ||||
|  | ||||
| =head1 DESCRIPTION | ||||
|  | ||||
| The script B<edit_episode> provides an editor interface to certain fields in | ||||
| the HPR database. The fields are: | ||||
|  | ||||
| =over 4 | ||||
|  | ||||
| =item B<title> | ||||
|  | ||||
|     A single line of up to 100 characters of text. The line is rendered as an | ||||
|     "<h1>" tag on the web page and is incorporated into the RSS feed, so it | ||||
|     must only contain characters legal in these contexts. | ||||
|  | ||||
| =item B<summary> | ||||
|  | ||||
|     A single line of up to 100 characters of text. The line is rendered as an | ||||
|     "<h3>" tag on the web page and is incorporated into the RSS feed, so it | ||||
|     must only contain characters legal in these contexts. | ||||
|  | ||||
| =item B<tags> | ||||
|  | ||||
|     A single line of up to 200 characters of text. The field holds tags | ||||
|     relevant to the content of the episode in CSV format. | ||||
|  | ||||
| =item B<notes> | ||||
|  | ||||
|     A block of HTML which is to be included inside "<article>" tags making up | ||||
|     the show notes on the web page for the episode. | ||||
|  | ||||
| =item B<comment_title> | ||||
|  | ||||
|     A single line of text. The title is stored in a 'text' field in the | ||||
|     database and could be of any length, but will not be rendered correctly | ||||
|     if it exceeds 100 characters. | ||||
|  | ||||
| =item B<comment_text> | ||||
|  | ||||
|     A block of text (NOT HTML) which is the body of the comment. There are no | ||||
|     limit contraints here although the code that initiaslly accepts a comment | ||||
|     does impose a limit. Thus it would be unwise to make this field too large. | ||||
|  | ||||
| =back | ||||
|  | ||||
| =head1 DIAGNOSTICS | ||||
|  | ||||
| =over 4 | ||||
|  | ||||
| =item B<Select one of -title, -summary, -tags, -notes, -ctitle and -ctext> | ||||
|  | ||||
| At least one of these options is required. This a fatal error. | ||||
|  | ||||
| =item B<Needs a comment number (-cnumber=N)> | ||||
|  | ||||
| If one of B<-ctitle> and B<-ctext> is provided then a comment number is needed. | ||||
|  | ||||
| =item B<Specify the show number> | ||||
|  | ||||
| The show number has been omitted. This a fatal error. | ||||
|  | ||||
| =item B<DBI connect ... failed: Access denied for user ... > | ||||
|  | ||||
| The database connection has been denied. Check the configuration details (see | ||||
| below). This a fatal error. | ||||
|  | ||||
| =item B<Edit failed> | ||||
|  | ||||
| If the Vim edit session fails in some way the script reports it this way. | ||||
|  | ||||
| =back | ||||
|  | ||||
| =head1 CONFIGURATION AND ENVIRONMENT | ||||
|  | ||||
| The script obtains the credentials it requires to open the HPR database from | ||||
| a configuration file. The name of the file it expects is B<.hpr_db.cfg> in the | ||||
| directory holding the script. This configuration file can be overridden using | ||||
| the B<-config=FILE> option as described above. | ||||
|  | ||||
| The configuration file format is as follows: | ||||
|  | ||||
|  <database> | ||||
|      host = 127.0.0.1 | ||||
|      port = PORT | ||||
|      name = DATABASE | ||||
|      user = USERNAME | ||||
|      password = PASSWORD | ||||
|  </database> | ||||
|  | ||||
| =head1 DEPENDENCIES | ||||
|  | ||||
|  Config::General | ||||
|  DBI | ||||
|  Data::Dumper | ||||
|  File::Slurp | ||||
|  File::Temp | ||||
|  Getopt::Long | ||||
|  Pod::Usage | ||||
|  SQL::Abstract | ||||
|  | ||||
| =head1 BUGS AND LIMITATIONS | ||||
|  | ||||
| There are no known bugs in this module. | ||||
| Please report problems to Dave Morriss  (Dave.Morriss@gmail.com) | ||||
| Patches are welcome. | ||||
|  | ||||
| =head1 AUTHOR | ||||
|  | ||||
| Dave Morriss (Dave.Morriss@gmail.com) | ||||
|  | ||||
|  | ||||
| =head1 LICENCE AND COPYRIGHT | ||||
|  | ||||
| Copyright (c) 2015-2019 Dave Morriss (Dave.Morriss@gmail.com). All rights reserved. | ||||
|  | ||||
| This module is free software; you can redistribute it and/or | ||||
| modify it under the same terms as Perl itself. See perldoc perlartistic. | ||||
|  | ||||
| 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. | ||||
|  | ||||
| =cut | ||||
|  | ||||
| #}}} | ||||
|  | ||||
| # [zo to open fold, zc to close] | ||||
|  | ||||
| # vim: syntax=perl:ts=8:sw=4:et:ai:tw=78:fo=tcrqn21:fdm=marker | ||||
		Reference in New Issue
	
	Block a user