Passed
Push — developer ( b6ebe7...0bf5e9 )
by Mariusz
47:54 queued 29:05
created

Base::log()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 1
dl 0
loc 3
rs 10
c 1
b 0
f 1
cc 1
nc 1
nop 4
1
<?php
2
/**
3
 * WooCommerce base synchronization file.
4
 *
5
 * The file is part of the paid functionality. Using the file is allowed only after purchasing a subscription.
6
 * File modification allowed only with the consent of the system producer.
7
 *
8
 * @package Integration
9
 *
10
 * @copyright YetiForce S.A.
11
 * @license   YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com)
12
 * @author    Mariusz Krzaczkowski <[email protected]>
13
 */
14
15
namespace App\Integrations\WooCommerce\Synchronizer;
16
17
/**
18
 * WooCommerce base synchronization class.
19
 */
20
abstract class Base
21
{
22
	/** @var \App\Integrations\WooCommerce\Connector\Base Connector. */
23
	protected $connector;
24
	/** @var \App\Integrations\WooCommerce\Synchronizer\Maps\Base Map synchronizer instance. */
25
	protected $maps;
26
	/** @var \App\Integrations\WooCommerce\Config Config instance. */
27
	public $config;
28
	/** @var \App\Integrations\WooCommerce Controller instance. */
29
	public $controller;
30
	/** @var array Last scan config data. */
31
	protected $lastScan = [];
32
	/** @var string Category name used for the log mechanism */
33
	const LOG_CATEGORY = 'Integrations/WooCommerce';
34
	/** @var int Synchronization direction: one-way from WooCommerce to YetiForce */
35
	const DIRECTION_API_TO_YF = 0;
36
	/** @var int Synchronization direction: one-way from YetiForce to WooCommerce */
37
	const DIRECTION_YF_TO_API = 1;
38
	/** @var int Synchronization direction: two-way */
39
	const DIRECTION_TWO_WAY = 2;
40
41
	/**
42
	 * Main process function.
43
	 *
44
	 * @return void
45
	 */
46
	abstract public function process(): void;
47
48
	/**
49
	 * Constructor.
50
	 *
51
	 * @param \App\Integrations\WooCommerce $controller
52
	 */
53
	public function __construct(\App\Integrations\WooCommerce $controller)
54
	{
55
		$this->connector = $controller->getConnector();
56
		$this->controller = $controller;
57
		$this->config = $controller->config;
58
	}
59
60
	/**
61
	 * Get map model instance.
62
	 *
63
	 * @param string $name
64
	 *
65
	 * @return \App\Integrations\WooCommerce\Synchronizer\Maps\Base
66
	 */
67
	public function getMapModel(string $name = ''): Maps\Base
68
	{
69
		if (empty($name)) {
70
			$name = rtrim(substr(strrchr(static::class, '\\'), 1), 's');
71
		}
72
		if (isset($this->maps[$name])) {
73
			return $this->maps[$name];
74
		}
75
		$className = "App\\Integrations\\WooCommerce\\Synchronizer\\Maps\\{$name}";
76
		if (isset($this->config->get('maps')[$name])) {
77
			$className = $this->config->get('maps')[$name];
78
		}
79
		return $this->maps[$name] = new $className($this);
80
	}
81
82
	/**
83
	 * Get data by path from API.
84
	 *
85
	 * @param string $path
86
	 * @param bool   $cache
87
	 *
88
	 * @return array
89
	 */
90
	public function getFromApi(string $path, bool $cache = true): array
91
	{
92
		$cacheKey = self::LOG_CATEGORY . '/API';
93
		if ($cache && \App\Cache::staticHas($cacheKey, $path)) {
94
			return \App\Cache::staticGet($cacheKey, $path);
95
		}
96
		$data = \App\Json::decode($this->connector->request('GET', $path));
97
		foreach ($data as &$item) {
98
			if (isset($item['_links'])) {
99
				unset($item['_links']);
100
			}
101
		}
102
		\App\Cache::staticSave($cacheKey, $path, $data);
103
		if ($this->config->get('logAll')) {
104
			$this->controller->log('Get from API', [
105
				'path' => $path,
106
				'rows' => \count($data),
107
			]);
108
		}
109
		return $data;
110
	}
111
112
	/**
113
	 * Get QueryGenerator to retrieve data from YF.
114
	 *
115
	 * @param string $moduleName
116
	 *
117
	 * @return \App\QueryGenerator
118
	 */
119
	public function getFromYf(string $moduleName): \App\QueryGenerator
120
	{
121
		$queryGenerator = new \App\QueryGenerator($moduleName);
122
		$queryGenerator->setStateCondition('All');
123
		$queryGenerator->setFields(['id'])->permissions = false;
124
		$queryGenerator->addCondition('woocommerce_server_id', $this->config->get('id'), 'e');
125
		return $queryGenerator;
126
	}
127
128
	/**
129
	 * Method to get search criteria WooCommerce records.
130
	 *
131
	 * @param int $pageSize
132
	 *
133
	 * @return string
134
	 */
135
	public function getSearchCriteria(int $pageSize = 10): string
136
	{
137
		$searchCriteria = ['dates_are_gmt=true'];
138
		if (!empty($this->lastScan['start_date'])) {
139
			$searchCriteria[] = 'modified_before=' . $this->getFormattedTime($this->lastScan['start_date']);
140
		}
141
		if (!empty($this->lastScan['end_date'])) {
142
			$searchCriteria[] = 'modified_after=' . $this->getFormattedTime($this->lastScan['end_date']);
143
		}
144
		$searchCriteria[] = 'per_page=' . $pageSize;
145
		$searchCriteria = implode('&', $searchCriteria);
146
		return $searchCriteria ?? 'searchCriteria';
147
	}
148
149
	/**
150
	 * Get YF id by API id.
151
	 *
152
	 * @param int         $apiId
153
	 * @param string|null $moduleName
154
	 *
155
	 * @return int
156
	 */
157
	public function getYfId(int $apiId, ?string $moduleName = null): int
158
	{
159
		$moduleName = $moduleName ?? $this->getMapModel()->getModule();
160
		$cacheKey = 'Integrations/WooCommerce/CRM_ID/' . $moduleName;
161
		if (\App\Cache::staticHas($cacheKey, $apiId)) {
162
			return \App\Cache::staticGet($cacheKey, $apiId);
163
		}
164
		$queryGenerator = $this->getFromYf($moduleName);
165
		$queryGenerator->addCondition('woocommerce_id', $apiId, 'e');
166
		$yfId = $queryGenerator->createQuery()->scalar() ?: 0;
167
		$this->updateMapIdCache($moduleName, $apiId, $yfId);
168
		return $yfId;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $yfId could return the type string which is incompatible with the type-hinted return integer. Consider adding an additional type-check to rule them out.
Loading history...
169
	}
170
171
	/**
172
	 * Get YF id by API id.
173
	 *
174
	 * @param int     $yfId
175
	 * @param ?string $moduleName
176
	 *
177
	 * @return int
178
	 */
179
	public function getApiId(int $yfId, ?string $moduleName = null): int
180
	{
181
		$moduleName = $moduleName ?? $this->getMapModel()->getModule();
182
		$cacheKey = 'Integrations/WooCommerce/API_ID/' . $moduleName;
183
		if (\App\Cache::staticHas($cacheKey, $yfId)) {
184
			return \App\Cache::staticGet($cacheKey, $yfId);
185
		}
186
		$apiId = 0;
187
		try {
188
			$recordModel = \Vtiger_Record_Model::getInstanceById($yfId, $moduleName);
189
			$apiId = $recordModel->get('woocommerce_id') ?: 0;
190
		} catch (\Throwable $th) {
191
			$this->controller->log('GetApiId', ['woocommerce_id' => $yfId, 'moduleName' => $moduleName], $th);
192
			\App\Log::error('Error GetApiId: ' . PHP_EOL . $th->__toString(), self::LOG_CATEGORY);
193
		}
194
		$this->updateMapIdCache($moduleName, $apiId, $yfId);
195
		return $apiId;
196
	}
197
198
	/**
199
	 * Update the identifier mapping of both systems.
200
	 *
201
	 * @param string $moduleName
202
	 * @param int    $apiId
203
	 * @param int    $yfId
204
	 *
205
	 * @return void
206
	 */
207
	public function updateMapIdCache(string $moduleName, int $apiId, int $yfId): void
208
	{
209
		\App\Cache::staticSave('Integrations/WooCommerce/API_ID/' . $moduleName, $yfId, $apiId);
210
		\App\Cache::staticSave('Integrations/WooCommerce/CRM_ID/' . $moduleName, $apiId, $yfId);
211
	}
212
213
	/**
214
	 * Return parsed time to WooCommerce time zone.
215
	 *
216
	 * @param string $value
217
	 *
218
	 * @return string
219
	 */
220
	public function getFormattedTime(string $value): string
221
	{
222
		return \DateTimeField::convertTimeZone($value, \App\Fields\DateTime::getTimeZone(), 'UTC')->format('Y-m-d\\TH:i:s');
223
	}
224
}
225