Passed
Push — master ( 8b153b...25e776 )
by Nicolaas
02:43 queued 42s
created

PruneAllVersionedRecords   A

Complexity

Total Complexity 27

Size/Duplication

Total Lines 166
Duplicated Lines 0 %

Importance

Changes 8
Bugs 0 Features 0
Metric Value
eloc 79
c 8
b 0
f 0
dl 0
loc 166
rs 10
wmc 27

7 Methods

Rating   Name   Duplication   Size   Complexity  
A setLimit() 0 5 1
A setVerbose() 0 5 1
A setDryRun() 0 5 1
C run() 0 52 14
A getAllVersionedDataClassesBase() 0 20 5
A getAllVersionedDataClasses() 0 11 3
A getObjectsPerClassName() 0 19 2
1
<?php
2
3
namespace Sunnysideup\VersionPruner\Tasks;
4
5
use SilverStripe\Core\ClassInfo;
6
use SilverStripe\Core\Config\Config;
7
use SilverStripe\Dev\BuildTask;
8
use SilverStripe\ORM\DataList;
9
use SilverStripe\ORM\DataObject;
10
use SilverStripe\ORM\DB;
11
use SilverStripe\Versioned\Versioned;
0 ignored issues
show
Bug introduced by
The type SilverStripe\Versioned\Versioned was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
12
13
use Sunnysideup\VersionPruner\Api\RunForOneObject;
14
15
class PruneAllVersionedRecords extends BuildTask
16
{
17
    /**
18
     * @var int
19
     */
20
    protected const MAX_ITEMS_PER_CLASS = 500;
21
22
    /**
23
     * @var string
24
     */
25
    protected $title = 'Prune all versioned records';
26
27
    protected $description = 'Go through all dataobjects that are versioned and prune them as per schema provided.';
28
29
    protected $limit = self::MAX_ITEMS_PER_CLASS;
30
31
    protected $verbose = false;
32
33
    protected $dryRun = false;
34
35
    /**
36
     * @var string
37
     */
38
    private static $segment = 'prune-all-versioned-records';
39
40
    public function setVerbose(?bool $verbose = true): self
41
    {
42
        $this->verbose = $verbose;
43
44
        return $this;
45
    }
46
47
    public function setDryRun(?bool $dryRun = true): self
48
    {
49
        $this->dryRun = $dryRun;
50
51
        return $this;
52
    }
53
54
    public function setLimit(int $limit): self
55
    {
56
        $this->limit = $limit;
57
58
        return $this;
59
    }
60
61
    /**
62
     * Prune all published DataObjects which are published according to config.
63
     *
64
     * @param mixed $request
65
     */
66
    public function run($request)
67
    {
68
        $classes = $this->getAllVersionedDataClasses();
69
        if ($request && $request->requestVar('verbose')) {
70
            $this->verbose = $request->requestVar('verbose');
71
        }
72
73
        if ($request && $request->requestVar('dry')) {
74
            $this->dryRun = $request->requestVar('dry');
75
        }
76
77
        if ($request && $request->requestVar('limit')) {
78
            $this->limit = $request->requestVar('limit');
79
        }
80
81
        DB::alteration_message('Pruning all DataObjects with a maximum of ' . self::MAX_ITEMS_PER_CLASS . ' per class.');
82
        $totalTotalDeleted = 0;
83
        $runObject = RunForOneObject::inst()
84
            ->setVerbose($this->verbose)
85
            ->setDryRun($this->dryRun)
86
        ;
87
        DB::alteration_message('settings (set as parameters)');
88
        DB::alteration_message('-------------------- ');
89
        DB::alteration_message('verbose: ' . ($this->verbose ? 'yes' : 'no'), 'created');
90
        DB::alteration_message('dry run: ' . ($this->dryRun ? 'yes' : 'no'), 'created');
91
        DB::alteration_message('limit per class: ' . $this->limit, 'created');
92
        DB::alteration_message('-------------------- ');
93
        foreach ($classes as $className) {
94
            DB::alteration_message('... Looking at ' . $className);
95
            $objects = $this->getObjectsPerClassName($runObject, $className);
96
            $totalDeleted = 0;
97
98
            foreach ($objects as $object) {
99
                // check if stages are present
100
                if($this->verbose) {
101
                    DB::alteration_message('... ... Checking #ID: ' . $object->ID);
102
                }
103
                $totalDeleted += $runObject->deleteSuperfluousVersions($object);
104
            }
105
106
            if ($totalDeleted > 0) {
107
                DB::alteration_message('... ... Deleted ' . $totalDeleted . ' version records');
108
                $totalTotalDeleted += $totalDeleted;
109
            }
110
        }
111
112
        DB::alteration_message('-------------------- ');
113
        DB::alteration_message('Completed, pruned ' . $totalTotalDeleted . ' version records');
114
        DB::alteration_message('-------------------- ');
115
        $array = $runObject->getCountRegister();
116
        foreach ($array as $table => $count) {
117
            DB::alteration_message('... '.$table . ' has ' . $count . ' version records left.');
118
        }
119
    }
120
121
    protected function getObjectsPerClassName($runObject, string $className): DataList
122
    {
123
        $rootTable = $runObject->getRootTable($className);
124
        $sql = '
125
            SELECT COUNT("ID") AS C, "RecordID"
126
            FROM "'.$rootTable.'_Versions"
127
            WHERE ClassName = \''.addslashes($className).'\'
128
            GROUP BY "RecordID"
129
            ORDER BY C DESC
130
            LIMIT '.$this->limit.';';
131
        $rows = DB::query($sql);
132
        $array = [-1 => 0];
133
        foreach($rows as $row) {
134
            print_r($row);
135
            $array[] = $row['RecordID'];
136
        }
137
        return Versioned::get_by_stage($className, Versioned::DRAFT)
138
            ->filter(['ID' => $array])
139
            ->limit($this->limit)
140
        ;
141
    }
142
143
    /**
144
     * Get all versioned database classes.
145
     */
146
    protected function getAllVersionedDataClasses(): array
147
    {
148
        $allClasses = ClassInfo::subclassesFor(DataObject::class);
149
        $versionedClasses = [];
150
        foreach ($allClasses as $className) {
151
            if (DataObject::has_extension($className, Versioned::class)) {
152
                $versionedClasses[$className] = $className;
153
            }
154
        }
155
156
        return $versionedClasses;
157
    }
158
    /**
159
     * Get all versioned database classes.
160
     */
161
    protected function getAllVersionedDataClassesBase(): array
162
    {
163
        $allClasses = ClassInfo::subclassesFor(DataObject::class);
164
        $versionedClasses = [];
165
        foreach ($allClasses as $className) {
166
            if (DataObject::has_extension($className, Versioned::class)) {
167
                $ancestors = ClassInfo::ancestry($className);
168
                foreach ($ancestors as $classNameInner) {
169
                    if (DataObject::has_extension($classNameInner, Versioned::class)) {
170
                        $versionedClasses[$classNameInner] = $classNameInner;
171
172
                        continue 2;
173
                    }
174
                }
175
176
                $versionedClasses[$className] = $className;
177
            }
178
        }
179
180
        return $versionedClasses;
181
    }
182
}
183