1 package File
::KDBX
::Group
;
2 # ABSTRACT: A KDBX database group
7 use Devel
::GlobalDestruction
;
8 use File
::KDBX
::Constants
qw(:icon);
10 use File
::KDBX
::Util
qw(generate_uuid);
11 use List
::Util
qw(sum0);
12 use Ref
::Util
qw(is_ref);
13 use Scalar
::Util
qw(blessed);
18 use parent
'File::KDBX::Object';
20 our $VERSION = '999.999'; # VERSION
22 my @ATTRS = qw(uuid custom_data entries groups);
24 # uuid => sub { generate_uuid(printable => 1) },
28 icon_id
=> ICON_FOLDER
,
29 custom_icon_uuid
=> undef,
31 default_auto_type_sequence
=> '',
32 enable_auto_type
=> undef,
33 enable_searching
=> undef,
34 last_top_visible_entry
=> undef,
35 # custom_data => sub { +{} },
36 previous_parent_group
=> undef,
37 # entries => sub { +[] },
38 # groups => sub { +[] },
41 last_modification_time
=> sub { gmtime },
42 creation_time
=> sub { gmtime },
43 last_access_time
=> sub { gmtime },
44 expiry_time
=> sub { gmtime },
47 location_changed
=> sub { gmtime },
50 while (my ($attr, $default) = each %ATTRS) {
51 no strict
'refs'; ## no critic (ProhibitNoStrict)
54 $self->{$attr} = shift if @_;
55 $self->{$attr} //= (ref $default eq 'CODE') ? $default->($self) : $default;
58 while (my ($attr, $default) = each %ATTRS_TIMES) {
59 no strict
'refs'; ## no critic (ProhibitNoStrict)
62 $self->{times}{$attr} = shift if @_;
63 $self->{times}{$attr} //= (ref $default eq 'CODE') ? $default->($self) : $default;
67 sub _set_default_attributes
{
69 $self->$_ for @ATTRS, keys %ATTRS, keys %ATTRS_TIMES;
74 if (@_ || !defined $self->{uuid
}) {
75 my %args = @_ % 2 == 1 ? (uuid
=> shift, @_) : @_;
76 my $old_uuid = $self->{uuid
};
77 my $uuid = $self->{uuid
} = delete $args{uuid
} // generate_uuid
;
78 # if (defined $old_uuid and my $kdbx = $KDBX{refaddr($self)}) {
79 # $kdbx->_update_group_uuid($old_uuid, $uuid, $self);
85 sub label
{ shift-
>name(@_) }
89 my $entries = $self->{entries
} //= [];
90 require File
::KDBX
::Entry
;
91 @$entries = map { File
::KDBX
::Entry-
>wrap($_, $self->kdbx) } @$entries;
97 my $groups = $self->{groups
} //= [];
98 @$groups = map { File
::KDBX
::Group-
>wrap($_, $self->kdbx) } @$groups;
102 sub _kpx_groups
{ shift-
>groups(@_) }
106 return $self->kdbx->all_groups(base
=> $self, include_base
=> false
);
111 return $self->kdbx->all_entries(base
=> $self);
117 return File
::KDBX
::Group-
>wrap($group, $self);
123 require File
::KDBX
::Entry
;
124 return File
::KDBX
::Entry-
>wrap($entry, $self);
130 push @{$self->{entries
} ||= []}, $entry;
137 push @{$self->{groups
} ||= []}, $group;
144 if ($obj->isa('File::KDBX::Entry')) {
145 $self->add_entry($obj);
147 elsif ($obj->isa('File::KDBX::Group')) {
148 $self->add_group($obj);
155 my $blessed = blessed
($object);
156 return $self->remove_group($object, @_) if $blessed && $object->isa('File::KDBX::Group');
157 return $self->remove_entry($object, @_) if $blessed && $object->isa('File::KDBX::Entry');
158 return $self->remove_group($object, @_) || $self->remove_entry($object, @_);
163 my $uuid = is_ref
($_[0]) ? $self->_group(shift)->uuid : shift;
164 my $objects = $self->{groups
};
165 for (my $i = 0; $i < @$objects; ++$i) {
166 my $o = $objects->[$i];
167 next if $uuid ne $o->uuid;
168 return splice @$objects, $i, 1;
174 my $uuid = is_ref
($_[0]) ? $self->_entry(shift)->uuid : shift;
175 my $objects = $self->{entries
};
176 for (my $i = 0; $i < @$objects; ++$i) {
177 my $o = $objects->[$i];
178 next if $uuid ne $o->uuid;
179 return splice @$objects, $i, 1;
185 my $lineage = $self->kdbx->trace_lineage($self) or return;
186 return join('.', map { $_->name } @$lineage);
191 return sum0
map { $_->size } @{$self->groups}, @{$self->entries};
194 sub level
{ $_[0]->kdbx->group_level($_[0]) }
196 sub TO_JSON
{ +{%{$_[0]}} }
213 =attr custom_icon_uuid
217 =attr default_auto_type_sequence
219 =attr enable_auto_type
221 =attr enable_searching
223 =attr last_top_visible_entry
227 =attr previous_parent_group
233 =attr last_modification_time
237 =attr last_access_time
245 =attr location_changed
247 Get or set various group fields.