Passed
Push — master ( 34dd63...33989f )
by Andreas
22:47
created

softdelete::undelete()   A

Complexity

Conditions 5
Paths 6

Size

Total Lines 33
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 17
c 1
b 0
f 0
nc 6
nop 1
dl 0
loc 33
ccs 0
cts 18
cp 0
crap 30
rs 9.3888
1
<?php
2
/**
3
 * @package midcom.dba
4
 * @author CONTENT CONTROL http://www.contentcontrol-berlin.de/
5
 * @copyright CONTENT CONTROL http://www.contentcontrol-berlin.de/
6
 * @license http://www.gnu.org/licenses/gpl.html GNU General Public License
7
 */
8
9
namespace midcom\dba;
10
11
use midcom;
12
use midcom_connection;
13
use midcom_helper_reflector_tree;
14
use midgard_query_builder;
15
use midgard\portable\api\mgdobject;
16
17
/**
18
 * Helpers for recursively undeleting/purging
19
 *
20
 * @package midcom.dba
21
 */
22
class softdelete
23
{
24
    /**
25
     * Undelete objects
26
     *
27
     * @param array $guids
28
     * @return integer Size of undeleted objects
29
     * @todo We should only undelete parameters & attachments deleted inside some small window of the main objects delete
30
     */
31
    public static function undelete($guids) : int
32
    {
33
        $undeleted_size = 0;
34
35
        foreach ((array) $guids as $guid) {
36
            if (!mgdobject::undelete($guid)) {
37
                debug_add("Failed to undelete object with GUID {$guid} errstr: " . midcom_connection::get_error_string(), MIDCOM_LOG_ERROR);
38
                continue;
39
            }
40
            // refresh
41
            $object = midcom::get()->dbfactory->get_object_by_guid($guid);
42
            $undeleted_size += $object->metadata->size;
43
            $parent = $object->get_parent();
44
            if (!empty($parent->guid)) {
45
                // Invalidate parent from cache so content caches have chance to react
46
                midcom::get()->cache->invalidate($parent->guid);
47
            }
48
49
            // FIXME: We should only undelete parameters & attachments deleted inside some small window of the main objects delete
50
            $undeleted_size += self::undelete_parameters($guid);
51
            $undeleted_size += self::undelete_attachments($guid);
52
53
            //FIXME: are we sure we want to undelete all children here unconditionally, shouldn't it be left as UI decision ??
54
            // List all deleted children
55
            $children_types = midcom_helper_reflector_tree::get_child_objects($object, true);
56
57
            foreach ($children_types as $children) {
58
                $child_guids = array_column($children, 'guid');
59
                $undeleted_size += self::undelete($child_guids);
60
            }
61
        }
62
63
        return $undeleted_size;
64
    }
65
66
    /**
67
     * Recover the parameters related to a deleted object
68
     *
69
     * @return integer Size of undeleted objects
70
     * @todo We should only undelete parameters & attachments deleted inside some small window of the main objects delete
71
     */
72
    public static function undelete_parameters(string $guid) : int
73
    {
74
        $undeleted_size = 0;
75
76
        $qb = new midgard_query_builder('midgard_parameter');
77
        $qb->include_deleted();
78
        $qb->add_constraint('parentguid', '=', $guid);
79
        $qb->add_constraint('metadata.deleted', '=', true);
80
        foreach ($qb->execute() as $param) {
81
            if ($param->undelete($param->guid)) {
82
                $undeleted_size += $param->metadata->size;
83
            }
84
        }
85
86
        return $undeleted_size;
87
    }
88
89
    /**
90
     * Recover the attachments related to a deleted object
91
     *
92
     * @return integer Size of undeleted objects
93
     * @todo We should only undelete parameters & attachments deleted inside some small window of the main objects delete
94
     */
95
    public static function undelete_attachments(string $guid) : int
96
    {
97
        $undeleted_size = 0;
98
99
        $qb = new midgard_query_builder('midgard_attachment');
100
        $qb->include_deleted();
101
        $qb->add_constraint('parentguid', '=', $guid);
102
        $qb->add_constraint('metadata.deleted', '=', true);
103
        foreach ($qb->execute() as $att) {
104
            if ($att->undelete($att->guid)) {
105
                midcom::get()->uimessages->add(midcom::get()->i18n->get_string('midgard.admin.asgard', 'midgard.admin.asgard'), sprintf(midcom::get()->i18n->get_string('attachment %s undeleted', 'midgard.admin.asgard'), $att->name, midcom_connection::get_error_string()));
106
                $undeleted_size += $att->metadata->size;
107
                $undeleted_size += self::undelete_parameters($att->guid);
108
            } else {
109
                midcom::get()->uimessages->add(midcom::get()->i18n->get_string('midgard.admin.asgard', 'midgard.admin.asgard'), sprintf(midcom::get()->i18n->get_string('failed undeleting attachment %s, reason %s', 'midgard.admin.asgard'), $att->name, midcom_connection::get_error_string()), 'error');
110
            }
111
        }
112
113
        return $undeleted_size;
114
    }
115
116
    /**
117
     * Purge objects
118
     *
119
     * @return integer Size of purged objects
120
     */
121 1
    public static function purge(array $guids, string $type) : int
122
    {
123 1
        $purged_size = 0;
124 1
        $qb = new midgard_query_builder($type);
125 1
        $qb->add_constraint('guid', 'IN', $guids);
126 1
        $qb->include_deleted();
127
128 1
        foreach ($qb->execute() as $object) {
129
            // first kill your children
130
            $children_types = midcom_helper_reflector_tree::get_child_objects($object, true);
131
            foreach ($children_types as $child_type => $children) {
132
                $child_guids = array_column($children, 'guid');
133
                self::purge($child_guids, $child_type);
134
            }
135
136
            // then shoot your dogs
137
            $purged_size += self::purge_parameters($object->guid);
138
            $purged_size += self::purge_attachments($object->guid);
139
140
            // now shoot yourself
141
            if (!$object->purge()) {
142
                debug_add("Failed to purge object " . get_class($object) . " {$object->guid}", MIDCOM_LOG_INFO);
143
            } else {
144
                $purged_size += $object->metadata->size;
145
            }
146
        }
147
148 1
        return $purged_size;
149
    }
150
151
    /**
152
     * Purge the parameters related to a deleted object
153
     *
154
     * @return integer Size of purged objects
155
     */
156
    public static function purge_parameters(string $guid) : int
157
    {
158
        $purged_size = 0;
159
160
        $qb = new midgard_query_builder('midgard_parameter');
161
        $qb->include_deleted();
162
        $qb->add_constraint('parentguid', '=', $guid);
163
        foreach ($qb->execute() as $param) {
164
            if ($param->purge()) {
165
                $purged_size += $param->metadata->size;
166
            } else {
167
                midcom::get()->uimessages->add(
168
                    midcom::get()->i18n->get_string('midgard.admin.asgard', 'midgard.admin.asgard'),
169
                    sprintf(midcom::get()->i18n->get_string('failed purging parameter %s => %s, reason %s', 'midgard.admin.asgard'), $param->domain, $param->name, midcom_connection::get_error_string()),
170
                    'error'
171
                );
172
            }
173
        }
174
175
        return $purged_size;
176
    }
177
178
    /**
179
     * Purge the attachments related to a deleted object
180
     *
181
     * @return integer Size of purged objects
182
     */
183
    public static function purge_attachments(string $guid) : int
184
    {
185
        $purged_size = 0;
186
187
        $qb = new midgard_query_builder('midgard_attachment');
188
        $qb->include_deleted();
189
        $qb->add_constraint('parentguid', '=', $guid);
190
        foreach ($qb->execute() as $att) {
191
            if ($att->purge()) {
192
                $purged_size += $att->metadata->size;
193
                self::purge_parameters($att->guid);
194
            } else {
195
                midcom::get()->uimessages->add(midcom::get()->i18n->get_string('midgard.admin.asgard', 'midgard.admin.asgard'), sprintf(midcom::get()->i18n->get_string('failed purging attachment %s => %s, reason %s', 'midgard.admin.asgard'), $att->guid, $att->name, midcom_connection::get_error_string()), 'error');
196
            }
197
        }
198
199
        return $purged_size;
200
    }
201
}
202