Catalyst-Plugin-AutoCRUD

 view release on metacpan or  search on metacpan

lib/Catalyst/Plugin/AutoCRUD/Model/StorageEngine/DBIC/CRUD.pm  view on Meta::CPAN

        $c->model($meta->extra('model'))->result_source->storage->debug(1);
    }

    my $success =
        eval{ $c->model($meta->extra('model'))
            ->result_source->storage->txn_do(\&_create_update_core, $c, $mk_self_row) };
    $response->{'success'} = (($success && !$@) ? 1 : 0);
    $c->log->debug($@) if $@ and $c->debug;

    if ($ENV{AUTOCRUD_DEBUG} and $c->debug) {
        $c->model($meta->extra('model'))->result_source->storage->debug(0);
    }
}

sub _create_update_core {
    my ($c, $mk_self_row) = @_;
    my $meta = $c->stash->{cpac}->{tm};
    my $params = $c->req->params;

    if ($ENV{AUTOCRUD_DEBUG} and $c->debug) {
        use Data::Dumper;
        $c->log->debug( Dumper $params );
    }

    my $self_row = $mk_self_row->($c);
    my $proxy_updates = {};
    my $update = {};

    COL: foreach my $col (@{$meta->extra('fields')}) {
        my $ci = $meta->f->{$col};
        next COL if $ci->extra('is_reverse') or $ci->extra('masked_by');

        if (not $ci->is_foreign_key) {
            # fix for HTML standard which excludes checkboxes
            $params->{$col} ||= 'false'
                if $ci->data_type and $ci->data_type eq 'boolean';

            # skip auto-inc cols unless they contain data
            next COL unless exists $params->{$col}
                and ($params->{$col} or not $ci->is_auto_increment);

            # only works if user doesn't change the FK val
            if ($ci->extra('is_proxy')) {
                $proxy_updates->{$ci->extra('proxy_field')}
                    ->{$ci->extra('proxy_rel_field')} = $params->{$col};
                next COL;
            }

            # copy simple form data into new row
            $self_row->set_inflated_columns({$col => $params->{$col}});

            next COL;
        }

        # else is foreign key
        my $link = $c->stash->{cpac}->{m}->t->{ $ci->extra('ref_table') };

        # some kind of update to an existing relation
        if (!exists $params->{'checkbox.' . $col}) {
            # someone is messing with the AJAX (tests?)
            next COL if !defined $params->{'combobox.' . $col};

            # user has blanked the field to remove the relation
            if (!length $params->{'combobox.' . $col}) {
                $self_row->set_column($_ => undef)
                    for @{$ci->extra('fields')};
                delete $proxy_updates->{$col};
            }

            # user has cleared or not updated the field
            next COL if $params->{'combobox.' . $col} !~ m/\000/;

            # update to new related record
            # we find the target and pass in the row object to DBIC
            my $finder = _extract_ID($params->{'combobox.' . $col});
            my $found_row = $c->model( $link->extra('model') )->find($finder, {key => 'primary'})
                or $self_row->throw_exception("autocrud: failed to find row for $col");
            $self_row->set_inflated_columns({$col => $found_row});
            delete $proxy_updates->{$col};

            next COL;
        }

        # else new related record to be created
        delete $proxy_updates->{$col};
        my $new_related = {};

        foreach my $fcol (@{$link->extra('fields')}) {
            my $fci = $link->f->{$fcol};
            next if $fci->extra('is_reverse') or $fci->extra('masked_by');

            # basic fields in the related record
            if (exists $params->{"$col.$fcol"}) {
                # fix for HTML standard which excludes checkboxes
                $params->{"$col.$fcol"} ||= 'false'
                    if $fci->data_type and $fci->data_type eq 'boolean';

                # skip auto-inc cols unless they contain data
                next unless exists $params->{"$col.$fcol"}
                    and ($params->{"$col.$fcol"} or not $fci->is_auto_increment);

                $new_related->{$fcol} = $params->{"$col.$fcol"};
            }
            # any foreign keys (belongs_to) in the related record
            # we find the target and pass the row object to DBIC
            elsif (exists $params->{"combobox.$col.$fcol"}) {
                next unless length $params->{"combobox.$col.$fcol"};

                my $finder = _extract_ID($params->{"combobox.$col.$fcol"});
                my $link_link = $c->stash->{cpac}->{m}->t->{ $fci->extra('ref_table') };
                $new_related->{$fcol} = 
                    $c->model( $link_link->extra('model') )->find($finder, {key => 'primary'})
                    or $self_row->throw_exception("autocrud: failed to find row for $fcol");
            }
        }

        my $new_col = $c->model( $link->extra('model') )->create($new_related)
            or $self_row->throw_exception("autocrud: failed to create row for $col");
        $self_row->set_inflated_columns({$col => $new_col});
    }

    foreach my $rel (keys %$proxy_updates) {
        next unless scalar keys %{$proxy_updates->{$rel}};
        foreach my $f (keys %{$proxy_updates->{$rel}}) {
            $self_row->$rel->set_inflated_columns({
                $f => $proxy_updates->{$rel}->{$f}
            });
        }
        $self_row->result_source->schema->txn_do(
            sub { $self_row->$rel->update }
        ); # save it
    }

    if ($ENV{AUTOCRUD_DEBUG} and $c->debug) {
        use Data::Dumper;
        $c->log->debug( Dumper $params );
    }

    return $self_row->result_source->schema->txn_do(sub {
        $self_row->in_storage ? $self_row->update : $self_row->insert
    });
}

sub delete {
    my ($self, $c) = @_;
    my $meta = $c->stash->{cpac}->{tm};
    my $response = $c->stash->{json_data} = {success => 0};

    return unless $c->req->params->{key};
    my $filter = _extract_ID($c->req->params->{key});

    if ($ENV{AUTOCRUD_DEBUG} and $c->debug) {
        $c->model($meta->extra('model'))->result_source->storage->debug(1);
    }
    my $row = eval { $c->model($meta->extra('model'))->find($filter) };

    if (blessed $row
        and eval { $row->result_source->schema->txn_do(sub { $row->delete }) }) {
        $response->{'success'} = 1;
    }

    if ($ENV{AUTOCRUD_DEBUG} and $c->debug) {
        $c->model($meta->extra('model'))->result_source->storage->debug(0);
    }
    return $self;
}

sub list_stringified {
    my ($self, $c) = @_;



( run in 0.500 second using v1.01-cache-2.11-cpan-39bf76dae61 )