Completed
Pull Request — 2.0 (#18)
by David
02:15
created

LocalChangesTracker::createUuidInsertTrigger()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 17
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 17
rs 9.4285
cc 1
eloc 5
nc 1
nop 1
1
<?php
2
3
namespace Wabel\Zoho\CRM\Copy;
4
5
use Doctrine\DBAL\Connection;
6
use Doctrine\DBAL\Schema\Table;
7
use Psr\Log\LoggerInterface;
8
9
/**
10
 * This class is in charge of tracking local files.
11
 * To do so, it can add a set of triggers that observe and track changes in tables.
12
 */
13
class LocalChangesTracker
14
{
15
    /**
16
     * @var Connection
17
     */
18
    private $connection;
19
20
    /**
21
     * @var LoggerInterface
22
     */
23
    private $logger;
24
25
    /**
26
     * @param Connection $connection
27
     */
28
    public function __construct(Connection $connection, LoggerInterface $logger)
29
    {
30
        $this->connection = $connection;
31
        $this->logger = $logger;
32
    }
33
34
    public function createTrackingTables()
35
    {
36
        $schema = new \Doctrine\DBAL\Schema\Schema();
37
38
        $localUpdate = $schema->createTable('local_update');
39
        $localUpdate->addColumn('table_name', 'string', ['length' => 100]);
40
        $localUpdate->addColumn('uid', 'string', ['length' => 36]);
41
        $localUpdate->addColumn('field_name', 'string', ['length' => 100]);
42
        $localUpdate->setPrimaryKey(array('table_name', 'uid', 'field_name'));
43
44
        $localInsert = $schema->createTable('local_insert');
45
        $localInsert->addColumn('table_name', 'string', ['length' => 100]);
46
        $localInsert->addColumn('uid', 'string', ['length' => 36]);
47
        $localInsert->setPrimaryKey(array('table_name', 'uid'));
48
49
        $localDelete = $schema->createTable('local_delete');
50
        $localDelete->addColumn('table_name', 'string', ['length' => 100]);
51
        $localDelete->addColumn('uid', 'string', ['length' => 36]);
52
        $localDelete->addColumn('id', 'string', ['length' => 100,'notnull'=>false]);
53
        $localDelete->setPrimaryKey(array('table_name', 'uid'));
54
        $localDelete->addUniqueIndex(['id', 'table_name']);
55
56
        $dbalTableDiffService = new DbalTableDiffService($this->connection, $this->logger);
57
        $dbalTableDiffService->createOrUpdateTable($localUpdate);
58
        $dbalTableDiffService->createOrUpdateTable($localInsert);
59
        $dbalTableDiffService->createOrUpdateTable($localDelete);
60
    }
61
62
    public function createUuidInsertTrigger(Table $table)
63
    {
64
        $triggerName = sprintf('TRG_%s_SETUUIDBEFOREINSERT', $table->getName());
65
66
        $sql = sprintf('
67
            DROP TRIGGER IF EXISTS %s;
68
            
69
            CREATE TRIGGER %s BEFORE INSERT ON `%s` 
70
            FOR EACH ROW
71
              IF new.uid IS NULL
72
              THEN
73
                SET new.uid = uuid();
74
              END IF;
75
            ', $triggerName, $triggerName, $table->getName());
76
77
        $this->connection->exec($sql);
78
    }
79
80 View Code Duplication
    public function createInsertTrigger(Table $table)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
81
    {
82
        $triggerName = sprintf('TRG_%s_ONINSERT', $table->getName());
83
84
        $sql = sprintf('
85
            DROP TRIGGER IF EXISTS %s;
86
            
87
            CREATE TRIGGER %s AFTER INSERT ON `%s` 
88
            FOR EACH ROW
89
            BEGIN
90
              IF (NEW.lastActivityTime IS NULL) THEN
91
                INSERT INTO local_insert VALUES (%s, NEW.uid);
92
                DELETE FROM local_delete WHERE table_name = %s AND uid = NEW.uid;
93
                DELETE FROM local_update WHERE table_name = %s AND uid = NEW.uid;
94
              END IF;
95
            END;
96
            
97
            ', $triggerName, $triggerName, $table->getName(), $this->connection->quote($table->getName()), $this->connection->quote($table->getName()), $this->connection->quote($table->getName()));
98
99
        $this->connection->exec($sql);
100
    }
101
102 View Code Duplication
    public function createDeleteTrigger(Table $table)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
103
    {
104
        $triggerName = sprintf('TRG_%s_ONDELETE', $table->getName());
105
106
        $sql = sprintf('
107
            DROP TRIGGER IF EXISTS %s;
108
            
109
            CREATE TRIGGER %s BEFORE DELETE ON `%s` 
110
            FOR EACH ROW
111
            BEGIN
112
              IF (OLD.id IS NOT NULL) THEN
113
                INSERT INTO local_delete VALUES (%s, OLD.uid, OLD.id);
114
              END IF;
115
              DELETE FROM local_insert WHERE table_name = %s AND uid = OLD.uid;
116
              DELETE FROM local_update WHERE table_name = %s AND uid = OLD.uid;
117
            END;
118
            
119
            ', $triggerName, $triggerName, $table->getName(), $this->connection->quote($table->getName()), $this->connection->quote($table->getName()), $this->connection->quote($table->getName()));
120
121
        $this->connection->exec($sql);
122
    }
123
124
    public function createUpdateTrigger(Table $table)
125
    {
126
        $triggerName = sprintf('TRG_%s_ONUPDATE', $table->getName());
127
128
        $innerCode = '';
129
130
        foreach ($table->getColumns() as $column) {
131
            if (in_array($column->getName(), ['id', 'uid'])) {
132
                continue;
133
            }
134
            $columnName = $this->connection->quoteIdentifier($column->getName());
135
            $innerCode .= sprintf('
136
                IF NOT(NEW.%s <=> OLD.%s) THEN
137
                  REPLACE INTO local_update VALUES (%s, NEW.uid, %s);
138
                END IF;
139
            ', $columnName, $columnName, $this->connection->quote($table->getName()), $this->connection->quote($column->getName()));
140
        }
141
142
        $sql = sprintf('
143
            DROP TRIGGER IF EXISTS %s;
144
            
145
            CREATE TRIGGER %s AFTER UPDATE ON `%s` 
146
            FOR EACH ROW
147
            BEGIN
148
              IF (NEW.lastActivityTime <=> OLD.lastActivityTime) THEN
149
            %s
150
              END IF;
151
            END;
152
            
153
            ', $triggerName, $triggerName, $table->getName(), $innerCode);
154
155
        $this->connection->exec($sql);
156
    }
157
}
158