Projekt

Allgemein

Profil

Herunterladen (5,04 KB) Statistiken
| Zweig: | Markierung: | Revision:
c805dfd9 Moritz Bunkus
package SL::Clipboard;

use strict;

use parent qw(Rose::Object);

use Rose::Object::MakeMethods::Generic (
'scalar --get_set_init' => [ qw(content) ],
);

use Carp;
use List::MoreUtils qw(apply);
use List::Util qw(first);
use Scalar::Util qw(blessed);

use SL::Clipboard::RequirementSpecItem;
use SL::Clipboard::RequirementSpecTextBlock;

sub init_content {
my $value = $::auth->get_session_value('clipboard-content');
return ref($value) eq 'HASH' ? $value : { entries => [] };
}

sub copy {
my ($self, $object) = @_;

my $copied = $self->_create_copy_of($object);
push @{ $self->content->{entries} }, $copied;

$self->_save_content;

return $copied;
}

sub get_entry {
my ($self, $type) = @_;

$type ||= qr/./;

return first { $_->type =~ $type }
reverse @{ $self->content->{entries} };
}

sub get_entries {
my ($self, $type) = @_;

$type ||= qr/./;

return grep { $_->{type} =~ $type }
reverse @{ $self->content->{entries} };
}

sub clear {
my ($self) = @_;

$self->content->{entries} = [];
$self->_save_content;

return $self;
}

sub _log_entries {
my ($self) = @_;

$::lxdebug->message(0, "Clipboard entries: " . scalar(@{ $self->content->{entries} }));
foreach (@{ $self->content->{entries} }) {
$::lxdebug->message(0, " " . $_->type . ' ' . $_->timestamp . ' ' . $_->describe);
}
}

sub _create_copy_of {
my ($self, $object) = @_;

croak "\$object is not a blessed reference." unless blessed($object);

my $type = (split(m/::/, ref($object)))[-1];
my $copied = eval { "SL::Clipboard::${type}"->new(timestamp => DateTime->now_local) };

croak "Class '" . ref($object) . "' not supported for copy/paste operations" if !$copied;

$copied->content($copied->dump($object));

return $copied;
}

sub _save_content {
my ($self) = @_;

$::auth->set_session_value('clipboard-content', $self->content);

return $self;
}

1;

__END__

=pod

=encoding utf8

=head1 NAME

SL::Clipboard - A session-based clipboard mechanism for
Rose::DB::Object instances

=head1 SYNOPSIS

# In a controller, e.g. for customers, you can react to a "copy" operation:
my $customer = SL::DB::Customer->new(id => $::form->{id});
SL::Clipboard->new->copy($customer);

# Later in a paste action:
my $copied = SL::Clipboard->new->get_entry(qr/^Customer$/);
if ($copied) {
my $customer = $copied->to_object;
$customer->save;
}

=head1 OVERVIEW

The clipboard can store an unlimited number of copies of
1fd3b737 Geoffrey Richardson
Rose::DB::Object instances. The instances are dumped into trees using
c805dfd9 Moritz Bunkus
L<Rose::DB::Object::Helpers/as_tree>. How much of such an object is
copied depends on its type. For example, a dump of a customer object
might also include the dumps of the shipping address and contact
objects belonging to the customer.

Each clipped object is stored in the user's session along with the
timestamp of the copy operation. A controller can then query the
clipboard for the latest clipped object of a certain type (or more
types if the situation allows insertion of different types). If such a
clipped object is available it can be turned into a shiny new
Rose::DB::Object instance that can be saved to the database.

Primary key columns will always be reset as will other columns
depending on the type. For example, a copied requirement spec item
will have its C<requirement_spec_id> column cleared. The controller is
responsible for setting the columns before saving the object.

Not every Rose::DB::Object instance can be copied. For each supported
type C<Type> there must be a specialized clipboard support class
C<SL::Clipboard::Type>. The type's name is derived from the Rose class
name: by stripping the leading C<SL::DB::>. So the clipboard support
class for a requirement spec item Rose class
C<SL::DB::RequirementSpecItem> would be
C<SL::Clipboard::RequirementSpecItem>. These support classes must
inherit from L<SL::Clipboard::Base> which offers almost a full set of
support functions so that the actual specialized class has to do very
52b6788d Geoffrey Richardson
little.
c805dfd9 Moritz Bunkus
As the clipboard is session-based its contents will be lost when the
session expires (either due to timeouts or to the user logging off).

=head1 FUNCTIONS

=over 4

=item C<clear>

Clears the clipboard (removes all entries).

=item C<copy $object>

Creates a dumped copy of C<$object> and stores that copy in the
52b6788d Geoffrey Richardson
session. An unlimited number of copies of differing types can be
c805dfd9 Moritz Bunkus
made.

Returns the instance of the copied object, a sub-class of
L<SL::Clipboard::Base>.

=item C<get_entries [$type]>

Returns an array of clipped objects whose type matches the regular
expression C<$type>. If C<$type> is not given then all elements are
returned.

The array is sorted by the copy timestamp: the first element in the
array is the one most recently copied.

=item C<get_entry [$type]>

Returns the most recently clipped object whose type matches the
52b6788d Geoffrey Richardson
regular expression C<$type>. If C<$type> is not given then the
c805dfd9 Moritz Bunkus
most recently copied object is returned.

If no such object exists C<undef> is returned instead.

=back

=head1 BUGS

Nothing here yet.

=head1 AUTHOR

Moritz Bunkus E<lt>m.bunkus@linet-services.deE<gt>

=cut