# A plugin for converting '[map:address-description]' string into an
# embeded map provided by mapping services.
#
# $Id$
#
# This software is provided as-is. You may use it for commercial or
# personal use. If you distribute it, please keep this notice intact.
#
# Copyright (c) 2006 Hirotaka Ogawa
package MT::Plugin::Mapper;
use strict;
use MT;
use MT::Template::Context;
use MT::ConfigMgr;
use base 'MT::Plugin';
sub BEGIN {
our $VERSION = '0.12';
my $plugin = MT::Plugin::Mapper->new({
name => 'Mapper',
version => $VERSION,
description => 'This plugin enables MTMapper container tag, which converts "[map:address-description]" string into an embeded map provided by mapping services such as Google Maps.',
doc_link => 'http://code.as-is.net/wiki/Mapper_Plugin',
author_name => 'Hirotaka Ogawa',
author_link => 'http://profile.typekey.com/ogawa/',
blog_config_template => \&blog_config_template,
settings => new MT::PluginSettings([
['google_maps_key', { Default => '' }]
]),
});
MT->add_plugin($plugin);
MT::Template::Context->add_container_tag(Mapper => sub { $plugin->mapper(@_) });
}
sub mapper {
my $plugin = shift;
my ($ctx, $args, $cond) = @_;
my $blog = $ctx->stash('blog') or return;
my $config = $plugin->get_config_hash('blog:' . $blog->id) or return;
%$config = (%$config, %$args);
$config->{unique} = $ctx->stash('entry')->id
if defined $ctx->stash('entry');
my $cfg = MT::ConfigMgr->instance;
$config->{language} ||= $cfg->DefaultLanguage;
$config->{charset} ||= $cfg->PublishCharset;
my $mapper_class = __PACKAGE__ . '::' . ($args->{method} || 'Google');
my $mapper = $mapper_class->new($config);
defined(my $html = $ctx->stash('builder')->build($ctx, $ctx->stash('tokens'), $cond)) or return;
$html =~ s!(?:<(?:div|p)\s+[^<>]*class="adr"[^<>]*>\s*([^<>]+)\s*(?:div|p)>)|(?:<(?:div|p)[^<>]*>\s*\[map:([^]]+)\]\s*(?:div|p)>)!$mapper->generate($1||$2)!ge;
$html;
}
sub blog_config_template {
my $tmpl = <<'EOT';
This plugin enables MTMapper container tag, which converts "[map:address-description]" string into an embeded map provided by mapping services such as Google Maps.
For more details, see "Mapper Plugin".
EOT
}
package MT::Plugin::Mapper::Google;
use strict;
use MT::Util qw(encode_url);
use LWP::Simple;
use HTML::Template;
sub new {
my $class = shift;
my($config) = @_;
$config->{count} = 0;
$config->{unique} ||= int(rand(65536));
bless $config, $class;
}
sub DESTROY { }
sub generate {
my $this = shift;
my($s) = @_;
$s =~ s/^\s+//;
$s =~ s/\s+$//;
my($str, $opt) = split(/:/, $s);
my $adr = $str;
$adr =~ s/\(.*\)//ge;
$adr =~ s/^\s+//;
$adr =~ s/\s+$//;
my($lat, $lon);
if ($adr =~ m!^x([-.\d]+)y([-.\d]+)$!) { # map:xy
($lat, $lon) = ($2, $1);
} elsif ($adr =~ m!^([-.\d]+),\s*([-.\d]+)$!) { # map:,
($lat, $lon) = ($1, $2);
} else {
($lat, $lon) = eval { $this->resolve_address($adr) };
return "$adr (Sorry, this address cannot be resolved.)
" if $@;
}
my $res = '';
$res .= $this->preamble unless $this->{count};
$res .= $this->body($lat, $lon, $str);
$this->{count}++;
$res;
}
sub resolve_address {
my $this = shift;
my($adr) = @_;
my $geo_url = $this->{language} eq 'ja' ?
'http://maps.google.co.jp/maps?q=' : 'http://maps.google.com/maps?q=';
$geo_url .= encode_url($adr) . '&output=kml';
$geo_url .= '&ie=' . $this->{charset} . '&oe=' . $this->{charset};
my $res = get($geo_url);
if ($res && $res =~ /coordinates>([-.\d]+),([-.\d]+),/is) {
return ($2, $1);
} else {
die "Cannot obtain the coordinates for this address.";
}
}
my $preamble_tmpl = <<'EOT';
EOT
sub preamble {
my $this = shift;
my $tmpl = HTML::Template->new(scalarref => \$preamble_tmpl);
$tmpl->param(
google_maps_key => $this->{google_maps_key},
language => $this->{language} || ''
);
$tmpl->output;
}
my $body_tmpl = <<'EOT';
" style="width:;height:;" class="adr">
EOT
sub body {
my $this = shift;
my($lat, $lon, $adr) = @_;
my $tmpl = HTML::Template->new(scalarref => \$body_tmpl);
$tmpl->param(
mapid => "MTPluginMapperGoogle-" . $this->{unique} . '-' . $this->{count},
width => $this->{width} || '400px',
height => $this->{height} || '300px',
latitude => $lat,
longitude => $lon,
address => $adr,
maptype => $this->{maptype} || 'G_NORMAL_MAP',
zoom => (defined $this->{zoom}) ? $this->{zoom} : 15
);
$tmpl->output;
}
sub postamble { '' }
package MT::Plugin::Mapper::Alps;
use strict;
use MT::Util qw(encode_url);
use MT::I18N;
sub new {
my $class = shift;
my($config) = @_;
bless $config, $class;
}
sub DESTROY { }
sub generate {
my $this = shift;
my($s) = @_;
$s =~ s/^\s+//;
$s =~ s/\s+$//;
my($str, $opt) = split(/:/, $s);
my $adr = $str;
$adr =~ s/\(.*\)//ge;
$adr =~ s/^\s+//;
$adr =~ s/\s+$//;
my $pos = '';
if ($adr =~ m!^x([-.\d]+)y([-.\d]+)$!) { # map:xy
$pos = "$2,$1";
} elsif ($adr =~ m!^([-.\d]+),\s*([-.\d]+)$!) { # map:,
$pos = $adr;
}
if ($pos) {
return qq[
];
}
$adr = MT::I18N::encode_text($adr, '', 'euc-jp') || '';
$adr = MT::Util::encode_url($adr);
qq[
];
}