1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
|
4
|
|
|
namespace Wabel\Zoho\CRM\Copy; |
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
|
|
|
|
35
|
|
|
public function createTrackingTables() |
36
|
|
|
{ |
37
|
|
|
$schema = new \Doctrine\DBAL\Schema\Schema(); |
38
|
|
|
|
39
|
|
|
$localUpdate = $schema->createTable("local_update"); |
40
|
|
|
$localUpdate->addColumn("table_name", 'string', ['length' => 100]); |
41
|
|
|
$localUpdate->addColumn("id", 'string', ['length' => 100]); |
42
|
|
|
$localUpdate->addColumn("field_name", 'string', ['length' => 100]); |
43
|
|
|
$localUpdate->setPrimaryKey(array("table_name", "id", "field_name")); |
44
|
|
|
|
45
|
|
|
$localInsert = $schema->createTable("local_insert"); |
46
|
|
|
$localInsert->addColumn("table_name", 'string', ['length' => 100]); |
47
|
|
|
$localInsert->addColumn("id", 'string', ['length' => 100]); |
48
|
|
|
$localInsert->setPrimaryKey(array("table_name", "id")); |
49
|
|
|
|
50
|
|
|
$localDelete = $schema->createTable("local_delete"); |
51
|
|
|
$localDelete->addColumn("table_name", 'string', ['length' => 100]); |
52
|
|
|
$localDelete->addColumn("id", 'string', ['length' => 100]); |
53
|
|
|
$localDelete->setPrimaryKey(array("table_name", "id")); |
54
|
|
|
|
55
|
|
|
$dbalTableDiffService = new DbalTableDiffService($this->connection, $this->logger); |
56
|
|
|
$dbalTableDiffService->createOrUpdateTable($localUpdate); |
57
|
|
|
$dbalTableDiffService->createOrUpdateTable($localInsert); |
58
|
|
|
$dbalTableDiffService->createOrUpdateTable($localDelete); |
59
|
|
|
} |
60
|
|
|
|
61
|
|
View Code Duplication |
public function createInsertTrigger(Table $table) |
|
|
|
|
62
|
|
|
{ |
63
|
|
|
$triggerName = sprintf("TRG_%s_ONINSERT", $table->getName()); |
64
|
|
|
|
65
|
|
|
$sql = sprintf(' |
66
|
|
|
DROP TRIGGER IF EXISTS %s; |
67
|
|
|
|
68
|
|
|
CREATE TRIGGER %s AFTER INSERT ON `%s` |
69
|
|
|
FOR EACH ROW |
70
|
|
|
BEGIN |
71
|
|
|
IF (NEW.lastActivityTime IS NULL) THEN |
72
|
|
|
INSERT INTO local_insert VALUES (%s, NEW.id); |
73
|
|
|
DELETE FROM local_delete WHERE table_name = %s AND id = NEW.id; |
74
|
|
|
DELETE FROM local_update WHERE table_name = %s AND id = NEW.id; |
75
|
|
|
END IF; |
76
|
|
|
END; |
77
|
|
|
|
78
|
|
|
', $triggerName, $triggerName, $table->getName(), $this->connection->quote($table->getName()), $this->connection->quote($table->getName()), $this->connection->quote($table->getName())); |
79
|
|
|
|
80
|
|
|
|
81
|
|
|
$this->connection->exec($sql); |
82
|
|
|
} |
83
|
|
|
|
84
|
|
View Code Duplication |
public function createDeleteTrigger(Table $table) |
|
|
|
|
85
|
|
|
{ |
86
|
|
|
$triggerName = sprintf("TRG_%s_ONDELETE", $table->getName()); |
87
|
|
|
|
88
|
|
|
$sql = sprintf(' |
89
|
|
|
DROP TRIGGER IF EXISTS %s; |
90
|
|
|
|
91
|
|
|
CREATE TRIGGER %s BEFORE DELETE ON `%s` |
92
|
|
|
FOR EACH ROW |
93
|
|
|
BEGIN |
94
|
|
|
INSERT INTO local_delete VALUES (%s, OLD.id); |
95
|
|
|
DELETE FROM local_insert WHERE table_name = %s AND id = OLD.id; |
96
|
|
|
DELETE FROM local_update WHERE table_name = %s AND id = OLD.id; |
97
|
|
|
END; |
98
|
|
|
|
99
|
|
|
', $triggerName, $triggerName, $table->getName(), $this->connection->quote($table->getName()), $this->connection->quote($table->getName()), $this->connection->quote($table->getName())); |
100
|
|
|
|
101
|
|
|
|
102
|
|
|
$this->connection->exec($sql); |
103
|
|
|
} |
104
|
|
|
|
105
|
|
|
public function createUpdateTrigger(Table $table) |
106
|
|
|
{ |
107
|
|
|
$triggerName = sprintf("TRG_%s_ONUPDATE", $table->getName()); |
108
|
|
|
|
109
|
|
|
$innerCode = ''; |
110
|
|
|
|
111
|
|
|
foreach ($table->getColumns() as $column) { |
112
|
|
|
$columnName = $this->connection->quoteIdentifier($column->getName()); |
113
|
|
|
$innerCode .= sprintf(' |
114
|
|
|
IF (NEW.%s != OLD.%s) THEN |
115
|
|
|
REPLACE INTO local_update VALUES (%s, NEW.id, %s); |
116
|
|
|
END IF; |
117
|
|
|
', $columnName, $columnName, $this->connection->quote($table->getName()), $this->connection->quote($column->getName())); |
118
|
|
|
} |
119
|
|
|
|
120
|
|
|
$sql = sprintf(' |
121
|
|
|
DROP TRIGGER IF EXISTS %s; |
122
|
|
|
|
123
|
|
|
CREATE TRIGGER %s AFTER UPDATE ON `%s` |
124
|
|
|
FOR EACH ROW |
125
|
|
|
BEGIN |
126
|
|
|
IF (NEW.lastActivityTime = OLD.lastActivityTime) THEN |
127
|
|
|
%s |
128
|
|
|
END IF; |
129
|
|
|
END; |
130
|
|
|
|
131
|
|
|
', $triggerName, $triggerName, $table->getName(), $innerCode); |
132
|
|
|
|
133
|
|
|
|
134
|
|
|
$this->connection->exec($sql); |
135
|
|
|
} |
136
|
|
|
} |
137
|
|
|
|
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.