Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
device.php
1<?php
2
11
12use Bitrix\Main;
17use Bitrix\Main\Authentication\Internal\EO_UserDevice;
18use Bitrix\Main\Authentication\Internal\EO_UserDeviceLogin;
25
26class Device
27{
28 protected const COOKIE_NAME = 'UIDD';
29 public const EMAIL_EVENT = 'NEW_DEVICE_LOGIN';
30
31 public static function addLogin(Context $context, array $user): void
32 {
33 $device = static::findByCookie($context);
34
35 if ($device === null)
36 {
37 $cookable = false;
38 $device = static::findByUserAgent($context);
39 }
40 else
41 {
42 // found by a cookie = supports cookies
43 $cookable = true;
44 }
45
46 if ($device === null)
47 {
48 // add a new device for the user
49 $device = static::add($context);
50 $deviceLogin = static::addDeviceLogin($device, $context);
51
52 if (Option::get('main', 'user_device_notify', 'N') === 'Y')
53 {
54 // send notification to the user
55 static::sendEmail($device, $deviceLogin, $user);
56 }
57 }
58 else
59 {
60 // update to actual data
61 static::update($device, $cookable);
62 static::addDeviceLogin($device, $context);
63 }
64
65 static::setCookie($device->getDeviceUid());
66 }
67
68 protected static function findByCookie(Context $context): ?EO_UserDevice
69 {
70 $request = Main\Context::getCurrent()->getRequest();
71 $deviceUid = $request->getCookie(static::COOKIE_NAME);
72
73 if (is_string($deviceUid) && $deviceUid != '')
74 {
75 return Internal\UserDeviceTable::query()
76 ->setSelect(['*'])
77 ->where('USER_ID', $context->getUserId())
78 ->where('DEVICE_UID', $deviceUid)
79 ->fetchObject()
80 ;
81 }
82
83 return null;
84 }
85
86 protected static function findByUserAgent(Context $context): ?EO_UserDevice
87 {
88 $request = Main\Context::getCurrent()->getRequest();
89 $userAgent = $request->getUserAgent();
90
91 // only user agents not supporting cookies
92 $query = Internal\UserDeviceTable::query()
93 ->setSelect(['*'])
94 ->where('USER_ID', $context->getUserId())
95 ->where('COOKABLE', false)
96 ->exec()
97 ;
98
99 while ($device = $query->fetchObject())
100 {
101 $pattern = preg_replace('/\\d+/i', '\\d+', preg_quote($device->getUserAgent(), '/'));
102 if (preg_match("/{$pattern}/i", $userAgent))
103 {
104 return $device;
105 }
106 }
107
108 return null;
109 }
110
111 protected static function add(Context $context): EO_UserDevice
112 {
113 $browser = Browser::detect();
114 $device = Internal\UserDeviceTable::createObject();
115
116 $device
117 ->setUserId($context->getUserId())
118 ->setDeviceUid(Security\Random::getString(32))
119 ->setDeviceType($browser->getDeviceType())
120 ->setBrowser($browser->getName())
121 ->setPlatform($browser->getPlatform())
122 ->setUserAgent($browser->getUserAgent())
123 ->save()
124 ;
125
126 return $device;
127 }
128
129 protected static function update(EO_UserDevice $device, bool $cookable): void
130 {
131 $browser = Browser::detect();
132
133 $device
134 ->setDeviceType($browser->getDeviceType())
135 ->setBrowser($browser->getName())
136 ->setPlatform($browser->getPlatform())
137 ->setUserAgent($browser->getUserAgent())
138 ->setCookable($cookable)
139 ->save()
140 ;
141 }
142
143 protected static function setCookie(string $value): void
144 {
145 $cookie = new Web\Cookie(static::COOKIE_NAME, $value, time() + 60 * 60 * 24 * 30 * 12);
146 Main\Context::getCurrent()->getResponse()->addCookie($cookie);
147 }
148
149 protected static function addDeviceLogin(EO_UserDevice $device, Context $context): EO_UserDeviceLogin
150 {
151 $ip = GeoIp\Manager::getRealIp();
152
153 $login = Internal\UserDeviceLoginTable::createObject();
154
155 $login
156 ->setDeviceId($device->getId())
157 ->setLoginDate(new Main\Type\DateTime())
158 ->setIp($ip)
159 ->setAppPasswordId($context->getApplicationPasswordId())
160 ->setStoredAuthId($context->getStoredAuthId())
161 ->setHitAuthId($context->getHitAuthId())
162 ;
163
164 if (Option::get('main', 'user_device_geodata', 'N') === 'Y')
165 {
166 $ipData = GeoIp\Manager::getDataResult($ip, '', ['cityGeonameId']);
167
168 if ($ipData && $ipData->isSuccess())
169 {
170 $data = $ipData->getGeoData();
171
172 $login
173 ->setCityGeoid($data->cityGeonameId)
174 ->setRegionGeoid($data->subRegionGeonameId ?? $data->regionGeonameId)
175 ->setCountryIsoCode($data->countryCode)
176 ;
177 }
178 }
179
180 $login->save();
181
182 return $login;
183 }
184
185 protected static function sendEmail(EO_UserDevice $device, EO_UserDeviceLogin $deviceLogin, array $user): void
186 {
187 $site = $user['LID'];
188 if (!$site)
189 {
190 $site = Main\Context::getCurrent()->getSite();
191 if (!$site)
192 {
193 $site = \CSite::GetDefSite();
194 }
195 }
196
197 $currentLang = Main\Context::getCurrent()->getLanguage();
198 $lang = $user['LANGUAGE_ID'] != '' ? $user['LANGUAGE_ID'] : $currentLang;
199
200 // Devices
201 $deviceTypes = DeviceType::getDescription($lang);
202
203 // City and Region names
204 $geoids = array_filter([$deviceLogin->getCityGeoid(), $deviceLogin->getRegionGeoid()]);
205 $geonames = GeonameTable::get($geoids);
206
207 $city = '';
208 $region = '';
209 if (!empty($geonames))
210 {
211 $langCode = '';
212 if ($user['LANGUAGE_ID'] != '' && $user['LANGUAGE_ID'] != $currentLang)
213 {
214 $language = LanguageTable::getList([
215 'filter' => ['=LID' => $user['LANGUAGE_ID'], '=ACTIVE' => 'Y'],
216 'cache' => ['ttl' => 86400],
217 ])->fetchObject();
218
219 if ($language)
220 {
221 $langCode = $language->getCode();
222 }
223 }
224 if ($langCode == '')
225 {
226 $langCode = Main\Context::getCurrent()->getLanguageObject()->getCode();
227 }
228
229 if (($cityCode = $deviceLogin->getCityGeoid()) > 0)
230 {
231 $city = $geonames[$cityCode][$langCode] ?? $geonames[$cityCode]['en'] ?? '';
232 }
233 if (($regionCode = $deviceLogin->getRegionGeoid()) > 0)
234 {
235 $region = $geonames[$regionCode][$langCode] ?? $geonames[$regionCode]['en'] ?? '';
236 }
237 }
238
239 // Country name
240 $country = '';
241 if (($countryCode = $deviceLogin->getCountryIsoCode()) != '')
242 {
243 $countries = \GetCountries($lang);
244 $country = $countries[$countryCode]['NAME'];
245 }
246
247 // Combined location
248 $location = implode(', ', array_filter([$city, $region, $country]));
249
250 $fields = [
251 'EMAIL' => $user['EMAIL'],
252 'LOGIN' => $user['LOGIN'],
253 'NAME' => $user['NAME'],
254 'LAST_NAME' => $user['LAST_NAME'],
255 'DEVICE' => $deviceTypes[$device->getDeviceType()],
256 'BROWSER' => $device->getBrowser(),
257 'PLATFORM' => $device->getPlatform(),
258 'USER_AGENT' => $device->getUserAgent(),
259 'IP' => $deviceLogin->getIp(),
260 'DATE' => $deviceLogin->getLoginDate(),
261 'COUNTRY' => $country,
262 'REGION' => $region,
263 'CITY' => $city,
264 'LOCATION' => $location,
265 ];
266
267 Mail\Event::send([
268 'EVENT_NAME' => self::EMAIL_EVENT,
269 'C_FIELDS' => $fields,
270 'LID' => $site,
271 'LANGUAGE_ID' => $lang,
272 ]);
273 }
274}
static sendEmail(EO_UserDevice $device, EO_UserDeviceLogin $deviceLogin, array $user)
Definition device.php:185
static addDeviceLogin(EO_UserDevice $device, Context $context)
Definition device.php:149
static findByCookie(Context $context)
Definition device.php:68
static findByUserAgent(Context $context)
Definition device.php:86
static addLogin(Context $context, array $user)
Definition device.php:31
static update(EO_UserDevice $device, bool $cookable)
Definition device.php:129
static setCookie(string $value)
Definition device.php:143
static add(Context $context)
Definition device.php:111
static get(array $ids, bool $decode=true)
static detect(?string $userAgent=null)
Definition browser.php:113