Completed
Push — 3.2 ( 8c2d5f...e78c57 )
by
unknown
08:28 queued 06:51
created

ZohoSyncDatabaseCommand::fetchDbInBulk()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 9
rs 9.9666
c 0
b 0
f 0
cc 2
nc 2
nop 1
1
<?php
2
3
namespace Wabel\Zoho\CRM\Copy;
4
5
use Mouf\Utils\Common\Lock;
6
use Mouf\Utils\Common\LockException;
7
use Symfony\Component\Console\Command\Command;
8
use Symfony\Component\Console\Input\InputInterface;
9
use Symfony\Component\Console\Logger\ConsoleLogger;
10
use Symfony\Component\Console\Output\OutputInterface;
11
use Symfony\Component\Console\Input\InputOption;
12
use Wabel\Zoho\CRM\AbstractZohoDao;
13
use Wabel\Zoho\CRM\Service\EntitiesGeneratorService;
14
use Wabel\Zoho\CRM\ZohoClient;
15
use Logger\Formatters\DateTimeFormatter;
16
use Mouf\Utils\Log\Psr\MultiLogger;
17
use Wabel\Zoho\CRM\Request\Response;
18
19
class ZohoSyncDatabaseCommand extends Command
20
{
21
    /**
22
     * The list of Zoho DAOs to copy.
23
     *
24
     * @var AbstractZohoDao[]
25
     */
26
    private $zohoDaos;
27
28
    /**
29
     * @var ZohoDatabaseModelSync
30
     */
31
    private $zohoDatabaseModelSync;
32
33
    /**
34
     * @var ZohoDatabaseCopier
35
     */
36
    private $zohoDatabaseCopier;
37
38
    /**
39
     * @var ZohoDatabasePusher
40
     */
41
    private $zohoDatabaseSync;
42
43
    /**
44
     *
45
     * @var MultiLogger
46
     */
47
    private $logger;
48
49
    /**
50
     * @var Lock
51
     */
52
    private $lock;
53
54
    /**
55
     * The Zoho Dao and Beans generator
56
     *
57
     * @var EntitiesGeneratorService
58
     */
59
    private $zohoEntitiesGenerator;
60
61
    /**
62
     *
63
     * @var ZohoClient
64
     */
65
    private $zohoClient;
66
67
    private $pathZohoDaos;
68
69
    private $namespaceZohoDaos;
70
71
    /**
72
     *
73
     * @var Response
74
     */
75
    private $usersResponse;
76
77
    /**
78
     * @var string[]
79
     */
80
    private $excludedZohoDao;
81
82
83
    /**
84
     * @param ZohoDatabaseModelSync $zohoDatabaseModelSync
85
     * @param ZohoDatabaseCopier $zohoDatabaseCopier
86
     * @param ZohoDatabasePusher $zohoDatabaseSync
87
     * @param EntitiesGeneratorService $zohoEntitiesGenerator The Zoho Dao and Beans generator
88
     * @param ZohoClient $zohoClient
89
     * @param string $pathZohoDaos Tht path where we need to generate the Daos.
90
     * @param string $namespaceZohoDaos Daos namespace
91
     * @param MultiLogger $logger
92
     * @param Lock $lock A lock that can be used to avoid running the same command (copy) twice at the same time
93
     * @param string[] $excludedZohoDao To exclude Dao and or solve Dao which can create ZohoResponse Error
94
     */
95
    public function __construct(ZohoDatabaseModelSync $zohoDatabaseModelSync, ZohoDatabaseCopier $zohoDatabaseCopier, ZohoDatabasePusher $zohoDatabaseSync,
96
                                EntitiesGeneratorService $zohoEntitiesGenerator, ZohoClient $zohoClient,
97
                                $pathZohoDaos, $namespaceZohoDaos, MultiLogger $logger, Lock $lock = null, $excludedZohoDao = []
98
    )
99
    {
100
        parent::__construct();
101
        $this->zohoDatabaseModelSync = $zohoDatabaseModelSync;
102
        $this->zohoDatabaseCopier = $zohoDatabaseCopier;
103
        $this->zohoDatabaseSync = $zohoDatabaseSync;
104
        $this->zohoEntitiesGenerator = $zohoEntitiesGenerator;
105
        $this->zohoClient = $zohoClient;
106
        $this->pathZohoDaos = $pathZohoDaos;
107
        $this->namespaceZohoDaos = $namespaceZohoDaos;
108
        $this->logger = $logger;
109
        $this->lock = $lock;
110
        $this->excludedZohoDao = $excludedZohoDao;
111
    }
112
113
    protected function configure()
114
    {
115
        $this
116
            ->setName('zoho:sync')
117
            ->setDescription('Synchronize the Zoho CRM data in a local database.')
118
            ->addOption('reset', 'r', InputOption::VALUE_NONE, 'Get a fresh copy of Zoho (rather than doing incremental copy)')
119
            ->addOption('skip-trigger', 's', InputOption::VALUE_NONE, 'Do not create or update the trigger')
120
            ->addOption('fetch-only', 'f', InputOption::VALUE_NONE, 'Fetch only the Zoho data in local database')
121
            ->addOption('push-only', 'p', InputOption::VALUE_NONE, 'Push only the local data to Zoho')
122
            ->addOption('limit', 'l', InputOption::VALUE_NONE, 'use defined memory limit or unlimited memory limit')
123
            ->addOption('log-path', null, InputOption::VALUE_OPTIONAL, 'Set the path of logs file')
124
            ->addOption('clear-logs', null, InputOption::VALUE_NONE, 'Clear logs file at startup')
125
            ->addOption('dump-logs', null, InputOption::VALUE_NONE, 'Dump logs into console when command finishes')
126
            ->addOption('continue-on-error', null, InputOption::VALUE_NONE, 'Don\'t stop the command on errors')
127
            ->addOption('fetch-bulk', null, InputOption::VALUE_NONE, 'Fetch the data module by module using bulk read API')
128
            ->addOption('modified-since', null, InputOption::VALUE_OPTIONAL, 'Fetch the data since a particular date (ISO 8601)');
129
    }
130
131
    protected function execute(InputInterface $input, OutputInterface $output)
132
    {
133
        $this->logger->addLogger(new DateTimeFormatter(new ConsoleLogger($output)));
134
        $this->logger->notice('Command ZohoSyncDatabase started');
135
        try {
136
            if ($this->lock) {
137
                $this->lock->acquireLock();
138
            }
139
140
            // TODO: find a better way when zohocrm/php-sdk:src/crm/utility/Logger.php will allow to get the filename, delete, etc.
141
            if ($input->getOption('log-path') && $input->getOption('clear-logs')) {
142
                $this->logger->notice('Clearing logs...');
143
                $path = $input->getOption('log-path');
144
                $logFile = $path . '/ZCRMClientLibrary.log';
145
                if (file_exists($logFile)) {
146
                    if (is_writable($logFile)) {
147
                        if (file_put_contents($logFile, '') === false) {
148
                            $this->logger->error(sprintf('Error when clearing log file in %s', $logFile));
149
                        }
150
                    } else {
151
                        $this->logger->warning(sprintf('Cannot write into log file in %s', $logFile));
152
                    }
153
                } else {
154
                    $this->logger->warning(sprintf('Cannot find log file in %s', $logFile));
155
                }
156
            }
157
158
            if (!$input->getOption('limit')) {
159
                ini_set('memory_limit', '-1');
160
            }
161
162
            if ($input->getOption('fetch-only') && $input->getOption('push-only')) {
163
                $this->logger->error('Options fetch-only and push-only are mutually exclusive.');
164
            }
165
166
            $this->syncUserModel();
167
168
            $this->regenerateZohoDao();
169
170
            $this->syncModel($input);
171
172
            if ($input->getOption('fetch-bulk')) {
173
                $this->fetchUserDb();
174
                $this->fetchDbInBulk($input);
175
            } else {
176
                if (!$input->getOption('push-only')) {
177
                    $this->fetchUserDb();
178
                    $this->fetchDb($input);
179
                }
180
                if (!$input->getOption('fetch-only')) {
181
                    $this->pushDb();
182
                }
183
            }
184
185
            if ($input->getOption('log-path') && $input->getOption('dump-logs')) {
186
                $this->logger->info('Dumping logs...');
187
                $path = $input->getOption('log-path');
188
                $logFile = $path . '/ZCRMClientLibrary.log';
189
                if (file_exists($logFile)) {
190
                    if (is_readable($logFile)) {
191
                        $this->logger->info(file_get_contents($logFile));
192
                    } else {
193
                        $this->logger->warning(sprintf('Cannot read into log file in %s', $logFile));
194
                    }
195
                } else {
196
                    $this->logger->warning(sprintf('Cannot find log file in %s', $logFile));
197
                }
198
            }
199
200
            if ($this->lock) {
201
                $this->lock->releaseLock();
202
            }
203
        } catch (LockException $e) {
204
            $this->logger->error('Could not start zoho:copy-db copy command. Another zoho:copy-db copy command is already running.');
205
        }
206
        $this->logger->notice('Command ZohoSyncDatabase finished');
207
    }
208
209
    /**
210
     * Sychronizes the model of the database with Zoho records.
211
     *
212
     * @param InputInterface $input
213
     */
214
    private function syncModel(InputInterface $input)
215
    {
216
        $twoWaysSync = !$input->getOption('fetch-only');
217
        $skipCreateTrigger = $input->getOption('skip-trigger');
218
219
        $this->logger->notice('Starting to synchronize Zoho DB model with the local database...');
220
        foreach ($this->zohoDaos as $zohoDao) {
221
            $this->zohoDatabaseModelSync->synchronizeDbModel($zohoDao, $twoWaysSync, $skipCreateTrigger);
222
        }
223
        $this->logger->notice('Zoho DB model successfully synchronized.');
224
    }
225
226
    /**
227
     * Sychronizes the model of the database with Zoho Users records.
228
     */
229
    private function syncUserModel()
230
    {
231
        $this->logger->notice('Starting to synchronize Zoho users DB model with the local database...');
232
        $this->zohoDatabaseModelSync->synchronizeUserDbModel();
233
        $this->logger->notice('Zoho users DB model successfully synchronized.');
234
    }
235
236
    /**
237
     * Regerate Zoho Daos
238
     */
239
    private function regenerateZohoDao()
240
    {
241
        $this->logger->notice('Starting to generate all the Zoho daos...');
242
        $zohoModules = $this->zohoEntitiesGenerator->generateAll($this->pathZohoDaos, $this->namespaceZohoDaos);
243
        foreach ($zohoModules as $daoFullClassName) {
244
            /* @var $zohoDao AbstractZohoDao */
245
            $zohoDao = new $daoFullClassName($this->zohoClient);
246
            //To have more module which is use time of modification (createdTime or lastActivityTime).
247
            //use an array of Excluded Dao by full namespace
248
            if ($this->excludedZohoDao && in_array(get_class($zohoDao), $this->excludedZohoDao)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->excludedZohoDao of type string[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
249
                $this->logger->debug(sprintf('%s has been excluded from generation', get_class($zohoDao)));
250
                continue;
251
            }
252
            $this->zohoDaos [] = $zohoDao;
253
            $this->logger->info(sprintf('%s has been created for module %s', get_class($zohoDao), $zohoDao->getPluralModuleName()));
254
        }
255
        $this->logger->notice('Finished to create all the Zoho daos.');
256
    }
257
258
    /**
259
     * Run the fetch User Db command.
260
     */
261
    private function fetchUserDb()
262
    {
263
        $this->logger->notice('Starting to copy Zoho users data into local database...');
264
        $this->zohoDatabaseCopier->fetchUserFromZoho();
265
        $this->logger->notice('Zoho users data successfully copied.');
266
    }
267
268
269
    /**
270
     * Run the fetch Db command.
271
     *
272
     * @param InputInterface $input
273
     */
274
    private function fetchDb(InputInterface $input)
275
    {
276
        $throwErrors = true;
277
        if ($input->getOption('continue-on-error')) {
278
            $throwErrors = false;
279
        }
280
281
        if ($input->getOption('reset')) {
282
            $incremental = false;
283
        } else {
284
            $incremental = true;
285
        }
286
287
        $modifiedSince = null;
288
        if ($input->getOption('modified-since')) {
289
            $modifiedSince = $input->getOption('modified-since');
290
        }
291
292
        $twoWaysSync = !$input->getOption('fetch-only');
293
294
        $this->logger->notice('Starting to fetch Zoho data into local database...');
295
        foreach ($this->zohoDaos as $zohoDao) {
296
            $this->logger->notice(sprintf('Copying data into local for module %s...', $zohoDao->getPluralModuleName()));
297
            $this->zohoDatabaseCopier->fetchFromZoho($zohoDao, $incremental, $twoWaysSync, $throwErrors, $modifiedSince);
298
        }
299
        $this->logger->notice('Zoho data successfully fetched.');
300
    }
301
302
303
    /**
304
     * Run the fetch Db command.
305
     *
306
     * @param InputInterface $input
307
     */
308
    private function fetchDbInBulk(InputInterface $input)
0 ignored issues
show
Unused Code introduced by
The parameter $input is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
309
    {
310
        $this->logger->notice('Starting to bulk fetch Zoho data into local database...');
311
        foreach ($this->zohoDaos as $zohoDao) {
312
            $this->logger->notice(sprintf('Copying data into local for module %s...', $zohoDao->getPluralModuleName()));
313
            $this->zohoDatabaseCopier->fetchFromZohoInBulk($zohoDao);
314
        }
315
        $this->logger->notice('Zoho data successfully fetched.');
316
    }
317
318
    /**
319
     * Run the push Db command.
320
     */
321
    private function pushDb()
322
    {
323
        $this->logger->notice('Starting to push data from local database into Zoho CRM...');
324
        foreach ($this->zohoDaos as $zohoDao) {
325
            if ($zohoDao->getFieldFromFieldName('createdTime')) {
326
                $this->zohoDatabaseSync->pushToZoho($zohoDao);
327
            }
328
        }
329
        $this->logger->notice('Zoho data successfully pushed.');
330
    }
331
}
332