From: Michael Wagner Date: Fri, 24 Sep 2021 19:42:26 +0000 (+0200) Subject: epic-ts X-Git-Tag: kivitendo-mebil_0.1-0~18 X-Git-Url: http://wagnertech.de/git?a=commitdiff_plain;h=b33bd26a82d846ed4b24b13acfac03ccaf8736b7;p=kivitendo-erp.git epic-ts --- diff --git a/SL/Clipboard/Base.pm b/SL/Clipboard/Base.pm deleted file mode 100644 index fc0a16a1f..000000000 --- a/SL/Clipboard/Base.pm +++ /dev/null @@ -1,236 +0,0 @@ -package SL::Clipboard::Base; - -use strict; - -use parent qw(Rose::Object); - -use Rose::Object::MakeMethods::Generic ( - 'scalar --get_set_init' => [ qw(content timestamp) ], -); - -use Rose::DB::Object::Helpers (); - -sub init_timestamp { die "'timestamp' property not set"; } -sub init_content { die "'content' property not set"; } - -sub type { - my ($self_or_class) = @_; - return (split m/::/, ref($self_or_class) ? ref($self_or_class) : $self_or_class)[-1]; -} - -sub reload_object { - my ($self, $object) = @_; - - return ref($object)->new(map { $_ => $object->$_ } $object->meta->primary_key)->load; -} - -sub as_tree { - my ($self, $object, %params) = @_; - - my $tree = Rose::DB::Object::Helpers::as_tree($object, %params); - $self->_fix_tree($tree, $object); - return $tree; -} - -sub to_object { - my ($self) = @_; - my $object = Rose::DB::Object::Helpers::new_from_tree("SL::DB::" . $self->type, $self->content); - - # Reset primary key columns and itime/mtime if the class supports it. - foreach ($object->meta->primary_key, 'itime', 'mtime') { - $object->$_(undef) if $object->can($_); - } - - # Let sub classes fix the objects further. - $self->_fix_object($object); - return $object; -} - -sub dump { - my ($self, $object) = @_; - return $self->as_tree($self->reload_object($object), max_depth => 1); -} - -sub describe { - die "'describe' method not overwritten by derived class"; -} - -sub _fix_object { - my ($self, $object) = @_; - # To be overwritten by child classes. -} - -sub _fix_tree { - my ($self, $tree, $object) = @_; - - # Delete primary key columns and itime/mtime if the class supports it. - foreach ($object->meta->primary_key, 'itime', 'mtime') { - delete $tree->{$_} if $object->can($_); - } -} - -sub _binary_column_names { - my ($self, $class) = @_; - return map { $_->name } - grep { ref($_) =~ m/Pg::Bytea$/i } - @{ $class->meta->columns }; -} - -1; -__END__ - -=pod - -=encoding utf8 - -=head1 NAME - -SL::Clipboard::Base - Base class for clipboard specialization classes - -=head1 SYNOPSIS - -See the synopsis of L. - -=head1 OVERVIEW - -This is a base class providing a lot of utility and -defaults. Sub-classes must overwrite at least the function -L but can overwrite others as well. - -Writing a specialized sub-class for a database type involves -overwriting one or more functions. These are: - -=over 4 - -=item * C - -Must be overwritten. Returns a human-readable description of the -content. Should only be one line. - -=item * C - -Optional. Overwrite if sub-class needs to dump more/less than the -implementation in this class dumps. - -=item * C<_fix_object> - -Optional. Overwrite if re-created Rose::DB::Object instances must be -cleaned further before they're returned to the caller. - -=item * C<_fix_tree> - -Optional. Overwrite if the tree created during a copy operation of a -Rose::DB::Object instance must be cleaned further before it's stored. - -=back - -You don't have to or should not overwrite the other functions: - -=over 4 - -=item * C - -=item * C - -=item * C - -=item * C - -=back - -Don't forget to C the specialized module here in Base! - -=head1 FUNCTIONS - -=over 4 - -=item C - -A convenience function calling L -with C<$object> and C<%params> as parameters. Returns a hash/array -reference tree of the function. - -Don't overwrite this function in sub-classes. Overwrite L -instead. - -=item C - -Returns a human-readable description of the content. This should only -be a single line without any markup. - -Sub-classes must overwrite this function. - -=item C - -Dumps the object as a hash/array tree and returns it by calling -L. The default implementation -reloads the object first by calling L. It also only -dumps the object itself, not any of the relationships, by calling -C with the parameter C 1>. - -Overwrite this in a sub-class if you need to dump more or differently -(see L for an example). - -=item C - -Reloads C<$object> from the database and returns a new instance. Can -be useful for sanitizing the object given to L before -converting into a tree. It is used by the default implementation of -L. - -=item C - -Converts the dumped representation back to a Rose::DB::Object -instance. Several columns of the newly created object are cleared by -C itself: the primary key columns (if any) and the columns -C and C (if the object has such columns). - -This function should not be overwritten by sub-classes. Instead, -functions can overwrite C<_fix_object> which can be used for sanitizing -the newly created object before handing it back to the caller. - -=item C - -Returns the actual clipped type (e.g. C). This is -derived from the actual class name of C<$self>. - -=item C<_binary_column_names $class> - -Returns an array of column names that have a binary type. Useful for -sub-classes which need to encode binary content in Base64 during -C. - -=item C<_fix_object $object> - -This function is called by L before the object is passed -back to the caller. It does not do anything in the default -implementation, but sub-classes are free to overwrite it if they need -to sanitize the object. See L for -an example. - -Its return value is ignored. - -=item C<_fix_tree $tree, $object> - -This function is called by L after dumping and before the -object is stored during a copy operation. In the default -implementation all primary key columns and the columns C and -C (if the object has such columns) are removed from the tree. -Sub-classes are free to overwrite it if they need to sanitize the -tree. See L for an example. - -C<$object> is just passed in for reference and should not be modified. - -Its return value is ignored. - -=back - -=head1 BUGS - -Nothing here yet. - -=head1 AUTHOR - -Moritz Bunkus Em.bunkus@linet-services.deE - -=cut diff --git a/SL/Clipboard/RequirementSpecItem.pm b/SL/Clipboard/RequirementSpecItem.pm deleted file mode 100644 index 85bd5d967..000000000 --- a/SL/Clipboard/RequirementSpecItem.pm +++ /dev/null @@ -1,101 +0,0 @@ -package SL::Clipboard::RequirementSpecItem; - -use strict; - -use parent qw(SL::Clipboard::Base); - -use List::Util qw(sum); - -use SL::Common; -use SL::Locale::String; - -sub dump { - my ($self, $object) = @_; - - return $self->as_tree(_load_children($self->reload_object($object)), exclude => sub { ref($_[0]) !~ m/::RequirementSpecItem$/ }); -} - -sub describe { - my ($self) = @_; - - my $item = $self->content; - my $num_children = @{ $item->{children} || [] }; - my $num_grandchildren = sum map { scalar(@{ $_->{children} || [] }) } @{ $item->{children} || [] }; - - if ($item->{item_type} eq 'section') { - return t8('Requirement spec section #1 "#2" with #3 function blocks and a total of #4 sub function blocks; preamble: "#5"', - $item->{fb_number}, $item->{title}, $num_children, $num_grandchildren, Common::truncate($item->{description}, strip => 'full')); - } elsif ($item->{item_type} eq 'function-block') { - return t8('Requirement spec function block #1 with #2 sub function blocks; description: "#3"', - $item->{fb_number}, $num_children, Common::truncate($item->{description}, strip => 'full')); - } else { - return t8('Requirement spec sub function block #1; description: "#2"', - $item->{fb_number}, Common::truncate($item->{description}, strip => 'full')); - } -} - -sub _load_children { - my ($object) = @_; - - _load_children($_) for @{ $object->children }; - - return $object; -} - -sub _fix_object { - my ($self, $object) = @_; - - $object->$_(undef) for qw(fb_number); - $self->_fix_object($_) for @{ $object->children || [] }; -} - -sub _fix_tree { - my ($self, $tree, $object) = @_; - - delete @{ $tree }{ qw(id itime mtime parent_id position requirement_spec_id) }; - $self->_fix_tree($_) for @{ $tree->{children} || [] }; -} - -1; -__END__ - -=pod - -=encoding utf8 - -=head1 NAME - -SL::Clipboard::RequirementSpecItem - Clipboard specialization for -SL::DB::RequirementSpecItem - -=head1 FUNCTIONS - -=over 4 - -=item C - -Returns a human-readable description depending on the copied type -(section, function block or sub function block). - -=item C - -This specialization reloads C<$object> from the database, loads all of -its children (but only the other requirement spec items, no other -relationships) and dumps it. - -=item C<_fix_object $object> - -Fixes C<$object> and all of its children by clearing certain columns -like the position or function block numbers. - -=back - -=head1 BUGS - -Nothing here yet. - -=head1 AUTHOR - -Moritz Bunkus Em.bunkus@linet-services.deE - -=cut diff --git a/SL/Clipboard/RequirementSpecPicture.pm b/SL/Clipboard/RequirementSpecPicture.pm deleted file mode 100644 index 7a3757f82..000000000 --- a/SL/Clipboard/RequirementSpecPicture.pm +++ /dev/null @@ -1,84 +0,0 @@ -package SL::Clipboard::RequirementSpecPicture; - -use strict; - -use parent qw(SL::Clipboard::Base); - -use SL::Common; -use SL::Locale::String; -use MIME::Base64; - -sub dump { - my ($self, $object) = @_; - - $self->reload_object($object); - - my $tree = $self->as_tree($object, exclude => sub { ref($_[0]) !~ m/::RequirementSpecPicture$/ }); - $tree->{$_} = encode_base64($tree->{$_}, '') for $self->_binary_column_names('SL::DB::RequirementSpecPicture'); - - return $tree; -} - -sub describe { - my ($self) = @_; - - return t8('Requirement spec picture "#1"', $self->content->{description} ? $self->content->{description} . ' (' . $self->content->{picture_file_name} . ')' : $self->content->{picture_file_name}); -} - -sub _fix_object { - my ($self, $object) = @_; - - $object->$_(undef) for qw(number); - $object->$_(decode_base64($object->$_)) for $self->_binary_column_names('SL::DB::RequirementSpecPicture'); - - return $object; -} - -1; -__END__ - -=pod - -=encoding utf8 - -=head1 NAME - -SL::Clipboard::RequirementSpecPicture - Clipboard specialization for -SL::DB::RequirementSpecPicture - -=head1 NOTES - -The underlying RDBO model contains binary columns, but binary data -cannot be dumped as YAML. Therefore the binary content is encoded in -Base64 in L and decoded back to binary form in L. - -=head1 FUNCTIONS - -=over 4 - -=item C - -Returns a human-readable description including the title and an -excerpt of its content. - -=item C - -This specialization reloads C<$object> from the database, and dumps -it. Binary columns are dumped encoded in Base64. - -=item C<_fix_object $object> - -Fixes C<$object> by clearing certain columns like the number. Also -decodes binary columns from Base64 back to binary. - -=back - -=head1 BUGS - -Nothing here yet. - -=head1 AUTHOR - -Moritz Bunkus Em.bunkus@linet-services.deE - -=cut diff --git a/SL/Clipboard/RequirementSpecTextBlock.pm b/SL/Clipboard/RequirementSpecTextBlock.pm deleted file mode 100644 index 4b40a8e8c..000000000 --- a/SL/Clipboard/RequirementSpecTextBlock.pm +++ /dev/null @@ -1,81 +0,0 @@ -package SL::Clipboard::RequirementSpecTextBlock; - -use strict; - -use parent qw(SL::Clipboard::Base); - -use SL::Clipboard::RequirementSpecPicture; -use SL::Common; -use SL::Locale::String; - -sub dump { - my ($self, $object) = @_; - - $self->reload_object($object); - - my $tree = $self->as_tree($object, exclude => sub { ref($_[0]) !~ m/::RequirementSpecTextBlock$/ }); - $tree->{pictures} = [ map { SL::Clipboard::RequirementSpecPicture->new->dump($_) } @{ $object->pictures } ]; - - return $tree; -} - -sub describe { - my ($self) = @_; - - return t8('Requirement spec text block "#1"; content: "#2"', $self->content->{title}, Common::truncate($self->content->{text}, strip => 'full')); -} - -sub _fix_object { - my ($self, $object) = @_; - - $object->$_(undef) for qw(output_position position requirement_spec_id); - - SL::Clipboard::RequirementSpecPicture->new->_fix_object($_) for @{ $object->pictures || [] }; - - return $object; -} - -1; -__END__ - -=pod - -=encoding utf8 - -=head1 NAME - -SL::Clipboard::RequirementSpecTextBlock - Clipboard specialization for -SL::DB::RequirementSpecTextBlock - -=head1 FUNCTIONS - -=over 4 - -=item C - -Returns a human-readable description including the title and an -excerpt of its content. - -=item C - -This specialization reloads C<$object> from the database, loads all of -its pictures and dumps it. The pictures are dumped using the clipboard -specialization for it, L. - -=item C<_fix_object $object> - -Fixes C<$object> by clearing certain columns like the position. Lets -pictures be fixed by the clipboard specialization for it, -L. - -=back - -=head1 BUGS - -Nothing here yet. - -=head1 AUTHOR - -Moritz Bunkus Em.bunkus@linet-services.deE - -=cut diff --git a/SL/Controller/CsvImport/Clipboard/Base.pm b/SL/Controller/CsvImport/Clipboard/Base.pm new file mode 100644 index 000000000..fc0a16a1f --- /dev/null +++ b/SL/Controller/CsvImport/Clipboard/Base.pm @@ -0,0 +1,236 @@ +package SL::Clipboard::Base; + +use strict; + +use parent qw(Rose::Object); + +use Rose::Object::MakeMethods::Generic ( + 'scalar --get_set_init' => [ qw(content timestamp) ], +); + +use Rose::DB::Object::Helpers (); + +sub init_timestamp { die "'timestamp' property not set"; } +sub init_content { die "'content' property not set"; } + +sub type { + my ($self_or_class) = @_; + return (split m/::/, ref($self_or_class) ? ref($self_or_class) : $self_or_class)[-1]; +} + +sub reload_object { + my ($self, $object) = @_; + + return ref($object)->new(map { $_ => $object->$_ } $object->meta->primary_key)->load; +} + +sub as_tree { + my ($self, $object, %params) = @_; + + my $tree = Rose::DB::Object::Helpers::as_tree($object, %params); + $self->_fix_tree($tree, $object); + return $tree; +} + +sub to_object { + my ($self) = @_; + my $object = Rose::DB::Object::Helpers::new_from_tree("SL::DB::" . $self->type, $self->content); + + # Reset primary key columns and itime/mtime if the class supports it. + foreach ($object->meta->primary_key, 'itime', 'mtime') { + $object->$_(undef) if $object->can($_); + } + + # Let sub classes fix the objects further. + $self->_fix_object($object); + return $object; +} + +sub dump { + my ($self, $object) = @_; + return $self->as_tree($self->reload_object($object), max_depth => 1); +} + +sub describe { + die "'describe' method not overwritten by derived class"; +} + +sub _fix_object { + my ($self, $object) = @_; + # To be overwritten by child classes. +} + +sub _fix_tree { + my ($self, $tree, $object) = @_; + + # Delete primary key columns and itime/mtime if the class supports it. + foreach ($object->meta->primary_key, 'itime', 'mtime') { + delete $tree->{$_} if $object->can($_); + } +} + +sub _binary_column_names { + my ($self, $class) = @_; + return map { $_->name } + grep { ref($_) =~ m/Pg::Bytea$/i } + @{ $class->meta->columns }; +} + +1; +__END__ + +=pod + +=encoding utf8 + +=head1 NAME + +SL::Clipboard::Base - Base class for clipboard specialization classes + +=head1 SYNOPSIS + +See the synopsis of L. + +=head1 OVERVIEW + +This is a base class providing a lot of utility and +defaults. Sub-classes must overwrite at least the function +L but can overwrite others as well. + +Writing a specialized sub-class for a database type involves +overwriting one or more functions. These are: + +=over 4 + +=item * C + +Must be overwritten. Returns a human-readable description of the +content. Should only be one line. + +=item * C + +Optional. Overwrite if sub-class needs to dump more/less than the +implementation in this class dumps. + +=item * C<_fix_object> + +Optional. Overwrite if re-created Rose::DB::Object instances must be +cleaned further before they're returned to the caller. + +=item * C<_fix_tree> + +Optional. Overwrite if the tree created during a copy operation of a +Rose::DB::Object instance must be cleaned further before it's stored. + +=back + +You don't have to or should not overwrite the other functions: + +=over 4 + +=item * C + +=item * C + +=item * C + +=item * C + +=back + +Don't forget to C the specialized module here in Base! + +=head1 FUNCTIONS + +=over 4 + +=item C + +A convenience function calling L +with C<$object> and C<%params> as parameters. Returns a hash/array +reference tree of the function. + +Don't overwrite this function in sub-classes. Overwrite L +instead. + +=item C + +Returns a human-readable description of the content. This should only +be a single line without any markup. + +Sub-classes must overwrite this function. + +=item C + +Dumps the object as a hash/array tree and returns it by calling +L. The default implementation +reloads the object first by calling L. It also only +dumps the object itself, not any of the relationships, by calling +C with the parameter C 1>. + +Overwrite this in a sub-class if you need to dump more or differently +(see L for an example). + +=item C + +Reloads C<$object> from the database and returns a new instance. Can +be useful for sanitizing the object given to L before +converting into a tree. It is used by the default implementation of +L. + +=item C + +Converts the dumped representation back to a Rose::DB::Object +instance. Several columns of the newly created object are cleared by +C itself: the primary key columns (if any) and the columns +C and C (if the object has such columns). + +This function should not be overwritten by sub-classes. Instead, +functions can overwrite C<_fix_object> which can be used for sanitizing +the newly created object before handing it back to the caller. + +=item C + +Returns the actual clipped type (e.g. C). This is +derived from the actual class name of C<$self>. + +=item C<_binary_column_names $class> + +Returns an array of column names that have a binary type. Useful for +sub-classes which need to encode binary content in Base64 during +C. + +=item C<_fix_object $object> + +This function is called by L before the object is passed +back to the caller. It does not do anything in the default +implementation, but sub-classes are free to overwrite it if they need +to sanitize the object. See L for +an example. + +Its return value is ignored. + +=item C<_fix_tree $tree, $object> + +This function is called by L after dumping and before the +object is stored during a copy operation. In the default +implementation all primary key columns and the columns C and +C (if the object has such columns) are removed from the tree. +Sub-classes are free to overwrite it if they need to sanitize the +tree. See L for an example. + +C<$object> is just passed in for reference and should not be modified. + +Its return value is ignored. + +=back + +=head1 BUGS + +Nothing here yet. + +=head1 AUTHOR + +Moritz Bunkus Em.bunkus@linet-services.deE + +=cut diff --git a/SL/Controller/CsvImport/Clipboard/RequirementSpecItem.pm b/SL/Controller/CsvImport/Clipboard/RequirementSpecItem.pm new file mode 100644 index 000000000..85bd5d967 --- /dev/null +++ b/SL/Controller/CsvImport/Clipboard/RequirementSpecItem.pm @@ -0,0 +1,101 @@ +package SL::Clipboard::RequirementSpecItem; + +use strict; + +use parent qw(SL::Clipboard::Base); + +use List::Util qw(sum); + +use SL::Common; +use SL::Locale::String; + +sub dump { + my ($self, $object) = @_; + + return $self->as_tree(_load_children($self->reload_object($object)), exclude => sub { ref($_[0]) !~ m/::RequirementSpecItem$/ }); +} + +sub describe { + my ($self) = @_; + + my $item = $self->content; + my $num_children = @{ $item->{children} || [] }; + my $num_grandchildren = sum map { scalar(@{ $_->{children} || [] }) } @{ $item->{children} || [] }; + + if ($item->{item_type} eq 'section') { + return t8('Requirement spec section #1 "#2" with #3 function blocks and a total of #4 sub function blocks; preamble: "#5"', + $item->{fb_number}, $item->{title}, $num_children, $num_grandchildren, Common::truncate($item->{description}, strip => 'full')); + } elsif ($item->{item_type} eq 'function-block') { + return t8('Requirement spec function block #1 with #2 sub function blocks; description: "#3"', + $item->{fb_number}, $num_children, Common::truncate($item->{description}, strip => 'full')); + } else { + return t8('Requirement spec sub function block #1; description: "#2"', + $item->{fb_number}, Common::truncate($item->{description}, strip => 'full')); + } +} + +sub _load_children { + my ($object) = @_; + + _load_children($_) for @{ $object->children }; + + return $object; +} + +sub _fix_object { + my ($self, $object) = @_; + + $object->$_(undef) for qw(fb_number); + $self->_fix_object($_) for @{ $object->children || [] }; +} + +sub _fix_tree { + my ($self, $tree, $object) = @_; + + delete @{ $tree }{ qw(id itime mtime parent_id position requirement_spec_id) }; + $self->_fix_tree($_) for @{ $tree->{children} || [] }; +} + +1; +__END__ + +=pod + +=encoding utf8 + +=head1 NAME + +SL::Clipboard::RequirementSpecItem - Clipboard specialization for +SL::DB::RequirementSpecItem + +=head1 FUNCTIONS + +=over 4 + +=item C + +Returns a human-readable description depending on the copied type +(section, function block or sub function block). + +=item C + +This specialization reloads C<$object> from the database, loads all of +its children (but only the other requirement spec items, no other +relationships) and dumps it. + +=item C<_fix_object $object> + +Fixes C<$object> and all of its children by clearing certain columns +like the position or function block numbers. + +=back + +=head1 BUGS + +Nothing here yet. + +=head1 AUTHOR + +Moritz Bunkus Em.bunkus@linet-services.deE + +=cut diff --git a/SL/Controller/CsvImport/Clipboard/RequirementSpecPicture.pm b/SL/Controller/CsvImport/Clipboard/RequirementSpecPicture.pm new file mode 100644 index 000000000..7a3757f82 --- /dev/null +++ b/SL/Controller/CsvImport/Clipboard/RequirementSpecPicture.pm @@ -0,0 +1,84 @@ +package SL::Clipboard::RequirementSpecPicture; + +use strict; + +use parent qw(SL::Clipboard::Base); + +use SL::Common; +use SL::Locale::String; +use MIME::Base64; + +sub dump { + my ($self, $object) = @_; + + $self->reload_object($object); + + my $tree = $self->as_tree($object, exclude => sub { ref($_[0]) !~ m/::RequirementSpecPicture$/ }); + $tree->{$_} = encode_base64($tree->{$_}, '') for $self->_binary_column_names('SL::DB::RequirementSpecPicture'); + + return $tree; +} + +sub describe { + my ($self) = @_; + + return t8('Requirement spec picture "#1"', $self->content->{description} ? $self->content->{description} . ' (' . $self->content->{picture_file_name} . ')' : $self->content->{picture_file_name}); +} + +sub _fix_object { + my ($self, $object) = @_; + + $object->$_(undef) for qw(number); + $object->$_(decode_base64($object->$_)) for $self->_binary_column_names('SL::DB::RequirementSpecPicture'); + + return $object; +} + +1; +__END__ + +=pod + +=encoding utf8 + +=head1 NAME + +SL::Clipboard::RequirementSpecPicture - Clipboard specialization for +SL::DB::RequirementSpecPicture + +=head1 NOTES + +The underlying RDBO model contains binary columns, but binary data +cannot be dumped as YAML. Therefore the binary content is encoded in +Base64 in L and decoded back to binary form in L. + +=head1 FUNCTIONS + +=over 4 + +=item C + +Returns a human-readable description including the title and an +excerpt of its content. + +=item C + +This specialization reloads C<$object> from the database, and dumps +it. Binary columns are dumped encoded in Base64. + +=item C<_fix_object $object> + +Fixes C<$object> by clearing certain columns like the number. Also +decodes binary columns from Base64 back to binary. + +=back + +=head1 BUGS + +Nothing here yet. + +=head1 AUTHOR + +Moritz Bunkus Em.bunkus@linet-services.deE + +=cut diff --git a/SL/Controller/CsvImport/Clipboard/RequirementSpecTextBlock.pm b/SL/Controller/CsvImport/Clipboard/RequirementSpecTextBlock.pm new file mode 100644 index 000000000..4b40a8e8c --- /dev/null +++ b/SL/Controller/CsvImport/Clipboard/RequirementSpecTextBlock.pm @@ -0,0 +1,81 @@ +package SL::Clipboard::RequirementSpecTextBlock; + +use strict; + +use parent qw(SL::Clipboard::Base); + +use SL::Clipboard::RequirementSpecPicture; +use SL::Common; +use SL::Locale::String; + +sub dump { + my ($self, $object) = @_; + + $self->reload_object($object); + + my $tree = $self->as_tree($object, exclude => sub { ref($_[0]) !~ m/::RequirementSpecTextBlock$/ }); + $tree->{pictures} = [ map { SL::Clipboard::RequirementSpecPicture->new->dump($_) } @{ $object->pictures } ]; + + return $tree; +} + +sub describe { + my ($self) = @_; + + return t8('Requirement spec text block "#1"; content: "#2"', $self->content->{title}, Common::truncate($self->content->{text}, strip => 'full')); +} + +sub _fix_object { + my ($self, $object) = @_; + + $object->$_(undef) for qw(output_position position requirement_spec_id); + + SL::Clipboard::RequirementSpecPicture->new->_fix_object($_) for @{ $object->pictures || [] }; + + return $object; +} + +1; +__END__ + +=pod + +=encoding utf8 + +=head1 NAME + +SL::Clipboard::RequirementSpecTextBlock - Clipboard specialization for +SL::DB::RequirementSpecTextBlock + +=head1 FUNCTIONS + +=over 4 + +=item C + +Returns a human-readable description including the title and an +excerpt of its content. + +=item C + +This specialization reloads C<$object> from the database, loads all of +its pictures and dumps it. The pictures are dumped using the clipboard +specialization for it, L. + +=item C<_fix_object $object> + +Fixes C<$object> by clearing certain columns like the position. Lets +pictures be fixed by the clipboard specialization for it, +L. + +=back + +=head1 BUGS + +Nothing here yet. + +=head1 AUTHOR + +Moritz Bunkus Em.bunkus@linet-services.deE + +=cut