· 4 years ago · Feb 02, 2021, 12:50 PM
1
2
3 /**
4 * Create new Advertisement by parameters
5 * Required fields: 'token', 'ad_title', 'ad_category', 'ad_body',
6 *
7 * @param $request
8 * @param $response
9 * @param $args
10 * @return mixed
11 * @throws \Exception
12 */
13 public function create($request, $response, $args)
14 {
15 // Checks if 'HTTP_TOKEN' key inside Headers array
16 $header_token = $request->getHeader('HTTP_TOKEN');
17 // If 'HTTP_TOKEN' key not exists
18 if(!$header_token){
19 $result['error'] = langHandler::getLangPhrase("app.required.token");
20 return $response->withJson($result, 410);
21 // If 'HTTP_TOKEN' value not exists
22 }elseif(empty($header_token[0])){
23 $result['error'] = langHandler::getLangPhrase("app.required.token");
24 return $response->withJson($result, 410);
25 }else{
26 $token = $header_token[0];
27 }
28
29 $user_id = null;
30
31 if ($token) {
32 // Checks if current 'token' exists with 'exp_date' parameter
33 $user_token = Token::get($this->pdo, $token, TOKEN_EXP_DATE);
34 // If 'token' not exists or expired
35 if (!$user_token) {
36 $user_token = Token::get($this->pdo, $token);
37 if ($user_token) {
38 Token::delete($this->pdo, $token);
39 }
40
41 $result['error'] = langHandler::getLangPhrase("token.!exists");
42 return $response->withJson($result, 401);
43 } else {
44 // If 'token' exists, we assign it to our variable $user_id
45 $user_id = (int)$user_token['user_id'];
46 }
47 }
48
49
50 // Checks if 'ad_title' field was filled
51 $ad_title = (string)htmlspecialchars($request->getParam('ad_title'));
52 // If 'ad_title' field not filled
53 if(!$ad_title){
54 $result['error'] = langHandler::getLangPhrase("advertisement.required.title");
55 return $response->withJson($result, 410);
56 }else{
57 // Formats text with required checks
58 $ad_title = formattingHandler::formattingText($ad_title);
59
60 // Checks min & max 'ad_title' length
61 $validateAdTitle = validationHandler::stringLengthMinMax($ad_title, 3, 255);
62 if(!$validateAdTitle){
63 $result['error'] = langHandler::getLangPhrase("social.required.length");
64 return $response->withJson($result, 411);
65 }
66 }
67
68
69 // Checks if 'ad_body' field was filled
70 $ad_body = (string)htmlspecialchars($request->getParam('ad_body'));
71 // If 'ad_body' field not filled
72 if(!$ad_body){
73 $result['error'] = langHandler::getLangPhrase("advertisement.required.body");
74 return $response->withJson($result, 410);
75 }else{
76 // Formats text with required checks
77 $ad_body = formattingHandler::formattingText($ad_body);
78
79 // Checks min & max 'ad_body' length
80 $validateAdBody = validationHandler::stringLengthMinMax($ad_body, 1, 5000);
81 if(!$validateAdBody){
82 $result['error'] = langHandler::getLangPhrase("social.required.length");
83 return $response->withJson($result, 411);
84 }
85 }
86
87
88 $parent_id = null;
89 $user_lat = null;
90 $user_lng = null;
91 $user_phone = null;
92 $user_address = null;
93 $geoInfo = null;
94 $currency_id = 1;
95
96 // Checks if 'category_id' field filled
97 $category_id = (int)urldecode(htmlspecialchars($request->getParam('category_id')));
98 // If 'category_id' field not filled
99 if(!$category_id){
100 $result['error'] = langHandler::getLangPhrase("category.required.id");
101 return $response->withJson($result, 410);
102 }else{
103 // Gets Category's 'parent_id' by 'category_id' parameter
104 $parent_id = (int)recursiveHandler::getCategoryParentByCategoryID($this->pdo, $category_id);
105
106 // Gets User's role name by Category's 'parent_id'
107 $user_role = converterHandler::getUserRoleByCategoryID($parent_id);
108
109 // Fill required 'params' to the array
110 $data_params = [
111 'pdo' => $this->pdo,
112 'user_id' => $user_id,
113 'user_role' => $user_role,
114 'param_id' => 16
115 ];
116
117 // Gets User's 'latitude' by 'user_role' & 'param_id' - 16
118 $user_lat = userModelHandler::getUserParamsItems($data_params);
119
120 $data_params['param_id'] = 17;
121 // Gets User's 'longitude' by 'user_role' & 'param_id' - 17
122 $user_lng = userModelHandler::getUserParamsItems($data_params);
123
124 $data_params['param_id'] = 51;
125 // Gets User's 'phone' by 'user_role' & 'param_id' - 51
126 $user_phone = userModelHandler::getUserParamsItems($data_params);
127
128 $data_params['param_id'] = 27;
129 // Gets User's 'address' by 'user_role' & 'param_id' - 27
130 $user_address = userModelHandler::getUserParamsItems($data_params);
131
132 // Gets 'postal_code' and 'country'
133 $geoInfo = geoHandler::getAddress($user_lat, $user_lng, ['postal_code', 'country']);
134
135 // Checks, if country USA, we use '3' for currency number
136 if($geoInfo['country'] == 'United States'){
137 $currency_id = 3;
138 }
139 }
140
141
142 // Checks if 'ad_params' field filled
143 $ad_params = (array)$request->getParam('ad_params');
144
145
146 $result = null;
147 $ad_pictures_name = null;
148
149 // Checks if User send post picture(s) via array $_FILES['file_pictures']
150 if(!empty($_FILES)
151 && !empty($_FILES['file_pictures'])
152 ){
153 // Number of maximum pictures
154 $picture_count = appHandler::getData('APP_MAX_PICTURE_COUNT');
155 $picture_max_size = appHandler::getData('APP_MAX_PICTURE_SIZE');
156
157 // Checks if number of files in 'file_pictures' more than in $picture_count
158 if(count($_FILES['file_pictures']['tmp_name']) > $picture_count){
159 $result['error'] = langHandler::getLangPhrase("file.validation.picture_count", $picture_count);
160 return $response->withJson($result, 403);
161 }
162
163 $counter = 0;
164 // Initiate 'status_code' variable to the response
165 $status_code = null;
166
167 for ($i = 0; $i <= count($_FILES['file_pictures']['tmp_name']); $i++)
168 {
169 if( $_FILES['file_pictures']['error'][$i] === UPLOAD_ERR_OK
170 && is_uploaded_file($_FILES['file_pictures']['tmp_name'][$i]))
171 {
172 // Checks if file size in 'file_pictures' more than 2 MB
173 $validateFileSize = validationHandler::fileSize($_FILES['file_pictures']['tmp_name'][$i]);
174 if(!$validateFileSize){
175 $result['error'] = langHandler::getLangPhrase("file.validation.picture_size", $picture_max_size);
176 $status_code = 403;
177 break;
178 }
179
180 // Checks if file extension in 'file_pictures' meets the requirements
181 $validateFileExt = validationHandler::fileExtension($_FILES["file_pictures"]['name'][$i]);
182 if(!$validateFileExt){
183 $result['error'] = langHandler::getLangPhrase("file.validation.picture_ext");
184 $status_code = 403;
185 break;
186 }
187
188 // Prepares file name in 'file_pictures' array to the requirements
189 $ad_pictures_name[$counter] = mediaHandler::prepareFileName($_FILES["file_pictures"]['name'][$i], MH_FILE_RENAME);
190 if(!$ad_pictures_name[$counter]){
191 $result['error'] = langHandler::getLangPhrase("file.preparation.file_name");
192 $status_code = 403;
193 break;
194 }
195
196 $counter += 1;
197 }else{
198 continue;
199 }
200 }
201
202 if($status_code){
203 return $response->withJson($result, $status_code);
204 }
205 }
206
207
208 $date = date ("Y-m-d H:i:s");
209
210 $status = "pending";
211
212 // Checks specific 'status' for new Advertisement
213 if($parent_id){
214 // Gets child category 'id's by parent
215 $getCategories = recursiveHandler::getCategoryChildrenByCategoryID($this->pdo, $parent_id);
216
217 // Adding 'category_id' from params to the array
218 array_unshift($getCategories, $category_id);
219
220 if(is_array($getCategories) && count($getCategories) > 0){
221 // Formats array with different 'category_id', cleans from duplicates and converts to required format
222 $getCategories = formattingHandler::formattingArrayWithDuplicateValues($getCategories, FH_ARRAY_INDEX, FH_RESULT_STRING);
223 }
224
225 $data_ads_params = [
226 'user_id' => $user_id,
227 'category_id' => $getCategories,
228 'status' => "approved"
229 ];
230
231 // Get amount of advertisements by 'user_id'
232 $ads_counter = Advertisement::getAdvertisementsCountByParams($this->pdo, $data_ads_params);
233
234 //Check, if advertisement counter more than 10 items, 'status' stands 'approved'
235 if($ads_counter > 10){
236 $status = "approved";
237 }
238 }
239
240 // Fill required advertisement 'params' for inserting to the DB
241 $data_ad = [
242 'user_id' => $user_id, // user_id
243 'category_id' => $category_id, // category_id
244 'ad_title' => $ad_title, // ad_title
245 'ad_body' => $ad_body, // ad_body
246 'ad_phone' => $user_phone, // ad_phone
247 'status' => $status, // approved or pending ('pending' by default)
248 'post_code' => $geoInfo['postal_code'], // post_code
249 'currency_id' => $currency_id, // currency_id
250 'created_at' => $date, // created_at time
251 'ad_lat' => $user_lat, // lat
252 'ad_lng' => $user_lng, // lng
253 ];
254
255 // Inserts new Advertisement to DB and returns new 'id'
256 $ad_id = Advertisement::insert($this->pdo, $data_ad);
257 // If 'ad_id' not exists
258 if(!$ad_id){
259 $result['error'] = langHandler::getLangPhrase("advertisement.!found");
260 return $response->withJson($result, 404);
261 }
262
263 // Checks, if something went wrong with inserting into DB and we got \Exception object
264 if(is_object($ad_id)){
265 if($ad_id->getMessage()){
266 $result['error'] = langHandler::getLangPhrase("app.!db",
267 $ad_id->getMessage()
268 ." at ". $ad_id->getFile()
269 ." on ". $ad_id->getLine() ." line."
270 );
271 return $response->withJson($result, 503);
272 }
273 }
274
275
276 // Formats 'ad_title' to the 'ad_slug'
277 $ad_slug = formattingHandler::formattingStringToURL($ad_title);
278
279 // Fill required 'params' to the array
280 $data_slug = [
281 'ad_id' => $ad_id,
282 'ad_slug' => $ad_slug,
283 'flag' => "invert",
284 ];
285
286 // Checks, if current 'ad_slug' exists in DB at 'xc_ads' table
287 $getAdSlug = Advertisement::getAdvertisementSlugByParams($this->pdo, $data_slug);
288
289 // Checks, if something went wrong with inserting into DB and we got \Exception object
290 if(is_object($getAdSlug)){
291 if($getAdSlug->getMessage()){
292 // Deletes previously created Advertisement by 'id'
293 Advertisement::deleteAdvertisementByID($this->pdo, $ad_id);
294
295 $result['error'] = langHandler::getLangPhrase("app.!db",
296 $getAdSlug->getMessage()
297 ." at ". $getAdSlug->getFile()
298 ." on ". $getAdSlug->getLine() ." line."
299 );
300 return $response->withJson($result, 503);
301 }
302 }
303
304 // Checks, if current 'ad_slug' exists in DB at 'xc_categories' table
305 $getCategorySlug = Category::getCategoryBySlug($this->pdo, $ad_slug);
306
307 // Checks, if something went wrong with inserting into DB and we got \Exception object
308 if(is_object($getCategorySlug)){
309 if($getCategorySlug->getMessage()){
310 // Deletes previously created Advertisement by 'id'
311 Advertisement::deleteAdvertisementByID($this->pdo, $ad_id);
312
313 $result['error'] = langHandler::getLangPhrase("app.!db",
314 $getCategorySlug->getMessage()
315 ." at ". $getCategorySlug->getFile()
316 ." on ". $getCategorySlug->getLine() ." line."
317 );
318 return $response->withJson($result, 503);
319 }
320 }
321
322 // If 'ad_slug' exists somewhere, we rename it and change it's value into 'params' array
323 if($getAdSlug || $getCategorySlug){
324 $ad_slug = $ad_id."_".$ad_slug;
325
326 $data_slug['ad_slug'] = $ad_slug;
327 }
328
329 $data_slug['user_id'] = $user_id;
330
331 // Updates 'ad_slug' in DB at 'xc_ads' table
332 $updateSlug = Advertisement::updateAdvertisementByParams($this->pdo, $data_slug);
333 if(!$updateSlug){
334 $result['error'] = langHandler::getLangPhrase("advertisement.!creation.slug");
335 return $response->withJson($result, 500);
336 }
337
338 // Checks, if something went wrong with inserting into DB and we got \Exception object
339 if(is_object($updateSlug)){
340 if($updateSlug->getMessage()){
341 // Deletes previously created Advertisement by 'id'
342 Advertisement::deleteAdvertisementByID($this->pdo, $ad_id);
343
344 $result['error'] = langHandler::getLangPhrase("app.!db",
345 $updateSlug->getMessage()
346 ." at ". $updateSlug->getFile()
347 ." on ". $updateSlug->getLine() ." line."
348 );
349 return $response->withJson($result, 503);
350 }
351 }
352
353
354 // Adds 'ad_param_id' to the array for error handling
355 $ad_param_ids = null;
356
357 // If 'ad_params' field filled
358 if(is_array($ad_params) && count($ad_params) > 0){
359
360 $status_code = null;
361
362 foreach ($ad_params as $ad_param) {
363 $param_id = (empty($ad_param['param_id'])) ? null : (int)$ad_param['param_id'];
364 $param_value = (empty($ad_param['param_value'])) ? null : $ad_param['param_value'];
365
366 if($param_id && $param_value){
367 // Gets additional information about current 'param_id'
368 $getParamOptions = Parameter::getParameterByID($this->pdo, $param_id);
369
370 // Checks, if current parameter has only number format,
371 if((int)$getParamOptions['is_number']){
372 // Checks, if 'param_value' consists ',' separator, replaces it to '.' by default method parameters
373 $param_value = formattingHandler::formattingDataWithSign($param_value);
374 }
375
376 // Checks for 'Price' (param_id = 5) and converts it to required format
377 if($param_id == 5){
378 $param_value = formattingHandler::formattingPriceWithCents($param_value);
379 }
380
381 // Checks for 'Weight' (param_id = 208) and converts it to required format
382 if($param_id == 208){
383 $param_value = formattingHandler::formattingWeightWithGrams($param_value);
384 }
385
386 // Checks, if 'param_value' is empty
387 if(is_null($param_value)){
388 // Checks, if 'param_id''s value is required
389 if($getParamOptions['required']){
390 $status_code = 403;
391 $result['error'] = langHandler::getLangPhrase("advertisement.required.param_value", $getParamOptions['name_filter']);
392 break;
393 }
394 }
395
396
397 // Checks, if parameter = 'checkbox' (type_id = 4), it has sub parameters in 'param_value's array
398 // and we adding it to 'xc_ads_params' table
399 $param_sub_values = null;
400 if($getParamOptions['type_id'] == 4){
401 if(!is_array($param_value)){
402 $param_sub_values = [$param_value];
403 }else{
404 $param_sub_values = $param_value;
405 }
406 $param_value = null;
407 }
408
409 // Checks for date & time formatting (type_id = 8 for date | type_id = 9 for date & time)
410 if($getParamOptions['type_id'] == 8){
411 $param_value = strtotime($param_value);
412 }elseif($getParamOptions['type_id'] == 9){
413 $param_value = strtotime($param_value[1]." ". $param_value[2]);
414 }
415
416 $data_ad_params = [
417 'ad_id' => $ad_id,
418 'param_id' => $param_id,
419 'param_value' => $param_value,
420 'is_number' => (int)$getParamOptions['is_number'],
421 ];
422
423 // Inserts new Advertisement Parameter to DB and returns new 'id'
424 $ad_param_id = AdvertisementParameter::insert($this->pdo, $data_ad_params);
425
426 // If 'ad_param_id' not exists
427 if(!$ad_param_id){
428 $status_code = 404;
429 $result['error'] = langHandler::getLangPhrase("advertisement.!creation.parameter");
430 break;
431 }
432
433 // Checks, if something went wrong with inserting into DB and we got \Exception object
434 if(is_object($ad_param_id)){
435 if($ad_param_id->getMessage()){
436 $status_code = 503;
437 $result['error'] = langHandler::getLangPhrase("app.!db",
438 $ad_param_id->getMessage()
439 ." at ". $ad_param_id->getFile()
440 ." on ". $ad_param_id->getLine() ." line."
441 );
442 break;
443 }
444 }
445
446 if(!is_null($param_sub_values)){
447 foreach ($param_sub_values as $param_sub_value) {
448
449 $data_ad_params['ad_param_id'] = $ad_param_id;
450 $data_ad_params['param_sub_value'] = $param_sub_value;
451
452 $ad_param_sub_id = AdvertisementParameterSub::insert($this->pdo, $data_ad_params);
453
454 // If 'ad_param_sub_id' not exists
455 if(!$ad_param_sub_id){
456 $status_code = 404;
457 $result['error'] = langHandler::getLangPhrase("advertisement.!creation.parameter");
458 break;
459 }
460
461 // Checks, if something went wrong with inserting into DB and we got \Exception object
462 if(is_object($ad_param_sub_id)){
463 if($ad_param_sub_id->getMessage()){
464 $status_code = 503;
465 $result['error'] = langHandler::getLangPhrase("app.!db",
466 $ad_param_sub_id->getMessage()
467 ." at ". $ad_param_sub_id->getFile()
468 ." on ". $ad_param_sub_id->getLine() ." line."
469 );
470 break;
471 }
472 }
473
474 // Adds 'ad_param_id' to the array for error handling
475 // Using it after DB check instead of before. It's important!
476 $ad_param_ids = [$ad_param_id];
477 }
478 }
479
480 // Checks, if some error code was added to the variable, breaks down foreach
481 if($status_code){
482 break;
483 }
484 }
485 }
486
487 if($status_code){
488 // Deletes previously created Advertisement by 'id'
489 Advertisement::deleteAdvertisementByID($this->pdo, $ad_id);
490 // Deletes previously created Advertisement Parameter by 'ad_id'
491 AdvertisementParameter::deleteAdParamsByAdID($this->pdo, $ad_id);
492
493 // Checks 'ad_param_id' in the array and deleting created records in the DB
494 if(!is_null($ad_param_ids)){
495 foreach ($ad_param_ids as $ad_param_id) {
496 // Deletes previously created Advertisement Sub Parameter by 'ad_param_id'
497 AdvertisementParameterSub::deleteAdParamsByAdID($this->pdo, $ad_param_id);
498 }
499 }
500
501 return $response->withJson($result, $status_code);
502 }
503 }
504
505 // Pictures links in response
506 $ad_pictures = null;
507
508 // Checks if array of pictures names was filled
509 if(!is_null($ad_pictures_name)
510 && is_array($ad_pictures_name)
511 && count($ad_pictures_name) > 0
512 ){
513 $counter = 0;
514 $main = null;
515 $ordering = null;
516 $status_code = null;
517
518 for ($i = 0; $i < count($_FILES['file_pictures']['tmp_name']); $i++)
519 {
520 $main = (is_null($ordering)) ? 1 : 0;
521 $ordering = (!is_null($main)) ? $counter++ : 0;
522
523 $data_picture = [
524 "ad_id" => $ad_id,
525 "picture" => $ad_pictures_name[$i],
526 "main" => $main,
527 "ordering" => $ordering,
528 'created_at' => $date, // created_at time
529 ];
530
531 $picture_id = AdvertisementPicture::insert($this->pdo, $data_picture);
532 // If picture was added to DB and we got its 'id' like 'picture_id'
533 if($picture_id){
534 $data_file = [
535 "directory" => mediaHandler::getMediaPath($ad_id, ["classifieds/", "pictures/"]),
536 "file" => $_FILES["file_pictures"]['tmp_name'][$i],
537 "file_name_raw" => $_FILES["file_pictures"]['name'][$i],
538 "file_name" => $ad_pictures_name[$i]
539 ];
540
541 $upload_file = mediaHandler::moveUploadedFile($data_file);
542 if(!$upload_file){
543 // Deletes previously created Advertisement by 'id'
544 Advertisement::deleteAdvertisementByID($this->pdo, $ad_id);
545 // Deletes previously created Advertisement Parameter by 'ad_id'
546 AdvertisementParameter::deleteAdParamsByAdID($this->pdo, $ad_id);
547
548 // Checks 'ad_param_id' in the array and deleting created records in the DB
549 if(!is_null($ad_param_ids)){
550 foreach ($ad_param_ids as $ad_param_id) {
551 // Deletes previously created Advertisement Sub Parameter by 'ad_param_id'
552 AdvertisementParameterSub::deleteAdParamsByAdID($this->pdo, $ad_param_id);
553 }
554 }
555
556 $status_code = 500;
557 $result['error'] = langHandler::getLangPhrase("file.!uploading.picture");
558 break;
559 }
560
561 $ad_pictures[$i] = (string)appHandler::getData('APP_PRODUCTION_URL')
562 .mediaHandler::getMediaPath($ad_id, ["classifieds/", "pictures/"])
563 .$ad_pictures_name[$i];
564 }
565 }
566
567 if($status_code){
568 return $response->withJson($result, $status_code);
569 }
570 }
571
572 $result['ad'] = $ad_id;
573 return $response->withJson($result, 201);
574 }