Passed
Push — master ( fc528a...501070 )
by Nicolaas
10:25
created

ArchiveOldRecords::copyTable()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 5
nc 2
nop 0
dl 0
loc 7
rs 10
c 1
b 0
f 0
1
<?php
2
3
namespace Sunnysideup\CleanupTables;
4
5
use SilverStripe\Core\Config\Config;
6
use SilverStripe\Dev\BuildTask;
7
use SilverStripe\ORM\DB;
8
9
class ArchiveOldRecords extends BuildTask
10
{
11
    protected $_schema;
12
13
    private static $segment = 'archive-old-records';
14
15
    protected $title = 'Archive old records from selected tables';
16
    protected $description = '
17
        You can set a list of tables and an expiration date.
18
        This will create a new table with the same name and the post-fix "_ARCHIVE" and
19
        move all records older than the expiration date to that table.';
20
21
    private static array  $tables = [
22
        'LoginAttempt',
23
    ];
24
    private static string $post_fix = '_ARCHIVE';
25
26
    private static int $days_ago = 365;
27
28
    private static bool $delete_only = false;
29
30
    protected string $table = '';
31
32
    private array $cacheTableExists = [];
33
34
35
36
    public function run($request)
37
    {
38
        foreach (Config::inst()->get(self::class, 'tables') as $table) {
39
            $this->setTable($table);
40
            $this->copyTable();
41
            $this->moveRecords();
42
        }
43
    }
44
45
    protected function setTable(string $table): ArchiveOldRecords
46
    {
47
        $this->table = $table;
48
49
        return $this;
50
    }
51
52
    protected function getTable(): string
53
    {
54
        return $this->table;
55
    }
56
57
    protected function getArchiveTable(): string
58
    {
59
        return $this->getTable() . Config::inst()->get(self::class, 'post_fix');
60
    }
61
62
    protected function copyTable()
63
    {
64
        $oldTable = $this->getTable();
65
        $newTable = $this->getArchiveTable();
66
        $deleteOnly = Config::inst()->get(static::class, 'delete_only');
67
        if (! $this->tableExists($newTable) && $deleteOnly !== true) {
68
            DB::query('CREATE TABLE "' . $newTable . '" LIKE "' . $oldTable . '";');
69
        }
70
    }
71
72
    protected function getCutOffTimestamp(): int
73
    {
74
        return time() - intval(86400 * intval(Config::inst()->get(self::class, 'days_ago')));
75
    }
76
77
    protected function moveRecords()
78
    {
79
        $oldTable = $this->getTable();
80
        $newTable = $this->getArchiveTable();
81
        $where = ' WHERE UNIX_TIMESTAMP("' . $oldTable . '"."LastEdited") < ' . $this->getCutOffTimestamp();
82
        $count = DB::query('SELECT COUNT(*) FROM "' . $oldTable . '" ' . $where)->value();
83
        $deleteOnly = Config::inst()->get(static::class, 'delete_only');
84
        DB::alteration_message('Archiving ' . $count . ' records from ' . $oldTable . ' to ' . $newTable, 'created');
85
        if ((bool) $deleteOnly !== true) {
86
            DB::query('INSERT INTO "' . $newTable . '" SELECT * FROM "' . $oldTable . '" ' . $where);
87
        }
88
        DB::query('DELETE FROM "' . $oldTable . '" ' . $where);
89
    }
90
91
    protected function tableExists($tableName): bool
92
    {
93
        $schema = $this->getSchema();
94
        return (bool) ($this->cacheTableExists[$tableName] = $schema->hasTable($tableName));
95
    }
96
97
    protected function getSchema()
98
    {
99
        if (null === $this->_schema) {
100
            $this->_schema = DB::get_schema();
101
            $this->_schema->schemaUpdate(function () {
102
                return true;
103
            });
104
        }
105
106
        return $this->_schema;
107
    }
108
}
109