Email-Abstract

 view release on metacpan or  search on metacpan

lib/Email/Abstract.pm  view on Meta::CPAN

use 5.006;
use warnings;
use strict;
package Email::Abstract;
# ABSTRACT: unified interface to mail representations
$Email::Abstract::VERSION = '3.010';
use Carp;
use Email::Simple;
use MRO::Compat;

use Module::Pluggable 1.5
  search_path => [__PACKAGE__],
  except      => 'Email::Abstract::Plugin',
  require     => 1;

use Scalar::Util ();

my @plugins = __PACKAGE__->plugins(); # Requires them.
my %adapter_for =
  map  { $_->target => $_ }
  grep {
    my $avail = eval { $_->is_available };
    $@ ? ($@ =~ /Can't locate object method "is_available"/) : $avail;
  }
  @plugins;

sub object {
  my ($self) = @_;
  return unless ref $self;
  return $self->[0];
}

sub new {
  my ($class, $foreign) = @_;

  return $foreign if eval { $foreign->isa($class) };

  $foreign = Email::Simple->new($foreign)
    unless Scalar::Util::blessed($foreign);

  my $adapter = $class->__class_for($foreign); # dies if none available
  return bless [ $foreign, $adapter ] => $class;
}

sub __class_for {
  my ($self, $foreign, $method, $skip_super) = @_;
  $method ||= 'handle';

  my $f_class = ref $foreign;
     $f_class = $foreign unless $f_class;

  return $f_class if ref $foreign and $f_class->isa($self);

  return $adapter_for{$f_class} if $adapter_for{$f_class};

  if (not $skip_super) {
    my @bases = @{ mro::get_linear_isa($f_class) };
    shift @bases;
    for my $base (@bases) {
      return $adapter_for{$base} if $adapter_for{$base};
    }
  }

  Carp::croak "Don't know how to $method $f_class";
}

sub _adapter_obj_and_args {
  my $self = shift;

  if (my $thing = $self->object) {
    return ($self->[1], $thing, @_);
  } else {
    my $thing   = shift;
    my $adapter = $self->__class_for(
      Scalar::Util::blessed($thing) ? $thing : 'Email::Simple'
    );
    return ($adapter, $thing, @_);
  }
}

for my $func (qw(get_header get_body set_header set_body as_string)) {
  no strict 'refs';
  *$func = sub {
    my $self = shift;
    my ($adapter, $thing, @args) = $self->_adapter_obj_and_args(@_);

    # In the event of Email::Abstract->get_body($email_abstract), convert
    # it into an object method call.
    $thing = $thing->object if eval { $thing->isa($self) };

    # I suppose we could work around this by leaving @_ intact and assigning to
    # it.  That seems ... not good. -- rjbs, 2007-07-18
    unless (Scalar::Util::blessed($thing)) {
      Carp::croak "can't alter string in place" if substr($func, 0, 3) eq 'set';
      $thing = Email::Simple->new(
        ref $thing ? \do{my$str=$$thing} : $thing
      );
    }

    return $adapter->$func($thing, @args);
  };
}

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

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