alt_val_test

main
Robert 2 months ago
parent c396101ccc
commit d734efaffe
  1. 6
      src/bootstrap/errors.php
  2. 6
      src/bootstrap/main.php
  3. 122
      src/bootstrap/safer_io.php
  4. 4
      src/classes/assets.php
  5. 1
      src/classes/base_controller.php
  6. 12
      src/classes/common.php
  7. 35
      src/classes/enums/form_input_types.php
  8. 210
      src/classes/form_builder/html_form.php
  9. 160
      src/classes/form_builder/html_helper.php

@ -150,7 +150,7 @@ set_error_handler(function($errno, $errstr, $errfile, $errline) {
if (!(error_reporting() & $errno)) { if (!(error_reporting() & $errno)) {
return false; return false;
} }
if (method_exists("errors", "get_handle_shutdown_errors") && ! errors::get_handle_shutdown_errors()) { if (method_exists(errors::class, "get_handle_shutdown_errors") && ! errors::get_handle_shutdown_errors()) {
return false; return false;
} }
@ -193,7 +193,7 @@ set_error_handler(function($errno, $errstr, $errfile, $errline) {
// Handle exceptions // Handle exceptions
set_exception_handler(function($e) { set_exception_handler(function($e) {
if (method_exists("errors", "get_handle_exceptions") && ! errors::get_handle_exceptions()) { if (method_exists(errors::class, "get_handle_exceptions") && ! errors::get_handle_exceptions()) {
return false; return false;
} }
$logMessage = " [EXCEPTION] " . $e->getMessage() . " in " . $e->getFile() . " on line " . $e->getLine() . PHP_EOL; $logMessage = " [EXCEPTION] " . $e->getMessage() . " in " . $e->getFile() . " on line " . $e->getLine() . PHP_EOL;
@ -216,7 +216,7 @@ set_exception_handler(function($e) {
// Handle fatal errors // Handle fatal errors
register_shutdown_function(function() { register_shutdown_function(function() {
if (method_exists("errors", "get_handle_global_errors") && ! errors::get_handle_global_errors()) { if (method_exists(errors::class, "get_handle_global_errors") && ! errors::get_handle_global_errors()) {
return false; return false;
} }
$error = error_get_last(); $error = error_get_last();

@ -12,8 +12,6 @@ namespace CodeHydrater\bootstrap;
define("Memory_Baseline", memory_get_usage()); define("Memory_Baseline", memory_get_usage());
site_helper::load_file(CodeHydrater_FRAMEWORK . 'bootstrap/errors.php');
final class views { final class views {
public static function ob_start(): void { public static function ob_start(): void {
if (extension_loaded('mbstring')) { if (extension_loaded('mbstring')) {
@ -60,6 +58,8 @@ final class errors {
} }
} }
site_helper::load_file(CodeHydrater_FRAMEWORK . 'bootstrap/errors.php');
final class configure { final class configure {
private static $config = []; private static $config = [];
@ -276,8 +276,10 @@ load_all::init(CodeHydrater_PROJECT);
if (! defined('ENVIRONMENT')) { if (! defined('ENVIRONMENT')) {
if (is_live() === false) { if (is_live() === false) {
define('ENVIRONMENT', 'development'); define('ENVIRONMENT', 'development');
error_reporting(E_ALL); // Show Deprecated erorrs when DEVing...
} else { } else {
define('ENVIRONMENT', 'production'); define('ENVIRONMENT', 'production');
error_reporting(E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED);
} }
} }

@ -5,7 +5,7 @@ declare(strict_types=1);
/** /**
* @author Robert Strutts * @author Robert Strutts
* @copyright Copyright (c) 2022, Robert Strutts. * @copyright Copyright (c) 2022, Robert Strutts.
* @license https://mit-license.org/ * @license MIT
*/ */
/* Sanitize Input, Validate data and Escape output. /* Sanitize Input, Validate data and Escape output.
@ -34,20 +34,23 @@ use \CodeHydrater\enums\FIELD_FILTER; // Defined in enum\safer_io_enums
use \CodeHydrater\enums\DB_FILTER; use \CodeHydrater\enums\DB_FILTER;
use \CodeHydrater\enums\HTML_FLAG; use \CodeHydrater\enums\HTML_FLAG;
use \CodeHydrater\enums\INPUTS; use \CodeHydrater\enums\INPUTS;
use \CodeHydrater\enums\form_input_types as FORM_INPUT_TYPES;
/** /**
* use_io defines public members to be used on safer_io INPUTS * use_io defines public members to be used on safer_io INPUTS
*/ */
final class use_io { final class use_io {
public $input_var; public $input_var;
public $input_type; public string $field_description;
public $field_filter; public FORM_INPUT_TYPES $form_type;
public $escape_html; public INPUTS $input_type;
public bool $error_on_null = false; public FIELD_FILTER $field_filter;
public $validation_rule; public HTML_FLAG $escape_html;
public $validation_message; public bool $error_on_null = false; // Should be false, as Required Validation Rule will force errors any ways...
public $skip_the_db; public string $validation_rule;
public $use_db_filter; public array $validation_message;
public bool $skip_the_db;
public DB_FILTER $use_db_filter;
} }
/** /**
@ -95,8 +98,13 @@ final class safer_io {
} }
// Get raw data for inputs, to be used by filters /**
* Get raw data for inputs, to be used by filters
* @todo remove this
*/
#[Deprecated("use useio input_var instead")]
public static function set_data_from(array|object $ao): void { public static function set_data_from(array|object $ao): void {
\CodeHydrater\common::deprecated_error("Please use useio input_var instead of set_data_from");
if (is_object($ao)) { if (is_object($ao)) {
$a = get_object_vars($ao); $a = get_object_vars($ao);
if ($a === false) { if ($a === false) {
@ -110,8 +118,14 @@ final class safer_io {
} }
} }
// Allow anything to set_data_inputs is desired here /**
* Get raw data for inputs, to be used by filters
* @todo remove this
*/
#[Deprecated("use useio input_var instead")]
public static function set_data_input(string $var_name, mixed $data_in): void { public static function set_data_input(string $var_name, mixed $data_in): void {
\CodeHydrater\common::deprecated_error("Please use useio input_var instead of: set_data_input");
if (! isset(self::$DATA_INPUTS[$var_name])) { if (! isset(self::$DATA_INPUTS[$var_name])) {
self::$DATA_INPUTS[$var_name] = $data_in; self::$DATA_INPUTS[$var_name] = $data_in;
} }
@ -453,7 +467,7 @@ final class safer_io {
} }
private static function sanitize_helper( private static function sanitize_helper(
string $from, string $for_what,
string $input_field_name, string $input_field_name,
use_io $a, use_io $a,
FIELD_FILTER $default_filter = FIELD_FILTER::raw_string, FIELD_FILTER $default_filter = FIELD_FILTER::raw_string,
@ -466,6 +480,20 @@ final class safer_io {
$rules = []; $rules = [];
$messages = []; $messages = [];
if (isset($a->field_description)) {
$meta['field_desc'][$input_field_name] = $a->field_description;
}
if (isset($a->validation_rule)) {
if (str_contains($a->validation_rule, "required")) {
$meta['required'][$input_field_name] = true;
}
}
if (isset($a->form_type)) {
$meta['form_type'][$input_field_name] = $a->form_type ?? FORM_INPUT_TYPES::text->value;
}
if (isset($a->field_filter) && $a->field_filter instanceof \UnitEnum) { if (isset($a->field_filter) && $a->field_filter instanceof \UnitEnum) {
$field_type = $a->field_filter; $field_type = $a->field_filter;
} else { } else {
@ -498,7 +526,6 @@ final class safer_io {
} }
$meta[$input_field_name]['validation_rules_set'] = (count($rules)) ? true : false; $meta[$input_field_name]['validation_rules_set'] = (count($rules)) ? true : false;
$db = (isset($a->skip_the_db)) ? $a->skip_the_db : false; $db = (isset($a->skip_the_db)) ? $a->skip_the_db : false;
$meta[$input_field_name]['type'] = $field_type->name; $meta[$input_field_name]['type'] = $field_type->name;
$meta[$input_field_name]['skip_db'] = $db; $meta[$input_field_name]['skip_db'] = $db;
@ -539,7 +566,7 @@ final class safer_io {
} }
} }
if ($from === "html") { if ($for_what === "html") {
$safer_html = self::get_safer_html($safer_data, $a); $safer_html = self::get_safer_html($safer_data, $a);
if ($safer_html !== false) { if ($safer_html !== false) {
$safer_html_data = $safer_html; $safer_html_data = $safer_html;
@ -558,7 +585,7 @@ final class safer_io {
if ($field_type == FIELD_FILTER::floating_point) { if ($field_type == FIELD_FILTER::floating_point) {
$safer_data = floatval($safer_data); $safer_data = floatval($safer_data);
} }
if ($from === "db") { if ($for_what === "db") {
if ($field_type == FIELD_FILTER::integer_number || $field_type == FIELD_FILTER::floating_point) { if ($field_type == FIELD_FILTER::integer_number || $field_type == FIELD_FILTER::floating_point) {
$safer_db_data = $safer_data; $safer_db_data = $safer_data;
} else { } else {
@ -575,13 +602,13 @@ final class safer_io {
} }
$ret['name'] = $input_field_name; $ret['name'] = $input_field_name;
$ret['meta'] = $meta; $ret['meta'] = $meta;
if ($from === "db") { if ($for_what === "db") {
$ret['db'] = $safer_db_data; $ret['db'] = $safer_db_data;
$data[$input_field_name] = $safer_db_data; $data[$input_field_name] = $safer_db_data;
} elseif ($from === "logic") { } elseif ($for_what === "logic") {
$ret['logic'] = $safer_data; $ret['logic'] = $safer_data;
$data[$input_field_name] = $safer_data; $data[$input_field_name] = $safer_data;
} elseif ($from === "html") { } elseif ($for_what === "html") {
$ret['html'] = $safer_html_data; $ret['html'] = $safer_html_data;
$data[$input_field_name] = $safer_html_data; $data[$input_field_name] = $safer_html_data;
} }
@ -601,69 +628,28 @@ final class safer_io {
return str_replace(chr(0), '', $input); return str_replace(chr(0), '', $input);
} }
public static function db_sanitize( public static function esv(
array $inputs,
FIELD_FILTER $default_filter = FIELD_FILTER::raw_string,
bool $trim = true,
) : \Generator {
foreach ($inputs as $input_field_name => $a) {
if (! $a instanceof use_io) {
continue;
}
$yield = static::sanitize_helper(
"db",
$input_field_name,
$a,
$default_filter,
$trim
);
yield $yield;
}
}
public static function logic_sanitize(
array $inputs,
FIELD_FILTER $default_filter = FIELD_FILTER::raw_string,
bool $trim = true,
) : \Generator {
foreach ($inputs as $input_field_name => $a) {
if (! $a instanceof use_io) {
continue;
}
$yield = static::sanitize_helper(
"logic",
$input_field_name,
$a,
$default_filter,
$trim
);
yield $yield;
}
}
/**
* Sanitize the inputs based on the rules an optionally trim the string
* @param FIELD_FILTER $default_filter FILTER_SANITIZE_STRING
* @param bool $trim
* @return Generator
*/
public static function html_escape_and_sanitize(
array $inputs, array $inputs,
string $for_what = "html",
FIELD_FILTER $default_filter = FIELD_FILTER::raw_string, FIELD_FILTER $default_filter = FIELD_FILTER::raw_string,
bool $trim = true, bool $trim = true,
) : \Generator { ) : \Generator {
$what = match($for_what) {
"db" => "db",
"logic" => "logic",
default => "html",
};
foreach ($inputs as $input_field_name => $a) { foreach ($inputs as $input_field_name => $a) {
if (! $a instanceof use_io) { if (! $a instanceof use_io) {
continue; continue;
} }
$yield = static::sanitize_helper( yield static::sanitize_helper(
"html", $what,
$input_field_name, $input_field_name,
$a, $a,
$default_filter, $default_filter,
$trim $trim
); );
yield $yield;
} }
} }

@ -172,7 +172,7 @@ final class assets {
* @param type $file - external JS file. * @param type $file - external JS file.
* @retval string of script src=file * @retval string of script src=file
*/ */
public static function wrap_js(string $file, string $scope = 'project', array $a = array(), $type = "module"): string { public static function wrap_js(string $file, string $scope = 'project', array $a = array()): string {
$more = ''; $more = '';
if (count($a)) { if (count($a)) {
foreach ($a as $k => $v) { foreach ($a as $k => $v) {
@ -185,7 +185,7 @@ final class assets {
if ($ver === false || $wrap_file === false) { if ($ver === false || $wrap_file === false) {
return "<!-- Script: {$file} not Found -->"; return "<!-- Script: {$file} not Found -->";
} }
return "<script src=\"{$wrap_file}{$ver}\" type=\"{$type}\"{$more}></script>\r\n"; return "<script src=\"{$wrap_file}{$ver}\"{$more}></script>\r\n";
//return "<script type=\"text/javascript\">js_loader(\"{$file}\");</script>"; //return "<script type=\"text/javascript\">js_loader(\"{$file}\");</script>";
} }

@ -20,6 +20,7 @@ use \CodeHydrater\http\response as Response;
* @author Robert Strutts <Bob_586@Yahoo.com> * @author Robert Strutts <Bob_586@Yahoo.com>
*/ */
class base_controller { class base_controller {
public string $page_output = ''; // To keep views working...without Dynamic Variable Error!
public static $params; // To keep Routes working... public static $params; // To keep Routes working...
public $view; public $view;
public $html; public $html;

@ -89,6 +89,18 @@ final class common {
} }
return $subject; return $subject;
} }
public static function deprecated_error(string $msg): void {
if (\CodeHydrater\bootstrap\configure::get('security', 'show_dumps') !== true) {
return; // Avoid Live Deprecated Errors
}
if (\PHP_VERSION_ID < 80400) {
trigger_error($msg);
echo "<pre>";
print_r(debug_backtrace()[1]);
echo "</pre>";
}
}
// Begin Strings Functions here:: // Begin Strings Functions here::
public static function string_position(string $string, string $needle, int $offset = 0, $encoding = null) { public static function string_position(string $string, string $needle, int $offset = 0, $encoding = null) {

@ -0,0 +1,35 @@
<?php
declare(strict_types = 1);
/**
* @author Robert Strutts <Bob_586@Yahoo.com>
* @copyright (c) 2025, Robert Strutts
* @license MIT
*/
namespace CodeHydrater\enums;
enum form_input_types: string {
case none = "none"; // Don't Display control
case checkbox ="checkbox";
case color = "color";
case date = "date";
case datetime = "datetime-local";
case email = "email";
case file = "file";
case hidden = "hidden";
case image = "image";
case month = "month";
case number = "number";
case password = "password";
case radio = "radio";
case range = "range";
case reset = "rest";
case search = "search";
case submit = "submit";
case tel = "tel";
case text = "text";
case time = "time";
case url = "url";
case week = "week";
}

@ -0,0 +1,210 @@
<?php
declare(strict_types = 1);
/**
* @author Robert Strutts <Bob_586@Yahoo.com>
* @copyright (c) 2020 Elusive, Modifications by (c) 2025 Robert Strutts
* @link https://github.com/elusivecodes/FyreFormBuilder/blob/main/LICENSE
* @license MIT
*/
namespace CodeHydrater\form_builder;
use \CodeHydrater\form_builder\html_helper as Helper;
use CodeHydrater\enums\form_input_types as FORM_TYPE;
class html_form {
private $output = "";
private bool $escape = true;
public function __construct(protected Helper $html = new Helper()) {}
public function get_output(): ?string {
return $this->output;
}
public function set_escape(bool $escape = true) {
$this->escape = $escape;
}
private function append_out(?string $out, int $tabs = 2): ?string {
$this->output .= str_repeat("\t", $tabs) . $out . PHP_EOL;
return $out;
}
public function __call(string $type, array $arguments): string {
// Get all valid values
$validTypes = array_column(FORM_TYPE::cases(), 'value');
if (!in_array($type, $validTypes, true)) {
throw new \InvalidArgumentException(
"Invalid input type: '$type'. Must be one of: " .
implode(', ', $validTypes)
);
}
if ($type === "none") {
return "";
}
$name = array_shift($arguments);
$options = array_shift($arguments) ?? [];
$options['type'] = $type;
return $this->input($name, $options);
}
private function do_escape(string $content, array & $options): ?string {
$escape = $options['escape'] ?? $this->escape;
if ($escape) {
return $this->html->escape($content);
}
return $content;
}
public function button(string $content = '', array $options = []): string
{
$options['type'] ??= 'button';
return $this->append_out('<button'.$this->html->attributes($options).'>'.$this->do_escape($content, $options).'</button>');
}
public function close(): string
{
return $this->append_out('</form>', 0);
}
public function fieldset_close(): string
{
return $this->append_out('</fieldset>');
}
public function fieldset_open(array $options = []): string
{
return $this->append_out('<fieldset'.$this->html->attributes($options).'>');
}
public function input(string|null $name = null, array $options = []): string
{
if ($name !== null) {
$options['name'] ??= $name;
}
$options['type'] ??= 'text';
return $this->append_out('<input'.$this->html->attributes($options).' />');
}
public function open_div(array $options = []): string
{
return $this->append_out('<div'.$this->html->attributes($options).'>');
}
public function close_div(): string
{
return $this->append_out('</div>');
}
public function label(string $content = '', array $options = []): string
{
return $this->append_out('<label'.$this->html->attributes($options).'>'.$this->do_escape($content, $options).'</label>');
}
public function legend(string $content = '', array $options = []): string
{
return $this->append_out('<legend'.$this->html->attributes($options).'>'.$this->do_escape($content, $options).'</legend>');
}
public function open(string|null $action = null, array $options = []): string
{
if ($action !== null) {
$options['action'] ??= $action;
}
$options['method'] ??= 'post';
$options['accept-charset'] ??= $this->html->get_charset();
return $this->append_out('<form'.$this->html->attributes($options).'>', 0);
}
public function open_multipart(string|null $action = null, array $options = []): string
{
$options['enctype'] = 'multipart/form-data';
return $this->append_out($this->open($action, $options));
}
public function select(string|null $name = null, array $options = []): string
{
if ($name !== null) {
$options['name'] ??= $name;
}
$select_options = $options['options'] ?? [];
unset($options['options']);
$selected = $options['value'] ?? [];
unset($options['value']);
if (!is_array($selected)) {
$selected = [$selected];
}
$html = '<select'.$this->html->attributes($options).'>';
$html .= $this->build_options($select_options, $selected);
$html .= '</select>';
return $this->append_out($html);
}
public function select_multi(string|null $name = null, array $options = []): string
{
$options[] = 'multiple';
return $this->append_out($this->select($name, $options));
}
public function textarea(string|null $name = null, array $options = []): string
{
if ($name !== null) {
$options['name'] ??= $name;
}
$value = $options['value'] ?? '';
unset($options['value']);
return $this->append_out('<textarea'.$this->html->attributes($options).'>'.$this->html->escape($value).'</textarea>');
}
protected function build_options(array $options, array $selected): string
{
$html = '';
foreach ($options as $value => $option) {
if (!is_array($option)) {
$option = [
'label' => $option,
];
}
if (array_key_exists('children', $option)) {
$children = $option['children'];
unset($option['children']);
$html .= '<optgroup'.$this->html->attributes($option).'>';
$html .= $this->build_options($children, $selected);
$html .= '</optgroup>';
} else {
$option['value'] ??= $value;
$label = $option['label'] ?? $option['value'];
unset($option['label']);
if (in_array($option['value'], $selected)) {
$option[] = 'selected';
}
$html .= '<option'.$this->html->attributes($option).'>'.$this->html->escape($label).'</option>';
}
}
return $html;
}
}

@ -0,0 +1,160 @@
<?php
declare(strict_types = 1);
/**
* @author Robert Strutts <Bob_586@Yahoo.com>
* @copyright (c) 2020 Elusive, Modifications by (c) 2025 Robert Strutts
* @link https://github.com/elusivecodes/FyreFormBuilder/blob/main/LICENSE
* @license MIT
*/
namespace CodeHydrater\form_builder;
class html_helper {
protected const ATTRIBUTES_ORDER = [
'action',
'class',
'id',
'placeholder',
'required',
'disabled',
'readonly',
'maxlength',
'minlength',
'min',
'max',
'step',
'pattern',
'autocomplete',
'size',
'name',
'data-',
'src',
'for',
'type',
'href',
'action',
'method',
'value',
'title',
'alt',
'target',
'role',
'aria-',
'accept-charset',
'charset',
'style',
];
protected string $charset = 'UTF-8';
/**
* Generate an attribute string.
*
* @param array $options The attributes.
* @return string The attribute string.
*/
public function attributes(array $options = []): string {
unset($options['escape']);
$attributes = [];
foreach ($options as $key => $value) {
if ($value === null) {
continue;
}
if (is_numeric($key)) {
$key = $value;
$value = null;
}
$key = preg_replace('/[^\w\-:.@]/', '', $key);
$key = strtolower($key);
if (!$key) {
continue;
}
if (is_bool($value)) {
$value = $value ? null : 'false';
} else if (is_array($value) || is_object($value)) {
$value = json_encode($value);
$value = $this->escape($value);
} else if ($value !== null) {
$value = $this->escape((string) $value);
}
$attributes[$key] = $value;
}
if ($attributes === []) {
return '';
}
uksort(
$attributes,
static fn(string $a, string $b): int => static::attribute_index($a) <=> static::attribute_index($b)
);
$html = '';
foreach ($attributes as $key => $value) {
if (str_contains($key, "data-") || str_contains($key, "aria-")) {
// Okay, it's valid...
} else {
if (!in_array($key, static::ATTRIBUTES_ORDER)) {
continue; // Not in the list, skip it
}
}
if ($value !== null) {
$html .= ' '.$key.'="'.$value.'"';
} else {
$html .= ' '.$key;
}
}
return $html;
}
/**
* Escape characters in a string for use in HTML.
*
* @param string $string The input string.
* @return string The escaped string.
*/
public function escape(string $string): string {
return htmlspecialchars($string, \ENT_QUOTES | \ENT_SUBSTITUTE | \ENT_HTML5, $this->charset);
}
public function get_charset(): string {
return $this->charset;
}
public function set_charset(string $charset): static {
$this->charset = $charset;
return $this;
}
/**
* Get the index for an attribute.
*
* @param string $attribute The attribute name.
* @return int The attribute index.
*/
protected static function attribute_index(string $attribute): int {
if (preg_match('/^(data|aria)-/', $attribute)) {
$attribute = substr($attribute, 0, 5);
}
$index = array_search($attribute, static::ATTRIBUTES_ORDER);
if ($index === false) {
return count(static::ATTRIBUTES_ORDER);
}
return $index;
}
}
Loading…
Cancel
Save