]> Dogcows Code - chaz/p5-File-KDBX/blobdiff - lib/File/KDBX/Object.pm
Add iterator
[chaz/p5-File-KDBX] / lib / File / KDBX / Object.pm
index 0d53dd91e4885345d8099fa5dad276fdd392ca67..7c538bf3df44d7b234b942b03df91713155dd119 100644 (file)
@@ -73,11 +73,11 @@ sub new {
 
     my $self = bless $data // {}, $class;
     $self->init(%args);
-    $self->_set_default_attributes if !$data;
+    $self->_set_nonlazy_attributes if !$data;
     return $self;
 }
 
-sub _set_default_attributes { die 'Not implemented' }
+sub _set_nonlazy_attributes { die 'Not implemented' }
 
 =method init
 
@@ -353,6 +353,8 @@ Remove the object from the database. If the object is a group, all contained obj
 =cut
 
 sub remove {
+    # TODO - need a way to not signal database because there are times like in the KDB loader and meta streams
+    # where we do not want to add UUIDs to deleted objects
     my $self = shift;
     my $parent = $self->parent;
     $parent->remove_object($self) if $parent;
@@ -469,56 +471,6 @@ sub custom_data_value {
 
 ##############################################################################
 
-sub _signal {
-    my $self = shift;
-    my $type = shift;
-
-    if ($self->_in_txn) {
-        my $stack = $self->_signal_stack;
-        my $queue = $stack->[-1];
-        push @$queue, [$type, @_];
-    }
-
-    $self->_signal_send([[$type, @_]]);
-}
-
-sub _signal_stack { $SIGNALS{$_[0]} //= [] }
-
-sub _signal_begin_work {
-    my $self = shift;
-    push @{$self->_signal_stack}, [];
-}
-
-sub _signal_commit {
-    my $self = shift;
-    my $signals = pop @{$self->_signal_stack};
-    my $previous = $self->_signal_stack->[-1] // [];
-    push @$previous, @$signals;
-    return $previous;
-}
-
-sub _signal_rollback {
-    my $self = shift;
-    pop @{$self->_signal_stack};
-}
-
-sub _signal_send {
-    my $self    = shift;
-    my $signals = shift // [];
-
-    my $kdbx = $KDBX{$self} or return;
-
-    # de-duplicate, keeping the most recent signal for each type
-    my %seen;
-    my @signals = grep { !$seen{$_->[0]}++ } reverse @$signals;
-
-    for my $sig (reverse @signals) {
-        $kdbx->_handle_signal($self, @$sig);
-    }
-}
-
-##############################################################################
-
 =method begin_work
 
     $txn = $object->begin_work(%options);
@@ -605,10 +557,6 @@ sub commit {
     return $self;
 }
 
-sub _commit { die 'Not implemented' }
-sub _in_txn { scalar @{$_[0]->_txns} }
-sub _txns   { $TXNS{$_[0]} //= [] }
-
 =method rollback
 
     $object->rollback;
@@ -631,6 +579,28 @@ sub rollback {
     return $self;
 }
 
+# Get whether or not there is at least one pending transaction.
+sub _in_txn { scalar @{$_[0]->_txns} }
+
+# Get an array ref of pending transactions.
+sub _txns   { $TXNS{$_[0]} //= [] }
+
+# The _commit hook notifies subclasses that a commit has occurred.
+sub _commit { die 'Not implemented' }
+
+# Get a reference to an object that represents an object's committed state. If there is no pending
+# transaction, this is just $self. If there is a transaction, this is the snapshot take before the transaction
+# began. This method is private because it provides direct access to the actual snapshot. It is important that
+# the snapshot not be changed or a rollback would roll back to an altered state.
+# This is used by File::KDBX::Dumper::XML so as to not dump uncommitted changes.
+sub _committed {
+    my $self = shift;
+    my ($orig) = @{$self->_txns};
+    return $orig // $self;
+}
+
+# In addition to cloning an object when beginning work, we also keep track its hashrefs and arrayrefs
+# internally so that we can restore to the very same structures in the case of a rollback.
 sub _save_references {
     my $id   = shift;
     my $self = shift;
@@ -650,6 +620,7 @@ sub _save_references {
     }
 }
 
+# During a rollback, copy data from the snapshot back into the original internal structures.
 sub _restore_references {
     my $id   = shift;
     my $orig = shift // return;
@@ -669,10 +640,56 @@ sub _restore_references {
     return $self;
 }
 
-sub _confirmed {
+##############################################################################
+
+sub _signal {
     my $self = shift;
-    my ($orig) = @{$self->_txns};
-    return $orig // $self;
+    my $type = shift;
+
+    if ($self->_in_txn) {
+        my $stack = $self->_signal_stack;
+        my $queue = $stack->[-1];
+        push @$queue, [$type, @_];
+    }
+
+    $self->_signal_send([[$type, @_]]);
+
+    return $self;
+}
+
+sub _signal_stack { $SIGNALS{$_[0]} //= [] }
+
+sub _signal_begin_work {
+    my $self = shift;
+    push @{$self->_signal_stack}, [];
+}
+
+sub _signal_commit {
+    my $self = shift;
+    my $signals = pop @{$self->_signal_stack};
+    my $previous = $self->_signal_stack->[-1] // [];
+    push @$previous, @$signals;
+    return $previous;
+}
+
+sub _signal_rollback {
+    my $self = shift;
+    pop @{$self->_signal_stack};
+}
+
+sub _signal_send {
+    my $self    = shift;
+    my $signals = shift // [];
+
+    my $kdbx = $KDBX{$self} or return;
+
+    # de-duplicate, keeping the most recent signal for each type
+    my %seen;
+    my @signals = grep { !$seen{$_->[0]}++ } reverse @$signals;
+
+    for my $sig (reverse @signals) {
+        $kdbx->_handle_signal($self, @$sig);
+    }
 }
 
 ##############################################################################
This page took 0.024512 seconds and 4 git commands to generate.