Completed
Pull Request — 1.1 (#3)
by Raphaël
02:28
created

ZohoDatabasePusher::pushDataToZoho()   C

Complexity

Conditions 11
Paths 104

Size

Total Lines 56
Code Lines 39

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 1
Metric Value
c 1
b 1
f 1
dl 0
loc 56
rs 6.4356
cc 11
eloc 39
nc 104
nop 2

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Wabel\Zoho\CRM\Copy;
4
5
use Doctrine\DBAL\Connection;
6
use Psr\Log\LoggerInterface;
7
use Psr\Log\NullLogger;
8
use Wabel\Zoho\CRM\AbstractZohoDao;
9
use Wabel\Zoho\CRM\ZohoBeanInterface;
10
11
/**
12
 * Description of ZohoDatabasePusher
13
 *
14
 * @author rbergina
15
 */
16
class ZohoDatabasePusher
17
{
18
19
    /**
20
     * @var Connection
21
     */
22
    private $connection;
23
24
    /**
25
     * @var LoggerInterface
26
     */
27
    private $logger;
28
29
    /**
30
     *
31
     * @var string
32
     */
33
    private $prefix;
34
35
    /**
36
     * @param Connection $connection
37
     * @param string $prefix
38
     * @param LoggerInterface $logger
39
     */
40
    public function __construct(Connection $connection, $prefix = 'zoho_', LoggerInterface $logger = null)
41
    {
42
        $this->connection = $connection;
43
        $this->prefix = $prefix;
44
        if ($logger === null) {
45
            $this->logger = new NullLogger();
46
        } else {
47
            $this->logger = $logger;
48
        }
49
    }
50
51
    /**
52
     *
53
     * @param AbstractZohoDao $zohoDao
54
     * @return array
55
     */
56
    private function findMethodValues(AbstractZohoDao $zohoDao){
57
        $fieldsMatching = array();
58
        foreach ($zohoDao->getFields() as $fieldsDescriptor) {
0 ignored issues
show
Bug introduced by
The method getFields() cannot be called from this context as it is declared protected in class Wabel\Zoho\CRM\AbstractZohoDao.

This check looks for access to methods that are not accessible from the current context.

If you need to make a method accessible to another context you can raise its visibility level in the defining class.

Loading history...
59
            foreach (array_values($fieldsDescriptor) as $fieldDescriptor) {
60
                $fieldsMatching[$fieldDescriptor['name']] = [
61
                    'setter' => $fieldDescriptor['setter'],
62
                    'type' => $fieldDescriptor['type']
63
                ];
64
            }
65
66
        }
67
        return $fieldsMatching;
68
    }
69
70
    /**
71
     * Insert or Update rows.
72
     * @param AbstractZohoDao $zohoDao
73
     */
74
    public function pushDataToZoho(AbstractZohoDao $zohoDao, $update = false){
75
        $localTable = $update ? 'local_update' : 'local_insert';
76
        $fieldsMatching = $this->findMethodValues($zohoDao);
77
        $tableName = ZohoDatabaseHelper::getTableName($zohoDao,$this->prefix);
78
        $rowsDeleted = [];
79
        $statement = $this->connection->createQueryBuilder();
80
        $statement->select('zcrm.*');
81
        if($update){
82
            $statement->addSelect('l.field_name as updated_fieldname');
83
        }
84
        $statement->from($localTable, 'l')
85
        ->join('l', $tableName, 'zcrm', 'zcrm.uid = l.uid')
86
        ->where('l.table_name=:table_name')
87
        ->setParameters([
88
            'table_name' => $tableName
89
        ]);
90
        $results = $statement->execute();
91
        /* @var $zohoBeans ZohoBeanInterface[] */
92
        $zohoBeans = array();
93
        while ($row = $results->fetch()) {
94
            $beanClassName = $zohoDao->getBeanClassName();
0 ignored issues
show
Bug introduced by
The method getBeanClassName() cannot be called from this context as it is declared protected in class Wabel\Zoho\CRM\AbstractZohoDao.

This check looks for access to methods that are not accessible from the current context.

If you need to make a method accessible to another context you can raise its visibility level in the defining class.

Loading history...
95
            /* @var $zohoBean ZohoBeanInterface */
96
            if(isset($zohoBeans[$row['uid']])){
97
                $zohoBean = $zohoBeans[$row['uid']];
98
            }else{
99
                $zohoBean = new $beanClassName();
100
            }
101
 
102
            if(!$update){
103
                $this->insertDataZohoBean($zohoBean, $fieldsMatching, $row);
104
                $zohoBeans[$row['uid']] =  $zohoBean;
105
                $rowsDeleted[] = $row['uid'];
106
            }
107
            if($update && isset($row['updated_fieldname'])){
108
               $columnName = $row['updated_fieldname'];
109
               $zohoBean->getZohoId()?:$zohoBean->setZohoId($row['id']);
110
               $this->updateDataZohoBean($zohoBean, $fieldsMatching, $columnName, $row[$columnName]);
111
               $zohoBeans[$row['uid']] = $zohoBean;
112
               $rowsDeleted[] = $row['uid'];
113
            }
114
        }
115
        $zohoDao->save($zohoBeans);
116
        if(!$update){
117
            foreach ($zohoBeans as $uid => $zohoBean) {
118
                $this->connection->update($tableName, [ 'id'=>$zohoBean->getZohoId() ], ['uid'=>$uid ]);
119
            }
120
        }
121
        $this->connection->executeUpdate('delete from '.$localTable.' where uid in ( :rowsDeleted)',
0 ignored issues
show
Security introduced by
If $localTable can contain user-input, it is usually preferable to use a parameter placeholder like :paramName and pass the dynamic input as second argument array('param' => $localTable).

Instead of embedding dynamic parameters in SQL, Doctrine also allows you to pass them separately and insert a placeholder instead:

function findUser(Doctrine\DBAL\Connection $con, $email) {
    // Unsafe
    $con->executeQuery("SELECT * FROM users WHERE email = '".$email."'");

    // Safe
    $con->executeQuery(
        "SELECT * FROM users WHERE email = :email",
        array('email' => $email)
    );
}
Loading history...
122
            [
123
            'rowsDeleted' => $rowsDeleted
124
            ],
125
            [
126
            'rowsDeleted' => Connection::PARAM_INT_ARRAY
127
            ]
128
        );
129
    }
130
131
    /**
132
     * Insert data to bean in order to insert zoho records.
133
     * @param ZohoBeanInterface $zohoBean
134
     * @param array $fieldsMatching
135
     * @param array $row
136
     */
137 View Code Duplication
    private function insertDataZohoBean(ZohoBeanInterface $zohoBean, array $fieldsMatching, array $row)
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...
138
    {
139
        foreach ($row as $columnName => $columnValue) {
140
            if ((!in_array($columnName, ['id', 'uid']) || isset($fieldsMatching[$columnName])) && !is_null($columnValue)) {
141
                $type = $fieldsMatching[$columnName]['type'];
142
                $value = $this->formatValueToBeans($type, $columnValue);
143
                $zohoBean->{$fieldsMatching[$columnName]['setter']}($value);
144
            }
145
        }
146
    }
147
148
    /**
149
     * Insert data to bean in order to update zoho records.
150
     * @param ZohoBeanInterface $zohoBean
151
     * @param array $fieldsMatching
152
     * @param type $columnName
153
     * @param type $valueDb
154
     */
155 View Code Duplication
    private function updateDataZohoBean(ZohoBeanInterface $zohoBean, array $fieldsMatching, $columnName, $valueDb){
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...
156
        if (!in_array($columnName,['id','uid']) || (isset($fieldsMatching[$columnName]))) {
157
            $type = $fieldsMatching[$columnName]['type'];
158
            $value = is_null($valueDb)?$valueDb:$this->formatValueToBeans($type, $valueDb);
159
            $zohoBean->{$fieldsMatching[$columnName]['setter']}($value);
160
        }
161
    }
162
163
    /**
164
     * Change the value to the good format.
165
     * @param string $type
166
     * @param mixed $value
167
     * @return mixed
168
     */
169
    private function formatValueToBeans($type ,$value)
170
    {
171
        switch ($type) {
172
            case 'Date':
173
                $value = \DateTime::createFromFormat('Y-m-d', $value);
174
                break;
175
            case 'DateTime':
176
                $value = \DateTime::createFromFormat('Y-m-d H:i:s', $value);
177
                break;
178
        }
179
        return $value;
180
    }
181
182
    /**
183
     * Run deleted rows to Zoho : local_delete.
184
     * @param AbstractZohoDao $zohoDao
185
     */
186
    public function pushDeletedRows(AbstractZohoDao $zohoDao){
187
        $localTable = 'local_delete';
188
        $tableName = ZohoDatabaseHelper::getTableName($zohoDao,$this->prefix);
189
        $statement = $this->connection->createQueryBuilder();
190
        $statement->select('l.id')
191
        ->from($localTable, 'l')
192
        ->where('l.table_name=:table_name')
193
        ->setParameters([
194
            'table_name' => $tableName
195
        ]);
196
        $results = $statement->execute();
197
        while ($row = $results->fetch()) {
198
            $zohoDao->delete($row['id']);
199
            $this->connection->delete($localTable, ['table_name' => $tableName,'id' => $row['id']]);
200
        }
201
}
202
    
203
    /**
204
     * Run inserted rows to Zoho : local_insert.
205
     * @param AbstractZohoDao $zohoDao
206
     */
207
    public function pushInsertedRows(AbstractZohoDao $zohoDao){
208
        return $this->pushDataToZoho($zohoDao);
209
    }
210
211
    /**
212
     * Run updated rows to Zoho : local_update.
213
     * @param AbstractZohoDao $zohoDao
214
     */
215
    public function pushUpdatedRows(AbstractZohoDao $zohoDao){
216
        $this->pushDataToZoho($zohoDao,true);
217
    }
218
219
    /**
220
     * Push data from db to Zoho.
221
     * @param AbstractZohoDao $zohoDao
222
     */
223
    public function pushToZoho(AbstractZohoDao $zohoDao)
224
    {
225
        $this->logger->info(' > Insert new rows using {class_name}', ['class_name'=>get_class($zohoDao)]);
226
        $this->pushInsertedRows($zohoDao);
227
        $this->logger->info(' > Update rows using {class_name}', ['class_name'=>get_class($zohoDao)]);
228
        $this->pushUpdatedRows($zohoDao);
229
        $this->logger->info(' > Delete rows using  {class_name}', ['class_name'=>get_class($zohoDao)]);
230
        $this->pushDeletedRows($zohoDao);
231
    }
232
233
    /**
234
     * @param LoggerInterface $logger
235
     */
236
    public function setLogger(LoggerInterface $logger)
237
    {
238
        $this->logger = $logger;
239
    }
240
241
242
}