Tie-Google

 view release on metacpan or  search on metacpan

Google.pm  view on Meta::CPAN

use Symbol qw(gensym);
use Net::Google;

# Offsets into the array-based object
sub KEY()     { 0 }     # The user's API key
sub TYPE()    { 1 }     # The tie type: SCALAR, ARRAY, HASH
sub QUERY()   { 2 }     # The query terms
sub OPTIONS() { 3 }     # Options tied in
sub DATA()    { 4 }     # Search results
sub GOOGLE()  { 5 }     # Net::Google instance

# Tie types that we support and have to differentiate between
sub SCALAR() { 0 }
sub ARRAY()  { 1 }
sub HASH()   { 2 }

$VERSION = 0.03;
$DEFAULT_BATCH_SIZE = 10 unless defined $DEFAULT_BATCH_SIZE;
$DEBUG = 0 unless defined $DEBUG;

# tie constructors
sub TIESCALAR { return shift->new(SCALAR, @_) }
sub TIEARRAY  { return shift->new(ARRAY, @_)  }
sub TIEHASH   { return shift->new(HASH, @_)   }

# ----------------------------------------------------------------------
# new($TYPE, $KEY, $query)
#
# Create a new Tie::Google instance.  This method should never be
# called by outside facing code, only by the TIEFOO methods.
#
# A Tie::Google instance maintains a few pieces of information:
#
#   0. The API key of the user
#
#   1. The type of tie (SCALAR, ARRAY, HASH)
#
#   2. The query
#
#   3. Options passed in
#
#   4. The results of the query.
#
#   5. The Net::Google instace, created with the API key (item 0)
#
# The interesting things happen here in new.  new must be passed a
# type, a key, and a query.  If the user is tieing a scalar ("I feel
# lucky"), then we are only interested in the first element returned
# by the search; if the user is tieing an array, then we want all of
# the elements; if the user is tieing a hash, then we want all of the
# elements of a number of searches.  My "solution" (heh heh heh) is to
# store all data in a hashref, indexed into the instance as DATA; if
# the user is tieing an array or scalar (Tie::Google treats them
# identically), then we store the results in the key named $KEY, so
# that we can treat all types of ties consistently; otherwise, search
# results are keyed by query.
# ----------------------------------------------------------------------
sub new {
    my ($class, $type, $KEY, $query, $options) = @_;
    $options = { } unless defined $options && ref($options) eq 'HASH';
    my $self = bless [ $KEY, $type, $query, $options, { }, undef, ] => $class;

    # Is $KEY actually a file?
    # I do this in DBD::google as well; perhaps there I should submit
    # a patch to Aaron so that Net::Google can do this directly.
    if (-e $KEY) {
        my $fh = gensym;
        open $fh, $KEY or die "Can't open keyfile $KEY for reading: $!";
        chomp($KEY = <$fh>);
        close $fh or die "Can't close keyfile $KEY: $!";

        $self->[KEY] = $KEY;
    }

    # Set some reasonable defaults search boundaries, and instantiate
    # the Net::Google instance.
    $options->{'starts_at'} = 0 unless defined $options->{'starts_at'};
    $options->{'max_results'} ||= $DEFAULT_BATCH_SIZE;

    $self->[GOOGLE] = Net::Google->new(key => $self->[KEY],
                                       debug => $options->{'debug'} || 0);

    # * If called from TIEHASH, then store the results keyed by
    #   search terms, otherwise keyed by $KEY
    #
    # * If called from TIESCALAR, we only want the first result.
    #
    # $self->[OPTIONS] contains starts_at and max_results.
    #
    if ($type == HASH) {
        $self->do_search($query, $query,
                         $self->[OPTIONS]->{'starts_at'},
                         $self->[OPTIONS]->{'max_results'});
    }
    elsif ($type == SCALAR) {
        $self->do_search($KEY, $query, 0, 1);
    }
    else {
        $self->do_search($KEY, $query,
                         $self->[OPTIONS]->{'starts_at'},
                         $self->[OPTIONS]->{'max_results'});
    }

    return $self;
}

# ----------------------------------------------------------------------
# do_search($store_as, $query)
#
# This is where all the Net::Google magic has to happen.
#
# do_search will use Net::Google to search for $query, and store the
# results in $self->[DATA]->{$store_as}.
# ----------------------------------------------------------------------
sub do_search {
    my ($self, $store_as, $query, $start, $num) = @_;

    # Preparation for the search
    #
    # do_search can conceivably be invoked with one argument,
    # in which case we use it both as search term and key into the

 view all matches for this distribution
 view release on metacpan -  search on metacpan

( run in 1.541 second using v1.00-cache-2.02-grep-82fe00e-cpan-d29e8ade9f55 )