base_controller, parameter_bag, exitondump...

main
Robert 4 months ago
parent faf188c951
commit 3f0cec856e
  1. 1
      docs/CodeHydrater.md
  2. 2
      docs/TODO.md
  3. 40
      src/classes/base_controller.php
  4. 6
      src/classes/common.php
  5. 15
      src/classes/enums/exit_on_dump.php
  6. 154
      src/classes/http/request.php
  7. 16
      src/classes/http/response.php
  8. 27
      src/classes/parameter_bag.php

@ -96,6 +96,7 @@ src/
     ├── kernel.php
     ├── request.php
     ├── response.php
     ├── route_service_provider
     └── service_provider.php
   ├── interfaces
   ├── lazy_collection.php

@ -5,7 +5,7 @@
- [x] → Encrypted/Compressed Sessions
- [ ] → Ensure JS error reporting works
- [ ] → Force Database methods to try Cache First and Save Cache Data
- [ ] → Kernels (exists but not used yet)
- [x] → Kernels
- [x] → HTTP → Requests, Responce
- [x] → Middleware
- [x] → Macros

@ -0,0 +1,40 @@
<?php
declare(strict_types = 1);
/**
* @author Robert Strutts <Bob_586@Yahoo.com>
* @copyright (c) 2025, Robert Strutts
* @license MIT
*/
namespace CodeHydrater;
use \CodeHydrater\http\request as Request;
use \CodeHydrater\http\response as Response;
/**
* Description of base_controller
*
* To setup child controllers to use request/response, and view/html.
*
* @author Robert Strutts <Bob_586@Yahoo.com>
*/
abstract class base_controller {
protected $view;
protected $html;
public function __construct(
protected Request $request,
protected Response $response
) {
$this->view = new \CodeHydrater\view();
$this->html = new \CodeHydrater\html_document();
// If the child controller has an init() method, call it automatically
if (method_exists($this, 'init')) {
$this->init();
}
}
}

@ -10,6 +10,7 @@ declare(strict_types=1);
namespace CodeHydrater;
use CodeHydrater\strings\string_facade as F;
use CodeHydrater\enums\exit_on_dump as endDump;
final class common {
@ -214,7 +215,10 @@ final class common {
* @param var - any type will display type and value of contents
* @param bool end - if true ends the script
*/
public static function dump($var = 'nothing', $end = true): void {
public static function dump(
$var = 'nothing',
endDump $end = endDump::exit_and_stop
): void {
if (\CodeHydrater\bootstrap\configure::get('security', 'show_dumps') !== true) {
return;
}

@ -0,0 +1,15 @@
<?php
declare(strict_types = 1);
/**
* @author Robert Strutts <Bob_586@Yahoo.com>
* @copyright (c) 2025, Robert Strutts
* @license MIT
*/
namespace CodeHydrater\enums;
enum exit_on_dump: int {
case exit_and_stop = 0;
case keep_working = 1;
}

@ -9,32 +9,38 @@ declare(strict_types = 1);
*/
namespace CodeHydrater\http;
class request
{
protected array $query_params;
protected array $post_data;
protected array $server;
protected array $cookies;
protected array $files;
protected array $headers;
use CodeHydrater\parameter_bag;
class request {
use \CodeHydrater\traits\Macroable;
protected $query_params = [];
protected $post_data = [];
protected $server = [];
protected $cookies = [];
protected $files = [];
protected $headers = [];
public function __construct(
array $query_params = [],
array $post_data = [],
array $server = [],
array $cookies = [],
array $files = [],
array $headers = []
$query_params = [],
$post_data = [],
$server = [],
$cookies = [],
$files = [],
$headers = []
) {
$this->query_params = $query_params;
$this->post_data = $post_data;
$this->server = $server;
$this->cookies = $cookies;
$this->files = $files;
$this->headers = $headers;
$this->query_params = new parameter_bag($query_params);
$this->post_data = new parameter_bag($post_data);
$this->server = new parameter_bag($server);
$this->cookies = new parameter_bag($cookies);
$this->files = new parameter_bag($files);
$this->headers = new parameter_bag($headers);
}
public static function create_from_globals(): self {
if (\CodeHydrater\console_app::is_cli()) {
return new self();
}
return new self(
$_GET,
$_POST,
@ -46,22 +52,122 @@ class request
}
public function get_method(): string {
return strtoupper($this->server['REQUEST_METHOD'] ?? 'GET');
return strtoupper($this->server->get('REQUEST_METHOD') ?? 'GET');
}
public function get_uri(): string {
return $this->server['REQUEST_URI'] ?? '/';
return rtrim(preg_replace('/\?.*/', '', $this->server->get('REQUEST_URI')), '/') ?? '/';
}
public function get_query_params(): array {
public function get_query_params(): parameter_bag {
return $this->query_params;
}
public function get_post_data(): array {
public function get_post_data(): parameter_bag {
return $this->post_data;
}
public function get_server_data(): parameter_bag {
return $this->server;
}
public function get_cookie_data(): parameter_bag {
return $this->cookies;
}
public function get_files(): parameter_bag {
return $this->files;
}
public function get_headers(): parameter_bag {
return $this->headers;
}
public function get_header(string $name): ?string {
return $this->headers[$name] ?? null;
}
public function ajax(): bool {
return $this->is_xml_http_request();
}
/**
* Determine if the request is the result of an AJAX call.
* Checks for the 'X-Requested-With' header, which is commonly sent by JavaScript libraries.
*/
public function is_xml_http_request(): bool {
// The header name is standardized, but we normalize it for case-insensitive comparison.
$header = $this->headers->get('X-Requested-With');
// Check if the header exists and its value is 'XMLHttpRequest'
return 'XMLHttpRequest' == $header;
}
/**
* Get the client's real IP address or Null if not known.
* This method is aware of common proxy headers that might contain the original client IP.
*/
public function ip(): ?string {
// Define a list of headers that proxies might use to forward the original IP.
// The order is important: we trust the left-most IP in the right-most header.
$proxyHeaders = [
'X-Forwarded-For',
'X-Real-IP',
'Client-IP', // Less common, but used sometimes
];
// First, check the proxy headers. We iterate in reverse order of trustworthiness.
// The last header in the array is considered the most trustworthy (closest to the client).
foreach (array_reverse($proxyHeaders) as $header) {
if ($this->headers->has($header)) {
// Headers like 'X-Forwarded-For' can contain a comma-separated list of IPs.
// The client's original IP is usually the first one in the list.
$ips = explode(',', $this->headers->get($header));
// Get the first IP from the list and trim any whitespace.
$clientIp = trim($ips[0]);
// Basic validation to ensure it's a plausible IP address.
if (filter_var($clientIp, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
return $clientIp;
}
}
}
// If no valid proxy header is found, fall back to the direct connection IP.
// This will be the IP of the last proxy talking to our server (e.g., the load balancer).
$directIp = $this->server->get('REMOTE_ADDR');
// Perform the same basic validation on the direct IP.
return filter_var($directIp, FILTER_VALIDATE_IP) ? $directIp : null;
}
/**
* Determine if the current request is expecting a JSON response.
* Primarily checks the 'Accept' header for application/json.
* Also returns true for any AJAX request that doesn't explicitly reject JSON.
*/
public function wants_json(): bool {
// 1. Get the 'Accept' header from the request.
$acceptHeader = $this->headers->get('Accept');
// 2. Check if the header explicitly contains 'application/json'.
// The header can be a comma-separated list of types, e.g., "text/html, application/json"
if (false !== strpos($acceptHeader, 'application/json')) {
return true;
}
// 3. If there's no explicit 'Accept' header, or it's wildcard (*/*),
// we can make an assumption for AJAX requests that they likely want JSON.
// This is a common convention for API calls that don't set a specific Accept header.
if (empty($acceptHeader) || $acceptHeader === '*/*') {
return $this->is_xml_http_request();
}
// 4. If none of the above conditions are met, the client wants something else (like HTML).
return false;
}
public function user_agent(): ?string {
return $this->headers->get('User-Agent');
}
}

@ -11,19 +11,13 @@ namespace CodeHydrater\http;
class response
{
protected string $content;
protected int $status_code;
protected array $headers;
use \CodeHydrater\traits\Macroable;
public function __construct(
string $content = '',
int $status_code = 200,
array $headers = []
) {
$this->content = $content;
$this->status_code = $status_code;
$this->headers = $headers;
}
protected string $content = '',
protected int $status_code = 200,
protected array $headers = []
) { }
public function send(): void {
http_response_code($this->status_code);

@ -0,0 +1,27 @@
<?php
declare(strict_types = 1);
/**
* @author Robert Strutts <Bob_586@Yahoo.com>
* @copyright (c) 2025, Robert Strutts
* @license MIT
*/
namespace CodeHydrater;
/**
* Description of parameter_bag
* Used by: http/request
* @author Robert Strutts <Bob_586@Yahoo.com>
*/
class parameter_bag {
public function __construct(private array $parameters = []) { }
public function get($key, $default = null) {
return $this->parameters[$key] ?? $default;
}
public function has($key) {
return array_key_exists($key, $this->parameters);
}
}
Loading…
Cancel
Save