Last active
September 12, 2019 10:57
-
-
Save tisuchi/0697044ead825a2c452393eda81db60d to your computer and use it in GitHub Desktop.
Handling InputExcpetion on the package side.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Http\Controllers; | |
use App\Exceptions\InputException; | |
use Bugsnag\BugsnagLaravel\Facades\Bugsnag; | |
use Illuminate\Foundation\Bus\DispatchesJobs; | |
use Illuminate\Routing\Controller as BaseController; | |
use Illuminate\Foundation\Validation\ValidatesRequests; | |
use Illuminate\Foundation\Auth\Access\AuthorizesRequests; | |
use Illuminate\Http\Request; | |
class Controller extends BaseController | |
{ | |
use AuthorizesRequests, DispatchesJobs, ValidatesRequests; | |
/** | |
* Global Error Response | |
* @param [type] $message [description] | |
* @param [type] $errorcode [description] | |
* @return [type] [description] | |
*/ | |
public function errorResponse($message, $errorcode) | |
{ | |
return \Response::json([ | |
'status' => 'error', | |
'code' => $errorcode, | |
'message' => $message, //Bad Request | |
], $errorcode); | |
} | |
public function facebookGraphErrors(\Facebook\Exceptions\FacebookResponseException $e) | |
{ | |
return [ | |
'graph-error-code' => $e->getCode(), | |
'source' => 'facebook-graph', | |
'message' => "Graph returned an error: " . $e->getMessage() | |
]; | |
} | |
public function facebookSDKErrors(\Facebook\Exceptions\FacebookSDKException $e) | |
{ | |
return [ | |
'facebook-sdk-error-code' => $e->getCode(), | |
'source' => 'facebook-sdk', | |
'message' => "Facebook SDK returned an error: " . $e->getMessage() | |
]; | |
} | |
/** | |
* @param mixed $response | |
* @return \Illuminate\Http\JsonResponse | |
*/ | |
protected function generateResponse($response="") | |
{ | |
if (!is_array($response) && !is_object($response)) { | |
$response = ['message' => $response]; | |
} else { | |
$response = json_decode(json_encode($response,true),true); | |
$response['status'] = 'success'; | |
} | |
if(request()->method() == 'DELETE') { | |
return response()->json(null, 204); | |
} else { | |
return response()->json($response, 200); | |
} | |
} | |
/** | |
* @param \Throwable $exception | |
* @param bool|string $userMessage | |
* @return \Illuminate\Http\JsonResponse | |
*/ | |
protected function generateErrorResponse(\Throwable $exception, $userMessage = false, $inputNamespace = false) | |
{ | |
$response = [ | |
'status' => 'error', | |
'message' => $userMessage ? $userMessage : $exception->getMessage() | |
]; | |
$statusCode = $exception->getCode() == 0 ? 500 : $exception->getCode(); | |
if (env('APP_ENV') == 'production' && $statusCode == 500) { | |
Bugsnag::notifyException($exception); | |
} | |
$response = array_merge($response, [ | |
'error_code' => $statusCode, | |
'error_message' => $exception->getMessage(), | |
'file' => $exception->getFile(), | |
'line' => $exception->getLine() | |
]); | |
if ($inputNamespace === false){ | |
if ($exception instanceof InputException){ | |
$response['message'] = $exception->getUserMessage(); | |
$response['fields'] = $exception->getValidatorError(); | |
} | |
} else { | |
if ($exception instanceof $inputNamespace.'\InputException' ) { | |
$response['message'] = $exception->getUserMessage(); | |
$response['fields'] = $exception->getValidatorError(); | |
} | |
} | |
return response()->json($response, $statusCode); | |
} | |
public static function generateFatalErrorResponse() | |
{ | |
$error = error_get_last(); | |
if (!$error) | |
return; | |
$response = [ | |
'error' => $error['type'] | |
]; | |
if (env('APP_ENV') == 'production') | |
{ | |
} | |
} | |
protected function getOptionalParameters(Request $request, $parameters) | |
{ | |
$params = []; | |
foreach ($parameters as $key => $parameter) { | |
if (!$request->has($parameter)) { | |
continue ; | |
} | |
$newKey = is_numeric($key) ? $parameter : $key; | |
$params[$newKey] = $request->$parameter; | |
} | |
return $params; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Avana\Shipping\Exceptions; | |
class InputException extends \Exception | |
{ | |
protected $validatorError; | |
public function __construct($validatorError) | |
{ | |
$this->validatorError = $validatorError; | |
parent::__construct("Please refer to \"fields\" for more details.", 400); | |
} | |
public function getValidatorError() | |
{ | |
return $this->validatorError; | |
} | |
public function getUserMessage() | |
{ | |
return "Input is invalid or missing required parameters."; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Http\Controllers\V3; | |
use Response; | |
use Validator; | |
use Exception; | |
use Illuminate\Http\Request; | |
use Avana\Shipping\ShippingZone; | |
use App\Exceptions\InputException; | |
use App\Http\Controllers\Controller; | |
class ShippingZoneController extends Controller | |
{ | |
public function index($shopId) | |
{ | |
try{ | |
$shippingZone = (new ShippingZone())->index($shopId); | |
return $this->generateResponse($shippingZone); | |
} catch(\Throwable $e){ | |
return $this->generateErrorResponse($e); | |
} | |
} | |
public function store(Request $request, $shopId) | |
{ | |
try{ | |
$shippingZone = (new ShippingZone)->createShippingZone($request, $shopId); | |
return $this->generateResponse($shippingZone); | |
} catch(\Throwable $e){ | |
return $this->generateErrorResponse($e, false, 'Avana\Shipping\Exceptions\InputException'); | |
} | |
} | |
public function update(Request $request, $shopId, $zoneId) | |
{ | |
try{ | |
$shippingZone = (new ShippingZone)->updateShippingZone($request, $shopId, $zoneId); | |
return $this->generateResponse($shippingZone); | |
} catch(\Throwable $e){ | |
return $this->generateErrorResponse($e, false, 'Avana\Shipping\Exceptions\InputException'); | |
} | |
} | |
/** | |
* Delete a shipping destination | |
* | |
* @param $shopId | |
* @param $zoneId | |
* @return \Illuminate\Http\JsonResponse | |
*/ | |
public function delete($shopId, $zoneId) | |
{ | |
try{ | |
$shippingZone = (new ShippingZone())->deleteShippingZone($shopId); | |
return $this->generateResponse($shippingZone); | |
} catch(\Throwable $e){ | |
return $this->generateErrorResponse($e); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Avana\Shipping\Repositories; | |
use App\Models\Shipping; | |
use App\Models\ShippingCountry; | |
use App\Models\ShippingRate; | |
use Avana\Shipping\Exceptions\InputException; | |
use Rakit\Validation\Validator; | |
class ShippingZoneRepository | |
{ | |
public function index($shopId) | |
{ | |
$shipping = $this->hasShipping($shopId); | |
return $this->formattedDataForIndex($shipping); | |
} | |
public function hasShipping($shopId) | |
{ | |
return Shipping::where('shop_id', $shopId)->first(); | |
} | |
public function hasShippingRate($shippingId) | |
{ | |
return ShippingRate::where('shipping_id', $shippingId)->first(); | |
} | |
protected function formattedDataForIndex($shippingData) | |
{ | |
if ($shippingData){ | |
$shippingRate = $this->hasShippingRate($shippingData->shipping_id); | |
$data['id'] = optional($shippingRate)->shipping_rate_id ; | |
$data['name'] = optional($shippingRate)->name; | |
$data['type'] = optional($shippingRate)->type; | |
$data['freeshipping_enabled'] = optional($shippingRate)->freeshipping_enabled; | |
$data['freeshipping_min_price'] = optional($shippingRate)->freeshipping_min_price; | |
$data['handling_fee'] = optional($shippingRate)->handling_fee; | |
$data['handling_fee_type'] = optional($shippingRate)->handling_fee_type; | |
return $data; | |
} | |
$data['id'] = ''; | |
$data['name'] = ''; | |
$data['type'] = ''; | |
$data['freeshipping_enabled'] = ''; | |
$data['freeshipping_min_price'] = ''; | |
$data['handling_fee'] = ''; | |
$data['handling_fee_type'] = ''; | |
return $data; | |
} | |
public function storeShippingZoneMethod($request, $shopId, $zoneId) | |
{ | |
$hasShippingRate = ShippingRate::where('shipping_rate_id', $zoneId)->firstOrFail(); | |
if ($hasShippingRate) { | |
$hasShippingRate->update([ | |
'dynamic_first_unit' => $request->dynamic_first_unit, | |
'dynamic_first_rate' => $request->dynamic_first_rate, | |
'dynamic_addon_unit' => $request->dynamic_addon_unit, | |
'dynamic_addon_rate' => $request->dynamic_addon_rate, | |
'flat_rate' => $request->flat_rate, | |
'range_fallback_rate' => $request->range_fallback_rate, | |
'courier_code' => $request->courier_code | |
]); | |
ShippingCountry::create([ | |
'shipping_id' => $hasShippingRate->shipping_id, | |
'country_id' => $request->country_id, | |
'total_states_selected' => count(explode(",", $request->states)) | |
]); | |
} | |
return $this->formattedDataForShippingMethod($hasShippingRate); | |
} | |
protected function formattedDataForShippingMethod($hasShippingRate) | |
{ | |
$data['id'] = $hasShippingRate->shipping_rate_id ; | |
$data['dynamic_first_unit'] = $hasShippingRate->dynamic_first_unit; | |
$data['dynamic_first_rate'] = $hasShippingRate->dynamic_first_rate; | |
$data['dynamic_addon_unit'] = $hasShippingRate->dynamic_addon_unit; | |
$data['dynamic_addon_rate'] = $hasShippingRate->dynamic_addon_rate; | |
$data['flat_rate'] = $hasShippingRate->flat_rate; | |
$data['range_fallback_rate'] = $hasShippingRate->range_fallback_rate; | |
$data['courier_code'] = $hasShippingRate->courier_code; | |
$data['shipping_id'] = $hasShippingRate->shipping_id; | |
$data['country_id'] = $hasShippingRate->country_id; | |
$data['total_states_selected'] = $hasShippingRate->total_states_selected; | |
return $data; | |
} | |
public function createShippingZone($request, $shopId) | |
{ | |
$validator = new Validator; | |
$validation = $validator->make($request->all(), [ | |
'type' => 'required', | |
'shipping_id' => 'required', | |
'freeshipping_enabled' => 'required', | |
'freeshipping_min_price' => 'required', | |
'handling_fee' => 'required', | |
'handling_fee_type' => 'required' | |
]); | |
$validation->validate(); | |
if ($validation->fails()){ | |
$errors = $validation->errors(); | |
throw new InputException($errors->firstOfAll()); | |
} | |
$createShippingZone = ShippingRate::create([ | |
'type' => $request->type, | |
'unit' => 'weight', | |
'shipping_id' => $request->shipping_id, | |
'freeshipping_enabled' => $request->freeshipping_enabled, | |
'freeshipping_min_price' => $request->freeshipping_min_price, | |
'handling_fee' => $request->handling_fee, | |
'handling_fee_type' => $request->handling_fee_type | |
]); | |
return $this->formattedDataForIndex($createShippingZone); | |
} | |
public function updateShippingZone($request, $shopId, $zoneId) | |
{ | |
$validator = new Validator; | |
$validation = $validator->make($request->all(), [ | |
'type' => 'required', | |
'shipping_id' => 'required|integer', | |
'freeshipping_enabled' => 'required|integer|max:1', | |
'freeshipping_min_price' => 'required|regex:/^\d*(\.\d{4})?$/', | |
'handling_fee' => 'required|regex:/^\d*(\.\d{4})?$/', | |
'handling_fee_type' => 'required' | |
]); | |
$validation->validate(); | |
if ($validation->fails()){ | |
$errors = $validation->errors(); | |
throw new InputException($errors->firstOfAll()); | |
} | |
$hasShippingZone = ShippingRate::where('shipping_rate_id', $zoneId)->first(); | |
if (! $hasShippingZone) { | |
return false; | |
} | |
$hasShippingZone->update([ | |
'type' => $request->type, | |
'unit' => 'weight', | |
'shipping_id' => $request->shipping_id, | |
'freeshipping_enabled' => $request->freeshipping_enabled, | |
'freeshipping_min_price' => $request->freeshipping_min_price, | |
'handling_fee' => $request->handling_fee, | |
'handling_fee_type' => $request->handling_fee_type | |
]); | |
return $this->formattedDataForIndex($hasShippingZone); | |
} | |
public function deleteShippingZone($shopId, $zoneId) | |
{ | |
$hasShipping = ShippingRate::where('shipping_rate_id', $zoneId)->firstOrFail(); | |
if (! $hasShipping) { | |
return false; | |
} | |
$hasShipping->delete(); | |
return true; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Plan
We are planning to use
InputException
on the package side. So, the package can act as standalone.Problem
Once we use
InputException
from the package, the namespace will be based on the package. For example-Structure:
Avana**{PackageName}**\Exceptions\InputException
Implementation:
Avana\Shipping\Exceptions\InputException'
.Now when we check in the action of generateErrorResponse() in the
controller
whether the exception is the instance ofInputException
(here the namespace of isApp\Exceptions\InputException
) or not, it will always return false. In this way, we cannot implement.Solution.
Passing an extra parameter in generateErrorResponse() action in the
controller
where it'sfalse
by default.Inside the action, it has been checked by
if-else
like this way-Implementation
By default, using
generateErrorResponse()
will be fine. None of the implemented parts will be affected by that.However, when we need to implement it from the different namespace or from the package, need to pass extra params.
Changed code
Controller:
77 line: Added extra parameter called
$inputNamespace
.97 line: Rewrite the if statement
Added InputException.php in the package side.
ShippingZoneController.php:
Line 33 & 44: Added parameters like this way-
ShippingZoneRepository.php:
Line 152: The
InputException
has been used from the package side.