# Movable Type (r) (C) 2007-2012 Six Apart, Ltd. All Rights Reserved.
# This code cannot be redistributed without permission from www.sixapart.com.
# For more information, consult your Movable Type license.
#
# $Id$
# Original Copyright (c) 2005-2007 Arvind Satyanarayan
package CustomFields::Template::ContextHandlers;
use strict;
use CustomFields::Util qw( get_meta field_loop _get_html load_meta_to_cache );
use MT::Util qw( asset_cleanup );
sub _hdlr_app_fields {
my ( $ctx, $args, $cond ) = @_;
my $plugin = MT->component("Commercial");
if ( !$ctx->var('field_loop') ) {
my %param = (
blog_id => $args->{blog_id} || $ctx->var('blog_id'),
object_type => $args->{object_type}
|| $ctx->var('object_type')
|| $ctx->var('type'),
object_id => $args->{object_id} || $ctx->var('id')
);
$ctx->var( 'field_loop', field_loop(%param) );
}
my $field_loop_tmpl = $args->{tmpl}
|| File::Spec->catdir( $plugin->path, 'tmpl', 'field_loop.tmpl' );
return $ctx->build(<<"EOT");
EOT
}
sub find_stashed_by_type {
my ( $ctx, $obj_type ) = @_;
my $obj = $ctx->stash($obj_type);
# So if $obj doesn't exist, lets try to figure out if we can find it
# First lets check for subclasses of MT::Entry and MT::Category which
# stash as entries or categories respectively.
if ( !$obj ) {
my $class = MT->model($obj_type);
$obj = $ctx->stash( $class->datasource );
}
# Otherwise lets try some hacks
if ( !$obj ) {
my $entry = $ctx->stash('entry');
if ( $obj_type eq 'category' ) {
$obj
= $entry ? $entry->category : $ctx->stash('archive_category');
}
elsif ( $obj_type eq 'author' ) {
$obj = $entry ? $entry->author : undef;
}
}
return $obj;
}
sub _hdlr_customfields {
my ( $ctx, $args, $cond ) = @_;
my ($obj_type) = lc( $ctx->stash('tag') ) =~ m/(.*)customfields/;
my $blog_id = $ctx->stash('blog_id');
my $builder = $ctx->stash('builder');
my $tokens = $ctx->stash('tokens');
my $res = '';
my %exclude;
if ( my $excl = $args->{exclude} ) {
$exclude{$_} = 1 for split /\s*,\s*/, $excl;
}
my %include;
my $i = 0;
if ( my $incl = $args->{include} ) {
$include{$_} = $i++ for split /\s*,\s*/, $incl;
}
my @incl_list = keys %include;
require CustomFields::Field;
my $terms = {
obj_type => $obj_type,
blog_id => ( $blog_id ? [ $blog_id, 0 ] : 0 ),
( %include ? ( name => \@incl_list ) : () )
};
my @fields = CustomFields::Field->load($terms);
if (%include) {
@fields
= sort { $include{ $a->name } <=> $include{ $b->name } } @fields;
}
foreach my $field (@fields) {
next if %exclude && exists( $exclude{ $field->name } );
local $ctx->{__stash}{field} = $field;
defined( my $out = $builder->build( $ctx, $tokens ) )
or return $ctx->error( $builder->errstr );
$res .= $out;
}
$res;
}
sub _hdlr_customfield_basename {
my ($ctx) = @_;
my $field = $ctx->stash('field')
or return _no_field($ctx);
return $field->basename;
}
sub _hdlr_customfield_name {
my ($ctx) = @_;
my $field = $ctx->stash('field')
or return _no_field($ctx);
return $field->name;
}
sub _hdlr_customfield_description {
my ($ctx) = @_;
my $field = $ctx->stash('field')
or return _no_field($ctx);
return $field->description;
}
sub _hdlr_customfield_value {
my ( $ctx, $args ) = @_;
my $field = $ctx->stash('field')
or return _no_field($ctx);
my $obj = eval { find_stashed_by_type( $ctx, $field->obj_type ) };
return $ctx->error($@) if $@;
return $ctx->error(
MT->translate(
"Are you sure you have used a '[_1]' tag in the correct context? We could not find the [_2]",
$ctx->stash('tag'),
$field->obj_type
)
) unless ref $obj;
my $obj_type = $obj->datasource;
my $obj_id = $obj->id;
my $res = '';
load_meta_to_cache($obj);
my $value = get_meta( $obj, $field->basename );
if ( defined $value ) {
my $fld_type = $field->type;
if ( $fld_type eq 'textarea' ) {
my $convert_breaks
= exists $args->{convert_breaks} ? $args->{convert_breaks}
: ( $obj_type eq 'entry' && defined $obj->convert_breaks )
? $obj->convert_breaks
: $ctx->stash('blog') ? $ctx->stash('blog')->convert_paras
: '__default__';
# Strip the mt:asset-id attribute from any span tags...
if ( $value =~ m/\smt:asset-id="\d+"/
&& !$args->{no_asset_cleanup} )
{
$value = asset_cleanup($value);
}
if ($convert_breaks) {
$convert_breaks = '__default__' if $convert_breaks eq '1';
$value = MT->apply_text_filters( $value, [$convert_breaks],
$ctx );
}
}
elsif ( $fld_type eq 'datetime' ) {
$value =~ s/\D//g;
return q() unless $value;
if ( length $value == 8 ) {
$value .= '000000';
}
if ( !$args->{form_field} ) {
$args->{ts} = $value;
if ( !exists $args->{format} ) {
if ( 'datetime' eq $field->options ) {
$args->{format} = '%x %X';
}
elsif ( 'date' eq $field->options ) {
$args->{format} = '%x';
}
elsif ( 'time' eq $field->options ) {
$args->{format} = '%X';
}
}
require MT::Template::Context;
$value = $ctx->invoke_handler( 'date', $args );
}
}
else {
if ( $args->{label} ) {
my $type_obj = MT->registry( 'customfield_types', $fld_type );
if ( $type_obj->{options_delimiter} ) {
my $expr = '\s*'
. quotemeta( $type_obj->{options_delimiter} ) . '\s*';
my @options = split /$expr/, $field->options;
my $value_label;
foreach my $option (@options) {
my $label = $option;
( $option, $label ) = split /\s*=\s*/, $option, 2
if $option =~ m/=/;
my $option_row
= { option => $option, label => $label };
if ( $value eq $option ) {
$value_label = $label;
last;
}
}
$value = $value_label;
}
}
}
$res = $value;
}
# Strip the mt:asset-id attribute from any span tags...
if ( $res =~ m/\smt:asset-id="\d+"/ && !$args->{no_asset_cleanup} ) {
$res = asset_cleanup($res);
}
$res;
}
sub _hdlr_customfield_asset {
my ( $ctx, $args, $cond ) = @_;
my $tokens = $ctx->stash('tokens');
my $builder = $ctx->stash('builder');
my $res = '';
$args->{no_asset_cleanup} = 1;
my $value = _hdlr_customfield_value(@_);
return '' unless $value;
require MT::Asset;
while ( $value
=~ m!!gis )
{
my $id = $1;
my $asset = MT::Asset->load($id);
next unless $asset;
local $ctx->{__stash}{asset} = $asset;
defined( my $out = $builder->build( $ctx, $tokens ) )
or return $ctx->error( $builder->errstr );
$res .= $out;
}
$res;
}
sub find_field_by_tag {
my ( $ctx, $tag ) = @_;
$tag ||= $ctx->stash('tag')
or return;
my $field = $ctx->stash('field');
return $field
if $field && lc $field->tag eq $tag;
my $blog_id = $ctx->stash('blog_id');
unless ($blog_id) {
my $blog = $ctx->stash('blog');
$blog_id = $blog->id if $blog;
}
my $blog_ids = $blog_id ? [ $blog_id, 0 ] : 0;
return MT->model('field')->load(
{ blog_id => $blog_ids,
tag => lc $tag,
}
);
}
sub _hdlr_customfield_value_by_tag {
my ($ctx) = @_;
my $field = find_field_by_tag($ctx)
or return _no_field($ctx);
local $ctx->{__stash}{field} = $field;
return _hdlr_customfield_value(@_);
}
sub _hdlr_customfield_asset_by_tag {
my ($ctx) = @_;
# Asset tags end in "asset."
my $tag = $ctx->stash('tag');
$tag =~ s{ asset \z }{}xmsi;
my $field = find_field_by_tag( $ctx, $tag )
or return _no_field($ctx);
local $ctx->{__stash}{field} = $field;
return _hdlr_customfield_asset(@_);
}
sub _hdlr_customfield_html {
my $ctx = shift;
my ($args) = @_;
my $field = $ctx->stash('field')
or return _no_field($ctx);
my ( $type, $basename ) = ( $field->type, $field->basename );
my $type_obj = MT->registry( 'customfield_types', $type );
my $row = $field->get_values();
$row->{blog_id} ||= 0;
my $field_value;
my $app = MT->instance();
if ( ( ( ref $app ) =~ /^MT::App::/ )
&& ( $app->param('customfield_beacon') )
&& ( $ctx->var('app_page_template') ) )
{
$field_value = $app->param("customfield_$basename");
}
else {
$args ||= {};
$field_value
= _hdlr_customfield_value( $ctx, { form_field => 1, %$args } );
}
$field_value = $field->default unless defined $field_value;
$row->{field_value} = $field_value;
$row->{value} = $field_value;
if ( $type_obj->{options_delimiter} ) {
my @option_loop;
my $expr
= '\s*' . quotemeta( $type_obj->{options_delimiter} ) . '\s*';
my @options = split /$expr/, $field->options;
foreach my $option (@options) {
my $label = $option;
( $option, $label ) = split /\s*=\s*/, $option, 2
if $option =~ m/=/;
my $option_row = { option => $option, label => $label };
$option_row->{is_selected}
= defined $row->{value} ? ( $row->{value} eq $option ) : 0;
push @option_loop, $option_row;
}
$row->{option_loop} = \@option_loop;
}
$row->{show_field}
= ( $field->obj_type eq 'entry' || $field->obj_type eq 'page' )
? 0
: 1;
$row->{show_hint} = $type ne 'checkbox' ? 1 : 0;
$row->{field_id} = $row->{field_name} = "customfield_$basename";
$row->{simple} = 1; # it's for asset-chooser.tmpl
return _get_html( $type, 'field_html', $row );
}
sub _no_field {
my ($ctx) = @_;
return $ctx->error(
MT->translate(
"You used an '[_1]' tag outside of the context of the correct content; ",
$ctx->stash('tag')
)
);
}
sub _hdlr_customfield_is_required {
my ( $ctx, $args, $cond ) = @_;
my $field = $ctx->stash('field')
or return _no_field($ctx);
return '' unless $field;
return $field->required ? 1 : 0;
}
1;