Skip to content

Commit

Permalink
Merge pull request #199 from Divyesh000/apireview
Browse files Browse the repository at this point in the history
create api controller for review
  • Loading branch information
creme332 authored May 22, 2024
2 parents e8ec61c + 2d7ec81 commit 1859e6a
Show file tree
Hide file tree
Showing 6 changed files with 416 additions and 139 deletions.
77 changes: 66 additions & 11 deletions src/controllers/API.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,12 @@ class API

public function __construct()
{
// Set the Content-Type header to application/json
header("Content-Type:application/json");

// Allow access from any origin (CORS)
header('Access-Control-Allow-Origin: *');

$this->resource = Utility::splitURL()[2] ?? "";
}

Expand All @@ -32,32 +36,83 @@ public function __construct()
*/
private function validateURLFormat(): bool
{
return preg_match("/^api\/v1/", $_GET["url"]) > 0;
return preg_match("/^api\/v1/", Utility::getURL()) > 0;
}


/**
* Returns the name of function responsible for handling the current request, as defined by the $routes variable.
* @param string $controllerName class name of controller
* @return string|null
*/
private function getHandler(string $controllerName): ?string
{
$all_routes = $controllerName::$routes;

// check if there are handlers defined for current request method
$my_routes = $all_routes[$_SERVER['REQUEST_METHOD']] ?? "";
if (empty($my_routes)) {
return null;
}

foreach ($my_routes as $route => $handler) {
$pattern = str_replace('/', '\/', $route); // Convert to regex pattern
$pattern = preg_replace(
'/\{([a-zA-Z0-9_]+)\}/',
'(?P<$1>[^\/]+)',
$pattern
); // Replace placeholders with regex capture groups
$pattern = '/^' . $pattern . '$/';

if (preg_match($pattern, '/' . Utility::getURL(), $matches)) {
return $handler;
}
}
return null;
}

public function index(): void
{
if (!$this->validateURLFormat()) {
http_response_code(400);
die();
return;
}

// call appropriate controller to handle resource
// check if there is a controller to handle resource
$controllerClassName = 'Steamy\\Controller\\API\\' . ucfirst($this->resource);
if (!class_exists($controllerClassName)) {
// no controller available
http_response_code(404);
echo 'Invalid resource: ' . $this->resource; // comment this line for production
return;
}

// determine which function to call in the controller to handle route
$functionName = $this->getHandler($controllerClassName);
if ($functionName === null) {
// Controller does not have any method defined for route
http_response_code(404);
echo "Request has not been defined in \$routes for " . $controllerClassName;
return;
}

$controller = new $controllerClassName();

if (!method_exists($controller, $functionName)) {
// handle function not found in controller
http_response_code(500);
echo $controllerClassName . ' does not have a public method ' . $functionName;
return;
}

// call function in controller for handling request
try {
if (class_exists($controllerClassName)) {
(new $controllerClassName())->index();
} else {
http_response_code(404);
die();
}
call_user_func(array($controller, $functionName));
} catch (Exception $e) {
http_response_code(500);

// Uncomment line below only when testing API
echo $e->getMessage();

die();
}
}
}
62 changes: 9 additions & 53 deletions src/controllers/api/Districts.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,17 @@ class Districts
{
use Model;

public static array $routes = [
'GET' => [
'/api/v1/districts' => 'getAllDistricts',
'/api/v1/districts/{id}' => 'getDistrictById',
]
];

/**
* Get the list of all districts available.
*/
private function getAllDistricts(): void
public function getAllDistricts(): void
{
// Retrieve all districts from the database
$allDistricts = District::getAll();
Expand All @@ -36,7 +43,7 @@ private function getAllDistricts(): void
/**
* Get the details of a specific district by its ID.
*/
private function getDistrictById(): void
public function getDistrictById(): void
{
$districtId = (int)Utility::splitURL()[3];

Expand All @@ -57,55 +64,4 @@ private function getDistrictById(): void
'name' => $district->getName()
]);
}

private function getHandler($routes): ?string
{
foreach ($routes[$_SERVER['REQUEST_METHOD']] as $route => $handler) {
$pattern = str_replace('/', '\/', $route); // Convert to regex pattern
$pattern = preg_replace(
'/\{([a-zA-Z0-9_]+)\}/',
'(?P<$1>[^\/]+)',
$pattern
); // Replace placeholders with regex capture groups
$pattern = '/^' . $pattern . '$/';

if (preg_match($pattern, '/' . Utility::getURL(), $matches)) {
return $handler;
}
}
return null;
}

/**
* Main entry point for the Districts API.
*/
public function index(): void
{
$routes = [
'GET' => [
'/api/v1/districts' => 'getAllDistricts',
'/api/v1/districts/{id}' => 'getDistrictById',
]
];

// Handle the request
$handler = $this->getHandler($routes);

if ($handler !== null) {
$functionName = $handler;
if (method_exists($this, $functionName)) {
call_user_func(array($this, $functionName));
} else {
// Handle function not found
http_response_code(404);
echo "Function Not Found";
die();
}
} else {
// Handle route not found
http_response_code(404);
echo "Route Not Found";
die();
}
}
}
98 changes: 37 additions & 61 deletions src/controllers/api/Products.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,28 @@ class Products
{
use Model;

public static array $routes = [
'GET' => [
'/api/v1/products' => 'getAllProducts',
'/api/v1/products/categories' => 'getProductCategories',
'/api/v1/products/{id}' => 'getProductById',
'/api/v1/products/{id}/reviews' => 'getAllReviewsForProduct',
],
'POST' => [
'/api/v1/products' => 'createProduct',
],
'PUT' => [
'/api/v1/products/{id}' => 'updateProduct',
],
'DELETE' => [
'/api/v1/products/{id}' => 'deleteProduct',
]
];

/**
* Get the list of all products available in the store.
*/
private function getAllProducts(): void
public function getAllProducts(): void
{
// Retrieve all products from the database
$allProducts = Product::getAll();
Expand All @@ -33,7 +51,7 @@ private function getAllProducts(): void
/**
* Get the details of a specific product by its ID.
*/
private function getProductById(): void
public function getProductById(): void
{
$productId = (int)Utility::splitURL()[3];

Expand All @@ -55,7 +73,7 @@ private function getProductById(): void
/**
* Get the list of product categories.
*/
private function getProductCategories(): void
public function getProductCategories(): void
{
// Retrieve all product categories from the database
$categories = Product::getCategories();
Expand All @@ -67,7 +85,7 @@ private function getProductCategories(): void
/**
* Create a new product entry in the database.
*/
private function createProduct(): void
public function createProduct(): void
{
// Retrieve POST data
$postData = $_POST;
Expand Down Expand Up @@ -126,7 +144,7 @@ private function createProduct(): void
/**
* Delete a product with the specified ID.
*/
private function deleteProduct(): void
public function deleteProduct(): void
{
$productId = (int)Utility::splitURL()[3];

Expand Down Expand Up @@ -155,7 +173,7 @@ private function deleteProduct(): void
/**
* Update the details of a product with the specified ID.
*/
private function updateProduct(): void
public function updateProduct(): void
{
$productId = (int)Utility::splitURL()[3];

Expand Down Expand Up @@ -195,64 +213,22 @@ private function updateProduct(): void
}
}

private function getHandler($routes): ?string
{
foreach ($routes[$_SERVER['REQUEST_METHOD']] as $route => $handler) {
$pattern = str_replace('/', '\/', $route); // Convert to regex pattern
$pattern = preg_replace(
'/\{([a-zA-Z0-9_]+)\}/',
'(?P<$1>[^\/]+)',
$pattern
); // Replace placeholders with regex capture groups
$pattern = '/^' . $pattern . '$/';

if (preg_match($pattern, '/' . Utility::getURL(), $matches)) {
return $handler;
}
}
return null;
}

/**
* Main entry point for the Products API.
* Get all reviews for a particular product by its ID.
*/
public function index(): void
public function getAllReviewsForProduct(): void
{
$routes = [
'GET' => [
'/api/v1/products' => 'getAllProducts',
'/api/v1/products/categories' => 'getProductCategories',
'/api/v1/products/{id}' => 'getProductById',
],
'POST' => [
'/api/v1/products' => 'createProduct',
],
'PUT' => [
'/api/v1/products/{id}' => 'updateProduct',
],
'DELETE' => [
'/api/v1/products/{id}' => 'deleteProduct',
]
];
// Get product ID from URL
$productId = (int)Utility::splitURL()[3];

// Handle the request
$handler = $this->getHandler($routes);

if ($handler !== null) {
$functionName = $handler;
if (method_exists($this, $functionName)) {
call_user_func(array($this, $functionName));
} else {
// Handle function not found
http_response_code(404);
echo "Function Not Found";
die();
}
} else {
// Handle route not found
http_response_code(404);
echo "Route Not Found";
die();
}
// Instantiate the Reviews controller
$reviewsController = new Reviews();

// Call the method to get all reviews for the specified product
// Since the Reviews controller method expects the ID to be in the URL, we'll set it directly
$_SERVER['REQUEST_URI'] = "/api/v1/products/$productId/reviews";

// Call the method from the Reviews controller
$reviewsController->getAllReviewsForProduct();
}
}
Loading

0 comments on commit 1859e6a

Please sign in to comment.