Skip to content

Instantly share code, notes, and snippets.

@kevindees
Last active November 29, 2017 02:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kevindees/0dfe80fd5dfe22be2432b918e6223590 to your computer and use it in GitHub Desktop.
Save kevindees/0dfe80fd5dfe22be2432b918e6223590 to your computer and use it in GitHub Desktop.
This is a code snippet of a framework I'm working on that I'm creating
<?php
/**
* Autoload PSR4 Classes
*
* @param array $map map auto loaders, initializer, and class map to avoid file exists checks
* @param string|null $cache_prefix cache the init files as one file.
*/
function autoload_psr4(array &$map = [], ?string $cache_prefix = null) {
if(isset($map['init']) && empty($cache_prefix) ) {
foreach ($map['init'] as $file) {
require $file;
}
} elseif( isset($map['init']) && !empty($cache_prefix) ) {
autoload_files_compress($map['init'], $cache_prefix, 1000);
}
spl_autoload_register(function ($class) use (&$map) {
if (isset($map['map'][$class])) {
require $map['map'][$class];
return;
}
$prefix = $map['prefix'];
$folder = $map['folder'];
$len = strlen($prefix);
if (strncmp($prefix, $class, $len) !== 0) { return; }
$file = $folder . str_replace('\\', DIRECTORY_SEPARATOR, substr($class, $len)) . '.php';
if ( is_file($file) ) {
require $file;
return;
}
});
}
/**
* Cache File
*
* @param array $files
* @param string $prefix
* @param int $length
*/
function autoload_files_compress( array $files, $prefix = 'app', $length = 20 ) {
$time = time();
$path = path_files('cache/' . $prefix . '.cache.php' );
if(is_file($path) ) {
$file_time = filemtime($path);
$length = $length * 60 + $file_time;
if( $time < $length) {
require $path;
return;
}
}
$cache = fopen($path, "w");
fwrite($cache, '<?php');
foreach ($files as $file) {
$data = file_get_contents($file);
$data = substr_replace( $data, '', strpos($data, '<?php'), 5 );
$data = preg_replace('/(namespace\W*.*(?<!\;))\;/', '${1} {', $data, 1);
fwrite($cache, $data . PHP_EOL . '}'. PHP_EOL);
}
fclose($cache);
}
/**
* Get Constant Variable
*
* @param string $name the constant variable name
* @param null|mixed $default The default value
*
* @return mixed
*/
function immutable($name, $default = null) {
return defined($name) ? constant($name) : $default;
}
/**
* Die and Dump
*
* Dump the variables and exit.
*
* @param array $params
*/
function dd( ...$params ) {
call_user_func_array('var_dump', $params);
exit();
}
/**
* Get Current Runtime
*
* @param bool $milliseconds get the run time in milliseconds
*
* @return mixed
*/
function get_runtime($milliseconds = false ) {
$run = microtime(true) - $_SERVER['REQUEST_TIME_FLOAT'];
if( $milliseconds ) { return $run * 1000; }
return $run;
}
/**
* Resolve Class
*
* @param string $class
*
* @return object
* @throws \Exception
*/
function resolve_class( string $class)
{
$reflector = new \ReflectionClass($class);
if ( ! $reflector->isInstantiable()) { throw new \Exception($class . ' is not instantiable'); }
if ( ! $constructor = $reflector->getConstructor()) { return new $class; }
// Get Dependencies
$dependencies = [];
$parameters = $constructor->getParameters();
// Auto Fill Parameters
foreach ($parameters as $parameter) {
if ( ! $dependency = $parameter->getClass()) {
if ($parameter->isDefaultValueAvailable()) {
$dependencies[] = $parameter->getDefaultValue();
} else {
throw new \Exception('Cannot resolve no default for ' . $parameter->name . ' in ' . $class);
}
} else {
$dependencies[] = resolve_class($dependency->name);
}
}
return $reflector->newInstanceArgs($dependencies);
}
/**
* Resolve Call
*
* @param mixed $call the function or object map to resolve
* @param array $map the values to map parameters
* @param bool $stub create stub of class if found
*
* @return mixed
*/
function resolve_method_args($call, $map = [], $stub = true)
{
if(is_array($call)) {
$ref = new \ReflectionMethod($call[0], $call[1]);
} else {
$ref = new \ReflectionFunction($call);
}
$params = $ref->getParameters();
$args = [];
foreach ($params as $param) {
$default = null;
$class = $param->getClass() ?? null;
if( $class ) { $class = resolve_class($class->getName()); }
if($param->isDefaultValueAvailable()) { $default = $param->getDefaultValue(); }
$param_name = $param->getName();
$loaded_obj = isset($map[$param_name]) && is_object($map[$param_name]) ? $map[$param_name] : null;
$args[] = $loaded_obj ?? $class ?? $map[$param_name] ?? $default ?? null;
}
$method_map = ['args' => $args, 'method' => $ref, 'caller' => $call];
if( $stub && $ref instanceof \ReflectionMethod ) {
if ( ! is_object($call[0]) ) {
$method_map['caller'][] = resolve_class($call[0]);
} else {
$method_map['caller'][] = $call[0];
}
}
return $method_map;
}
/**
* Resolve Method Map
*
* @param $method_map
*
* @return mixed
*/
function resolve_method_map($method_map) {
if( $method_map['method'] instanceof \ReflectionMethod ) {
return $method_map['method']->invokeArgs( $method_map['caller'][2], $method_map['args'] );
} else {
return call_user_func_array($method_map['caller'], $method_map['args']);
}
}
function gen_args( string $gen ) {
if( strpos($gen, ',') !== false ) {
$args = [];
$segments = explode(',', $gen);
foreach ($segments as $segment) {
[$name, $value] = array_map('trim', explode(':', $segment, 2) );
$args[$name] = $value;
}
return $args;
}
return null;
}
/**
* Emit HTTP Body
*
* @param mixed $value emit HTTP body from value
*/
function echo_as_http_body($value) {
if( is_array($value) ) {
echo json_encode($value);
} elseif( is_object($value) && method_exists($value, 'echoAsHttpBody') ) {
$value->echoAsHttpBody();
} elseif (is_string($value) ) {
echo $value;
}
}
/**
* Explode Path
*
* Explode a path accounting for Windows or Unix.
*
* @param string $path The input string such as a path
* @param int $limit negative starts with last positive start with first
*
* @return array
*/
function explode_path( string $path, $limit = PHP_INT_MAX ) {
return explode(DIRECTORY_SEPARATOR, trim($path, DIRECTORY_SEPARATOR), $limit);
}
/**
* Explode URL
*
* @param string $path
* @param int $limit
*
* @return array
*/
function explode_url_path( string $path, $limit = PHP_INT_MAX ) {
return explode('/', trim($path, '/'), $limit);
}
/**
* Dots Filter
*
* Traverse array with dot notation and filter the array.
*
* @param string $dots dot notation key.next.final or key.*.final
* @param array $array an array to traverse
* @param callable $callback a callback to filter matches
* @param bool $through only apply filter to last key in dots
*
* @return array|mixed
*/
function dots_filter(string $dots, array $array, callable $callback, $through = true) : array {
$set = &$array;
$traverse = explode('.', $dots);
foreach($traverse as $step) {
array_shift($traverse);
if( $step === '*' && is_array($set) && !isset($indexes) ) {
$multi = &$set;
$indexes = array_keys($multi);
foreach($indexes as $index) {
if( is_array($multi[$index]) && !empty($traverse) ) {
$multi[$index] = dots_filter(implode('.', $traverse), $multi[$index], $callback, $through);
} elseif( empty($traverse) || $through === false ) {
$multi[$index] = call_user_func($callback, $multi[$index]);
}
}
} elseif( isset($set[$step]) && ! is_string($set) ) {
$set = &$set[$step];
}
}
if(!isset($indexes)) {
$set = call_user_func($callback, $set);
}
return $array;
}
/**
* Dots Walk
*
* Traverse array with dot notation.
*
* @param string $dots dot notation key.next.final or key.*.final
* @param array $array an array to traverse
* @param null $default
*
* @return array|mixed|null
*/
function dots_walk(string $dots, array $array, $default = null) {
$traverse = explode('.', $dots);
foreach ($traverse as $step) {
if( ! isset($array[$step]) && ! is_string($array) ) { return $default; }
$array = $array[$step];
}
return $array;
}
/**
* Dots Meld
*
* Flatten array dimensions to one level and meld keys into dot
* notation. liken meld to ['key.child' => 'value'].
*
* @param array $array the values to meld
*
* @return array
*/
function dots_meld(array $array) : array
{
$iterator = new \RecursiveIteratorIterator(new \RecursiveArrayIterator($array));
$result = [];
foreach ($iterator as $value) {
$keys = [];
$depth = range(0, $iterator->getDepth());
foreach ($depth as $step) {
$keys[] = $iterator->getSubIterator($step)->key();
}
$result[ implode('.', $keys) ] = $value;
}
return $result;
}
/**
* Dots Meld Process Regular Expression Filter
*
* Using a regular expression filter the matched array values
* matched using a callback.
*
* @param string $pattern the regular expression pattern
* @param array $array the original array
* @param callable $callback a callback to filter matches
* @param bool $expand return a multidimensional array by default
*
* @return array
*/
function dots_meld_preg_filter($pattern, array $array, callable $callback, $expand = true) : array {
$melded = dots_meld($array);
foreach ($melded as $dots => $value) {
if(preg_match($pattern, $dots)) {
$melded[$dots] = call_user_func($callback, $value);
}
}
return $expand ? dots_meld_expand($melded) : $melded;
}
/**
* Dots Set
*
* Set an array value using dot notation.
*
* @param string $dots dot notation path to set
* @param array $array the original array
* @param mixed $value the value to set
*
* @return array
*/
function dots_set(string $dots, array $array, $value) : array
{
$set = &$array;
$traverse = explode('.', $dots);
foreach($traverse as $step) {
$set = &$set[$step];
}
$set = $value;
return $array;
}
/**
* Dots Meld Expand
*
* Expand a dots melded array into a multi dimensional array.
*
* @param array $array dots melded array to expand
*
* @return array
*/
function dots_meld_expand( array $array ) : array {
$expand = [];
foreach ($array as $dots => $value ) {
$traverse = explode('.', $dots);
$set = &$expand;
foreach ($traverse as $key) {
$set = &$set[$key];
}
$set = $value;
}
return $expand;
}
/**
* Array Keys Exist
*
* @param array $search needle list of array keys to match
* @param array $array haystack array
*
* @return bool
*/
function array_keys_exist(array $search, array $array) {
return count(array_intersect_key(array_flip($search), $array)) === count($search);
}
// Special Array Functions
function in_array_key($needle, $haystack, $key, $in = true) {
return isset($haystack[$key]) && ( in_array($needle, $haystack[$key] ) === $in);
}
function array_any_key( array $needle, $haystack, $flip = null) {
return array_intersect_key($haystack, $flip ? array_flip($needle) : $needle );
}
/**
* String Ends
*
* @param $haystack
* @param $needle
*
* @return bool
*/
function str_ends($haystack, $needle)
{
$length = mb_strlen($needle);
if ($length == 0) {
return true;
}
return ( mb_substr($haystack, -$length ) === $needle );
}
/**
* String Contains
*
* @param $haystack
* @param $needle
*
* @return bool
*/
function str_contains($haystack, $needle)
{
return ( mb_strpos( $haystack, $needle ) !== false );
}
/**
* String Starts
*
* @param $haystack
* @param $needle
*
* @return bool
*/
function str_starts($haystack, $needle)
{
return mb_substr($haystack, 0, mb_strlen($needle) ) === $needle;
}
/**
* String Starts
*
* @param $haystack
* @param $needle
*
* @return bool
*/
function str_starts_ascii($haystack, $needle)
{
return substr($haystack, 0, strlen($needle) ) === $needle;
}
/**
* String Ends
*
* @param $haystack
* @param $needle
*
* @return bool
*/
function str_ends_ascii($haystack, $needle )
{
$length = strlen($needle);
if ($length == 0) { return true; }
return ( substr($haystack, -$length ) === $needle );
}
/**
* String Contains
*
* @param $haystack
* @param $needle
*
* @return bool
*/
function str_contains_ascii($haystack, $needle)
{
return ( strpos( $haystack, $needle ) !== false );
}
// Browser Helpers
function browser_log($message) {
echo '<script>console.log("PHP Logs |> '.$message.'")</script>';
}
function browser_alert($message) {
echo '<script>alert("PHP Alerts |> '.$message.'")</script>';
}
@kevindees
Copy link
Author

kevindees commented Sep 3, 2017

Example of using blazing fast PSR autoloader:

$map = [
    'prefix' => 'App\\',
    'folder' => __DIR__ . '/src/',
    'init' => [
        'Core\\Kernel' => __DIR__ . '/src/Core/Kernel.php',
        'Core\\Config' => __DIR__ . '/src/Core/Config.php',
        'Http\\Request' => __DIR__ . '/src/Http/Request.php',
    ],
    'map' => [
        'Http\\Router' => __DIR__ . '/src/Http/Router.php',
    ]
];
autoload_psr4($map);

Example of using some dots functions:

dots_walk('one.two.three', ['one' => ['two' => ['three' => 'success' ]]]);
// result 'success'

$array = [
      'one' => 'capitalize',
      'two' => 'capitalize'
];
dots_filter('*', $array, 'ucfirst');
// result [ 'one' => 'Capitalize', 'two' => 'Capitalize' ]

$array = [
    'one' => ['child' => 10],
    'two' => ['child' => 12]
];
$reg = '/^one\.child$/';
$callback = function($int) { return $int * 2; };
$melded = dots_meld_preg_filter( $reg, $array, $callback );
// result $melded['one']['child'] === 20

$melded = dots_meld_preg_filter( $reg, $array, $callback, false );
// result $melded['one.child'] === 20

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment