Completed
Push — 2.0 ( ef9d4b...036124 )
by Raphaël
14s
created

LocalChangesTracker::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 5
rs 9.4285
cc 1
eloc 3
nc 1
nop 2
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', 'integer');
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', 'integer');
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', 'integer');
52
        $localDelete->addColumn('id',  'string', ['length' => 100]);
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 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...
63
    {
64
        $triggerName = sprintf('TRG_%s_ONINSERT', $table->getName());
65
66
        $sql = sprintf('
67
            DROP TRIGGER IF EXISTS %s;
68
            
69
            CREATE TRIGGER %s AFTER INSERT ON `%s` 
70
            FOR EACH ROW
71
            BEGIN
72
              IF (NEW.lastActivityTime IS NULL) THEN
73
                INSERT INTO local_insert VALUES (%s, NEW.uid);
74
                DELETE FROM local_delete WHERE table_name = %s AND uid = NEW.uid;
75
                DELETE FROM local_update WHERE table_name = %s AND uid = NEW.uid;
76
              END IF;
77
            END;
78
            
79
            ', $triggerName, $triggerName, $table->getName(), $this->connection->quote($table->getName()), $this->connection->quote($table->getName()), $this->connection->quote($table->getName()));
80
81
        $this->connection->exec($sql);
82
    }
83
84 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...
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.uid, OLD.id);
95
              DELETE FROM local_insert WHERE table_name = %s AND uid = OLD.uid;
96
              DELETE FROM local_update WHERE table_name = %s AND uid = OLD.uid;
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
        $this->connection->exec($sql);
102
    }
103
104
    public function createUpdateTrigger(Table $table)
105
    {
106
        $triggerName = sprintf('TRG_%s_ONUPDATE', $table->getName());
107
108
        $innerCode = '';
109
110
        foreach ($table->getColumns() as $column) {
111
            if (in_array($column->getName(), ['id', 'uid'])) {
112
                continue;
113
            }
114
            $columnName = $this->connection->quoteIdentifier($column->getName());
115
            $innerCode .= sprintf('
116
                IF (NEW.%s != OLD.%s) THEN
117
                  REPLACE INTO local_update VALUES (%s, NEW.uid, %s);
118
                END IF;
119
            ', $columnName, $columnName, $this->connection->quote($table->getName()), $this->connection->quote($column->getName()));
120
        }
121
122
        $sql = sprintf('
123
            DROP TRIGGER IF EXISTS %s;
124
            
125
            CREATE TRIGGER %s AFTER UPDATE ON `%s` 
126
            FOR EACH ROW
127
            BEGIN
128
              IF (NEW.lastActivityTime <=> OLD.lastActivityTime) THEN
129
            %s
130
              END IF;
131
            END;
132
            
133
            ', $triggerName, $triggerName, $table->getName(), $innerCode);
134
135
        $this->connection->exec($sql);
136
    }
137
}
138