Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
97.96% |
240 / 245 |
|
78.57% |
11 / 14 |
CRAP | |
0.00% |
0 / 1 |
ConversionController | |
97.96% |
240 / 245 |
|
78.57% |
11 / 14 |
81 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
postConversion | |
100.00% |
47 / 47 |
|
100.00% |
1 / 1 |
36 | |||
getConversionsDigest | |
100.00% |
58 / 58 |
|
100.00% |
1 / 1 |
18 | |||
getConversion | |
100.00% |
8 / 8 |
|
100.00% |
1 / 1 |
2 | |||
getConversionTransactions | |
100.00% |
11 / 11 |
|
100.00% |
1 / 1 |
2 | |||
postConversionApprove | |
94.87% |
37 / 39 |
|
0.00% |
0 / 1 |
5.00 | |||
postConversionReject | |
100.00% |
18 / 18 |
|
100.00% |
1 / 1 |
2 | |||
postConversionFlag | |
100.00% |
18 / 18 |
|
100.00% |
1 / 1 |
2 | |||
postConversionNote | |
100.00% |
23 / 23 |
|
100.00% |
1 / 1 |
3 | |||
__validateNoteRequest | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
__validateConversionRequest | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
__validateYYYYMMDD | |
75.00% |
3 / 4 |
|
0.00% |
0 / 1 |
3.14 | |||
__validateConversionApprovalRequest | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
getGoogleCampaignIds | |
66.67% |
4 / 6 |
|
0.00% |
0 / 1 |
1.04 |
1 | <?php |
2 | |
3 | namespace App\Http\Controllers\api; |
4 | |
5 | use DB; |
6 | use App\Http\Controllers\Controller; |
7 | use Illuminate\Http\Request; |
8 | use Illuminate\Http\JsonResponse; |
9 | use Illuminate\Database\Eloquent\Builder; |
10 | |
11 | use App\Models\Role; |
12 | use App\Models\Conversion; |
13 | use App\Models\ConversionNote; |
14 | use App\Models\ConversionDigest; |
15 | use App\Models\ConversionStatus; |
16 | use App\Models\GoogleAdsCampaign; |
17 | use App\Models\GoogleAdsCustomer; |
18 | use App\Models\ConversionCurrency; |
19 | use App\Models\ConversionTransaction; |
20 | |
21 | use App\Libs\GoogleAds; |
22 | use App\Libs\SqlFormatter; |
23 | |
24 | use Carbon\Carbon; |
25 | |
26 | use App\Traits\GoogleTrait; |
27 | |
28 | class ConversionController extends BaseController |
29 | { |
30 | use GoogleTrait; |
31 | |
32 | protected GoogleAds $googleAds; |
33 | |
34 | /** |
35 | * Constructore |
36 | */ |
37 | public function __construct(\App\Libs\GoogleAds $ga) { |
38 | $this->googleAds = $ga; |
39 | } |
40 | |
41 | /** |
42 | * Creates one conversion record |
43 | * |
44 | * @author gbh |
45 | * @see http://swagger-humanverify.fruitbat.systems/#post-/api/conversions |
46 | */ |
47 | public function postConversion(Request $request):JsonResponse |
48 | { |
49 | //$this->uploadOfflineConversion(); |
50 | //return $this->sendResponse(201, "woozozo"); |
51 | |
52 | /** |
53 | * Validate request body |
54 | * HTTP 400 |
55 | */ |
56 | $validationTest = $this->__validateConversionRequest($request); |
57 | if (is_object($validationTest)) { |
58 | return $validationTest; |
59 | } |
60 | |
61 | /** |
62 | * Get status id |
63 | */ |
64 | $statusId = ConversionStatus::where('name', '=', 'new')->first()->id; |
65 | |
66 | /** |
67 | * Figure out the conversion currency |
68 | */ |
69 | $conversionCurrencyId = 1; |
70 | if (ConversionCurrency::where('name', '=', $request->conversion_currency)->count() > 0) { |
71 | $conversionCurrencyId = ConversionCurrency::where('name', '=', $request->conversion_currency)->first()->id; |
72 | } |
73 | |
74 | /** |
75 | * Create the conversion |
76 | */ |
77 | $conversion = new Conversion(); |
78 | |
79 | // mandatory and defined fields |
80 | $conversion->website_url = $request->website_url; |
81 | $conversion->status_id = $statusId; |
82 | $conversion->mobile = isset($request->mobile) ? (bool)$request->mobile : false; |
83 | $conversion->conversion_currency = $conversionCurrencyId; |
84 | $conversion->conversion_time = date("Y-m-d H:i:s"); |
85 | |
86 | // optional strings fields |
87 | $conversion->conversion_value = isset($request->conversion_value) ? (string)$request->conversion_value : null; |
88 | $conversion->gclid = isset($request->gclid) ? (string)$request->gclid : null; |
89 | $conversion->fbclid = isset($request->fbclid) ? (string)$request->fbclid : null; |
90 | $conversion->event_category = isset($request->event_category) ? (string)$request->event_category : null; |
91 | $conversion->event_action = isset($request->event_action) ? (string)$request->event_action : null; |
92 | $conversion->event_label = isset($request->event_label) ? (string)$request->event_label : null; |
93 | $conversion->utm_campaign_id = isset($request->utm_campaign_id) ? (string)$request->utm_campaign_id : null; |
94 | $conversion->utm_campaign_source = isset($request->utm_campaign_source) ? (string)$request->utm_campaign_source : null; |
95 | $conversion->utm_campaign_medium = isset($request->utm_campaign_medium) ? (string)$request->utm_campaign_medium : null; |
96 | $conversion->utm_campaign_name = isset($request->utm_campaign_name) ? (string)$request->utm_campaign_name : null; |
97 | $conversion->utm_campaign_term = isset($request->utm_campaign_term) ? (string)$request->utm_campaign_term : null; |
98 | $conversion->utm_campaign_content = isset($request->utm_campaign_content) ? (string)$request->utm_campaign_content : null; |
99 | $conversion->conversion_name = isset($request->conversion_name) ? (string)$request->conversion_name : null; |
100 | $conversion->nw = isset($request->nw) ? (string)$request->nw : null; |
101 | $conversion->cmpid = isset($request->cmpid) ? (string)$request->cmpid : null; |
102 | $conversion->agid = isset($request->agid) ? (string)$request->agid : null; |
103 | $conversion->fiid = isset($request->fiid) ? (string)$request->fiid : null; |
104 | $conversion->tgid = isset($request->tgid) ? (string)$request->tgid : null; |
105 | $conversion->loc = isset($request->loc) ? (string)$request->loc : null; |
106 | $conversion->ploc = isset($request->ploc) ? (string)$request->ploc : null; |
107 | $conversion->match = isset($request->match) ? (string)$request->match : null; |
108 | $conversion->dev = isset($request->dev) ? (string)$request->dev : null; |
109 | $conversion->devm = isset($request->devm) ? (string)$request->devm : null; |
110 | $conversion->cmpt = isset($request->cmpt) ? (string)$request->cmpt : null; |
111 | $conversion->ad = isset($request->ad) ? (string)$request->ad : null; |
112 | $conversion->pl = isset($request->pl) ? (string)$request->pl : null; |
113 | $conversion->pltar = isset($request->pltar) ? (string)$request->pltar : null; |
114 | $conversion->pr1 = isset($request->pr1) ? (string)$request->pr1 : null; |
115 | $conversion->pr2 = isset($request->pr2) ? (string)$request->pr2 : null; |
116 | $conversion->url = isset($request->url) ? (string)$request->url : null; |
117 | $conversion->adpos = isset($request->adpos) ? (string)$request->adpos : null; |
118 | $conversion->form_data = isset($request->form_data) ? (string)$request->form_data : null; |
119 | $conversion->save(); |
120 | |
121 | /** |
122 | * HTTP 201 |
123 | */ |
124 | return $this->sendResponse(201, null); |
125 | } // postConversion |
126 | |
127 | |
128 | /** |
129 | * Return one page of conversions |
130 | * |
131 | * query string 'status' value is one of: |
132 | * - new |
133 | * - approved |
134 | * - rejected |
135 | * - all *default |
136 | * |
137 | * query string 'order' value is one of: |
138 | * - customer (sorts by name of customer) |
139 | * - campaign (sorts by name of campaign) |
140 | * - gclid |
141 | * - fbclid |
142 | * - *default created_at |
143 | * |
144 | * query string args: |
145 | * - customer_id |
146 | * - campaign_id |
147 | * - status (the name of the status) |
148 | * - start |
149 | * - end |
150 | * - order |
151 | * - sort |
152 | * - page |
153 | * - size |
154 | * |
155 | * @author gbh |
156 | * @see http://swagger.humanverify.test/#get-/api/conversions/digest |
157 | */ |
158 | public function getConversionsDigest(Request $request):JsonResponse |
159 | { |
160 | /** |
161 | * Get pagination data from request |
162 | */ |
163 | $paginationDataResult = $this->__validateAndExtractPaginationData($request); |
164 | $size = $paginationDataResult['size']; |
165 | |
166 | /** |
167 | * Get filters, order and sort data from request |
168 | */ |
169 | $order = in_array($request->query('order'), ['campaign', 'customer', 'gclid', 'fbclid']) ? $request->query('order') : 'created_at'; |
170 | $sort = in_array(strtolower($request->query('sort')), ['asc', 'desc']) ? $request->query('sort') : 'desc'; |
171 | $status = $request->query('status', null); |
172 | $filter_campaign_id = $request->query('campaign_id', null); |
173 | $filter_customer_id = $request->query('customer_id', null); |
174 | |
175 | /** |
176 | * Function to yield start and end dates |
177 | * |
178 | * @param Request $request |
179 | * @return Generator |
180 | */ |
181 | $getStartEndDates = function (Request $request) { |
182 | // default start and end dates |
183 | $startDate = (string)Carbon::createFromFormat('Y-m-d', '1980-01-01')->format('Y-m-d').' 00:00:01'; |
184 | $endDate = (string)Carbon::now()->addDay()->format('Y-m-d').' 23:59:59'; |
185 | |
186 | // use provided dates if present and valid, otherwise use defaults |
187 | $start = $request->query('start', null); |
188 | $end = $request->query('end', null); |
189 | |
190 | // validate and assign start date if non null |
191 | if (!is_null($start) && $this->__validateYYYYMMDD($start)) { |
192 | $startDate = (string)Carbon::createFromFormat('Y-m-d', $start)->format('Y-m-d').' 00:00:01'; |
193 | } |
194 | |
195 | // validate and assign end date if non null |
196 | if (!is_null($end) && $this->__validateYYYYMMDD($end)) { |
197 | $endDate = (string)Carbon::createFromFormat('Y-m-d', $end)->format('Y-m-d').' 23:59:59'; |
198 | } |
199 | |
200 | yield $startDate; |
201 | yield $endDate; |
202 | }; // getStartEndDates |
203 | |
204 | /** |
205 | * Get start and end dates |
206 | */ |
207 | $startEndDate = $getStartEndDates($request); |
208 | $startDate = $startEndDate->current(); |
209 | $startEndDate->next(); |
210 | $endDate = $startEndDate->current(); |
211 | |
212 | /** |
213 | * Function to optionally filter query by status id from status name |
214 | * |
215 | * @param Builder $conversionsPage The builder to add the status filter to |
216 | * @param Request $request |
217 | * @return Builder |
218 | */ |
219 | $filterByStatus = function (Builder $conversionsPage, Request $request) { |
220 | try { |
221 | $statusId = ConversionStatus::where('name', '=', $request->query('status'))->first()->id; |
222 | return $statusId ? $conversionsPage->where('status_id', '=', $statusId) : $conversionsPage; |
223 | } catch (\Exception $e) { |
224 | return $conversionsPage; |
225 | } |
226 | }; //filterByStatus |
227 | |
228 | |
229 | $googleAdsCustomers = $this->googleAds->getGoogleAdsCustomers(); |
230 | $googleAdsCampaignIds = self::getGoogleCampaignIds($googleAdsCustomers, $request); |
231 | #return $this->sendResponse(200, $googleAdsCampaignIds); |
232 | |
233 | /** |
234 | * Base query |
235 | */ |
236 | $conversionsPage = ConversionDigest::leftJoin('google_ads_campaigns', 'google_ads_campaigns.campaign_id', '=', 'cmpid') |
237 | ->select( |
238 | 'conversions.id', |
239 | 'conversions.gclid', |
240 | 'conversions.fbclid', |
241 | 'conversions.website_url', |
242 | 'conversions.cmpid', |
243 | 'conversions.created_at', |
244 | 'conversions.status_id', |
245 | 'google_ads_customers.customer_id', |
246 | 'google_ads_customers.customer_descriptive_name', |
247 | 'google_ads_campaigns.campaign_id', |
248 | 'google_ads_campaigns.campaign_name' |
249 | ) |
250 | ->leftJoin('google_ads_customers', 'google_ads_customers.customer_id', '=', 'google_ads_campaigns.customer_id') |
251 | ->whereIn('cmpid', $googleAdsCampaignIds) // only return campaigns of the session user |
252 | ->where('conversions.created_at', '>', $startDate) |
253 | ->where('conversions.created_at', '<', $endDate); |
254 | |
255 | |
256 | /** |
257 | * Optional filters |
258 | */ |
259 | $conversionsPage = $filter_customer_id ? $conversionsPage->where('google_ads_customers.customer_id', '=', $filter_customer_id) : $conversionsPage; |
260 | $conversionsPage = $filter_campaign_id ? $conversionsPage->where('google_ads_campaigns.campaign_id', '=', $filter_campaign_id) : $conversionsPage; |
261 | $conversionsPage = $request->query('gclid') ? $conversionsPage->where('gclid', '=', $request->query('gclid')) : $conversionsPage; |
262 | $conversionsPage = $request->query('fbclid') ? $conversionsPage->where('fbclid', '=', $request->query('fbclid')) : $conversionsPage; |
263 | |
264 | /** |
265 | * Optional filter by status name |
266 | */ |
267 | $conversionsPage = $filterByStatus($conversionsPage, $request); |
268 | |
269 | /** |
270 | * Order and sort |
271 | */ |
272 | switch ($order) { |
273 | // sort by campaign name |
274 | case 'campaign': |
275 | $conversionsPage->orderBy('google_ads_campaigns.campaign_name', $sort); |
276 | break; |
277 | |
278 | // sort by customer name |
279 | case 'customer': |
280 | $conversionsPage->orderBy('google_ads_customers.customer_descriptive_name', $sort); |
281 | break; |
282 | |
283 | // sort by click ids |
284 | case 'gclid': |
285 | case 'fbclid': |
286 | $conversionsPage->orderBy($order, $sort); |
287 | break; |
288 | |
289 | case 'created_at': |
290 | $conversionsPage->orderBy('conversions.created_at', $sort); |
291 | break; |
292 | } |
293 | |
294 | /** |
295 | * Page and items |
296 | */ |
297 | $conversionsPage = $conversionsPage->paginate($size); |
298 | $conversionsItems = $conversionsPage->items(); |
299 | |
300 | /** |
301 | * Build pagination hateoas |
302 | */ |
303 | $paginationHateoas = $this->createPaginationFromOrm($conversionsPage); |
304 | |
305 | /** |
306 | * HTTP 200 |
307 | */ |
308 | return $this->sendResponse(200, $conversionsItems, $paginationHateoas); |
309 | } // getConversionsDigest |
310 | |
311 | |
312 | /** |
313 | * Return one conversion |
314 | * |
315 | * @author gbh |
316 | * @see http://swagger-humanverify.fruitbat.systems/#get-/api/conversions/-id- |
317 | */ |
318 | public function getConversion(Request $request, Int $id):JsonResponse |
319 | { |
320 | $googleAdsCustomers = $this->googleAds->getGoogleAdsCustomers(); |
321 | $googleAdsCampaignIds = self::getGoogleCampaignIds($googleAdsCustomers, $request); |
322 | |
323 | /** |
324 | * Get conversion |
325 | */ |
326 | $conversion = Conversion::where('id', '=', $id) |
327 | ->whereIn('cmpid', $googleAdsCampaignIds) // only return campaigns of the session user |
328 | ->first(); |
329 | |
330 | /** |
331 | * No record |
332 | * HTTP 404 |
333 | */ |
334 | if (is_null($conversion)) { |
335 | return $this->sendError(404, null, null); |
336 | } |
337 | |
338 | /** |
339 | * HTTP 200 |
340 | */ |
341 | return $this->sendResponse(200, $conversion); |
342 | } // getConversion |
343 | |
344 | |
345 | /** |
346 | * Return transactions for one conversion |
347 | * |
348 | * @author gbh |
349 | * @see http://swagger-humanverify.fruitbat.systems/#get-/api/conversions/-id-/transactions |
350 | */ |
351 | public function getConversionTransactions(Request $request, Int $id):JsonResponse |
352 | { |
353 | $googleAdsCustomers = $this->googleAds->getGoogleAdsCustomers(); |
354 | $googleAdsCampaignIds = self::getGoogleCampaignIds($googleAdsCustomers, $request); |
355 | |
356 | /** |
357 | * Get conversion |
358 | */ |
359 | $conversion = Conversion::where('id', '=', $id) |
360 | ->whereIn('cmpid', $googleAdsCampaignIds) // only return campaigns of the session user |
361 | ->first(); |
362 | |
363 | /** |
364 | * No record |
365 | * HTTP 404 |
366 | */ |
367 | if (is_null($conversion)) { |
368 | return $this->sendError(404, null, null); |
369 | } |
370 | |
371 | $transactions = ConversionTransaction::where('conversion_id', '=', $id) |
372 | ->orderBy('created_at', 'desc') |
373 | ->get(); |
374 | |
375 | /** |
376 | * HTTP 200 |
377 | */ |
378 | return $this->sendResponse(200, $transactions); |
379 | } |
380 | |
381 | |
382 | /* |
383 | public function postConversionApproveTest(Request $request, Int $id):JsonResponse |
384 | { |
385 | * attempting to get the 'conversion acctions' attached to a 'customer' here, |
386 | * see: https://groups.google.com/g/adwords-api/c/8f50BJxpaQI |
387 | * https://groups.google.com/g/adwords-api/c/8f50BJxpaQI |
388 | |
389 | $googleCustomerIds = $this->getGoogleAdsCustomerIds(); |
390 | $gcid = $googleCustomerIds[2]; |
391 | |
392 | $t = $this->getGoogleAdsCampaigns($gcid); |
393 | return $this->sendResponse(200, $t); |
394 | |
395 | |
396 | //$googleAdsClient = $this->getAdsClient($gcid); |
397 | $googleAdsClient = $this->getAdsClient(); |
398 | |
399 | $googleAdsServiceClient = $googleAdsClient->getGoogleAdsServiceClient(); |
400 | $query = 'SELECT conversion_action.id, conversion_action.name FROM conversion_action'; |
401 | $query = 'SELECT campaign.id, campaign.name FROM campaign ORDER BY campaign.id'; |
402 | $stream =$googleAdsServiceClient->search($gcid, $query); |
403 | |
404 | foreach ($stream->iterateAllElements() as $googleAdsRow) { |
405 | //print_r($googleAdsRow); |
406 | print "."; |
407 | print_r($googleAdsRow->getCampaign()->getName()); |
408 | print_r($googleAdsRow->getCampaign()->getId()); |
409 | } |
410 | |
411 | |
412 | return $this->sendResponse(200, "END postConversionApproveTest test"); |
413 | // end |
414 | |
415 | * Get conversion |
416 | $conversion = Conversion::find($id); |
417 | print json_encode($conversion); |
418 | |
419 | $googleAdsClient = $this->getAdsClient(); |
420 | |
421 | $conversionArgs = [ |
422 | 'name' => 'Earth to Mars Cruises Conversion #', |
423 | 'category' => \Google\Ads\GoogleAds\V10\Enums\ConversionActionCategoryEnum\ConversionActionCategory::PBDEFAULT, |
424 | 'type' => \Google\Ads\GoogleAds\V10\Enums\ConversionActionTypeEnum\ConversionActionType::WEBPAGE, |
425 | 'status' => \Google\Ads\GoogleAds\V10\Enums\ConversionActionStatusEnum\ConversionActionStatus::ENABLED, |
426 | 'view_through_lookback_window_days' => 15, |
427 | 'value_settings' => new \Google\Ads\GoogleAds\V10\Resources\ConversionAction\ValueSettings([ |
428 | 'default_value' => 23.41, |
429 | 'always_use_default_value' => true |
430 | ]) |
431 | ]; |
432 | |
433 | $ca = new \Google\Ads\GoogleAds\V10\Resources\ConversionAction(); |
434 | return $this->sendResponse(200, "postConversionApproveTest test"); |
435 | } |
436 | */ |
437 | |
438 | /** |
439 | * Set on conversion as approved |
440 | * |
441 | * @note conversion_action_id comes from GET /api/googleads/customers/{id}/conversionaction |
442 | * @author gbh |
443 | * @see http://swagger-humanverify.fruitbat.systems/#post-/api/conversions/-id-/approved |
444 | */ |
445 | public function postConversionApprove(Request $request, Int $id):JsonResponse |
446 | { |
447 | $googleAdsCustomers = $this->googleAds->getGoogleAdsCustomers(); |
448 | $googleAdsCampaignIds = self::getGoogleCampaignIds($googleAdsCustomers, $request); |
449 | |
450 | /** |
451 | * Validate request body |
452 | * HTTP 400 |
453 | */ |
454 | $validationTest = $this->__validateConversionApprovalRequest($request); |
455 | if (is_object($validationTest)) { |
456 | return $validationTest; |
457 | } |
458 | |
459 | /** |
460 | * Get conversion |
461 | */ |
462 | $conversion = Conversion::where('id', '=', $id) |
463 | ->whereIn('cmpid', $googleAdsCampaignIds) // only return campaigns of the session user |
464 | ->first(); |
465 | |
466 | /** |
467 | * No record |
468 | * HTTP 404 |
469 | */ |
470 | if (is_null($conversion)) { |
471 | return $this->sendError(404, null, null); |
472 | } |
473 | |
474 | /** |
475 | * Get status id for 'approved' |
476 | */ |
477 | $statusId = ConversionStatus::where('name', '=', 'approved')->first()->id; |
478 | |
479 | /** |
480 | * Get the currency code |
481 | */ |
482 | $currencyCode = ConversionCurrency::where('id', '=', $conversion->conversion_currency)->first()->name; |
483 | |
484 | /** |
485 | * BOOKMARK |
486 | * Approve in google |
487 | */ |
488 | |
489 | /** |
490 | * Build the click conversion |
491 | * @see https://developers.google.com/google-ads/api/docs/samples/upload-conversion-with-identifiers |
492 | */ |
493 | $campaignId = $conversion->cmpid; |
494 | $conversionId = $conversion->id; |
495 | $gclid = $conversion->gclid; |
496 | $currencyCode = $conversion->conversion_currency; |
497 | $conversionActionId = $request->conversion_action_id; |
498 | $conversionValue = $request->conversion_value; |
499 | $conversionDateTime = date("Y-m-d H:i:sP"); // store |
500 | $orderId = $request->order_id ?? null; |
501 | |
502 | // get the customer id from the campaign id via cache |
503 | $customerId = $this->googleAds->getGoogleAdsCustomerFromCampaign($campaignId); |
504 | |
505 | // the conversion action here is just an endpoint, but we get it the canonical way anyway. |
506 | $conversionAction = \Google\Ads\GoogleAds\Util\V10\ResourceNames::forConversionAction($customerId, $conversionActionId); |
507 | |
508 | // the click conversion object |
509 | $clickConversion = new \Google\Ads\GoogleAds\V10\Services\ClickConversion([ |
510 | 'conversion_action' => $conversionAction, |
511 | 'conversion_date_time' => $conversionDateTime, |
512 | 'conversion_value' => $conversionValue, |
513 | 'currency_code' => $currencyCode |
514 | ]); |
515 | |
516 | // optional order id from body of request |
517 | if ($orderId) { |
518 | $clickConversion->setOrderId($orderId); |
519 | } |
520 | |
521 | // BOOKMARK SET USER IDENTIFIER |
522 | // see https://developers.google.com/google-ads/api/docs/samples/upload-conversion-with-identifiers |
523 | |
524 | /** |
525 | * Submit conversion to google |
526 | */ |
527 | try { |
528 | $this->googleAds->submitConversionToGoogle($customerId, $clickConversion); |
529 | } |
530 | catch (\Exception $e) { |
531 | return $this->sendError(500, $e->getMessage(), null); |
532 | } |
533 | |
534 | /** |
535 | * Approve locally |
536 | */ |
537 | |
538 | /** |
539 | * Update conversion as 'approved' |
540 | */ |
541 | $conversion->status_id = $statusId; |
542 | $conversion->status_user_id = $this->getLoggedInUserId(); |
543 | $conversion->approved_datetime = $conversionDateTime; |
544 | $conversion->save(); |
545 | |
546 | /** |
547 | * Write transaction |
548 | */ |
549 | $conversionTransaction = new ConversionTransaction(); |
550 | $conversionTransaction->conversion_id = $id; |
551 | $conversionTransaction->user_id = $this->getLoggedInUserId(); |
552 | $conversionTransaction->status_id = $statusId; |
553 | $conversionTransaction->event = "approved"; |
554 | $conversionTransaction->save(); |
555 | |
556 | /** |
557 | * HTTP 201 |
558 | */ |
559 | return $this->sendResponse(201, null); |
560 | } // postConversionApprove |
561 | |
562 | |
563 | /** |
564 | * Set one conversion as rejected |
565 | * |
566 | * @author gbh |
567 | * @see http://swagger-humanverify.fruitbat.systems/#post-/api/conversions/-id-/rejected |
568 | */ |
569 | public function postConversionReject(Request $request, Int $id):JsonResponse |
570 | { |
571 | $googleAdsCustomers = $this->googleAds->getGoogleAdsCustomers(); |
572 | $googleAdsCampaignIds = self::getGoogleCampaignIds($googleAdsCustomers, $request); |
573 | |
574 | /** |
575 | * Get conversion |
576 | */ |
577 | $conversion = Conversion::where('id', '=', $id) |
578 | ->whereIn('cmpid', $googleAdsCampaignIds) // only return campaigns of the session user |
579 | ->first(); |
580 | |
581 | /** |
582 | * No record |
583 | * HTTP 404 |
584 | */ |
585 | if (is_null($conversion)) { |
586 | return $this->sendError(404, null, null); |
587 | } |
588 | |
589 | /** |
590 | * Get status id for 'rejected' |
591 | */ |
592 | $statusId = ConversionStatus::where('name', '=', 'rejected')->first()->id; |
593 | |
594 | /** |
595 | * Update status id |
596 | */ |
597 | $conversion->status_id = $statusId; |
598 | $conversion->status_user_id = $this->getLoggedInUserId(); |
599 | $conversion->save(); |
600 | |
601 | /** |
602 | * Write transaction |
603 | */ |
604 | $conversionTransaction = new ConversionTransaction(); |
605 | $conversionTransaction->conversion_id = $id; |
606 | $conversionTransaction->user_id = $this->getLoggedInUserId(); |
607 | $conversionTransaction->status_id = $statusId; |
608 | $conversionTransaction->event = "rejected"; |
609 | $conversionTransaction->save(); |
610 | |
611 | /** |
612 | * HTTP 201 |
613 | */ |
614 | return $this->sendResponse(201, null); |
615 | } // postConversionReject |
616 | |
617 | |
618 | /** |
619 | * Set on conversion as flagged |
620 | * |
621 | * @author gbh |
622 | * @see http://swagger-humanverify.fruitbat.systems/#post-/api/conversions/-id-/flagged |
623 | */ |
624 | public function postConversionFlag(Request $request, Int $id):JsonResponse |
625 | { |
626 | $googleAdsCustomers = $this->googleAds->getGoogleAdsCustomers(); |
627 | $googleAdsCampaignIds = self::getGoogleCampaignIds($googleAdsCustomers, $request); |
628 | |
629 | /** |
630 | * Get conversion |
631 | */ |
632 | $conversion = Conversion::where('id', '=', $id) |
633 | ->whereIn('cmpid', $googleAdsCampaignIds) // only return campaigns of the session user |
634 | ->first(); |
635 | |
636 | /** |
637 | * No record |
638 | * HTTP 404 |
639 | */ |
640 | if (is_null($conversion)) { |
641 | return $this->sendError(404, null, null); |
642 | } |
643 | |
644 | /** |
645 | * Get status id for 'flagged' |
646 | */ |
647 | $statusId = ConversionStatus::where('name', '=', 'flagged')->first()->id; |
648 | |
649 | /** |
650 | * Update status id |
651 | */ |
652 | $conversion->status_id = $statusId; |
653 | $conversion->status_user_id = $this->getLoggedInUserId(); |
654 | $conversion->save(); |
655 | |
656 | /** |
657 | * Write transaction |
658 | */ |
659 | $conversionTransaction = new ConversionTransaction(); |
660 | $conversionTransaction->conversion_id = $id; |
661 | $conversionTransaction->user_id = $this->getLoggedInUserId(); |
662 | $conversionTransaction->status_id = $statusId; |
663 | $conversionTransaction->event = "flagged"; |
664 | $conversionTransaction->save(); |
665 | |
666 | /** |
667 | * HTTP 201 |
668 | */ |
669 | return $this->sendResponse(201, null); |
670 | } // postConversionFlag |
671 | |
672 | |
673 | /** |
674 | * Post one note to a conversion |
675 | * |
676 | * @author gbh |
677 | * @see http://swagger-humanverify.fruitbat.systems/#post-/api/conversions/-id-/note |
678 | */ |
679 | public function postConversionNote(Int $id, Request $request):JsonResponse |
680 | { |
681 | $googleAdsCustomers = $this->googleAds->getGoogleAdsCustomers(); |
682 | $googleAdsCampaignIds = self::getGoogleCampaignIds($googleAdsCustomers, $request); |
683 | |
684 | /** |
685 | * Get conversion |
686 | */ |
687 | $conversion = Conversion::where('id', '=', $id) |
688 | ->whereIn('cmpid', $googleAdsCampaignIds) // only return campaigns of the session user |
689 | ->first(); |
690 | |
691 | /** |
692 | * No record |
693 | * HTTP 404 |
694 | */ |
695 | if (is_null($conversion)) { |
696 | return $this->sendError(404, null, null); |
697 | } |
698 | |
699 | /** |
700 | * Validate request body |
701 | * HTTP 400 |
702 | */ |
703 | $validationTest = $this->__validateNoteRequest($request); |
704 | if (is_object($validationTest)) { |
705 | return $validationTest; |
706 | } |
707 | |
708 | /** |
709 | * Create the note |
710 | */ |
711 | $conversionNote = new ConversionNote(); |
712 | $conversionNote->conversion_id = $id; |
713 | $conversionNote->note = $request->note; |
714 | $conversionNote->user_id = $this->getLoggedInUserId(); |
715 | $conversionNote->save(); |
716 | |
717 | /** |
718 | * Write transaction |
719 | */ |
720 | $conversionTransaction = new ConversionTransaction(); |
721 | $conversionTransaction->conversion_id = $id; |
722 | $conversionTransaction->user_id = $this->getLoggedInUserId(); |
723 | $conversionTransaction->status_id = $conversion->status_id; |
724 | $conversionTransaction->event = "note"; |
725 | $conversionTransaction->note = $request->note; |
726 | $conversionTransaction->save(); |
727 | |
728 | /** |
729 | * HTTP 201 |
730 | */ |
731 | return $this->sendResponse(201, null); |
732 | } // postConversionNote |
733 | |
734 | |
735 | /** |
736 | * Validates request body of a Note |
737 | * |
738 | */ |
739 | protected function __validateNoteRequest(Request $request) // @phpstan-ignore-line |
740 | { |
741 | $itemValidationRules = [ |
742 | 'note' => 'required|string', |
743 | ]; |
744 | |
745 | $validationResult = $this->__validateJson($itemValidationRules, $request); |
746 | |
747 | if (is_array($validationResult)) { |
748 | return $this->sendError(400, $validationResult, "Validation error"); |
749 | } else { |
750 | return true; |
751 | } |
752 | } // __validateNoteRequest |
753 | |
754 | |
755 | /** |
756 | * Validates request body of a Conversion |
757 | * |
758 | */ |
759 | protected function __validateConversionRequest(Request $request) // @phpstan-ignore-line |
760 | { |
761 | $itemValidationRules = [ |
762 | 'website_url' => 'required|string', |
763 | ]; |
764 | |
765 | $validationResult = $this->__validateJson($itemValidationRules, $request); |
766 | |
767 | if (is_array($validationResult)) { |
768 | return $this->sendError(400, $validationResult, "Validation error"); |
769 | } else { |
770 | return true; |
771 | } |
772 | } // __validateConversionRequest |
773 | |
774 | |
775 | /** |
776 | * Validates that string $date is a valid yyyy-mm-dd date |
777 | */ |
778 | protected function __validateYYYYMMDD(String $date):bool |
779 | { |
780 | if (preg_match("/^([0-9]{4})-([0-9]{2})-([0-9]{2})$/", $date, $parts)) { |
781 | if (checkdate($parts[2], $parts[3], $parts[1])) { |
782 | return true; |
783 | } |
784 | } |
785 | return false; |
786 | } |
787 | |
788 | |
789 | /** |
790 | * Validates request body of conversion approval |
791 | * |
792 | */ |
793 | protected function __validateConversionApprovalRequest(Request $request) // @phpstan-ignore-line |
794 | { |
795 | $itemValidationRules = [ |
796 | 'conversion_action_id' => 'required|integer', |
797 | 'conversion_value' => 'required|numeric|min:0.01', |
798 | 'order_id' => 'string', |
799 | ]; |
800 | |
801 | $validationResult = $this->__validateJson($itemValidationRules, $request); |
802 | |
803 | if (is_array($validationResult)) { |
804 | return $this->sendError(400, $validationResult, "Validation error"); |
805 | } else { |
806 | return true; |
807 | } |
808 | } // __validateNoteRequest |
809 | |
810 | |
811 | protected static function getGoogleCampaignIds(array $googleAdsCustomers, Request $request) |
812 | { |
813 | // refresh cache of customers and campaigns if required. select all customers |
814 | //$googleCustomers = $this->googleAds->getGoogleAdsCustomers(); |
815 | |
816 | // unique, non-null ids as array |
817 | $googleCustomerIds = array_unique( |
818 | array_filter( |
819 | array_map( |
820 | fn ($n) => $n['customer_id'], |
821 | $googleAdsCustomers |
822 | ), |
823 | fn ($n) => strlen($n) > 0 |
824 | ) |
825 | ); |
826 | |
827 | // campaign cache has just been refreshed so safe to select from it |
828 | return GoogleAdsCampaign::whereIn('customer_id', $googleCustomerIds)->pluck('campaign_id')->toArray(); |
829 | } |
830 | } |