Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 216
0.00% covered (danger)
0.00%
0 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
FlyGrammarController
0.00% covered (danger)
0.00%
0 / 216
0.00% covered (danger)
0.00%
0 / 5
1980
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 quota
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 create
0.00% covered (danger)
0.00%
0 / 38
0.00% covered (danger)
0.00%
0 / 1
56
 actions
0.00% covered (danger)
0.00%
0 / 170
0.00% covered (danger)
0.00%
0 / 1
1190
 dictionary
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace App\Http\Controllers\v1;
4
5use App\Http\Models\FlyGrammarActions;
6use App\Http\Requests\TrackingFlyGrammarFormRequest;
7use App\Traits\SubscriptionTrait;
8use Exception;
9use Illuminate\Http\JsonResponse;
10use App\Http\Controllers\Controller;
11use App\Http\Models\Auth\User;
12use App\Http\Models\Setting;
13use App\Http\Models\UserExtensionTrackActions;
14use App\Http\Services\StatisticsService;
15use Illuminate\Http\Request;
16use Symfony\Component\HttpFoundation\Response;
17use App\Http\Models\UserInfo;
18use App\Http\Services\WPSService;
19use App\Services\UserInfo\UserInfoService;
20use Carbon\Carbon;
21use Illuminate\Support\Facades\Log;
22use MongoDB\BSON\UTCDateTime;
23
24class FlyGrammarController extends Controller
25{
26    use SubscriptionTrait;
27
28    public function __construct(
29        protected StatisticsService $statisticsService,
30        protected UserInfoService $userInfoService,
31        protected WPSService $wpsService
32    ) {}
33
34    public function quota(Request $request): JsonResponse
35    {
36        $user = $request->user();
37
38        $quota = $this->getGrammarQuota($user);
39
40        return response()->json(['data' => $quota], Response::HTTP_OK);
41    }
42
43    public function create(TrackingFlyGrammarFormRequest $request): JsonResponse
44    {
45        try {
46            $data = $request->validated();
47            $user = $request->user();
48
49            $chromeVersion = $request->header('flymsg_extension_version_for_chrome') ?? $request->header('Flymsg_extension_version_for_chrome') ?? $request->header('flymsgextensionversionforchrome') ?? $request->header('flymsgExtensionVersionForChrome');
50            $edgeVersion = $request->header('flymsg_extension_version_for_edge') ?? $request->header('Flymsg_extension_version_for_edge') ?? $request->header('flymsgextensionversionforedge') ?? $request->header('flymsgExtensionVersionForEdge');
51
52            if (empty($chromeVersion) && empty($edgeVersion)) {
53                Log::info('Extension version not found in headers. User: ' . $user->email, [
54                    'user' => $user,
55                    'headers' => $request->header()
56                ]);
57            }
58
59            $plan = $this->getCurrentPlan($user);
60
61            $charactersSaved = strlen($data['result_text'] ?? '');
62            $timeSaved = $this->statisticsService->getTimeSaved($user, $charactersSaved);
63            $costSaved = $this->statisticsService->getCostSaved($user, $timeSaved, now());
64
65            FlyGrammarActions::create([
66                'name' => $data['description'] ?? '',
67                'original_text' => $data['original_text'] ?? '',
68                'result_text' => $data['result_text'] ?? '',
69                'action_type' => $data['description'] ?? '',
70                'user_id' => $user->id,
71                'provider' => $data['provider'] ?? '',
72                'characters_count' => $charactersSaved,
73                'characters_saved' => $charactersSaved,
74                // 'characters_saved' => strlen($data['result_text']) <= strlen($data['original_text']) ? strlen($data['result_text']) : (strlen($data['original_text']) - strlen($data['result_text'])),
75                'time_saved' => $timeSaved,
76                'cost_saved' => $costSaved,
77                'plan_id' => $plan?->id,
78                'company_id' => $user->company_id,
79                'language' => $data['language'] ?? '',
80            ]);
81
82            $userInfo = UserInfo::where('user_id', $user->id)->first();
83            if ($userInfo) {
84                $userInfo->last_date_user_used_flygrammar = new UTCDateTime(now()->getTimestamp() * 1000);
85                if (!empty($chromeVersion)) {
86                    $userInfo->flymsg_extension_version_for_chrome = $chromeVersion;
87                }
88
89                if (!empty($edgeVersion)) {
90                    $userInfo->flymsg_extension_version_for_edge = $edgeVersion;
91                }
92            }
93        } catch (Exception $e) {
94            return response()->json(['data' => [], 'message' => $e->getMessage(), 'error' => 1], Response::HTTP_INTERNAL_SERVER_ERROR);
95        }
96
97        return response()->json(['data' => [], 'message' => 'Succeed', 'error' => 0], Response::HTTP_OK);
98    }
99
100    public function actions(Request $request): JsonResponse
101    {
102        try {
103            $user = $request->user();
104
105            $chromeVersion = $request->header('flymsg_extension_version_for_chrome') ?? $request->header('Flymsg_extension_version_for_chrome') ?? $request->header('flymsgextensionversionforchrome') ?? $request->header('flymsgExtensionVersionForChrome');
106            $edgeVersion = $request->header('flymsg_extension_version_for_edge') ?? $request->header('Flymsg_extension_version_for_edge') ?? $request->header('flymsgextensionversionforedge') ?? $request->header('flymsgExtensionVersionForEdge');
107
108            if (empty($chromeVersion) && empty($edgeVersion)) {
109                Log::info('Extension version not found in headers. User: ' . $user->email, [
110                    'user' => $user,
111                    'headers' => $request->header()
112                ]);
113            }
114
115            $plan = $this->getCurrentPlan($user);
116
117
118            $action = $request->input('action', '');
119
120            if ($action !== 'check') {
121
122                if ($action === 'accept' || $action === 'replace' || $action === 'accept') {
123                    if (!empty($user)) {
124                        $event = new UserExtensionTrackActions();
125                        $event->user_id = $user->id;
126                        $event->heap_analytics_id = $user->heap_analytics_id;
127                        $event->event_name = 'flymsg_extension_flygrammar_accept_suggestion';
128                        $event->type = $request->input('type', '');
129
130                        if (!empty($request->extension_version)) {
131                            $event->extension_version = $request->extension_version;
132                        }
133
134                        if (!empty($request->domain)) {
135                            $event->domain = $request->domain;
136                        }
137
138                        if (!empty($request->url)) {
139                            $event->url = $request->url;
140                        }
141
142                        if (!empty($request->browser)) {
143                            $event->browser = $request->browser;
144                        }
145
146                        if (!empty($request->executed_at)) {
147                            $date = Carbon::parse($request->executed_at);
148                            $event->executed_at = new UTCDateTime($date->getTimestamp() * 1000);
149                        }
150
151                        $event->save();
152                    }
153                }
154
155                if ($action === 'autocorrect') {
156                    $charactersSaved = strlen($request->input('replacement', ''));
157                    $timeSaved = $this->statisticsService->getTimeSaved($user, $charactersSaved);
158                    $costSaved = $this->statisticsService->getCostSaved($user, $timeSaved, now());
159                    $userSettings = Setting::where('user_id', $user->id)->first();
160
161                    $quota = $this->getGrammarQuota($user);
162
163                    FlyGrammarActions::create([
164                        'name' => $request->input('action', ''),
165                        'original_text' => $request->input('word', ''),
166                        'result_text' => $request->input('replacement', ''),
167                        'action_type' => $action,
168                        'user_id' => $user->id,
169                        'provider' => 'wsc',
170                        'characters_count' => $charactersSaved,
171                        'characters_saved' => $charactersSaved,
172                        'time_saved' => $timeSaved,
173                        'cost_saved' => $costSaved,
174                        'plan_id' => $plan?->id,
175                        'company_id' => $user->company_id,
176                        'language' => $userSettings?->fly_grammar_default_language ?? 'auto',
177                        'executed_at' => $request->input('executed_at', '')
178                    ]);
179
180                    $quota['remaining'] = max($quota['remaining'] - 1, 0);
181                    $quota['used'] += 1;
182
183                    return response()->json(['data' => [
184                        'quota' => $quota,
185                    ], 'message' => 'Succeed'], Response::HTTP_OK);
186                }
187
188                if ($action === 'replace') {
189                    $charactersSaved = strlen($request->input('newText', ''));
190                    $timeSaved = $this->statisticsService->getTimeSaved($user, $charactersSaved);
191                    $costSaved = $this->statisticsService->getCostSaved($user, $timeSaved, now());
192
193                    $type = $request->input('type', '');
194
195                    $multiplierNegativeCount = 1;
196
197                    if ($type === 'autocorrect') {
198                        $multiplierNegativeCount = -1;
199                    }
200                    $quota = $this->getGrammarQuota($user);
201
202                    FlyGrammarActions::create([
203                        'name' => $type,
204                        'original_text' => $request->input('text', ''),
205                        'result_text' => $request->input('newText', ''),
206                        'action_type' => $action,
207                        'user_id' => $user->id,
208                        'provider' => 'wsc',
209                        'characters_count' => $charactersSaved * $multiplierNegativeCount,
210                        'characters_saved' => $charactersSaved * $multiplierNegativeCount,
211                        // 'characters_saved' => strlen($data['result_text']) <= strlen($data['original_text']) ? strlen($data['result_text']) : (strlen($data['original_text']) - strlen($data['result_text'])),
212                        'time_saved' => $timeSaved * $multiplierNegativeCount,
213                        'cost_saved' => $costSaved * $multiplierNegativeCount,
214                        'plan_id' => $plan?->id,
215                        'company_id' => $user->company_id,
216                        'language' => $request->input('detectedLang', $request->input('lang', 'auto')),
217                        'executed_at' => $request->input('executed_at', ''),
218                        'context' => $request->input('context', ''),
219                    ]);
220
221                    $userInfo = UserInfo::where('user_id', $user->id)->first();
222                    if ($userInfo) {
223                        $userInfo->last_date_user_used_flygrammar = new UTCDateTime(now()->getTimestamp() * 1000);
224                        if (!empty($chromeVersion)) {
225                            $userInfo->flymsg_extension_version_for_chrome = $chromeVersion;
226                        }
227
228                        if (!empty($edgeVersion)) {
229                            $userInfo->flymsg_extension_version_for_edge = $edgeVersion;
230                        }
231                    }
232
233                    $quota['remaining'] = max($quota['remaining'] - 1, 0);
234                    $quota['used'] += 1;
235
236                    return response()->json(['data' => [
237                        'quota' => $quota,
238                    ], 'message' => 'Succeed'], Response::HTTP_OK);
239                }
240
241                $type = $request->input('type', '');
242                if ($action === 'accept' && $type === 'autocomplete') {
243                    $charactersSaved = strlen($request->input('newText', ''));
244                    $timeSaved = $this->statisticsService->getTimeSaved($user, $charactersSaved);
245                    $costSaved = $this->statisticsService->getCostSaved($user, $timeSaved, now());
246
247                    $quota = $this->getGrammarQuota($user);
248
249                    FlyGrammarActions::create([
250                        'name' => $action,
251                        'original_text' => $request->input('text', ''),
252                        'result_text' => $request->input('newText', ''),
253                        'action_type' => $type,
254                        'user_id' => $user->id,
255                        'provider' => 'wsc',
256                        'characters_count' => $charactersSaved,
257                        'characters_saved' => $charactersSaved,
258                        'time_saved' => $timeSaved,
259                        'cost_saved' => $costSaved,
260                        'plan_id' => $plan?->id,
261                        'company_id' => $user->company_id,
262                        'language' => $request->input('lang', 'auto'),
263                        'executed_at' => $request->input('url', ''),
264                        'context' => $request->input('context', ''),
265                    ]);
266
267                    $userInfo = UserInfo::where('user_id', $user->id)->first();
268                    if ($userInfo) {
269                        $userInfo->last_date_user_used_flygrammar = new UTCDateTime(now()->getTimestamp() * 1000);
270                        if (!empty($chromeVersion)) {
271                            $userInfo->flymsg_extension_version_for_chrome = $chromeVersion;
272                        }
273
274                        if (!empty($edgeVersion)) {
275                            $userInfo->flymsg_extension_version_for_edge = $edgeVersion;
276                        }
277                    }
278
279                    $quota['remaining'] = max($quota['remaining'] - 1, 0);
280                    $quota['used'] += 1;
281
282                    return response()->json(['data' => [
283                        'quota' => $quota,
284                    ], 'message' => 'Succeed'], Response::HTTP_OK);
285                }
286
287                if ($action === 'settings_change' && $request->input('settings', false)) {
288                    $userSettings = Setting::where('user_id', $user->id)->first();
289                    $newSettings = [];
290
291                    if ($userSettings) {
292                        if (!empty($userSettings->fly_grammar_settings)) {
293                            $newSettings = $userSettings->fly_grammar_settings;
294                        }
295
296                        foreach ($request->input('settings') as $key => $value) {
297                            $newSettings[$key] = $value;
298                        }
299
300                        $userSettings->fly_grammar_settings = $newSettings;
301                        $userSettings->save();
302                    } else {
303                        $newSettings = $request->input('settings');
304                        Setting::create([
305                            'user_id' => $user->id,
306                            'fly_grammar_settings' => $request->input('settings'),
307                        ]);
308                    }
309
310                    if (!empty($request->input('settings')['lang'])) {
311                        $userSetting = Setting::where('user_id', $user->id)->first();
312                        if ($userSetting) {
313                            $userSetting->fly_grammar_default_language = $request->input('settings')['lang'];
314                            $userSetting->save();
315                        }
316                    }
317
318                    return response()->json(['data' => [
319                        'grammar_settings' => $newSettings,
320                    ], 'message' => 'Succeed'], Response::HTTP_OK);
321                }
322
323                if ($action === 'delete') {
324                    $word = $request->input('text', '');
325
326                    $this->wpsService->removeWordToUserDictionary($user, $word);
327
328                    $dictionary = $this->wpsService->getUserDictionary($request->user());
329
330                    return response()->json(['data' => [
331                        'dictionary' => $dictionary,
332                    ], 'message' => 'Succeed'], Response::HTTP_OK);
333                }
334                if ($action === 'add') {
335                    $word = $request->input('text', '');
336
337                    $this->wpsService->addWordToUserDictionary($user, $word);
338
339                    $dictionary = $this->wpsService->getUserDictionary($request->user());
340
341                    return response()->json(['data' => [
342                        'dictionary' => $dictionary,
343                    ], 'message' => 'Succeed'], Response::HTTP_OK);
344                }
345            }
346        } catch (Exception $e) {
347            return response()->json(['data' => [], 'message' => $e->getMessage(), 'error' => 1], Response::HTTP_OK);
348        }
349        return response()->json(['data' => [], 'message' => 'Succeed'], Response::HTTP_OK);
350    }
351
352    public function dictionary(Request $request): JsonResponse
353    {
354        $word = $request->input('word', '');
355
356        $this->wpsService->addWordToUserDictionary($request->user(), $word);
357
358        $dictionary = $this->wpsService->getUserDictionary($request->user());
359
360        return response()->json(['data' => $dictionary, 'message' => 'Succeed'], Response::HTTP_OK);
361    }
362}