Optimize perl code - perl

I have to write to check array ref for more than 3 params. If the value is coming from an array then I have written a foreach loop for that, then chop that and assign to a new variable after concatenating pipe.
Code
if ( defined $args->{hotel} ) {
if ( ref( $args->{hotel} ) eq "ARRAY" ) {
foreach my $hotel ( #{ $args->{hotel} } ) {
$hotel .= $hotel . "|";
}
chop($hotel);
$args->{hotel_name} = $hotel;
} else {
$args->{hotel_name} = $args->{hotel};
}
} else {
$args->{hotel_name} = $hotel;
}
if ( defined $args->{country} ) {
if ( ref( $args->{country} ) eq "ARRAY" ) {
foreach my $country_name ( #{ $args->{country} } ) {
$country_name .= $country_name . "|";
}
chop($country_name);
$args->{country_name} = $country_name;
} else {
$args->{country_name} = $args->{country};
}
} else {
$args->{country_name} = $country_name;
}
if ( defined $args->{city} ) {
if ( ref( $args->{city} ) eq "ARRAY" ) {
foreach my $city ( #{ $args->{city} } ) {
$city .= $city . "|";
}
chop($city);
$args->{city_name} = $city;
} else {
$args->{city_name} = $args->{city};
}
} else {
$args->{city_name} = $city;
}
I want to write a function for this kind of work so that there will be no repetition of same code. Please help me; how can we do this in Perl?

You can write:
sub convert_to_name ($$) { # ($value, $fallback_name)
my ($value, $fallback_name) = #_;
if (defined $value) {
if (ref($value) eq 'ARRAY') {
return join '|', #$value;
} else {
return "$value";
}
} else {
return $fallback_name;
}
}
$args->{'hotel_name'} = convert_to_name $args->{'hotel'}, $hotel;
$args->{'country_name'} = convert_to_name $args->{'country'}, $country;
$args->{'city_name'} = convert_to_name $args->{'city'}, $city;

There appear to be some potential bugs in your code, the biggest centering around reusing variable names at lower scopes.
However, of course you can add an iteration loop to your code that would remove the need for 3 nearly identical sections. The following does that by creating a intermediate hash data structure to relate field names to values.
Note: I also simplified the code by inverting the logic if your first if statement so that all ifs could be at the same level. Additionally, it makes sense to use a join instead of rolling your own such functionality.
my %hash = (
hotel => $hotel,
country => $country_name,
city => $city,
);
while ( my ( $field, $value ) = each %hash ) {
if ( !defined $args->{$field} ) {
$args->{"${field}_name"} = $value;
} elsif ( ref( $args->{$field} ) eq "ARRAY" ) {
$args->{"${field}_name"} = join '|', #{ $args->{$field} };
} else {
$args->{"${field}_name"} = $args->{$field};
}
}
Also, if you're comfortable with the Conditional operator, this can be reduced further. However, some would consider this too cluttered:
while ( my ( $field, $value ) = each %hash ) {
$args->{"${field}_name"} = !defined $args->{$field}
? $value
: ref( $args->{$field} ) eq "ARRAY"
? join( '|', #{ $args->{$field} } )
: $args->{$field};
}

Related

Remove duplicated date in Woocommerce product page

I'm using "Woo estimated shipping date" plugin to sell pre-order products with estimated shipping date but the pluging show the message plus the date, and I need to show only the message not the "06/04/2022:
That is given by the product page editor option in "Estimated Delivery Time in Days":
Here's the plugin code:
<?php
namespace Saimon\WCESD\Views;
use Saimon\WCESD\Date_Calculator;
use Saimon\WCESD\Helper;
defined( 'ABSPATH' ) || exit;
class Single_Product {
public function __construct() {
$this->hooks();
}
private function hooks() {
add_action( 'woocommerce_after_add_to_cart_form', [ self::class, 'show_date' ] );
}
public static function show_date() {
if ( 'yes' !== Helper::get_option( 'wc_esd_date_enable' ) ) {
return;
}
$wc_esd_date = Helper::get_option( 'wc_esd_date' );
$wc_esd_date = $wc_esd_date ? $wc_esd_date : 5;
$wc_esd_date_message = Helper::get_option( 'wc_esd_date_message' );
$wc_esd_date_message = $wc_esd_date_message ? $wc_esd_date_message : __( 'Estimated Delivery Date', 'wcesd' );
$today = strtotime( current_time( 'mysql' ) );
$to_date = '';
if ( Helper::is_weekend_excluded() ) {
$date = ( new Date_Calculator( $today, $wc_esd_date ) )->get_date();
if ( Helper::is_date_range_enabled() ) {
$wc_esd_date = $wc_esd_date + Helper::get_date_range_gap();
$to_date = ( new Date_Calculator( $today, $wc_esd_date ) )->get_date();
}
} else {
$date = ( new Date_Calculator( $today, $wc_esd_date, false ) )->get_date();
if ( Helper::is_date_range_enabled() ) {
$wc_esd_date = $wc_esd_date + Helper::get_date_range_gap();
$to_date = ( new Date_Calculator( $today, $wc_esd_date ) )->get_date();
}
}
if ( ! empty( $to_date ) ) {
$message = $wc_esd_date_message . ' ' . Helper::display_date( $date ) . ' - ' . Helper::display_date( $to_date );
} else {
$message = $wc_esd_date_message . ' ' . Helper::display_date( $date );
}
$html = '<div class="wesd-box">';
$html .= '<strong class="shipper-date">';
$html .= $message;
$html .= '</strong>';
$html .= '</div>';
echo wp_kses_post(
$html
);
}
}
And I need to achieve this:
The problem is if I don't put a day in the "Estimated delivery time in days" field, the system use a default 5 days time and put the date again (06/04/2022) again.
Any idea how to achieve this guys? Thank you very much.

Custom Storable hooks for dclone-ing a light-weight object referencing a heavy-weight object

Say I have a tiny object that has a reference to a huge object:
package Tiny;
sub new {
my ($class, $tiny, $large) = #_;
return bless { tiny => $tiny, large => $large };
}
I'd like to create a STORABLE_freeze/STORABLE_thaw pair that lets me (recursively) clone $tiny but maintain/keep the reference to $large as-is without cloning $large too.
I tried temporarily deleting $self->{large} (see below), and putting it in a hash with a Scalar::Util::refaddr key and a weak reference to $large, serializing the rest of $self, and then putting the (weak) reference back into both the original object immediately and the cloned one in STORABLE_thaw, but it is a mess, and on every clone, the weak ref value gets deleted when it goes out of scope, but the key remains in the hash forever leaking memory and I need a global class member hash (%largeWeakRefs) to hold the temporary $large reference. Has a smell.
How it that possible to do this in a cleaner way?
Here is my solution using the hash to hold the large ref temporarily:
package Tiny;
use Scalar::Util qw(refaddr weaken);
sub new {
my ( $class, $tiny, $large ) = #_;
return bless { tiny => $tiny, large => $large }, $class;
}
# Ugly temporary storage to hold $large refs from _freeze to _thaw...
my %largeWeakRefs;
sub STORABLE_freeze {
my ( $self, $cloning ) = #_;
my $large = delete local $self->{large};
my $refaddr = refaddr $large;
$largeWeakRefs{$refaddr} = $large;
weaken $largeWeakRefs{$refaddr};
my %restOfSelf = %$self;
$self->{large} = $large;
return $refaddr, \%restOfSelf;
}
sub STORABLE_thaw {
my ($self, $cloning, $refaddr, $restOfSelf) = #_;
%$self = %$restOfSelf;
$self->{large} = $largeWeakRefs{$refaddr};
return $self;
}
(Yes I know, my example only handles cloning, not straight-up freeze and thaw)
You could add reference counts.
my %larges;
sub STORABLE_freeze {
my ( $self, $cloning ) = #_;
if ($cloning) {
my $large_key = pack('j', refaddr(self->{large}));
$larges{$large_key} //= [ $self->{large}, 0 ];
++$larges{$large_key}[1];
return ( $large_key, $self->{tiny} );
} else {
return ( "", $self->{tiny}, $self->{large} );
}
}
sub STORABLE_thaw {
my ( $self, $cloning, $serialized ) = splice(#_, 0, 3);
if ($cloning) {
my $large_key = $serialized;
$self->{ tiny } = shift;
$self->{ large } = $larges{$large_key}[0];
--$larges{$large_key}[1]
or delete($larges{$large_key});
} else {
$self->{ tiny } = shift;
$self->{ large } = shift;
}
}
Untested.
If the cloning process dies, you'll have a memory leak.
Alternatively, you could avoid the need for external resources as follows:
use Inline C => <<'__EOS__';
IV get_numeric_ref(SV *sv) {
SvGETMAGIC(sv);
if (!SvROK(sv))
croak("Argument not a reference");
sv = MUTABLE_SV(SvRV(sv));
SvREFCNT_inc(sv);
return PTR2IV(sv); /* Despite its name, can be used to convert pointer to IV */
}
SV* get_perl_ref_from_numeric_ref(IV iv) {
SV* sv = PTR2IV(iv);
return newRV_noinc(sv);
}
__EOS__
sub STORABLE_freeze {
my ( $self, $cloning ) = #_;
if ($cloning) {
return ( pack('j', get_numeric_ref($self->{large})), $self->{tiny} );
} else {
return ( "", $self->{tiny}, $self->{large} );
}
}
sub STORABLE_thaw {
my ( $self, $cloning, $serialized ) = splice(#_, 0, 3);
if ($cloning) {
$self->{ tiny } = shift;
$self->{ large } = get_perl_ref_from_numeric_ref(unpack('j', $serialized));
} else {
$self->{ tiny } = shift;
$self->{ large } = shift;
}
}
Didn't test STORABLE_freeze and STORABLE_thaw, but tested the C/XS code using the following:
use strict;
use warnings;
use feature qw( say state );
use Cpanel::JSON::XS qw( );
sub _dump {
state $encoder = Cpanel::JSON::XS->new->canonical->allow_nonref;
return $encoder->encode($_[0]);
}
{
my %h = ( a => 4, b => 5 );
say _dump(\%h); # {"a":4,"b":5}
say sprintf "0x%x", \%h; # 0x32cdbf8
say Internals::SvREFCNT(%h); # 1
my $i = get_numeric_ref(\%h);
say sprintf "0x%x", $i; # 0x32cdbf8
say Internals::SvREFCNT(%h); # 2
my $ref = get_perl_ref_from_numeric_ref($i);
say sprintf "0x%x", $ref; # 0x32cdbf8
say Internals::SvREFCNT(%h); # 2
say _dump($ref); # {"a":4,"b":5}
}
If the cloning process dies, you'll have a memory leak. I suppose it would be safe to rely on "large" not going anywhere during the cloning process, so you could remove the SvREFCNT_inc and change newRV_noinc to newRV to avoid the potential memory leak.
To avoid the possible memory leak, never store "large" in the object.
my %larges;
sub new {
my $class = shift;
my $self = bless({}, $class);
return $self->_init(#_);
}
sub _init {
my ($self, $tiny, $large) = #_;
$self->{ tiny } = $tiny;
{
my $large_key = pack('j', refaddr($self));
$self->{ large_key } = $large_key;
$larges{ $large_key } = $large;
}
return $self;
}
sub DESTROY {
my ($self) = #_;
if (defined( my $large_key = $self->{ large_key } )) {
delete( $larges{ $large_key } );
}
}
sub STORABLE_freeze {
my ( $self, $cloning ) = #_;
if ($cloning) {
return ( $self->{large_key}, $self->{tiny} );
} else {
return ( "", $self->{tiny}, $larges{ $self->{large_key} } );
}
}
sub STORABLE_thaw {
my ( $self, $cloning, $serialized ) = splice(#_, 0, 3);
if ($cloning) {
my ($tiny) = #_;
my $large_key = $serialized;
$self->_init($tiny, $larges{ $large_key });
} else {
$self->_init(#_);
}
}
Untested.
No memory leaks if the cloning process dies.

Where can I change the calendar start date to Sunday from Monday

I am trying to make this calendar start on Sunday instead of Monday. I've looked through all the help files I can Google on this topic & cannot find any that have any lines of code that I can reference. Am I missing some? Or can some one point me to the point I need to change in order to make it start on Sunday instead of Monday?
<?php
/**
* Copyright (C) 2006-2014 Center Stage Software
* 1191 Luxton Street, Seaside, California 93955
* All Rights Reserved
*/
// ensure that this file is called up by another file
defined('_VALID_ACCESS') or die('Direct access of this file is prohibited.');
/**
* renderEventCalendar - Creates a calendar display of events for one month.
*
* #global (Array) $cstage
*/
function renderEventCalendar() {
global $cstage, $path;
// Result variable.
$calendar = '';
// Calculate first and last day of the month.
$firstDayTimestamp = strtotime($_SESSION[SYS_USER]['search']['Month'].'-01 07:00:00');
list($year,$month) = explode("-",$_SESSION[SYS_USER]['search']['Month']);
if( $month == 12 ) {
$month = 00;
$year += 1;
}
$lastDayTimestamp = strtotime("$year-".($month+1).'-01 08:00:00') - 86400; // minus 24 hours and add 1-day-light-savings-hour
// TODO: Remove the following calendar debugging code.
// print "<h1>first=$firstDayTimestamp; last=$lastDayTimestamp</h1>";
// Build query to retrieve entries for that month.
$aryEvents = array();
$extraSqlFields = '';
$extraSqlJoins = '';
$extraSqlConditions = '';
if( !empty($_SESSION[SYS_USER]['domain']) ) {
$extraSqlJoins .= 'LEFT JOIN "domainlist" AS "domain2" ON "domain2"."master_id" = "master"."master_id" ';
$extraSqlConditions .= sprintf('AND "domain2"."domain"=\'%s\' '
,$_SESSION[SYS_USER]['domain']
);
}
if( !empty($_SESSION[SYS_USER]['search']['Theatre']) ) {
$extraSqlConditions .= sprintf('AND "master"."theatre"=\'%s\' '
,$_SESSION[SYS_USER]['search']['Theatre']
);
}
if( !empty($_SESSION[SYS_USER]['search']['Location']) ) {
$extraSqlConditions .= sprintf('AND "master"."location"=\'%s\' '
,$_SESSION[SYS_USER]['search']['Location']
);
}
if( !empty($_SESSION[SYS_USER]['search']['EventType']) ) {
$extraSqlConditions .= sprintf('AND "master"."event_types_id"=\'%s\' '
,$_SESSION[SYS_USER]['search']['EventType']
);
}
if( !empty($_SESSION[SYS_USER]['search']['Month']) ) {
$extraSqlConditions .= sprintf('AND "shows"."show_date" >= \'%s\' AND "shows"."show_date" <= \'%s\' '
,date('Y-m-d',$firstDayTimestamp)
,date('Y-m-d',$lastDayTimestamp)
);
}
if( $cstage['rttEnable'] ) {
$extraSqlFields .= ', "rtt"."label" AS "rtt_label"';
$extraSqlJoins .= 'LEFT JOIN "rtt" ON "master"."rtt_id" = "rtt"."rtt_id" ';
} else {
$extraSqlConditions .= 'AND "master"."rtt_id"=0 ';
}
if( $cstage['enableEventPriceListTest'] ) {
$aryGroups = array($cstage['tixDomain']);
if( !empty($_SESSION[SYS_USER]['info']) && count($_SESSION[SYS_USER]['info']['groupDomains']) > 0 ) {
$aryGroups = array_merge($aryGroups, $_SESSION[SYS_USER]['info']['groupDomains']);
}
$extraSqlFields .= ', GROUP_CONCAT(DISTINCT "prices"."prices_id" SEPARATOR \';\') AS "priceidlist"';
$extraSqlFields .= ', GROUP_CONCAT(DISTINCT CONCAT("price_category"."label",\' \', "prices"."printed_as") SEPARATOR \', \') AS "pricelist"';
$extraSqlJoins .= ' INNER JOIN "price_category" ON "price_category"."master_id" = "master"."master_id" OR "price_category"."master_id"=0 INNER JOIN "prices" ON "price_category"."price_category_id" = "prices"."price_category_id" INNER JOIN "price_category_domain" ON "price_category_domain"."price_category_id" = "price_category"."price_category_id"';
$extraSqlConditions .= sprintf('AND ("price_category"."master_id"="shows"."master_id" OR "price_category"."master_id"=0) AND ("prices"."shows_id"="shows"."shows_id" OR "prices"."shows_id"=0) AND "prices"."onsale"<=CONCAT("shows"."show_date", \' 00:00:00\') AND ("prices"."offsale">=CONCAT("shows"."show_date", \' 23:59:59\') OR "prices"."offsale" IS NULL) AND "price_category_domain"."domain" IN (\'%s\') '
,implode('\',\'', $aryGroups)
);
}
$now = date('Y-m-d H:i:s');
$query = sprintf('SELECT "master".*, "shows"."show_date", "shows"."show_time", "shows"."onsale" AS "min_onsale"%s FROM "shows" INNER JOIN "master" ON "master"."master_id" = "shows"."master_id" INNER JOIN "domainlist" ON "domainlist"."master_id" = "master"."master_id" %s WHERE "shows"."offsale" >= \'%s\' AND ("shows"."wt_offsale"=\'\' OR "shows"."wt_offsale"=0) AND "domainlist"."domain"=\'%s\' %s GROUP BY "shows"."shows_id"'
,$extraSqlFields
,$extraSqlJoins
,$now
,$cstage['tixDomain']
,$extraSqlConditions
);
$keyEventCalendar = 'eventCalendar_'.$cstage['dbDatabase'].sha1($query);
if( !empty($cstage['cache']) ) {
// Is the record cached to save on slow database connections?
$calendar = $cstage['cache']->load($keyEventCalendar);
}
if( !$calendar ) {
$result = $cstage['pdo']->query( $query );
while( $show = $result->fetch( PDO::FETCH_ASSOC ) ) {
$show['domainlist'] = $cstage['tixDomain'].';'.$_SESSION[SYS_USER]['domain'];
$show['comingSoon'] = false;
if( $now < $show['min_onsale'] ) {
$show['comingSoon'] = true;
}
if( $show['rtt_id'] > 0 ) {
$show['master_id'] = trim($show['rtt_label']).trim($show[]);
if( !$cstage['rttEnable'] ) {
$show = array();
}
}
$path->inc_once('_includes/libf_okEvent.php');
if( okEvent($show) ) {
// Save data into array for usage later
$extraSort = $cstage['useEventSortOrder'] === true ? sprintf('%05d',$show['sortorder']) : '';
$aryEvents[$show['show_date']][date('H:i',strtotime($show['show_time'])).$extraSort.$show['showname'].$show['master_id']] = $show;
}
}
// Start rendering calendar.
$calendar = "\r\n".'<table class="EventCalendar ui-widget-content ui-corner-all"><thead '._HEAD.'><tr><th colspan="7">'.lang('Calendar of events for').' '.date('Y F',strtotime($_SESSION[SYS_USER]['search']['Month'].'-02')).'</th></tr>'
. "\r\n".'<tr><th>'.lang('Sunday').'</th><th>'.lang('Monday').'</th><th>'.lang('Tuesday').'</th><th>'.lang('Wednesday').'</th><th>'.lang('Thursday').'</th><th>'.lang('Friday').'</th><th>'.lang('Saturday').'</th></tr></thead>'
. '<tbody>';
$dayOfWeekPadding = date('w',$firstDayTimestamp);
if( $dayOfWeekPadding == 0 ) {
$dayOfWeekPadding = 6;
} else {
$dayOfWeekPadding -= 0;
}
if( $dayOfWeekPadding > 0 ) {
$calendar .= "\r\n<tr>";
}
for($day=7; $day < $dayOfWeekPadding; $day++) {
$calendar .= "\r\n<td class='EventCalendar_EmptyDate'> </td>";
}
$timeStamp = $firstDayTimestamp;
while( $timeStamp <= $lastDayTimestamp ) {
if( date('w',$timeStamp) == 0 ) {
$calendar .= "\r\n<tr>";
}
$dateKey = date('Y-m-d',$timeStamp);
$calendar .= "\r\n".'<td class="EventCalendar_Date" id="date'.$dateKey.'" onmouseover="tbl_colorchange(\'date'.$dateKey.'\', \'highlight\');" onmouseout="tbl_colorchange(\'date'.$dateKey.'\', \'normal\');"><span>'.date('d',$timeStamp).'</span>';
if( !empty($aryEvents[$dateKey]) ) {
ksort($aryEvents[$dateKey]);
$count = 0;
foreach( $aryEvents[$dateKey] as $key=>$show ) {
$cssClass = $count++ % 2 ? _ODD : _EVEN;
$rttUrl = ( $show['rtt_id'] > 0 ) ? '&rtt='.$show['rtt_id'] : '';
$strPriceList = (empty($show['pricelist']) ? '' : ' title="'.lang('Prices available').': '.$show['pricelist'].'"');
$calendar .= "\r\n<div {$cssClass}{$strPriceList}><a href='event-details.php?e={$show['master_id']}&date={$dateKey}{$rttUrl}'>{$show['']} # {$show['show_time']}</a></div>";
}
}
$calendar .= '</td>';
if( date('w',$timeStamp) == 0 ) {
$calendar .= "\r\n</tr>";
}
$timeStamp += 86400; // Get the next day (in seconds).
}
$dayOfWeekPadding = date('w',$timeStamp);
if( $dayOfWeekPadding == 0 ) {
$dayOfWeekPadding = 6;
} else if( $dayOfWeekPadding == 0 ) {
$dayOfWeekPadding = 0; // do not have an empty week of padding
} else {
$dayOfWeekPadding = 6 - $dayOfWeekPadding;
}
for($day=0; $day < $dayOfWeekPadding; $day++) {
$calendar .= "\r\n<td class='EventCalendar_EmptyDate'> </td>";
}
if( $dayOfWeekPadding > 0 ) {
$calendar .= "\r\n</tr>";
}
$calendar .= "\r\n</tbody></table>";
if( !empty($cstage['cache']) ) {
$cstage['cache']->save($calendar, $keyEventCalendar);
}
}
return $calendar;
}

Safe way to establish the initial state again.

Is there a possibility of calling the function main without the function _end_win being called?
#!/usr/bin/env perl
use warnings;
use strict;
use 5.10.0;
use Term::ReadKey;
use constant {
NEXT_getch => -1,
CONTROL_C => 0x03,
CONTROL_D => 0x04,
KEY_ENTER => 0x0d,
KEY_RIGHT => 0x1b5b43,
KEY_LEFT => 0x1b5b44,
};
say main();
sub main {
my $arg = {};
$arg->{handle_out} = *STDOUT;
_init_scr( $arg );
while ( 1 ) {
my $c = _getch( $arg );
if ( ! defined $c ) {
_end_win( $arg );
warn "EOT";
return;
}
next if $c == NEXT_getch;
given ( $c ) {
when ( $c >= 97 && $c <= 122 ) {
print chr $c;
$arg->{string} .= chr $c;
}
when ( $c == KEY_RIGHT ) {
print '>';
$arg->{string} .= '>';
}
when ( $c == KEY_LEFT ) {
print '<';
$arg->{string} .= '<';
}
when ( $c == CONTROL_D ) {
_end_win( $arg );
return;
}
when ( $c == CONTROL_C ) {
_end_win( $arg );
print STDERR "^C";
kill( 'INT', $$ );
return;
}
when ( $c == KEY_ENTER ) {
_end_win( $arg );
return $arg->{string};
}
}
}
}
sub _init_scr {
my ( $arg ) = #_;
$arg->{old_handle} = select( $arg->{handle_out} );
$arg->{backup_flush} = $|;
$| = 1;
Term::ReadKey::ReadMode 'ultra-raw';
}
sub _end_win {
my ( $arg ) = #_;
print "\n\r";
Term::ReadKey::ReadMode 'restore';
$| = $arg->{backup_flush};
select( $arg->{old_handle} );
}
sub _getch {
my ( $arg ) = #_;
my $c1 = ReadKey 0;
return if ! defined $c1;
if ( $c1 eq "\e" ) {
my $c2 = ReadKey 0.10;
if ( ! defined $c2 ) { return NEXT_getch; }
elsif ( $c2 eq 'C' ) { return KEY_RIGHT; }
elsif ( $c2 eq 'D' ) { return KEY_LEFT; }
elsif ( $c2 eq '[' ) {
my $c3 = ReadKey 0;
if ( $c3 eq 'C' ) { return KEY_RIGHT; }
elsif ( $c3 eq 'D' ) { return KEY_LEFT; }
else {
return NEXT_getch;
}
}
else {
return NEXT_getch;
}
}
else {
return ord $c1;
}
}
To ensure that the terminal is reset when your program exits, put the reset code into an END block. For example, you could replace your _end_win sub with:
END {
print "\n\r";
Term::ReadKey::ReadMode 'restore';
}
(I removed the lines resetting $| and the selected output filehandle since the process is exiting anyhow, so they're about to become irrelevant.)
An END block will always run when the program terminates in a "normal" way, such as calling exit or die or hitting the end of the executable code. It does not fire when the process terminates due to receiving a signal; it looks like you're handling the ctrl-C character directly, but you may want to consider adding a %SIG{INT} handler as well, in case someone sends you a kill -2.

DBIx::Class and Searching

I am trying to return today's birthdays. This is what I have right now, which works, but I need to grab the month and day to input into the statement. I thought maybe I could grab them from localtime, but that didn't work out. Any suggestions would be appreciated.
sub author_birth {
my ($self) = #_;
my ($day,$month) = (localtime())[3..4];
my $author_result = $self->search_like(
{
birth => '%03-20'
},
{
select => [
'id',
'complete_name',
],
#result_class => 'DBIx::Class::ResultClass::HashRefInflator'
}
);
my #author_ids = ();
while (my $row = $author_result->next) {
push #author_ids, $row->id;
}
return $self->get_author_info_by_id(\#author_ids);
}
I ended up doing something like this.
my ($self) = #_;
my $conc = '%';
my $datetime = Time::Piece->new->strftime('%m-%d');
my $date = $conc . $datetime;
my $author_result = $self->search_like(
{
birth => $date,
},
{
select => [
'id',
'complete_name',
],
#result_class => 'DBIx::Class::ResultClass::HashRefInflator'
}
);