The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
<%args>
$schema
$neato => 0
</%args>
<%once>
use Alzabo::Create;
eval 'use GraphViz'; # optional feature
</%once>
<%init>
my $s = Alzabo::Create::Schema->load_from_file( name => $schema );

my $layout = $neato ? 'neato' : 'dot';
my $g = GraphViz->new( node => { shape => 'box' },
                       layout => $layout,
                       directed => 1,
                       no_overlap => 1,
                     );

foreach my $t ($s->tables)
{
    $g->add_node( $t->name );
}

my %fk;
foreach my $t ($s->tables)
{
    foreach my $fk ($t->all_foreign_keys)
    {
	my @from_id = qw( columns_from columns_to );
	    my $id1 = join "\0", map { $_->name } map { $fk->$_() } @from_id, qw( table_from table_to );
	$id1 .= "\0";
	$id1 .= join "\0", $fk->cardinality;

	my @to_id = qw( columns_to columns_from );
	my $id2 = join "\0", map { $_->name } map { $fk->$_() } @to_id, qw( table_to table_from );
	$id2 .= "\0";
	$id2 .= join "\0", reverse $fk->cardinality;

	next if $fk{$id1} || $fk{$id2};

	my $taillabel = join '..', $fk->cardinality;
	$taillabel .= ' (dependent on ' . $fk->table_to->name . ')' if $fk->from_is_dependent;

	my $headlabel = join '..', reverse $fk->cardinality;
	$headlabel .= ' (dependent on ' . $fk->table_from->name . ')' if $fk->to_is_dependent;

	my %p;
	if ($fk->is_one_to_one)
	{
	    $p{dir} = 'none';
	    $p{arrowhead} = $fk->from_is_dependent ? 'dot' : 'odot';
	    $p{arrowtail} = $fk->to_is_dependent ? 'dot' : 'odot';
	}
	elsif ($fk->is_many_to_one)
	{
	    $p{dir} = 'forward';
	    $p{arrowhead} = $fk->from_is_dependent ? 'dot' : 'odot';
	    $p{arrowtail} = $fk->to_is_dependent ? 'invdot' : 'invodot';
	}
	else
	{
	    $p{dir} = 'back';
	    $p{arrowhead} = $fk->from_is_dependent ? 'invdot' : 'invodot';
	    $p{arrowtail} = $fk->to_is_dependent ? 'dot' : 'odot';
	}

	$g->add_edge( $fk->table_from->name, $fk->table_to->name,
		      %p,
		    );

	$fk{$id1} = $fk{$id2} = 1;
    }
}

if ( my $r = $m->apache_req )
{
    $r->content_type('image/png');
}
else
{
    my $cat = eval "$c";
    die $@ if $@;

    $cat->response()->content_type('image/png');
}

$m->clear_buffer; # no extra whitespace or anything
$m->flush_buffer;
$g->as_png( sub { $m->out(@_); $m->flush_buffer; } );
$m->abort(200); # make sure nothing extra sneaks out
</%init>
<%flags>
inherit => undef
</%flags>