First Local Commit - After Clean up.

Signed-off-by: Rick Hays <rhays@haysgang.com>
This commit is contained in:
2019-12-02 14:54:38 -06:00
commit 10412ab7f6
486 changed files with 123242 additions and 0 deletions

View File

@@ -0,0 +1,124 @@
<?php
/**
* CodeIgniter
*
* An open source application development framework for PHP
*
* This content is released under the MIT License (MIT)
*
* Copyright (c) 2014-2019 British Columbia Institute of Technology
* Copyright (c) 2019 CodeIgniter Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @package CodeIgniter
* @author CodeIgniter Dev Team
* @copyright 2019 CodeIgniter Foundation
* @license https://opensource.org/licenses/MIT MIT License
* @link https://codeigniter.com
* @since Version 4.0.0
* @filesource
*/
/**
* CodeIgniter Array Helpers
*
* @package CodeIgniter
*/
if (! function_exists('dot_array_search'))
{
/**
* Searches an array through dot syntax. Supports
* wildcard searches, like foo.*.bar
*
* @param string $index
* @param array $array
*
* @return mixed|null
*/
function dot_array_search(string $index, array $array)
{
$segments = explode('.', rtrim(rtrim($index, '* '), '.'));
return _array_search_dot($segments, $array);
}
}
if (! function_exists('_array_search_dot'))
{
/**
* Used by dot_array_search to recursively search the
* array with wildcards.
*
* @param array $indexes
* @param array $array
*
* @return mixed|null
*/
function _array_search_dot(array $indexes, array $array)
{
// Grab the current index
$currentIndex = $indexes
? array_shift($indexes)
: null;
if (empty($currentIndex) || (! isset($array[$currentIndex]) && $currentIndex !== '*'))
{
return null;
}
// Handle Wildcard (*)
if ($currentIndex === '*')
{
// If $array has more than 1 item, we have to loop over each.
if (is_array($array))
{
foreach ($array as $key => $value)
{
$answer = _array_search_dot($indexes, $value);
if ($answer !== null)
{
return $answer;
}
}
// Still here after searching all child nodes?
return null;
}
}
// If this is the last index, make sure to return it now,
// and not try to recurse through things.
if (empty($indexes))
{
return $array[$currentIndex];
}
// Do we need to recursively search this value?
if (is_array($array[$currentIndex]) && $array[$currentIndex])
{
return _array_search_dot($indexes, $array[$currentIndex]);
}
// Otherwise we've found our match!
return $array[$currentIndex];
}
}

View File

@@ -0,0 +1,124 @@
<?php
/**
* CodeIgniter
*
* An open source application development framework for PHP
*
* This content is released under the MIT License (MIT)
*
* Copyright (c) 2014-2019 British Columbia Institute of Technology
* Copyright (c) 2019 CodeIgniter Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @package CodeIgniter
* @author CodeIgniter Dev Team
* @copyright 2019 CodeIgniter Foundation
* @license https://opensource.org/licenses/MIT MIT License
* @link https://codeigniter.com
* @since Version 4.0.0
* @filesource
*/
// --------------------------------------------------------------------
/**
* CodeIgniter Cookie Helpers
*
* @package CodeIgniter
*/
if (! function_exists('set_cookie'))
{
/**
* Set cookie
*
* Accepts seven parameters, or you can submit an associative
* array in the first parameter containing all the values.
*
* @param string|array $name Cookie name or array containing binds
* @param string $value The value of the cookie
* @param string $expire The number of seconds until expiration
* @param string $domain For site-wide cookie.
* Usually: .yourdomain.com
* @param string $path The cookie path
* @param string $prefix The cookie prefix
* @param boolean $secure True makes the cookie secure
* @param boolean $httpOnly True makes the cookie accessible via
* http(s) only (no javascript)
*
* @see (\Config\Services::response())->setCookie()
* @see \CodeIgniter\HTTP\Response::setCookie()
*/
function set_cookie($name, string $value = '', string $expire = '', string $domain = '', string $path = '/', string $prefix = '', bool $secure = false, bool $httpOnly = false)
{
// The following line shows as a syntax error in NetBeans IDE
//(\Config\Services::response())->setcookie
$response = \Config\Services::response();
$response->setcookie($name, $value, $expire, $domain, $path, $prefix, $secure, $httpOnly);
}
}
//--------------------------------------------------------------------
if (! function_exists('get_cookie'))
{
/**
* Fetch an item from the COOKIE array
*
* @param string $index
* @param boolean $xssClean
*
* @see (\Config\Services::request())->getCookie()
* @see \CodeIgniter\HTTP\IncomingRequest::getCookie()
* @return mixed
*/
function get_cookie($index, bool $xssClean = false)
{
$app = config(\Config\App::class);
$appCookiePrefix = $app->cookiePrefix;
$prefix = isset($_COOKIE[$index]) ? '' : $appCookiePrefix;
$request = \Config\Services::request();
$filter = true === $xssClean ? FILTER_SANITIZE_STRING : null;
$cookie = $request->getCookie($prefix . $index, $filter);
return $cookie;
}
}
//--------------------------------------------------------------------
if (! function_exists('delete_cookie'))
{
/**
* Delete a COOKIE
*
* @param mixed $name
* @param string $domain the cookie domain. Usually: .yourdomain.com
* @param string $path the cookie path
* @param string $prefix the cookie prefix
* @see (\Config\Services::response())->setCookie()
* @see \CodeIgniter\HTTP\Response::setcookie()
* @return void
*/
function delete_cookie($name, string $domain = '', string $path = '/', string $prefix = '')
{
\Config\Services::response()->deleteCookie($name, $domain, $path, $prefix);
}
}

View File

@@ -0,0 +1,103 @@
<?php
/**
* CodeIgniter
*
* An open source application development framework for PHP
*
* This content is released under the MIT License (MIT)
*
* Copyright (c) 2014-2019 British Columbia Institute of Technology
* Copyright (c) 2019 CodeIgniter Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @package CodeIgniter
* @author CodeIgniter Dev Team
* @copyright 2019 CodeIgniter Foundation
* @license https://opensource.org/licenses/MIT MIT License
* @link https://codeigniter.com
* @since Version 4.0.0
* @filesource
*/
/**
* CodeIgniter Date Helpers
*
* @package CodeIgniter
*/
if (! function_exists('now'))
{
/**
* Get "now" time
*
* Returns time() based on the timezone parameter or on the
* app_timezone() setting
*
* @param string $timezone
*
* @return integer
* @throws \Exception
*/
function now(string $timezone = null): int
{
$timezone = empty($timezone) ? app_timezone() : $timezone;
if ($timezone === 'local' || $timezone === date_default_timezone_get())
{
return time();
}
$datetime = new DateTime('now', new DateTimeZone($timezone));
sscanf($datetime->format('j-n-Y G:i:s'), '%d-%d-%d %d:%d:%d', $day, $month, $year, $hour, $minute, $second);
return mktime($hour, $minute, $second, $month, $day, $year);
}
}
if (! function_exists('timezone_select'))
{
/**
* Generates a select field of all available timezones
*
* Returns a string with the formatted HTML
*
* @param string $class Optional class to apply to the select field
* @param string $default Default value for initial selection
* @param integer $what One of the DateTimeZone class constants (for listIdentifiers)
* @param string $country A two-letter ISO 3166-1 compatible country code (for listIdentifiers)
*
* @return string
* @throws \Exception
*/
function timezone_select(string $class = '', string $default = '', int $what = \DateTimeZone::ALL, string $country = null): string
{
$timezones = \DateTimeZone::listIdentifiers($what, $country);
$buffer = "<select name='timezone' class='{$class}'>" . PHP_EOL;
foreach ($timezones as $timezone)
{
$selected = ($timezone === $default) ? 'selected' : '';
$buffer .= "<option value='{$timezone}' {$selected}>{$timezone}</option>" . PHP_EOL;
}
$buffer .= '</select>' . PHP_EOL;
return $buffer;
}
}

View File

@@ -0,0 +1,494 @@
<?php
/**
* CodeIgniter
*
* An open source application development framework for PHP
*
* This content is released under the MIT License (MIT)
*
* Copyright (c) 2014-2019 British Columbia Institute of Technology
* Copyright (c) 2019 CodeIgniter Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @package CodeIgniter
* @author CodeIgniter Dev Team
* @copyright 2008-2014 EllisLab, Inc. (https://ellislab.com/)
* @copyright 2019 CodeIgniter Foundation
* @license https://opensource.org/licenses/MIT MIT License
* @link https://codeigniter.com
* @since Version 1.0.0
* @filesource
*/
/**
* CodeIgniter File System Helpers
*
* @package CodeIgniter
*/
// ------------------------------------------------------------------------
if (! function_exists('directory_map'))
{
/**
* Create a Directory Map
*
* Reads the specified directory and builds an array
* representation of it. Sub-folders contained with the
* directory will be mapped as well.
*
* @param string $source_dir Path to source
* @param integer $directory_depth Depth of directories to traverse
* (0 = fully recursive, 1 = current dir, etc)
* @param boolean $hidden Whether to show hidden files
*
* @return array
*/
function directory_map(string $source_dir, int $directory_depth = 0, bool $hidden = false): array
{
try
{
$fp = opendir($source_dir);
$fileData = [];
$new_depth = $directory_depth - 1;
$source_dir = rtrim($source_dir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
while (false !== ($file = readdir($fp)))
{
// Remove '.', '..', and hidden files [optional]
if ($file === '.' || $file === '..' || ($hidden === false && $file[0] === '.'))
{
continue;
}
is_dir($source_dir . $file) && $file .= DIRECTORY_SEPARATOR;
if (($directory_depth < 1 || $new_depth > 0) && is_dir($source_dir . $file))
{
$fileData[$file] = directory_map($source_dir . $file, $new_depth, $hidden);
}
else
{
$fileData[] = $file;
}
}
closedir($fp);
return $fileData;
}
catch (\Exception $fe)
{
return [];
}
}
}
// ------------------------------------------------------------------------
if (! function_exists('write_file'))
{
/**
* Write File
*
* Writes data to the file specified in the path.
* Creates a new file if non-existent.
*
* @param string $path File path
* @param string $data Data to write
* @param string $mode fopen() mode (default: 'wb')
*
* @return boolean
*/
function write_file(string $path, string $data, string $mode = 'wb'): bool
{
try
{
$fp = fopen($path, $mode);
flock($fp, LOCK_EX);
for ($result = $written = 0, $length = strlen($data); $written < $length; $written += $result)
{
if (($result = fwrite($fp, substr($data, $written))) === false)
{
break;
}
}
flock($fp, LOCK_UN);
fclose($fp);
return is_int($result);
}
catch (\Exception $fe)
{
return false;
}
}
}
// ------------------------------------------------------------------------
if (! function_exists('delete_files'))
{
/**
* Delete Files
*
* Deletes all files contained in the supplied directory path.
* Files must be writable or owned by the system in order to be deleted.
* If the second parameter is set to true, any directories contained
* within the supplied base directory will be nuked as well.
*
* @param string $path File path
* @param boolean $del_dir Whether to delete any directories found in the path
* @param boolean $htdocs Whether to skip deleting .htaccess and index page files
* @param integer $_level Current directory depth level (default: 0; internal use only)
*
* @return boolean
*/
function delete_files(string $path, bool $del_dir = false, bool $htdocs = false, int $_level = 0): bool
{
// Trim the trailing slash
$path = rtrim($path, '/\\');
try
{
$current_dir = opendir($path);
while (false !== ($filename = @readdir($current_dir)))
{
if ($filename !== '.' && $filename !== '..')
{
if (is_dir($path . DIRECTORY_SEPARATOR . $filename) && $filename[0] !== '.')
{
delete_files($path . DIRECTORY_SEPARATOR . $filename, $del_dir, $htdocs, $_level + 1);
}
elseif ($htdocs !== true || ! preg_match('/^(\.htaccess|index\.(html|htm|php)|web\.config)$/i', $filename))
{
@unlink($path . DIRECTORY_SEPARATOR . $filename);
}
}
}
closedir($current_dir);
return ($del_dir === true && $_level > 0) ? @rmdir($path) : true;
}
catch (\Exception $fe)
{
return false;
}
}
}
// ------------------------------------------------------------------------
if (! function_exists('get_filenames'))
{
/**
* Get Filenames
*
* Reads the specified directory and builds an array containing the filenames.
* Any sub-folders contained within the specified path are read as well.
*
* @param string $source_dir Path to source
* @param boolean $include_path Whether to include the path as part of the filename
* @param boolean $recursion Internal variable to determine recursion status - do not use in calls
*
* @return array
*/
function get_filenames(string $source_dir, bool $include_path = false, bool $recursion = false): array
{
static $fileData = [];
try
{
$fp = opendir($source_dir);
// reset the array and make sure $source_dir has a trailing slash on the initial call
if ($recursion === false)
{
$fileData = [];
$source_dir = rtrim(realpath($source_dir), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
}
while (false !== ($file = readdir($fp)))
{
if (is_dir($source_dir . $file) && $file[0] !== '.')
{
get_filenames($source_dir . $file . DIRECTORY_SEPARATOR, $include_path, true);
}
elseif ($file[0] !== '.')
{
$fileData[] = ($include_path === true) ? $source_dir . $file : $file;
}
}
closedir($fp);
return $fileData;
}
catch (\Exception $fe)
{
return [];
}
}
}
// --------------------------------------------------------------------
if (! function_exists('get_dir_file_info'))
{
/**
* Get Directory File Information
*
* Reads the specified directory and builds an array containing the filenames,
* filesize, dates, and permissions
*
* Any sub-folders contained within the specified path are read as well.
*
* @param string $source_dir Path to source
* @param boolean $top_level_only Look only at the top level directory specified?
* @param boolean $recursion Internal variable to determine recursion status - do not use in calls
*
* @return array
*/
function get_dir_file_info(string $source_dir, bool $top_level_only = true, bool $recursion = false): array
{
static $fileData = [];
$relative_path = $source_dir;
try
{
$fp = @opendir($source_dir); {
// reset the array and make sure $source_dir has a trailing slash on the initial call
if ($recursion === false)
{
$fileData = [];
$source_dir = rtrim(realpath($source_dir), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
}
// Used to be foreach (scandir($source_dir, 1) as $file), but scandir() is simply not as fast
while (false !== ($file = readdir($fp)))
{
if (is_dir($source_dir . $file) && $file[0] !== '.' && $top_level_only === false)
{
get_dir_file_info($source_dir . $file . DIRECTORY_SEPARATOR, $top_level_only, true);
}
elseif ($file[0] !== '.')
{
$fileData[$file] = get_file_info($source_dir . $file);
$fileData[$file]['relative_path'] = $relative_path;
}
}
closedir($fp);
return $fileData;
}
}
catch (\Exception $fe)
{
return [];
}
}
}
// --------------------------------------------------------------------
if (! function_exists('get_file_info'))
{
/**
* Get File Info
*
* Given a file and path, returns the name, path, size, date modified
* Second parameter allows you to explicitly declare what information you want returned
* Options are: name, server_path, size, date, readable, writable, executable, fileperms
* Returns false if the file cannot be found.
*
* @param string $file Path to file
* @param mixed $returned_values Array or comma separated string of information returned
*
* @return array|null
*/
function get_file_info(string $file, $returned_values = ['name', 'server_path', 'size', 'date'])
{
if (! is_file($file))
{
return null;
}
if (is_string($returned_values))
{
$returned_values = explode(',', $returned_values);
}
foreach ($returned_values as $key)
{
switch ($key) {
case 'name':
$fileInfo['name'] = basename($file);
break;
case 'server_path':
$fileInfo['server_path'] = $file;
break;
case 'size':
$fileInfo['size'] = filesize($file);
break;
case 'date':
$fileInfo['date'] = filemtime($file);
break;
case 'readable':
$fileInfo['readable'] = is_readable($file);
break;
case 'writable':
$fileInfo['writable'] = is_really_writable($file);
break;
case 'executable':
$fileInfo['executable'] = is_executable($file);
break;
case 'fileperms':
$fileInfo['fileperms'] = fileperms($file);
break;
}
}
return $fileInfo;
}
}
// --------------------------------------------------------------------
if (! function_exists('symbolic_permissions'))
{
/**
* Symbolic Permissions
*
* Takes a numeric value representing a file's permissions and returns
* standard symbolic notation representing that value
*
* @param integer $perms Permissions
* @return string
*/
function symbolic_permissions(int $perms): string
{
if (($perms & 0xC000) === 0xC000)
{
$symbolic = 's'; // Socket
}
elseif (($perms & 0xA000) === 0xA000)
{
$symbolic = 'l'; // Symbolic Link
}
elseif (($perms & 0x8000) === 0x8000)
{
$symbolic = '-'; // Regular
}
elseif (($perms & 0x6000) === 0x6000)
{
$symbolic = 'b'; // Block special
}
elseif (($perms & 0x4000) === 0x4000)
{
$symbolic = 'd'; // Directory
}
elseif (($perms & 0x2000) === 0x2000)
{
$symbolic = 'c'; // Character special
}
elseif (($perms & 0x1000) === 0x1000)
{
$symbolic = 'p'; // FIFO pipe
}
else
{
$symbolic = 'u'; // Unknown
}
// Owner
$symbolic .= (($perms & 0x0100) ? 'r' : '-')
. (($perms & 0x0080) ? 'w' : '-')
. (($perms & 0x0040) ? (($perms & 0x0800) ? 's' : 'x' ) : (($perms & 0x0800) ? 'S' : '-'));
// Group
$symbolic .= (($perms & 0x0020) ? 'r' : '-')
. (($perms & 0x0010) ? 'w' : '-')
. (($perms & 0x0008) ? (($perms & 0x0400) ? 's' : 'x' ) : (($perms & 0x0400) ? 'S' : '-'));
// World
$symbolic .= (($perms & 0x0004) ? 'r' : '-')
. (($perms & 0x0002) ? 'w' : '-')
. (($perms & 0x0001) ? (($perms & 0x0200) ? 't' : 'x' ) : (($perms & 0x0200) ? 'T' : '-'));
return $symbolic;
}
}
// --------------------------------------------------------------------
if (! function_exists('octal_permissions'))
{
/**
* Octal Permissions
*
* Takes a numeric value representing a file's permissions and returns
* a three character string representing the file's octal permissions
*
* @param integer $perms Permissions
* @return string
*/
function octal_permissions(int $perms): string
{
return substr(sprintf('%o', $perms), -3);
}
}
// ------------------------------------------------------------------------
if (! function_exists('set_realpath'))
{
/**
* Set Realpath
*
* @param string $path
* @param boolean $check_existence Checks to see if the path exists
*
* @return string
*/
function set_realpath(string $path, bool $check_existence = false): string
{
// Security check to make sure the path is NOT a URL. No remote file inclusion!
if (preg_match('#^(http:\/\/|https:\/\/|www\.|ftp)#i', $path) || filter_var($path, FILTER_VALIDATE_IP) === $path)
{
throw new InvalidArgumentException('The path you submitted must be a local server path, not a URL');
}
// Resolve the path
if (realpath($path) !== false)
{
$path = realpath($path);
}
elseif ($check_existence && ! is_dir($path) && ! is_file($path))
{
throw new InvalidArgumentException('Not a valid path: ' . $path);
}
// Add a trailing slash, if this is a directory
return is_dir($path) ? rtrim($path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR : $path;
}
}

View File

@@ -0,0 +1,965 @@
<?php
/**
* CodeIgniter
*
* An open source application development framework for PHP
*
* This content is released under the MIT License (MIT)
*
* Copyright (c) 2014-2019 British Columbia Institute of Technology
* Copyright (c) 2019 CodeIgniter Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @package CodeIgniter
* @author CodeIgniter Dev Team
* @copyright 2019 CodeIgniter Foundation
* @license https://opensource.org/licenses/MIT MIT License
* @link https://codeigniter.com
* @since Version 4.0.0
* @filesource
*/
use Config\Services;
/**
* CodeIgniter Form Helpers
*
* @package CodeIgniter
*/
//--------------------------------------------------------------------
if (! function_exists('form_open'))
{
/**
* Form Declaration
*
* Creates the opening portion of the form.
*
* @param string $action the URI segments of the form destination
* @param array|string $attributes a key/value pair of attributes, or string representation
* @param array $hidden a key/value pair hidden data
*
* @return string
*/
function form_open(string $action = '', $attributes = [], array $hidden = []): string
{
// If no action is provided then set to the current url
if (! $action)
{
$action = current_url(true);
} // If an action is not a full URL then turn it into one
elseif (strpos($action, '://') === false)
{
$action = site_url($action);
}
if (is_array($attributes) && array_key_exists('csrf_id', $attributes))
{
$csrfId = $attributes['csrf_id'];
unset($attributes['csrf_id']);
}
$attributes = stringify_attributes($attributes);
if (stripos($attributes, 'method=') === false)
{
$attributes .= ' method="post"';
}
if (stripos($attributes, 'accept-charset=') === false)
{
$config = config(\Config\App::class);
$attributes .= ' accept-charset="' . strtolower($config->charset) . '"';
}
$form = '<form action="' . $action . '"' . $attributes . ">\n";
// Add CSRF field if enabled, but leave it out for GET requests and requests to external websites
$before = Services::filters()
->getFilters()['before'];
if ((in_array('csrf', $before) || array_key_exists('csrf', $before)) && strpos($action, base_url()) !== false && ! stripos($form, 'method="get"'))
{
$form .= csrf_field($csrfId ?? null);
}
if (is_array($hidden))
{
foreach ($hidden as $name => $value)
{
$form .= form_hidden($name, $value);
}
}
return $form;
}
}
//--------------------------------------------------------------------
if (! function_exists('form_open_multipart'))
{
/**
* Form Declaration - Multipart type
*
* Creates the opening portion of the form, but with "multipart/form-data".
*
* @param string $action The URI segments of the form destination
* @param array|string $attributes A key/value pair of attributes, or the same as a string
* @param array $hidden A key/value pair hidden data
*
* @return string
*/
function form_open_multipart(string $action = '', $attributes = [], array $hidden = []): string
{
if (is_string($attributes))
{
$attributes .= ' enctype="' . esc('multipart/form-data', 'attr') . '"';
}
else
{
$attributes['enctype'] = 'multipart/form-data';
}
return form_open($action, $attributes, $hidden);
}
}
//--------------------------------------------------------------------
if (! function_exists('form_hidden'))
{
/**
* Hidden Input Field
*
* Generates hidden fields. You can pass a simple key/value string or
* an associative array with multiple values.
*
* @param string|array $name Field name or associative array to create multiple fields
* @param string|array $value Field value
* @param boolean $recursing
*
* @return string
*/
function form_hidden($name, $value = '', bool $recursing = false): string
{
static $form;
if ($recursing === false)
{
$form = "\n";
}
if (is_array($name))
{
foreach ($name as $key => $val)
{
form_hidden($key, $val, true);
}
return $form;
}
if (! is_array($value))
{
$form .= '<input type="hidden" name="' . $name . '" value="' . esc($value, 'html') . "\" style=\"display:none;\" />\n";
}
else
{
foreach ($value as $k => $v)
{
$k = is_int($k) ? '' : $k;
form_hidden($name . '[' . $k . ']', $v, true);
}
}
return $form;
}
}
//--------------------------------------------------------------------
if (! function_exists('form_input'))
{
/**
* Text Input Field. If 'type' is passed in the $type field, it will be
* used as the input type, for making 'email', 'phone', etc input fields.
*
* @param mixed $data
* @param string $value
* @param mixed $extra
* @param string $type
*
* @return string
*/
function form_input($data = '', string $value = '', $extra = '', string $type = 'text'): string
{
$defaults = [
'type' => $type,
'name' => is_array($data) ? '' : $data,
'value' => $value,
];
return '<input ' . parse_form_attributes($data, $defaults) . stringify_attributes($extra) . " />\n";
}
}
//--------------------------------------------------------------------
if (! function_exists('form_password'))
{
/**
* Password Field
*
* Identical to the input function but adds the "password" type
*
* @param mixed $data
* @param string $value
* @param mixed $extra
*
* @return string
*/
function form_password($data = '', string $value = '', $extra = ''): string
{
is_array($data) || $data = ['name' => $data];
$data['type'] = 'password';
return form_input($data, $value, $extra);
}
}
//--------------------------------------------------------------------
if (! function_exists('form_upload'))
{
/**
* Upload Field
*
* Identical to the input function but adds the "file" type
*
* @param mixed $data
* @param string $value
* @param mixed $extra
*
* @return string
*/
function form_upload($data = '', string $value = '', $extra = ''): string
{
$defaults = [
'type' => 'file',
'name' => '',
];
is_array($data) || $data = ['name' => $data];
$data['type'] = 'file';
return '<input ' . parse_form_attributes($data, $defaults) . stringify_attributes($extra) . " />\n";
}
}
//--------------------------------------------------------------------
if (! function_exists('form_textarea'))
{
/**
* Textarea field
*
* @param mixed $data
* @param string $value
* @param mixed $extra
*
* @return string
*/
function form_textarea($data = '', string $value = '', $extra = ''): string
{
$defaults = [
'name' => is_array($data) ? '' : $data,
'cols' => '40',
'rows' => '10',
];
if (! is_array($data) || ! isset($data['value']))
{
$val = $value;
}
else
{
$val = $data['value'];
unset($data['value']); // textareas don't use the value attribute
}
return '<textarea ' . parse_form_attributes($data, $defaults) . stringify_attributes($extra) . '>'
. htmlspecialchars($val)
. "</textarea>\n";
}
}
//--------------------------------------------------------------------
if (! function_exists('form_multiselect'))
{
/**
* Multi-select menu
*
* @param string $name
* @param array $options
* @param array $selected
* @param mixed $extra
*
* @return string
*/
function form_multiselect(string $name = '', array $options = [], array $selected = [], $extra = ''): string
{
$extra = stringify_attributes($extra);
if (stripos($extra, 'multiple') === false)
{
$extra .= ' multiple="multiple"';
}
return form_dropdown($name, $options, $selected, $extra);
}
}
//--------------------------------------------------------------------
if (! function_exists('form_dropdown'))
{
/**
* Drop-down Menu
*
* @param mixed $data
* @param mixed $options
* @param mixed $selected
* @param mixed $extra
*
* @return string
*/
function form_dropdown($data = '', $options = [], $selected = [], $extra = ''): string
{
$defaults = [];
if (is_array($data))
{
if (isset($data['selected']))
{
$selected = $data['selected'];
unset($data['selected']); // select tags don't have a selected attribute
}
if (isset($data['options']))
{
$options = $data['options'];
unset($data['options']); // select tags don't use an options attribute
}
}
else
{
$defaults = ['name' => $data];
}
is_array($selected) || $selected = [$selected];
is_array($options) || $options = [$options];
// If no selected state was submitted we will attempt to set it automatically
if (empty($selected))
{
if (is_array($data))
{
if (isset($data['name'], $_POST[$data['name']]))
{
$selected = [$_POST[$data['name']]];
}
}
elseif (isset($_POST[$data]))
{
$selected = [$_POST[$data]];
}
}
$extra = stringify_attributes($extra);
$multiple = (count($selected) > 1 && stripos($extra, 'multiple') === false) ? ' multiple="multiple"' : '';
$form = '<select ' . rtrim(parse_form_attributes($data, $defaults)) . $extra . $multiple . ">\n";
foreach ($options as $key => $val)
{
$key = (string) $key;
if (is_array($val))
{
if (empty($val))
{
continue;
}
$form .= '<optgroup label="' . $key . "\">\n";
foreach ($val as $optgroup_key => $optgroup_val)
{
$sel = in_array($optgroup_key, $selected) ? ' selected="selected"' : '';
$form .= '<option value="' . htmlspecialchars($optgroup_key) . '"' . $sel . '>'
. (string) $optgroup_val . "</option>\n";
}
$form .= "</optgroup>\n";
}
else
{
$form .= '<option value="' . htmlspecialchars($key) . '"'
. (in_array($key, $selected) ? ' selected="selected"' : '') . '>'
. (string) $val . "</option>\n";
}
}
return $form . "</select>\n";
}
}
//--------------------------------------------------------------------
if (! function_exists('form_checkbox'))
{
/**
* Checkbox Field
*
* @param mixed $data
* @param string $value
* @param boolean $checked
* @param mixed $extra
*
* @return string
*/
function form_checkbox($data = '', string $value = '', bool $checked = false, $extra = ''): string
{
$defaults = [
'type' => 'checkbox',
'name' => ( ! is_array($data) ? $data : ''),
'value' => $value,
];
if (is_array($data) && array_key_exists('checked', $data))
{
$checked = $data['checked'];
if ($checked === false)
{
unset($data['checked']);
}
else
{
$data['checked'] = 'checked';
}
}
if ($checked === true)
{
$defaults['checked'] = 'checked';
}
else
{
unset($defaults['checked']);
}
return '<input ' . parse_form_attributes($data, $defaults) . stringify_attributes($extra) . " />\n";
}
}
//--------------------------------------------------------------------
if (! function_exists('form_radio'))
{
/**
* Radio Button
*
* @param mixed $data
* @param string $value
* @param boolean $checked
* @param mixed $extra
*
* @return string
*/
function form_radio($data = '', string $value = '', bool $checked = false, $extra = ''): string
{
is_array($data) || $data = ['name' => $data];
$data['type'] = 'radio';
return form_checkbox($data, $value, $checked, $extra);
}
}
//--------------------------------------------------------------------
if (! function_exists('form_submit'))
{
/**
* Submit Button
*
* @param mixed $data
* @param string $value
* @param mixed $extra
*
* @return string
*/
function form_submit($data = '', string $value = '', $extra = ''): string
{
$defaults = [
'type' => 'submit',
'name' => is_array($data) ? '' : $data,
'value' => $value,
];
return '<input ' . parse_form_attributes($data, $defaults) . stringify_attributes($extra) . " />\n";
}
}
//--------------------------------------------------------------------
if (! function_exists('form_reset'))
{
/**
* Reset Button
*
* @param mixed $data
* @param string $value
* @param mixed $extra
*
* @return string
*/
function form_reset($data = '', string $value = '', $extra = ''): string
{
$defaults = [
'type' => 'reset',
'name' => is_array($data) ? '' : $data,
'value' => $value,
];
return '<input ' . parse_form_attributes($data, $defaults) . stringify_attributes($extra) . " />\n";
}
}
//--------------------------------------------------------------------
if (! function_exists('form_button'))
{
/**
* Form Button
*
* @param mixed $data
* @param string $content
* @param mixed $extra
*
* @return string
*/
function form_button($data = '', string $content = '', $extra = ''): string
{
$defaults = [
'name' => is_array($data) ? '' : $data,
'type' => 'button',
];
if (is_array($data) && isset($data['content']))
{
$content = $data['content'];
unset($data['content']); // content is not an attribute
}
return '<button ' . parse_form_attributes($data, $defaults) . stringify_attributes($extra) . '>'
. $content
. "</button>\n";
}
}
//--------------------------------------------------------------------
if (! function_exists('form_label'))
{
/**
* Form Label Tag
*
* @param string $label_text The text to appear onscreen
* @param string $id The id the label applies to
* @param array $attributes Additional attributes
*
* @return string
*/
function form_label(string $label_text = '', string $id = '', array $attributes = []): string
{
$label = '<label';
if ($id !== '')
{
$label .= ' for="' . $id . '"';
}
if (is_array($attributes) && $attributes)
{
foreach ($attributes as $key => $val)
{
$label .= ' ' . $key . '="' . $val . '"';
}
}
return $label . '>' . $label_text . '</label>';
}
}
//--------------------------------------------------------------------
if (! function_exists('form_datalist'))
{
/**
* Datalist
*
* The <datalist> element specifies a list of pre-defined options for an <input> element.
* Users will see a drop-down list of pre-defined options as they input data.
* The list attribute of the <input> element, must refer to the id attribute of the <datalist> element.
*
* @param string $name
* @param string $value
* @param array $options
*
* @return string
*/
function form_datalist(string $name, string $value, array $options): string
{
$data = [
'type' => 'text',
'name' => $name,
'list' => $name . '_list',
'value' => $value,
];
$out = form_input($data) . "\n";
$out .= "<datalist id='" . $name . '_list' . "'>";
foreach ($options as $option)
{
$out .= "<option value='$option'>" . "\n";
}
$out .= '</datalist>' . "\n";
return $out;
}
}
//--------------------------------------------------------------------
if (! function_exists('form_fieldset'))
{
/**
* Fieldset Tag
*
* Used to produce <fieldset><legend>text</legend>. To close fieldset
* use form_fieldset_close()
*
* @param string $legend_text The legend text
* @param array $attributes Additional attributes
*
* @return string
*/
function form_fieldset(string $legend_text = '', array $attributes = []): string
{
$fieldset = '<fieldset' . stringify_attributes($attributes) . ">\n";
if ($legend_text !== '')
{
return $fieldset . '<legend>' . $legend_text . "</legend>\n";
}
return $fieldset;
}
}
//--------------------------------------------------------------------
if (! function_exists('form_fieldset_close'))
{
/**
* Fieldset Close Tag
*
* @param string $extra
*
* @return string
*/
function form_fieldset_close(string $extra = ''): string
{
return '</fieldset>' . $extra;
}
}
//--------------------------------------------------------------------
if (! function_exists('form_close'))
{
/**
* Form Close Tag
*
* @param string $extra
*
* @return string
*/
function form_close(string $extra = ''): string
{
return '</form>' . $extra;
}
}
//--------------------------------------------------------------------
if (! function_exists('set_value'))
{
/**
* Form Value
*
* Grabs a value from the POST array for the specified field so you can
* re-populate an input field or textarea
*
* @param string $field Field name
* @param string $default Default value
* @param boolean $html_escape Whether to escape HTML special characters or not
*
* @return string
*/
function set_value(string $field, string $default = '', bool $html_escape = true): string
{
$request = Services::request();
// Try any old input data we may have first
$value = $request->getOldInput($field);
if ($value === null)
{
$value = $request->getPost($field) ?? $default;
}
return ($html_escape) ? esc($value, 'html') : $value;
}
}
//--------------------------------------------------------------------
if (! function_exists('set_select'))
{
/**
* Set Select
*
* Let's you set the selected value of a <select> menu via data in the POST array.
* If Form Validation is active it retrieves the info from the validation class
*
* @param string $field
* @param string $value
* @param boolean $default
*
* @return string
*/
function set_select(string $field, string $value = '', bool $default = false): string
{
$request = Services::request();
// Try any old input data we may have first
$input = $request->getOldInput($field);
if ($input === null)
{
$input = $request->getPost($field);
}
if ($input === null)
{
return ($default === true) ? ' selected="selected"' : '';
}
if (is_array($input))
{
// Note: in_array('', array(0)) returns TRUE, do not use it
foreach ($input as &$v)
{
if ($value === $v)
{
return ' selected="selected"';
}
}
return '';
}
return ($input === $value) ? ' selected="selected"' : '';
}
}
//--------------------------------------------------------------------
if (! function_exists('set_checkbox'))
{
/**
* Set Checkbox
*
* Let's you set the selected value of a checkbox via the value in the POST array.
* If Form Validation is active it retrieves the info from the validation class
*
* @param string $field
* @param string $value
* @param boolean $default
*
* @return string
*/
function set_checkbox(string $field, string $value = '', bool $default = false): string
{
$request = Services::request();
// Try any old input data we may have first
$input = $request->getOldInput($field);
if ($input === null)
{
$input = $request->getPost($field);
}
if (is_array($input))
{
// Note: in_array('', array(0)) returns TRUE, do not use it
foreach ($input as &$v)
{
if ($value === $v)
{
return ' checked="checked"';
}
}
return '';
}
// Unchecked checkbox and radio inputs are not even submitted by browsers ...
if (! empty($request->getPost()) || ! empty(old($field)))
{
return ($input === $value) ? ' checked="checked"' : '';
}
return ($default === true) ? ' checked="checked"' : '';
}
}
//--------------------------------------------------------------------
if (! function_exists('set_radio'))
{
/**
* Set Radio
*
* Let's you set the selected value of a radio field via info in the POST array.
* If Form Validation is active it retrieves the info from the validation class
*
* @param string $field
* @param string $value
* @param boolean $default
*
* @return string
*/
function set_radio(string $field, string $value = '', bool $default = false): string
{
$request = Services::request();
// Try any old input data we may have first
$input = $request->getOldInput($field);
if ($input === null)
{
$input = $request->getPost($field) ?? $default;
}
if (is_array($input))
{
// Note: in_array('', array(0)) returns TRUE, do not use it
foreach ($input as &$v)
{
if ($value === $v)
{
return ' checked="checked"';
}
}
return '';
}
// Unchecked checkbox and radio inputs are not even submitted by browsers ...
$result = '';
if (! empty($input = $request->getPost($field)) || ! empty($input = old($field)))
{
$result = ($input === $value) ? ' checked="checked"' : '';
}
if (empty($result))
{
$result = ($default === true) ? ' checked="checked"' : '';
}
return $result;
}
}
//--------------------------------------------------------------------
if (! function_exists('parse_form_attributes'))
{
/**
* Parse the form attributes
*
* Helper function used by some of the form helpers
*
* @param string|array $attributes List of attributes
* @param array $default Default values
*
* @return string
*/
function parse_form_attributes($attributes, array $default): string
{
if (is_array($attributes))
{
foreach ($default as $key => $val)
{
if (isset($attributes[$key]))
{
$default[$key] = $attributes[$key];
unset($attributes[$key]);
}
}
if (! empty($attributes))
{
$default = array_merge($default, $attributes);
}
}
$att = '';
foreach ($default as $key => $val)
{
if (! is_bool($val))
{
if ($key === 'value')
{
$val = esc($val, 'html');
}
elseif ($key === 'name' && ! strlen($default['name']))
{
continue;
}
$att .= $key . '="' . $val . '" ';
}
else
{
$att .= $key . ' ';
}
}
return $att;
}
//--------------------------------------------------------------------
}

View File

@@ -0,0 +1,726 @@
<?php
/**
* CodeIgniter
*
* An open source application development framework for PHP
*
* This content is released under the MIT License (MIT)
*
* Copyright (c) 2014-2019 British Columbia Institute of Technology
* Copyright (c) 2019 CodeIgniter Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @package CodeIgniter
* @author CodeIgniter Dev Team
* @copyright 2019 CodeIgniter Foundation
* @license https://opensource.org/licenses/MIT MIT License
* @link https://codeigniter.com
* @since Version 4.0.0
* @filesource
*/
// --------------------------------------------------------------------
/**
* CodeIgniter HTML Helpers
*
* @package CodeIgniter
*/
if (! function_exists('ul'))
{
/**
* Unordered List
*
* Generates an HTML unordered list from an single or
* multi-dimensional array.
*
* @param array $list
* @param string $attributes HTML attributes
* @return string
*/
function ul(array $list, string $attributes = ''): string
{
return _list('ul', $list, $attributes);
}
}
// ------------------------------------------------------------------------
if (! function_exists('ol'))
{
/**
* Ordered List
*
* Generates an HTML ordered list from an single or multi-dimensional array.
*
* @param array $list
* @param string $attributes HTML attributes
* @return string
*/
function ol(array $list, string $attributes = ''): string
{
return _list('ol', $list, $attributes);
}
}
// ------------------------------------------------------------------------
if (! function_exists('_list'))
{
/**
* Generates the list
*
* Generates an HTML ordered list from an single or multi-dimensional array.
*
* @param string $type
* @param mixed $list
* @param string $attributes
* @param integer $depth
* @return string
*/
function _list(string $type = 'ul', $list = [], string $attributes = '', int $depth = 0): string
{
// Set the indentation based on the depth
$out = str_repeat(' ', $depth)
// Write the opening list tag
. '<' . $type . stringify_attributes($attributes) . ">\n";
// Cycle through the list elements. If an array is
// encountered we will recursively call _list()
static $_last_list_item = '';
foreach ($list as $key => $val)
{
$_last_list_item = $key;
$out .= str_repeat(' ', $depth + 2) . '<li>';
if (! is_array($val))
{
$out .= $val;
}
else
{
$out .= $_last_list_item
. "\n"
. _list($type, $val, '', $depth + 4)
. str_repeat(' ', $depth + 2);
}
$out .= "</li>\n";
}
// Set the indentation for the closing tag and apply it
return $out . str_repeat(' ', $depth) . '</' . $type . ">\n";
}
}
// ------------------------------------------------------------------------
if (! function_exists('img'))
{
/**
* Image
*
* Generates an image element
*
* @param mixed $src
* @param boolean $indexPage
* @param mixed $attributes
* @return string
*/
function img($src = '', bool $indexPage = false, $attributes = ''): string
{
if (! is_array($src))
{
$src = ['src' => $src];
}
if (! isset($src['alt']))
{
$src['alt'] = $attributes['alt'] ?? '';
}
$img = '<img';
foreach ($src as $k => $v)
{
//Include a protocol if nothing is explicitely defined.
if ($k === 'src' && ! preg_match('#^([a-z]+:)?//#i', $v))
{
if ($indexPage === true)
{
$img .= ' src="' . site_url($v) . '"';
}
else
{
$img .= ' src="' . slash_item('baseURL') . $v . '"';
}
}
else
{
$img .= ' ' . $k . '="' . $v . '"';
}
}
// prevent passing "alt" to stringify_attributes
if (is_array($attributes) && isset($attributes['alt']))
{
unset($attributes['alt']);
}
return $img . stringify_attributes($attributes) . ' />';
}
}
// ------------------------------------------------------------------------
if (! function_exists('doctype'))
{
/**
* Doctype
*
* Generates a page document type declaration
*
* Examples of valid options: html5, xhtml-11, xhtml-strict, xhtml-trans,
* xhtml-frame, html4-strict, html4-trans, and html4-frame.
* All values are saved in the doctypes config file.
*
* @param string $type The doctype to be generated
* @return string
*/
function doctype(string $type = 'html5'): string
{
$config = new \Config\DocTypes();
$doctypes = $config->list;
return $doctypes[$type] ?? false;
}
}
// ------------------------------------------------------------------------
if (! function_exists('script_tag'))
{
/**
* Script
*
* Generates link to a JS file
*
* @param mixed $src Script source or an array
* @param boolean $indexPage Should indexPage be added to the JS path
* @return string
*/
function script_tag($src = '', bool $indexPage = false): string
{
$script = '<script ';
if (! is_array($src))
{
$src = ['src' => $src];
}
foreach ($src as $k => $v)
{
if ($k === 'src' && ! preg_match('#^([a-z]+:)?//#i', $v))
{
if ($indexPage === true)
{
$script .= 'src="' . site_url($v) . '" ';
}
else
{
$script .= 'src="' . slash_item('baseURL') . $v . '" ';
}
}
else
{
$script .= $k . '="' . $v . '" ';
}
}
return $script . 'type="text/javascript"' . '></script>';
}
}
// ------------------------------------------------------------------------
if (! function_exists('link_tag'))
{
/**
* Link
*
* Generates link to a CSS file
*
* @param mixed $href Stylesheet href or an array
* @param string $rel
* @param string $type
* @param string $title
* @param string $media
* @param boolean $indexPage should indexPage be added to the CSS path.
* @return string
*/
function link_tag($href = '', string $rel = 'stylesheet', string $type = 'text/css', string $title = '', string $media = '', bool $indexPage = false): string
{
$link = '<link ';
// extract fields if needed
if (is_array($href))
{
$rel = $href['rel'] ?? $rel;
$type = $href['type'] ?? $type;
$title = $href['title'] ?? $title;
$media = $href['media'] ?? $media;
$indexPage = $href['indexPage'] ?? $indexPage;
$href = $href['href'] ?? '';
}
if (! preg_match('#^([a-z]+:)?//#i', $href))
{
if ($indexPage === true)
{
$link .= 'href="' . site_url($href) . '" ';
}
else
{
$link .= 'href="' . slash_item('baseURL') . $href . '" ';
}
}
else
{
$link .= 'href="' . $href . '" ';
}
$link .= 'rel="' . $rel . '" type="' . $type . '" ';
if ($media !== '')
{
$link .= 'media="' . $media . '" ';
}
if ($title !== '')
{
$link .= 'title="' . $title . '" ';
}
return $link . '/>';
}
}
// ------------------------------------------------------------------------
if (! function_exists('video'))
{
/**
* Video
*
* Generates a video element to embed videos. The video element can
* contain one or more video sources
*
* @param mixed $src Either a source string or an array of sources
* @param string $unsupportedMessage The message to display if the media tag is not supported by the browser
* @param string $attributes HTML attributes
* @param array $tracks
* @param boolean $indexPage
* @return string
*/
function video($src, string $unsupportedMessage = '', string $attributes = '', array $tracks = [], bool $indexPage = false): string
{
if (is_array($src))
{
return _media('video', $src, $unsupportedMessage, $attributes, $tracks);
}
$video = '<video';
if (_has_protocol($src))
{
$video .= ' src="' . $src . '"';
}
elseif ($indexPage === true)
{
$video .= ' src="' . site_url($src) . '"';
}
else
{
$video .= ' src="' . slash_item('baseURL') . $src . '"';
}
if ($attributes !== '')
{
$video .= ' ' . $attributes;
}
$video .= ">\n";
if (! empty($tracks))
{
foreach ($tracks as $track)
{
$video .= _space_indent() . $track . "\n";
}
}
if (! empty($unsupportedMessage))
{
$video .= _space_indent()
. $unsupportedMessage
. "\n";
}
$video .= "</video>\n";
return $video;
}
}
// ------------------------------------------------------------------------
if (! function_exists('audio'))
{
/**
* Audio
*
* Generates an audio element to embed sounds
*
* @param mixed $src Either a source string or an array of sources
* @param string $unsupportedMessage The message to display if the media tag is not supported by the browser.
* @param string $attributes HTML attributes
* @param array $tracks
* @param boolean $indexPage
*
* @return string
*/
function audio($src, string $unsupportedMessage = '', string $attributes = '', array $tracks = [], bool $indexPage = false): string
{
if (is_array($src))
{
return _media('audio', $src, $unsupportedMessage, $attributes, $tracks);
}
$audio = '<audio';
if (_has_protocol($src))
{
$audio .= ' src="' . $src . '"';
}
elseif ($indexPage === true)
{
$audio .= ' src="' . site_url($src) . '"';
}
else
{
$audio .= ' src="' . slash_item('baseURL') . $src . '"';
}
if ($attributes !== '')
{
$audio .= ' ' . $attributes;
}
$audio .= '>';
if (! empty($tracks))
{
foreach ($tracks as $track)
{
$audio .= "\n" . _space_indent() . $track;
}
}
if (! empty($unsupportedMessage))
{
$audio .= "\n" . _space_indent() . $unsupportedMessage . "\n";
}
$audio .= "</audio>\n";
return $audio;
}
}
// ------------------------------------------------------------------------
if (! function_exists('_media'))
{
/**
* Generate media based tag
*
* @param string $name
* @param array $types
* @param string $unsupportedMessage The message to display if the media tag is not supported by the browser.
* @param string $attributes
* @param array $tracks
*
* @return string
*/
function _media(string $name, array $types = [], string $unsupportedMessage = '', string $attributes = '', array $tracks = []): string
{
$media = '<' . $name;
if (empty($attributes))
{
$media .= '>';
}
else
{
$media .= ' ' . $attributes . '>';
}
$media .= "\n";
foreach ($types as $option)
{
$media .= _space_indent() . $option . "\n";
}
if (! empty($tracks))
{
foreach ($tracks as $track)
{
$media .= _space_indent() . $track . "\n";
}
}
if (! empty($unsupportedMessage))
{
$media .= _space_indent() . $unsupportedMessage . "\n";
}
$media .= '</' . $name . ">\n";
return $media;
}
}
// ------------------------------------------------------------------------
if (! function_exists('source'))
{
/**
* Source
*
* Generates a source element that specifies multiple media resources
* for either audio or video element
*
* @param string $src The path of the media resource
* @param string $type The MIME-type of the resource with optional codecs parameters
* @param string $attributes HTML attributes
* @param boolean $indexPage
* @return string
*/
function source(string $src, string $type = 'unknown', string $attributes = '', bool $indexPage = false): string
{
if (! _has_protocol($src))
{
if ($indexPage === true)
{
$src = site_url($src);
}
else
{
$src = slash_item('baseURL') . $src;
}
}
$source = '<source src="' . $src
. '" type="' . $type . '"';
if (! empty($attributes))
{
$source .= ' ' . $attributes;
}
$source .= ' />';
return $source;
}
}
// ------------------------------------------------------------------------
if (! function_exists('track'))
{
/**
* Track
*
* Generates a track element to specify timed tracks. The tracks are
* formatted in WebVTT format.
*
* @param string $src The path of the .VTT file
* @param string $kind
* @param string $srcLanguage
* @param string $label
* @return string
*/
function track(string $src, string $kind, string $srcLanguage, string $label): string
{
return '<track src="' . $src
. '" kind="' . $kind
. '" srclang="' . $srcLanguage
. '" label="' . $label
. '" />';
}
}
// ------------------------------------------------------------------------
if (! function_exists('object'))
{
/**
* Object
*
* Generates an object element that represents the media
* as either image or a resource plugin such as audio, video,
* Java applets, ActiveX, PDF and Flash
*
* @param string $data A resource URL
* @param string $type Content-type of the resource
* @param string $attributes HTML attributes
* @param array $params
* @param boolean $indexPage
*
* @return string
*/
function object(string $data, string $type = 'unknown', string $attributes = '', array $params = [], bool $indexPage = false): string
{
if (! _has_protocol($data))
{
if ($indexPage === true)
{
$data = site_url($data);
}
else
{
$data = slash_item('baseURL') . $data;
}
}
$object = '<object data="' . $data . '" '
. $attributes . '>';
if (! empty($params))
{
$object .= "\n";
}
foreach ($params as $param)
{
$object .= _space_indent() . $param . "\n";
}
$object .= "</object>\n";
return $object;
}
}
// ------------------------------------------------------------------------
if (! function_exists('param'))
{
/**
* Param
*
* Generates a param element that defines parameters
* for the object element.
*
* @param string $name The name of the parameter
* @param string $value The value of the parameter
* @param string $type The MIME-type
* @param string $attributes HTML attributes
* @return string
*/
function param(string $name, string $value, string $type = 'ref', string $attributes = ''): string
{
return '<param name="' . $name
. '" type="' . $type
. '" value="' . $value
. '" ' . $attributes . ' />';
}
}
// ------------------------------------------------------------------------
if (! function_exists('embed'))
{
/**
* Embed
*
* Generates an embed element
*
* @param string $src The path of the resource to embed
* @param string $type MIME-type
* @param string $attributes HTML attributes
* @param boolean $indexPage
* @return string
*/
function embed(string $src, string $type = 'unknown', string $attributes = '', bool $indexPage = false): string
{
if (! _has_protocol($src))
{
if ($indexPage === true)
{
$src = site_url($src);
}
else
{
$src = slash_item('baseURL') . $src;
}
}
return '<embed src="' . $src
. '" type="' . $type . '" '
. $attributes . " />\n";
}
}
// ------------------------------------------------------------------------
if (! function_exists('_has_protocol'))
{
/**
* Test the protocol of a URI.
*
* @param string $url
*
* @return false|integer
*/
function _has_protocol(string $url)
{
return preg_match('#^([a-z]+:)?//#i', $url);
}
}
// ------------------------------------------------------------------------
if (! function_exists('_space_indent'))
{
/**
* Provide space indenting.
*
* @param integer $depth
*
* @return string
*/
function _space_indent(int $depth = 2): string
{
return str_repeat(' ', $depth);
}
}
// ------------------------------------------------------------------------

View File

@@ -0,0 +1,406 @@
<?php
/**
* CodeIgniter
*
* An open source application development framework for PHP
*
* This content is released under the MIT License (MIT)
*
* Copyright (c) 2014-2019 British Columbia Institute of Technology
* Copyright (c) 2019 CodeIgniter Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @package CodeIgniter
* @author CodeIgniter Dev Team
* @copyright 2019 CodeIgniter Foundation
* @license https://opensource.org/licenses/MIT MIT License
* @link https://codeigniter.com
* @since Version 4.0.0
* @filesource
*/
// --------------------------------------------------------------------
/**
* CodeIgniter Inflector Helpers
*
* @package CodeIgniter
*/
if (! function_exists('singular'))
{
/**
* Singular
*
* Takes a plural word and makes it singular
*
* @param string $string Input string
* @return string
*/
function singular(string $string): string
{
$result = strval($string);
if (! is_pluralizable($result))
{
return $result;
}
//Arranged in order.
$singularRules = [
'/(matr)ices$/' => '\1ix',
'/(vert|ind)ices$/' => '\1ex',
'/^(ox)en/' => '\1',
'/(alias)es$/' => '\1',
'/([octop|vir])i$/' => '\1us',
'/(cris|ax|test)es$/' => '\1is',
'/(shoe)s$/' => '\1',
'/(o)es$/' => '\1',
'/(bus|campus)es$/' => '\1',
'/([m|l])ice$/' => '\1ouse',
'/(x|ch|ss|sh)es$/' => '\1',
'/(m)ovies$/' => '\1\2ovie',
'/(s)eries$/' => '\1\2eries',
'/([^aeiouy]|qu)ies$/' => '\1y',
'/([lr])ves$/' => '\1f',
'/(tive)s$/' => '\1',
'/(hive)s$/' => '\1',
'/([^f])ves$/' => '\1fe',
'/(^analy)ses$/' => '\1sis',
'/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/' => '\1\2sis',
'/([ti])a$/' => '\1um',
'/(p)eople$/' => '\1\2erson',
'/(m)en$/' => '\1an',
'/(s)tatuses$/' => '\1\2tatus',
'/(c)hildren$/' => '\1\2hild',
'/(n)ews$/' => '\1\2ews',
'/(quiz)zes$/' => '\1',
'/([^us])s$/' => '\1',
];
foreach ($singularRules as $rule => $replacement)
{
if (preg_match($rule, $result))
{
$result = preg_replace($rule, $replacement, $result);
break;
}
}
return $result;
}
}
//--------------------------------------------------------------------
if (! function_exists('plural'))
{
/**
* Plural
*
* Takes a singular word and makes it plural
*
* @param string $string Input string
* @return string
*/
function plural(string $string): string
{
$result = strval($string);
if (! is_pluralizable($result))
{
return $result;
}
$pluralRules = [
'/(quiz)$/' => '\1zes', // quizzes
'/^(ox)$/' => '\1\2en', // ox
'/([m|l])ouse$/' => '\1ice', // mouse, louse
'/(matr|vert|ind)ix|ex$/' => '\1ices', // matrix, vertex, index
'/(x|ch|ss|sh)$/' => '\1es', // search, switch, fix, box, process, address
'/([^aeiouy]|qu)y$/' => '\1ies', // query, ability, agency
'/(hive)$/' => '\1s', // archive, hive
'/(?:([^f])fe|([lr])f)$/' => '\1\2ves', // half, safe, wife
'/sis$/' => 'ses', // basis, diagnosis
'/([ti])um$/' => '\1a', // datum, medium
'/(p)erson$/' => '\1eople', // person, salesperson
'/(m)an$/' => '\1en', // man, woman, spokesman
'/(c)hild$/' => '\1hildren', // child
'/(buffal|tomat)o$/' => '\1\2oes', // buffalo, tomato
'/(bu|campu)s$/' => '\1\2ses', // bus, campus
'/(alias|status|virus)$/' => '\1es', // alias
'/(octop)us$/' => '\1i', // octopus
'/(ax|cris|test)is$/' => '\1es', // axis, crisis
'/s$/' => 's', // no change (compatibility)
'/$/' => 's',
];
foreach ($pluralRules as $rule => $replacement)
{
if (preg_match($rule, $result))
{
$result = preg_replace($rule, $replacement, $result);
break;
}
}
return $result;
}
}
//--------------------------------------------------------------------
if (! function_exists('counted'))
{
/**
* Counted
*
* Takes a number and a word to return the plural or not
* E.g. 0 cats, 1 cat, 2 cats, ...
*
* @param integer $count Number of items
* @param string $string Input string
* @return string
*/
function counted(int $count, string $string): string
{
$result = "{$count} ";
$result .= $count === 1 ? singular($string) : plural($string);
return $result;
}
}
//--------------------------------------------------------------------
if (! function_exists('camelize'))
{
/**
* Camelize
*
* Takes multiple words separated by spaces or
* underscores and converts them to camel case.
*
* @param string $string Input string
* @return string
*/
function camelize(string $string): string
{
return lcfirst(str_replace(' ', '', ucwords(preg_replace('/[\s_]+/', ' ', $string))));
}
}
//--------------------------------------------------------------------
if (! function_exists('pascalize'))
{
/**
* Pascalize
*
* Takes multiple words separated by spaces or
* underscores and converts them to Pascal case,
* which is camel case with an uppercase first letter.
*
* @param string $string Input string
* @return string
*/
function pascalize(string $string): string
{
return ucfirst(camelize($string));
}
}
//--------------------------------------------------------------------
if (! function_exists('underscore'))
{
/**
* Underscore
*
* Takes multiple words separated by spaces and underscores them
*
* @param string $string Input string
* @return string
*/
function underscore(string $string): string
{
$replacement = trim($string);
return preg_replace('/[\s]+/', '_', $replacement);
}
}
//--------------------------------------------------------------------
if (! function_exists('humanize'))
{
/**
* Humanize
*
* Takes multiple words separated by the separator,
* camelizes and changes them to spaces
*
* @param string $string Input string
* @param string $separator Input separator
* @return string
*/
function humanize(string $string, string $separator = '_'): string
{
$replacement = trim($string);
$upperCased = ucwords
(
preg_replace('/[' . $separator . ']+/', ' ', $replacement)
);
return $upperCased;
}
}
// ------------------------------------------------------------------------
if (! function_exists('is_pluralizable'))
{
/**
* Checks if the given word has a plural version.
*
* @param string $word Word to check
* @return boolean
*/
function is_pluralizable(string $word): bool
{
$uncountables = in_array
(
strtolower($word), [
'advice',
'bravery',
'butter',
'chaos',
'clarity',
'coal',
'courage',
'cowardice',
'curiosity',
'education',
'equipment',
'evidence',
'fish',
'fun',
'furniture',
'greed',
'help',
'homework',
'honesty',
'information',
'insurance',
'jewelry',
'knowledge',
'livestock',
'love',
'luck',
'marketing',
'meta',
'money',
'mud',
'news',
'patriotism',
'racism',
'rice',
'satisfaction',
'scenery',
'series',
'sexism',
'silence',
'species',
'spelling',
'sugar',
'water',
'weather',
'wisdom',
'work',
]);
return ! $uncountables;
}
}
// ------------------------------------------------------------------------
if (! function_exists('dasherize'))
{
/**
* Replaces underscores with dashes in the string.
*
* @param string $string Input string
* @return string
*/
function dasherize(string $string): string
{
return str_replace('_', '-', $string);
}
}
// ------------------------------------------------------------------------
if (! function_exists('ordinal'))
{
/**
* Returns the suffix that should be added to a
* number to denote the position in an ordered
* sequence such as 1st, 2nd, 3rd, 4th.
*
* @param integer $integer The integer to determine
* the suffix
* @return string
*/
function ordinal(int $integer): string
{
$suffixes = [
'th',
'st',
'nd',
'rd',
'th',
'th',
'th',
'th',
'th',
'th',
];
return $integer % 100 >= 11 && $integer % 100 <= 13 ? 'th' : $suffixes[$integer % 10];
}
}
// ------------------------------------------------------------------------
if (! function_exists('ordinalize'))
{
/**
* Turns a number into an ordinal string used
* to denote the position in an ordered sequence
* such as 1st, 2nd, 3rd, 4th.
*
* @param integer $integer The integer to ordinalize
* @return string
*/
function ordinalize(int $integer): string
{
return $integer . ordinal($integer);
}
}

View File

@@ -0,0 +1,338 @@
<?php
/**
* CodeIgniter
*
* An open source application development framework for PHP
*
* This content is released under the MIT License (MIT)
*
* Copyright (c) 2014-2019 British Columbia Institute of Technology
* Copyright (c) 2019 CodeIgniter Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @package CodeIgniter
* @author CodeIgniter Dev Team
* @copyright 2008-2014 EllisLab, Inc. (https://ellislab.com/)
* @copyright 2019 CodeIgniter Foundation
* @license https://opensource.org/licenses/MIT MIT License
* @link https://codeigniter.com
* @since Version 1.0.0
* @filesource
*/
/**
* CodeIgniter Number Helpers
*
* @package CodeIgniter
*/
if (! function_exists('number_to_size'))
{
/**
* Formats a numbers as bytes, based on size, and adds the appropriate suffix
*
* @param mixed $num Will be cast as int
* @param integer $precision
* @param string $locale
*
* @return boolean|string
*/
function number_to_size($num, int $precision = 1, string $locale = null)
{
// Strip any formatting & ensure numeric input
try
{
$num = 0 + str_replace(',', '', $num);
}
catch (\ErrorException $ee)
{
return false;
}
// ignore sub part
$generalLocale = $locale;
if (! empty($locale) && ( $underscorePos = strpos($locale, '_')))
{
$generalLocale = substr($locale, 0, $underscorePos);
}
if ($num >= 1000000000000)
{
$num = round($num / 1099511627776, $precision);
$unit = lang('Number.terabyteAbbr', [], $generalLocale);
}
elseif ($num >= 1000000000)
{
$num = round($num / 1073741824, $precision);
$unit = lang('Number.gigabyteAbbr', [], $generalLocale);
}
elseif ($num >= 1000000)
{
$num = round($num / 1048576, $precision);
$unit = lang('Number.megabyteAbbr', [], $generalLocale);
}
elseif ($num >= 1000)
{
$num = round($num / 1024, $precision);
$unit = lang('Number.kilobyteAbbr', [], $generalLocale);
}
else
{
$unit = lang('Number.bytes', [], $generalLocale);
}
return format_number($num, $precision, $locale, ['after' => ' ' . $unit]);
}
}
//--------------------------------------------------------------------
if (! function_exists('number_to_amount'))
{
/**
* Converts numbers to a more readable representation
* when dealing with very large numbers (in the thousands or above),
* up to the quadrillions, because you won't often deal with numbers
* larger than that.
*
* It uses the "short form" numbering system as this is most commonly
* used within most English-speaking countries today.
*
* @see https://simple.wikipedia.org/wiki/Names_for_large_numbers
*
* @param string $num
* @param integer $precision
* @param string|null $locale
*
* @return boolean|string
*/
function number_to_amount($num, int $precision = 0, string $locale = null)
{
// Strip any formatting & ensure numeric input
try
{
$num = 0 + str_replace(',', '', $num);
}
catch (\ErrorException $ee)
{
return false;
}
$suffix = '';
// ignore sub part
$generalLocale = $locale;
if (! empty($locale) && ( $underscorePos = strpos($locale, '_')))
{
$generalLocale = substr($locale, 0, $underscorePos);
}
if ($num > 1000000000000000)
{
$suffix = lang('Number.quadrillion', [], $generalLocale);
$num = round(($num / 1000000000000000), $precision);
}
elseif ($num > 1000000000000)
{
$suffix = lang('Number.trillion', [], $generalLocale);
$num = round(($num / 1000000000000), $precision);
}
else if ($num > 1000000000)
{
$suffix = lang('Number.billion', [], $generalLocale);
$num = round(($num / 1000000000), $precision);
}
else if ($num > 1000000)
{
$suffix = lang('Number.million', [], $generalLocale);
$num = round(($num / 1000000), $precision);
}
else if ($num > 1000)
{
$suffix = lang('Number.thousand', [], $generalLocale);
$num = round(($num / 1000), $precision);
}
return format_number($num, $precision, $locale, ['after' => $suffix]);
}
}
//--------------------------------------------------------------------
if (! function_exists('number_to_currency'))
{
/**
* @param float $num
* @param string $currency
* @param string $locale
*
* @return string
*/
function number_to_currency(float $num, string $currency, string $locale = null): string
{
return format_number($num, 1, $locale, [
'type' => NumberFormatter::CURRENCY,
'currency' => $currency,
]);
}
}
//--------------------------------------------------------------------
if (! function_exists('format_number'))
{
/**
* A general purpose, locale-aware, number_format method.
* Used by all of the functions of the number_helper.
*
* @param float $num
* @param integer $precision
* @param string|null $locale
* @param array $options
*
* @return string
*/
function format_number(float $num, int $precision = 1, string $locale = null, array $options = []): string
{
// Locale is either passed in here, negotiated with client, or grabbed from our config file.
$locale = $locale ?? \CodeIgniter\Config\Services::request()->getLocale();
// Type can be any of the NumberFormatter options, but provide a default.
$type = (int) ($options['type'] ?? NumberFormatter::DECIMAL);
// In order to specify a precision, we'll have to modify
// the pattern used by NumberFormatter.
$pattern = '#,##0.' . str_repeat('#', $precision);
$formatter = new NumberFormatter($locale, $type);
// Try to format it per the locale
if ($type === NumberFormatter::CURRENCY)
{
$output = $formatter->formatCurrency($num, $options['currency']);
}
else
{
$formatter->setPattern($pattern);
$output = $formatter->format($num);
}
// This might lead a trailing period if $precision == 0
$output = trim($output, '. ');
if (intl_is_failure($formatter->getErrorCode()))
{
throw new BadFunctionCallException($formatter->getErrorMessage());
}
// Add on any before/after text.
if (isset($options['before']) && is_string($options['before']))
{
$output = $options['before'] . $output;
}
if (isset($options['after']) && is_string($options['after']))
{
$output .= $options['after'];
}
return $output;
}
}
//--------------------------------------------------------------------
if (! function_exists('number_to_roman'))
{
/**
* Convert a number to a roman numeral.
*
* @param string $num it will convert to int
*
* @return string|null
*/
function number_to_roman(string $num): ?string
{
$num = (int) $num;
if ($num < 1 || $num > 3999)
{
return null;
}
$_number_to_roman = function ($num, $th) use (&$_number_to_roman) {
$return = '';
$key1 = null;
$key2 = null;
switch ($th) {
case 1:
$key1 = 'I';
$key2 = 'V';
$key_f = 'X';
break;
case 2:
$key1 = 'X';
$key2 = 'L';
$key_f = 'C';
break;
case 3:
$key1 = 'C';
$key2 = 'D';
$key_f = 'M';
break;
case 4:
$key1 = 'M';
break;
}
$n = $num % 10;
switch ($n) {
case 1:
case 2:
case 3:
$return = str_repeat($key1, $n);
break;
case 4:
$return = $key1 . $key2;
break;
case 5:
$return = $key2;
break;
case 6:
case 7:
case 8:
$return = $key2 . str_repeat($key1, $n - 5);
break;
case 9:
$return = $key1 . $key_f;
break;
}
switch ($num) {
case 10:
$return = $key_f;
break;
}
if ($num > 10)
{
$return = $_number_to_roman($num / 10, ++ $th) . $return;
}
return $return;
};
return $_number_to_roman($num, 1);
}
}

View File

@@ -0,0 +1,99 @@
<?php
/**
* CodeIgniter
*
* An open source application development framework for PHP
*
* This content is released under the MIT License (MIT)
*
* Copyright (c) 2014-2019 British Columbia Institute of Technology
* Copyright (c) 2019 CodeIgniter Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @package CodeIgniter
* @author CodeIgniter Dev Team
* @copyright 2019 CodeIgniter Foundation
* @license https://opensource.org/licenses/MIT MIT License
* @link https://codeigniter.com
* @since Version 4.0.0
* @filesource
*/
use Config\Services;
/**
* CodeIgniter Security Helpers
*
* @package CodeIgniter
*/
if (! function_exists('sanitize_filename'))
{
/**
* Sanitize a filename to use in a URI.
*
* @param string $filename
*
* @return string
*/
function sanitize_filename(string $filename): string
{
return Services::security()->sanitizeFilename($filename);
}
}
//--------------------------------------------------------------------
if (! function_exists('strip_image_tags'))
{
/**
* Strip Image Tags
*
* @param string $str
* @return string
*/
function strip_image_tags(string $str): string
{
return preg_replace([
'#<img[\s/]+.*?src\s*=\s*(["\'])([^\\1]+?)\\1.*?\>#i',
'#<img[\s/]+.*?src\s*=\s*?(([^\s"\'=<>`]+)).*?\>#i',
], '\\2', $str
);
}
}
//--------------------------------------------------------------------
if (! function_exists('encode_php_tags'))
{
/**
* Convert PHP tags to entities
*
* @param string $str
* @return string
*/
function encode_php_tags(string $str): string
{
return str_replace(['<?', '?>'], ['&lt;?', '?&gt;'], $str);
}
}
//--------------------------------------------------------------------

View File

@@ -0,0 +1,883 @@
<?php
/**
* CodeIgniter
*
* An open source application development framework for PHP
*
* This content is released under the MIT License (MIT)
*
* Copyright (c) 2014-2019 British Columbia Institute of Technology
* Copyright (c) 2019 CodeIgniter Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @package CodeIgniter
* @author CodeIgniter Dev Team
* @copyright 2008-2014 EllisLab, Inc. (https://ellislab.com/)
* @copyright 2019 CodeIgniter Foundation
* @license https://opensource.org/licenses/MIT MIT License
* @link https://codeigniter.com
* @since Version 1.0.0
* @filesource
*/
/**
* CodeIgniter Text Helpers
*
* @package CodeIgniter
*/
//--------------------------------------------------------------------
if (! function_exists('word_limiter'))
{
/**
* Word Limiter
*
* Limits a string to X number of words.
*
* @param string $str
* @param integer $limit
* @param string $end_char the end character. Usually an ellipsis
*
* @return string
*/
function word_limiter(string $str, int $limit = 100, string $end_char = '&#8230;'): string
{
if (trim($str) === '')
{
return $str;
}
preg_match('/^\s*+(?:\S++\s*+){1,' . (int) $limit . '}/', $str, $matches);
if (strlen($str) === strlen($matches[0]))
{
$end_char = '';
}
return rtrim($matches[0]) . $end_char;
}
}
//--------------------------------------------------------------------
if (! function_exists('character_limiter'))
{
/**
* Character Limiter
*
* Limits the string based on the character count. Preserves complete words
* so the character count may not be exactly as specified.
*
* @param string $str
* @param integer $n
* @param string $end_char the end character. Usually an ellipsis
*
* @return string
*/
function character_limiter(string $str, int $n = 500, string $end_char = '&#8230;'): string
{
if (mb_strlen($str) < $n)
{
return $str;
}
// a bit complicated, but faster than preg_replace with \s+
$str = preg_replace('/ {2,}/', ' ', str_replace(["\r", "\n", "\t", "\x0B", "\x0C"], ' ', $str));
if (mb_strlen($str) <= $n)
{
return $str;
}
$out = '';
foreach (explode(' ', trim($str)) as $val)
{
$out .= $val . ' ';
if (mb_strlen($out) >= $n)
{
$out = trim($out);
break;
}
}
return (mb_strlen($out) === mb_strlen($str)) ? $out : $out . $end_char;
}
}
//--------------------------------------------------------------------
if (! function_exists('ascii_to_entities'))
{
/**
* High ASCII to Entities
*
* Converts high ASCII text and MS Word special characters to character entities
*
* @param string $str
*
* @return string
*/
function ascii_to_entities(string $str): string
{
$out = '';
for ($i = 0, $s = strlen($str) - 1, $count = 1, $temp = []; $i <= $s; $i ++)
{
$ordinal = ord($str[$i]);
if ($ordinal < 128)
{
/*
If the $temp array has a value but we have moved on, then it seems only
fair that we output that entity and restart $temp before continuing.
*/
if (count($temp) === 1)
{
$out .= '&#' . array_shift($temp) . ';';
$count = 1;
}
$out .= $str[$i];
}
else
{
if (empty($temp))
{
$count = ($ordinal < 224) ? 2 : 3;
}
$temp[] = $ordinal;
if (count($temp) === $count)
{
$number = ($count === 3) ? (($temp[0] % 16) * 4096) + (($temp[1] % 64) * 64) + ($temp[2] % 64) : (($temp[0] % 32) * 64) + ($temp[1] % 64);
$out .= '&#' . $number . ';';
$count = 1;
$temp = [];
}
// If this is the last iteration, just output whatever we have
elseif ($i === $s)
{
$out .= '&#' . implode(';', $temp) . ';';
}
}
}
return $out;
}
}
//--------------------------------------------------------------------
if (! function_exists('entities_to_ascii'))
{
/**
* Entities to ASCII
*
* Converts character entities back to ASCII
*
* @param string $str
* @param boolean $all
*
* @return string
*/
function entities_to_ascii(string $str, bool $all = true): string
{
if (preg_match_all('/\&#(\d+)\;/', $str, $matches))
{
for ($i = 0, $s = count($matches[0]); $i < $s; $i ++)
{
$digits = $matches[1][$i];
$out = '';
if ($digits < 128)
{
$out .= chr($digits);
}
elseif ($digits < 2048)
{
$out .= chr(192 + (($digits - ($digits % 64)) / 64)) . chr(128 + ($digits % 64));
}
else
{
$out .= chr(224 + (($digits - ($digits % 4096)) / 4096))
. chr(128 + ((($digits % 4096) - ($digits % 64)) / 64))
. chr(128 + ($digits % 64));
}
$str = str_replace($matches[0][$i], $out, $str);
}
}
if ($all)
{
return str_replace([
'&amp;',
'&lt;',
'&gt;',
'&quot;',
'&apos;',
'&#45;',
], [
'&',
'<',
'>',
'"',
"'",
'-',
], $str
);
}
return $str;
}
}
//--------------------------------------------------------------------
if (! function_exists('word_censor'))
{
/**
* Word Censoring Function
*
* Supply a string and an array of disallowed words and any
* matched words will be converted to #### or to the replacement
* word you've submitted.
*
* @param string $str the text string
* @param array $censored the array of censored words
* @param string $replacement the optional replacement value
*
* @return string
*/
function word_censor(string $str, array $censored, string $replacement = ''): string
{
if (empty($censored))
{
return $str;
}
$str = ' ' . $str . ' ';
// \w, \b and a few others do not match on a unicode character
// set for performance reasons. As a result words like über
// will not match on a word boundary. Instead, we'll assume that
// a bad word will be bookended by any of these characters.
$delim = '[-_\'\"`(){}<>\[\]|!?@#%&,.:;^~*+=\/ 0-9\n\r\t]';
foreach ($censored as $badword)
{
$badword = str_replace('\*', '\w*?', preg_quote($badword, '/'));
if ($replacement !== '')
{
$str = preg_replace(
"/({$delim})(" . $badword . ")({$delim})/i", "\\1{$replacement}\\3", $str
);
}
elseif (preg_match_all("/{$delim}(" . $badword . "){$delim}/i", $str, $matches, PREG_PATTERN_ORDER | PREG_OFFSET_CAPTURE))
{
$matches = $matches[1];
for ($i = count($matches) - 1; $i >= 0; $i --)
{
$length = strlen($matches[$i][0]);
$str = substr_replace(
$str, str_repeat('#', $length), $matches[$i][1], $length
);
}
}
}
return trim($str);
}
}
//--------------------------------------------------------------------
if (! function_exists('highlight_code'))
{
/**
* Code Highlighter
*
* Colorizes code strings
*
* @param string $str the text string
*
* @return string
*/
function highlight_code(string $str): string
{
/* The highlight string function encodes and highlights
* brackets so we need them to start raw.
*
* Also replace any existing PHP tags to temporary markers
* so they don't accidentally break the string out of PHP,
* and thus, thwart the highlighting.
*/
$str = str_replace([
'&lt;',
'&gt;',
'<?',
'?>',
'<%',
'%>',
'\\',
'</script>',
], [
'<',
'>',
'phptagopen',
'phptagclose',
'asptagopen',
'asptagclose',
'backslashtmp',
'scriptclose',
], $str
);
// The highlight_string function requires that the text be surrounded
// by PHP tags, which we will remove later
$str = highlight_string('<?php ' . $str . ' ?>', true);
// Remove our artificially added PHP, and the syntax highlighting that came with it
$str = preg_replace([
'/<span style="color: #([A-Z0-9]+)">&lt;\?php(&nbsp;| )/i',
'/(<span style="color: #[A-Z0-9]+">.*?)\?&gt;<\/span>\n<\/span>\n<\/code>/is',
'/<span style="color: #[A-Z0-9]+"\><\/span>/i',
], [
'<span style="color: #$1">',
"$1</span>\n</span>\n</code>",
'',
], $str
);
// Replace our markers back to PHP tags.
return str_replace([
'phptagopen',
'phptagclose',
'asptagopen',
'asptagclose',
'backslashtmp',
'scriptclose',
], [
'&lt;?',
'?&gt;',
'&lt;%',
'%&gt;',
'\\',
'&lt;/script&gt;',
], $str
);
}
}
//--------------------------------------------------------------------
if (! function_exists('highlight_phrase'))
{
/**
* Phrase Highlighter
*
* Highlights a phrase within a text string
*
* @param string $str the text string
* @param string $phrase the phrase you'd like to highlight
* @param string $tag_open the opening tag to precede the phrase with
* @param string $tag_close the closing tag to end the phrase with
*
* @return string
*/
function highlight_phrase(string $str, string $phrase, string $tag_open = '<mark>', string $tag_close = '</mark>'): string
{
return ($str !== '' && $phrase !== '') ? preg_replace('/(' . preg_quote($phrase, '/') . ')/i', $tag_open . '\\1' . $tag_close, $str) : $str;
}
}
//--------------------------------------------------------------------
if (! function_exists('convert_accented_characters'))
{
/**
* Convert Accented Foreign Characters to ASCII
*
* @param string $str Input string
*
* @return string
*/
function convert_accented_characters(string $str): string
{
static $array_from, $array_to;
if (! is_array($array_from))
{
$config = new Config\ForeignCharacters();
if (empty($config->characterList) || ! is_array($config->characterList))
{
$array_from = [];
$array_to = [];
return $str;
}
$array_from = array_keys($config->characterList);
$array_to = array_values($config->characterList);
unset($config);
}
return preg_replace($array_from, $array_to, $str);
}
}
//--------------------------------------------------------------------
if (! function_exists('word_wrap'))
{
/**
* Word Wrap
*
* Wraps text at the specified character. Maintains the integrity of words.
* Anything placed between {unwrap}{/unwrap} will not be word wrapped, nor
* will URLs.
*
* @param string $str the text string
* @param integer $charlim = 76 the number of characters to wrap at
*
* @return string
*/
function word_wrap(string $str, int $charlim = 76): string
{
// Set the character limit
is_numeric($charlim) || $charlim = 76;
// Reduce multiple spaces
$str = preg_replace('| +|', ' ', $str);
// Standardize newlines
if (strpos($str, "\r") !== false)
{
$str = str_replace(["\r\n", "\r"], "\n", $str);
}
// If the current word is surrounded by {unwrap} tags we'll
// strip the entire chunk and replace it with a marker.
$unwrap = [];
if (preg_match_all('|\{unwrap\}(.+?)\{/unwrap\}|s', $str, $matches))
{
for ($i = 0, $c = count($matches[0]); $i < $c; $i ++)
{
$unwrap[] = $matches[1][$i];
$str = str_replace($matches[0][$i], '{{unwrapped' . $i . '}}', $str);
}
}
// Use PHP's native function to do the initial wordwrap.
// We set the cut flag to FALSE so that any individual words that are
// too long get left alone. In the next step we'll deal with them.
$str = wordwrap($str, $charlim, "\n", false);
// Split the string into individual lines of text and cycle through them
$output = '';
foreach (explode("\n", $str) as $line)
{
// Is the line within the allowed character count?
// If so we'll join it to the output and continue
if (mb_strlen($line) <= $charlim)
{
$output .= $line . "\n";
continue;
}
$temp = '';
while (mb_strlen($line) > $charlim)
{
// If the over-length word is a URL we won't wrap it
if (preg_match('!\[url.+\]|://|www\.!', $line))
{
break;
}
// Trim the word down
$temp .= mb_substr($line, 0, $charlim - 1);
$line = mb_substr($line, $charlim - 1);
}
// If $temp contains data it means we had to split up an over-length
// word into smaller chunks so we'll add it back to our current line
if ($temp !== '')
{
$output .= $temp . "\n" . $line . "\n";
}
else
{
$output .= $line . "\n";
}
}
// Put our markers back
if (! empty($unwrap))
{
foreach ($unwrap as $key => $val)
{
$output = str_replace('{{unwrapped' . $key . '}}', $val, $output);
}
}
// remove any trailing newline
$output = rtrim($output);
return $output;
}
}
//--------------------------------------------------------------------
if (! function_exists('ellipsize'))
{
/**
* Ellipsize String
*
* This function will strip tags from a string, split it at its max_length and ellipsize
*
* @param string $str String to ellipsize
* @param integer $max_length Max length of string
* @param mixed $position int (1|0) or float, .5, .2, etc for position to split
* @param string $ellipsis ellipsis ; Default '...'
*
* @return string Ellipsized string
*/
function ellipsize(string $str, int $max_length, $position = 1, string $ellipsis = '&hellip;'): string
{
// Strip tags
$str = trim(strip_tags($str));
// Is the string long enough to ellipsize?
if (mb_strlen($str) <= $max_length)
{
return $str;
}
$beg = mb_substr($str, 0, floor($max_length * $position));
$position = ($position > 1) ? 1 : $position;
if ($position === 1)
{
$end = mb_substr($str, 0, -($max_length - mb_strlen($beg)));
}
else
{
$end = mb_substr($str, -($max_length - mb_strlen($beg)));
}
return $beg . $ellipsis . $end;
}
}
//--------------------------------------------------------------------
if (! function_exists('strip_slashes'))
{
/**
* Strip Slashes
*
* Removes slashes contained in a string or in an array
*
* @param mixed $str string or array
*
* @return mixed string or array
*/
function strip_slashes($str)
{
if (! is_array($str))
{
return stripslashes($str);
}
foreach ($str as $key => $val)
{
$str[$key] = strip_slashes($val);
}
return $str;
}
}
//--------------------------------------------------------------------
if (! function_exists('strip_quotes'))
{
/**
* Strip Quotes
*
* Removes single and double quotes from a string
*
* @param string $str
*
* @return string
*/
function strip_quotes(string $str): string
{
return str_replace(['"', "'"], '', $str);
}
}
//--------------------------------------------------------------------
if (! function_exists('quotes_to_entities'))
{
/**
* Quotes to Entities
*
* Converts single and double quotes to entities
*
* @param string $str
*
* @return string
*/
function quotes_to_entities(string $str): string
{
return str_replace(["\'", '"', "'", '"'], ['&#39;', '&quot;', '&#39;', '&quot;'], $str);
}
}
//--------------------------------------------------------------------
if (! function_exists('reduce_double_slashes'))
{
/**
* Reduce Double Slashes
*
* Converts double slashes in a string to a single slash,
* except those found in http://
*
* http://www.some-site.com//index.php
*
* becomes:
*
* http://www.some-site.com/index.php
*
* @param string $str
*
* @return string
*/
function reduce_double_slashes(string $str): string
{
return preg_replace('#(^|[^:])//+#', '\\1/', $str);
}
}
//--------------------------------------------------------------------
if (! function_exists('reduce_multiples'))
{
/**
* Reduce Multiples
*
* Reduces multiple instances of a particular character. Example:
*
* Fred, Bill,, Joe, Jimmy
*
* becomes:
*
* Fred, Bill, Joe, Jimmy
*
* @param string $str
* @param string $character the character you wish to reduce
* @param boolean $trim TRUE/FALSE - whether to trim the character from the beginning/end
*
* @return string
*/
function reduce_multiples(string $str, string $character = ',', bool $trim = false): string
{
$str = preg_replace('#' . preg_quote($character, '#') . '{2,}#', $character, $str);
return ($trim) ? trim($str, $character) : $str;
}
}
//--------------------------------------------------------------------
if (! function_exists('random_string'))
{
/**
* Create a Random String
*
* Useful for generating passwords or hashes.
*
* @param string $type Type of random string. basic, alpha, alnum, numeric, nozero, md5, sha1, and crypto
* @param integer $len Number of characters
*
* @return string
*/
function random_string(string $type = 'alnum', int $len = 8): string
{
switch ($type)
{
case 'alnum':
case 'numeric':
case 'nozero':
case 'alpha':
switch ($type)
{
case 'alpha':
$pool = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
break;
case 'alnum':
$pool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
break;
case 'numeric':
$pool = '0123456789';
break;
case 'nozero':
$pool = '123456789';
break;
}
return substr(str_shuffle(str_repeat($pool, ceil($len / strlen($pool)))), 0, $len);
case 'md5':
return md5(uniqid(mt_rand(), true));
case 'sha1':
return sha1(uniqid(mt_rand(), true));
case 'crypto':
return bin2hex(random_bytes($len / 2));
}
// 'basic' type treated as default
return (string) mt_rand();
}
}
//--------------------------------------------------------------------
if (! function_exists('increment_string'))
{
/**
* Add's _1 to a string or increment the ending number to allow _2, _3, etc
*
* @param string $str Required
* @param string $separator What should the duplicate number be appended with
* @param integer $first Which number should be used for the first dupe increment
*
* @return string
*/
function increment_string(string $str, string $separator = '_', int $first = 1): string
{
preg_match('/(.+)' . preg_quote($separator, '/') . '([0-9]+)$/', $str, $match);
return isset($match[2]) ? $match[1] . $separator . ($match[2] + 1) : $str . $separator . $first;
}
}
//--------------------------------------------------------------------
if (! function_exists('alternator'))
{
/**
* Alternator
*
* Allows strings to be alternated. See docs...
*
* @param string (as many parameters as needed)
*
* @return string
*/
function alternator(): string
{
static $i;
if (func_num_args() === 0)
{
$i = 0;
return '';
}
$args = func_get_args();
return $args[($i++ % count($args))];
}
}
//--------------------------------------------------------------------
if (! function_exists('excerpt'))
{
/**
* Excerpt.
*
* Allows to extract a piece of text surrounding a word or phrase.
*
* @param string $text String to search the phrase
* @param string $phrase Phrase that will be searched for.
* @param integer $radius The amount of characters returned around the phrase.
* @param string $ellipsis Ending that will be appended
*
* @return string
*
* If no $phrase is passed, will generate an excerpt of $radius characters
* from the beginning of $text.
*/
function excerpt(string $text, string $phrase = null, int $radius = 100, string $ellipsis = '...'): string
{
if (isset($phrase))
{
$phrasePos = strpos(strtolower($text), strtolower($phrase));
$phraseLen = strlen($phrase);
}
elseif (! isset($phrase))
{
$phrasePos = $radius / 2;
$phraseLen = 1;
}
$pre = explode(' ', substr($text, 0, $phrasePos));
$pos = explode(' ', substr($text, $phrasePos + $phraseLen));
$prev = ' ';
$post = ' ';
$count = 0;
foreach (array_reverse($pre) as $pr => $e)
{
if ((strlen($e) + $count + 1) < $radius)
{
$prev = ' ' . $e . $prev;
}
$count = ++ $count + strlen($e);
}
$count = 0;
foreach ($pos as $po => $s)
{
if ((strlen($s) + $count + 1) < $radius)
{
$post .= $s . ' ';
}
$count = ++ $count + strlen($s);
}
$ellPre = $phrase ? $ellipsis : '';
return str_replace(' ', ' ', $ellPre . $prev . $phrase . $post . $ellipsis);
}
//--------------------------------------------------------------------
}

View File

@@ -0,0 +1,593 @@
<?php
/**
* CodeIgniter
*
* An open source application development framework for PHP
*
* This content is released under the MIT License (MIT)
*
* Copyright (c) 2014-2019 British Columbia Institute of Technology
* Copyright (c) 2019 CodeIgniter Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @package CodeIgniter
* @author CodeIgniter Dev Team
* @copyright 2019 CodeIgniter Foundation
* @license https://opensource.org/licenses/MIT MIT License
* @link https://codeigniter.com
* @since Version 4.0.0
* @filesource
*/
/**
* CodeIgniter URL Helpers
*
* @package CodeIgniter
*/
if (! function_exists('site_url'))
{
/**
* Return a site URL to use in views
*
* @param mixed $uri URI string or array of URI segments
* @param string|null $protocol
* @param \Config\App|null $altConfig Alternate configuration to use
*
* @return string
*/
function site_url($uri = '', string $protocol = null, \Config\App $altConfig = null): string
{
// convert segment array to string
if (is_array($uri))
{
$uri = implode('/', $uri);
}
// use alternate config if provided, else default one
$config = $altConfig ?? config(\Config\App::class);
$fullPath = rtrim(base_url(), '/') . '/';
// Add index page, if so configured
if (! empty($config->indexPage))
{
$fullPath .= rtrim($config->indexPage, '/');
}
if (! empty($uri))
{
$fullPath .= '/' . $uri;
}
$url = new \CodeIgniter\HTTP\URI($fullPath);
// allow the scheme to be over-ridden; else, use default
if (! empty($protocol))
{
$url->setScheme($protocol);
}
return (string) $url;
}
}
//--------------------------------------------------------------------
if (! function_exists('base_url'))
{
/**
* Return the base URL to use in views
*
* @param mixed $uri URI string or array of URI segments
* @param string $protocol
* @return string
*/
function base_url($uri = '', string $protocol = null): string
{
// convert segment array to string
if (is_array($uri))
{
$uri = implode('/', $uri);
}
// We should be using the configured baseURL that the user set;
// otherwise get rid of the path, because we have
// no way of knowing the intent...
$config = \CodeIgniter\Config\Services::request()->config;
$url = new \CodeIgniter\HTTP\URI($config->baseURL);
unset($config);
// Merge in the path set by the user, if any
if (! empty($uri))
{
$url = $url->resolveRelativeURI($uri);
}
// If the scheme wasn't provided, check to
// see if it was a secure request
if (empty($protocol) && \CodeIgniter\Config\Services::request()->isSecure())
{
$protocol = 'https';
}
if (! empty($protocol))
{
$url->setScheme($protocol);
}
return (string) $url;
}
}
//--------------------------------------------------------------------
if (! function_exists('current_url'))
{
/**
* Current URL
*
* Returns the full URL (including segments) of the page where this
* function is placed
*
* @param boolean $returnObject True to return an object instead of a strong
*
* @return string|\CodeIgniter\HTTP\URI
*/
function current_url(bool $returnObject = false)
{
return $returnObject ? \CodeIgniter\Config\Services::request()->uri : (string) \CodeIgniter\Config\Services::request()->uri;
}
}
//--------------------------------------------------------------------
if (! function_exists('previous_url'))
{
/**
* Returns the previous URL the current visitor was on. For security reasons
* we first check in a saved session variable, if it exists, and use that.
* If that's not available, however, we'll use a sanitized url from $_SERVER['HTTP_REFERER']
* which can be set by the user so is untrusted and not set by certain browsers/servers.
*
* @param boolean $returnObject
*
* @return \CodeIgniter\HTTP\URI|mixed|string
*/
function previous_url(bool $returnObject = false)
{
// Grab from the session first, if we have it,
// since it's more reliable and safer.
// Otherwise, grab a sanitized version from $_SERVER.
$referer = $_SESSION['_ci_previous_url'] ?? \CodeIgniter\Config\Services::request()->getServer('HTTP_REFERER', FILTER_SANITIZE_URL);
$referer = $referer ?? site_url('/');
return $returnObject ? new \CodeIgniter\HTTP\URI($referer) : $referer;
}
}
//--------------------------------------------------------------------
if (! function_exists('uri_string'))
{
/**
* URL String
*
* Returns the path part of the current URL
*
* @return string
*/
function uri_string(): string
{
return \CodeIgniter\Config\Services::request()->uri->getPath();
}
}
//--------------------------------------------------------------------
if (! function_exists('index_page'))
{
/**
* Index page
*
* Returns the "index_page" from your config file
*
* @param \Config\App|null $altConfig Alternate configuration to use
* @return string
*/
function index_page(\Config\App $altConfig = null): string
{
// use alternate config if provided, else default one
$config = $altConfig ?? config(\Config\App::class);
return $config->indexPage;
}
}
// ------------------------------------------------------------------------
if (! function_exists('anchor'))
{
/**
* Anchor Link
*
* Creates an anchor based on the local URL.
*
* @param mixed $uri URI string or array of URI segments
* @param string $title The link title
* @param mixed $attributes Any attributes
* @param \Config\App|null $altConfig Alternate configuration to use
*
* @return string
*/
function anchor($uri = '', string $title = '', $attributes = '', \Config\App $altConfig = null): string
{
// use alternate config if provided, else default one
$config = $altConfig ?? config(\Config\App::class);
$site_url = is_array($uri) ? site_url($uri, null, $config) : (preg_match('#^(\w+:)?//#i', $uri) ? $uri : site_url($uri, null, $config));
// eliminate trailing slash
$site_url = rtrim($site_url, '/');
if ($title === '')
{
$title = $site_url;
}
if ($attributes !== '')
{
$attributes = stringify_attributes($attributes);
}
return '<a href="' . $site_url . '"' . $attributes . '>' . $title . '</a>';
}
}
// ------------------------------------------------------------------------
if (! function_exists('anchor_popup'))
{
/**
* Anchor Link - Pop-up version
*
* Creates an anchor based on the local URL. The link
* opens a new window based on the attributes specified.
*
* @param string $uri the URL
* @param string $title the link title
* @param mixed $attributes any attributes
* @param \Config\App|null $altConfig Alternate configuration to use
*
* @return string
*/
function anchor_popup($uri = '', string $title = '', $attributes = false, \Config\App $altConfig = null): string
{
// use alternate config if provided, else default one
$config = $altConfig ?? config(\Config\App::class);
$site_url = preg_match('#^(\w+:)?//#i', $uri) ? $uri : site_url($uri, '', $config);
$site_url = rtrim($site_url, '/');
if ($title === '')
{
$title = $site_url;
}
if ($attributes === false)
{
return '<a href="' . $site_url . '" onclick="window.open(\'' . $site_url . "', '_blank'); return false;\">" . $title . '</a>';
}
if (! is_array($attributes))
{
$attributes = [$attributes];
// Ref: http://www.w3schools.com/jsref/met_win_open.asp
$window_name = '_blank';
}
elseif (! empty($attributes['window_name']))
{
$window_name = $attributes['window_name'];
unset($attributes['window_name']);
}
else
{
$window_name = '_blank';
}
foreach (['width' => '800', 'height' => '600', 'scrollbars' => 'yes', 'menubar' => 'no', 'status' => 'yes', 'resizable' => 'yes', 'screenx' => '0', 'screeny' => '0'] as $key => $val)
{
$atts[$key] = $attributes[$key] ?? $val;
unset($attributes[$key]);
}
$attributes = stringify_attributes($attributes);
return '<a href="' . $site_url
. '" onclick="window.open(\'' . $site_url . "', '" . $window_name . "', '" . stringify_attributes($atts, true) . "'); return false;\""
. $attributes . '>' . $title . '</a>';
}
}
// ------------------------------------------------------------------------
if (! function_exists('mailto'))
{
/**
* Mailto Link
*
* @param string $email the email address
* @param string $title the link title
* @param mixed $attributes any attributes
*
* @return string
*/
function mailto(string $email, string $title = '', $attributes = ''): string
{
if (trim($title) === '')
{
$title = $email;
}
return '<a href="mailto:' . $email . '"' . stringify_attributes($attributes) . '>' . $title . '</a>';
}
}
// ------------------------------------------------------------------------
if (! function_exists('safe_mailto'))
{
/**
* Encoded Mailto Link
*
* Create a spam-protected mailto link written in Javascript
*
* @param string $email the email address
* @param string $title the link title
* @param mixed $attributes any attributes
*
* @return string
*/
function safe_mailto(string $email, string $title = '', $attributes = ''): string
{
if (trim($title) === '')
{
$title = $email;
}
$x = str_split('<a href="mailto:', 1);
for ($i = 0, $l = strlen($email); $i < $l; $i ++)
{
$x[] = '|' . ord($email[$i]);
}
$x[] = '"';
if ($attributes !== '')
{
if (is_array($attributes))
{
foreach ($attributes as $key => $val)
{
$x[] = ' ' . $key . '="';
for ($i = 0, $l = strlen($val); $i < $l; $i ++)
{
$x[] = '|' . ord($val[$i]);
}
$x[] = '"';
}
}
else
{
for ($i = 0, $l = strlen($attributes); $i < $l; $i ++)
{
$x[] = $attributes[$i];
}
}
}
$x[] = '>';
$temp = [];
for ($i = 0, $l = strlen($title); $i < $l; $i ++)
{
$ordinal = ord($title[$i]);
if ($ordinal < 128)
{
$x[] = '|' . $ordinal;
}
else
{
if (empty($temp))
{
$count = ($ordinal < 224) ? 2 : 3;
}
$temp[] = $ordinal;
if (count($temp) === $count)
{
$number = ($count === 3) ? (($temp[0] % 16) * 4096) + (($temp[1] % 64) * 64) + ($temp[2] % 64) : (($temp[0] % 32) * 64) + ($temp[1] % 64);
$x[] = '|' . $number;
$count = 1;
$temp = [];
}
}
}
$x[] = '<';
$x[] = '/';
$x[] = 'a';
$x[] = '>';
$x = array_reverse($x);
// improve obfuscation by eliminating newlines & whitespace
$output = '<script type="text/javascript">'
. 'var l=new Array();';
for ($i = 0, $c = count($x); $i < $c; $i ++)
{
$output .= 'l[' . $i . "] = '" . $x[$i] . "';";
}
$output .= 'for (var i = l.length-1; i >= 0; i=i-1) {'
. "if (l[i].substring(0, 1) === '|') document.write(\"&#\"+unescape(l[i].substring(1))+\";\");"
. 'else document.write(unescape(l[i]));'
. '}'
. '</script>';
return $output;
}
}
// ------------------------------------------------------------------------
if (! function_exists('auto_link'))
{
/**
* Auto-linker
*
* Automatically links URL and Email addresses.
* Note: There's a bit of extra code here to deal with
* URLs or emails that end in a period. We'll strip these
* off and add them after the link.
*
* @param string $str the string
* @param string $type the type: email, url, or both
* @param boolean $popup whether to create pop-up links
*
* @return string
*/
function auto_link(string $str, string $type = 'both', bool $popup = false): string
{
// Find and replace any URLs.
if ($type !== 'email' && preg_match_all('#(\w*://|www\.)[^\s()<>;]+\w#i', $str, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER))
{
// Set our target HTML if using popup links.
$target = ($popup) ? ' target="_blank"' : '';
// We process the links in reverse order (last -> first) so that
// the returned string offsets from preg_match_all() are not
// moved as we add more HTML.
foreach (array_reverse($matches) as $match)
{
// $match[0] is the matched string/link
// $match[1] is either a protocol prefix or 'www.'
//
// With PREG_OFFSET_CAPTURE, both of the above is an array,
// where the actual value is held in [0] and its offset at the [1] index.
$a = '<a href="' . (strpos($match[1][0], '/') ? '' : 'http://') . $match[0][0] . '"' . $target . '>' . $match[0][0] . '</a>';
$str = substr_replace($str, $a, $match[0][1], strlen($match[0][0]));
}
}
// Find and replace any emails.
if ($type !== 'url' && preg_match_all('#([\w\.\-\+]+@[a-z0-9\-]+\.[a-z0-9\-\.]+[^[:punct:]\s])#i', $str, $matches, PREG_OFFSET_CAPTURE))
{
foreach (array_reverse($matches[0]) as $match)
{
if (filter_var($match[0], FILTER_VALIDATE_EMAIL) !== false)
{
$str = substr_replace($str, safe_mailto($match[0]), $match[1], strlen($match[0]));
}
}
}
return $str;
}
}
// ------------------------------------------------------------------------
if (! function_exists('prep_url'))
{
/**
* Prep URL - Simply adds the http:// part if no scheme is included.
*
* Formerly used URI, but that does not play nicely with URIs missing
* the scheme.
*
* @param string $str the URL
* @return string
*/
function prep_url(string $str = ''): string
{
if ($str === 'http://' || $str === '')
{
return '';
}
$url = parse_url($str);
if (! $url || ! isset($url['scheme']))
{
return 'http://' . $str;
}
return $str;
}
}
// ------------------------------------------------------------------------
if (! function_exists('url_title'))
{
/**
* Create URL Title
*
* Takes a "title" string as input and creates a
* human-friendly URL string with a "separator" string
* as the word separator.
*
* @param string $str Input string
* @param string $separator Word separator (usually '-' or '_')
* @param boolean $lowercase Whether to transform the output string to lowercase
* @return string
*/
function url_title(string $str, string $separator = '-', bool $lowercase = false): string
{
$q_separator = preg_quote($separator, '#');
$trans = [
'&.+?;' => '',
'[^\w\d _-]' => '',
'\s+' => $separator,
'(' . $q_separator . ')+' => $separator,
];
$str = strip_tags($str);
foreach ($trans as $key => $val)
{
// $str = preg_replace('#'.$key.'#i'.( UTF8_ENABLED ? 'u' : ''), $val, $str);
$str = preg_replace('#' . $key . '#iu', $val, $str);
}
if ($lowercase === true)
{
$str = mb_strtolower($str);
}
return trim(trim($str, $separator));
}
}
//--------------------------------------------------------------------

View File

@@ -0,0 +1,95 @@
<?php
/**
* CodeIgniter
*
* An open source application development framework for PHP
*
* This content is released under the MIT License (MIT)
*
* Copyright (c) 2014-2019 British Columbia Institute of Technology
* Copyright (c) 2019 CodeIgniter Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @package CodeIgniter
* @author CodeIgniter Dev Team
* @copyright 2019 CodeIgniter Foundation
* @license https://opensource.org/licenses/MIT MIT License
* @link https://codeigniter.com
* @since Version 1.0.0
* @filesource
*/
/**
* CodeIgniter XML Helpers
*
* @package CodeIgniter
*/
if (! function_exists('xml_convert'))
{
/**
* Convert Reserved XML characters to Entities
*
* @param string $str
* @param boolean $protect_all
* @return string
*/
function xml_convert(string $str, bool $protect_all = false): string
{
$temp = '__TEMP_AMPERSANDS__';
// Replace entities to temporary markers so that
// ampersands won't get messed up
$str = preg_replace('/&#(\d+);/', $temp . '\\1;', $str);
if ($protect_all === true)
{
$str = preg_replace('/&(\w+);/', $temp . '\\1;', $str);
}
$original = [
'&',
'<',
'>',
'"',
"'",
'-',
];
$replacement = [
'&amp;',
'&lt;',
'&gt;',
'&quot;',
'&apos;',
'&#45;',
];
$str = str_replace($original, $replacement, $str);
// Decode the temp markers back to entities
$str = preg_replace('/' . $temp . '(\d+);/', '&#\\1;', $str);
if ($protect_all === true)
{
return preg_replace('/' . $temp . '(\w+);/', '&\\1;', $str);
}
return $str;
}
}