PruneAllVersionedRecords   A
last analyzed

Complexity

Total Complexity 23

Size/Duplication

Total Lines 146
Duplicated Lines 0 %

Importance

Changes 9
Bugs 0 Features 0
Metric Value
eloc 70
c 9
b 0
f 0
dl 0
loc 146
rs 10
wmc 23

6 Methods

Rating   Name   Duplication   Size   Complexity  
A getAllVersionedDataClasses() 0 11 3
D run() 0 55 15
A getObjectsPerClassName() 0 19 2
A setLimit() 0 5 1
A setVerbose() 0 5 1
A setDryRun() 0 5 1
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
use Sunnysideup\VersionPruner\Api\RunForOneObject;
13
14
class PruneAllVersionedRecords extends BuildTask
15
{
16
    /**
17
     * the number of unique records in the LIVE / DRAFT Table
18
     * that will be looked at in one go.
19
     * @var int
20
     */
21
    protected const MAX_ITEMS_PER_CLASS = 10000;
22
23
    /**
24
     * @var string
25
     */
26
    protected $title = 'Prune all versioned records';
27
28
    protected $description = 'Go through all dataobjects that are versioned and prune them as per schema provided.';
29
30
    protected $limit = self::MAX_ITEMS_PER_CLASS;
31
32
    protected $verbose = false;
33
34
    protected $dryRun = false;
35
36
    /**
37
     * @var string
38
     */
39
    private static $segment = 'prune-all-versioned-records';
40
41
    public function setVerbose(?bool $verbose = true): self
42
    {
43
        $this->verbose = $verbose;
44
45
        return $this;
46
    }
47
48
    public function setDryRun(?bool $dryRun = true): self
49
    {
50
        $this->dryRun = $dryRun;
51
52
        return $this;
53
    }
54
55
    public function setLimit(int $limit): self
56
    {
57
        $this->limit = $limit;
58
59
        return $this;
60
    }
61
62
    /**
63
     * Prune all published DataObjects which are published according to config.
64
     *
65
     * @param mixed $request
66
     */
67
    public function run($request)
68
    {
69
        $classes = $this->getAllVersionedDataClasses();
70
        if ($request && $request->requestVar('verbose')) {
71
            $this->verbose = $request->requestVar('verbose');
72
        }
73
74
        if ($request && $request->requestVar('dry')) {
75
            $this->dryRun = $request->requestVar('dry');
76
        }
77
78
        if ($request && $request->requestVar('limit')) {
79
            $this->limit = $request->requestVar('limit');
80
        }
81
82
        DB::alteration_message('Pruning all DataObjects with a maximum of ' . self::MAX_ITEMS_PER_CLASS . ' per class.');
83
        $totalTotalDeleted = 0;
84
        $runObject = RunForOneObject::inst()
85
            ->setVerbose($this->verbose)
86
            ->setDryRun($this->dryRun);
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
            $objects = $this->getObjectsPerClassName($runObject, $className);
95
            $noData = '';
96
            if (! $objects->exists()) {
97
                $noData = '- nothing to do';
98
            }
99
            DB::alteration_message('... Looking at ' . $className . ' ' . $noData);
100
            $totalDeleted = 0;
101
102
            foreach ($objects as $object) {
103
                // check if stages are present
104
                if ($this->verbose) {
105
                    DB::alteration_message('... ... Checking #ID: ' . $object->ID);
106
                }
107
                $totalDeleted += $runObject->deleteSuperfluousVersions($object);
108
            }
109
110
            if ($totalDeleted > 0) {
111
                DB::alteration_message('... ... Deleted ' . $totalDeleted . ' version records');
112
                $totalTotalDeleted += $totalDeleted;
113
            }
114
        }
115
116
        DB::alteration_message('-------------------- ');
117
        DB::alteration_message('Completed, pruned ' . $totalTotalDeleted . ' version records');
118
        DB::alteration_message('-------------------- ');
119
        $array = $runObject->getCountRegister();
120
        foreach ($array as $table => $count) {
121
            DB::alteration_message('... ' . $table . ' has ' . $count . ' version records left.');
122
        }
123
    }
124
125
    protected function getObjectsPerClassName($runObject, string $className): DataList
126
    {
127
        $rootTable = $runObject->getRootTable($className);
128
        $sql = '
129
            SELECT COUNT("ID") AS C, "RecordID"
130
            FROM "' . $rootTable . '_Versions"
131
            WHERE ClassName = \'' . addslashes($className) . '\'
132
            GROUP BY "RecordID"
133
            ORDER BY C DESC
134
            LIMIT ' . $this->limit . ';';
135
        $rows = DB::query($sql);
136
        $array = [-1 => 0];
137
        foreach ($rows as $row) {
138
            $array[] = $row['RecordID'];
139
        }
140
141
        return Versioned::get_by_stage($className, Versioned::DRAFT)
142
            ->filter(['ID' => $array])
143
            ->limit($this->limit);
144
    }
145
146
    /**
147
     * Get all versioned database classes.
148
     */
149
    protected function getAllVersionedDataClasses(): array
150
    {
151
        $allClasses = ClassInfo::subclassesFor(DataObject::class);
152
        $versionedClasses = [];
153
        foreach ($allClasses as $className) {
154
            if (DataObject::has_extension($className, Versioned::class)) {
155
                $versionedClasses[$className] = $className;
156
            }
157
        }
158
159
        return $versionedClasses;
160
    }
161
}
162