protected function releaseLock(): bool
	{
		if (! $this->lock)
		{
			return true;
		}

		if ($this->platform === 'mysql')
		{
			if ($this->db->query("SELECT RELEASE_LOCK('{$this->lock}') AS ci_session_lock")->getRow()->ci_session_lock)
			{
				$this->lock = false;
				return true;
			}

			return $this->fail();
		}
		elseif ($this->platform === 'postgre')
		{
			if ($this->db->simpleQuery("SELECT pg_advisory_unlock({$this->lock})"))
			{
				$this->lock = false;
				return true;
			}

			return $this->fail();
		}

		// Unsupported DB? Let the parent handle the simple version.
		return parent::releaseLock();
	}

Releases the lock, if any.

@return boolean


public function attachHoneypot(ResponseInterface $response)
	{
		$prep_field = $this->prepareTemplate($this->config->template);

		$body = $response->getBody();
		$body = str_ireplace('</form>', $prep_field, $body);
		$response->setBody($body);
	}

public function attachHoneypot ( ResponseInterface $ response ) { $ prep_field = $ this -> prepareTemplate ( $ this -> config -> template ) ; $ body = $ response -> getBody ( ) ; $ body = str_ireplace ( '</form>' , $ prep_field , $ body ) ; $ response -> setBody ( $ body ) ; }

Attaches Honeypot template to response.

@param \CodeIgniter\HTTP\ResponseInterface $response

Attaches Honeypot template to response .


protected function prepareTemplate(string $template): string
	{
		$template = str_ireplace('{label}', $this->config->label, $template);
		$template = str_ireplace('{name}', $this->config->name, $template);

		if ($this->config->hidden)
		{
			$template = '
' . $template . '
';
		}
		return $template;
	}

protected
function
prepareTemplate
(
string
$
template
)
:
string
{
$
template
=
str_ireplace
(
'{label}'
,
$
this
->
config
->
label
,
$
template
)
;
$
template
=
str_ireplace
(
'{name}'
,
$
this
->
config
->
name
,
$
template
)
;
if
(
$
this
->
config
->
hidden
)
{
$
template
=
'
'
.
$
template
.
'
'
;
}
return
$
template
;
}

Prepares the template by adding label
content and field name.

@param  string $template
@return string

Prepares the template by adding label content and field name .


protected function fetchObject(string $className = 'stdClass')
	{
		// No native support for fetching rows as objects
		if (($row = $this->fetchAssoc()) === false)
		{
			return false;
		}
		elseif ($className === 'stdClass')
		{
			return (object) $row;
		}

		$classObj = new $className();
		$classSet = \Closure::bind(function ($key, $value) {
			$this->$key = $value;
		}, $classObj, $className
		);
		foreach (array_keys($row) as $key)
		{
			$classSet($key, $row[$key]);
		}
		return $classObj;
	}

Returns the result set as an object.

Overridden by child classes.

@param string $className

@return object|boolean


public function makeColumns($array = [], $columnLimit = 0)
	{
		if (! is_array($array) || count($array) === 0 || ! is_int($columnLimit))
		{
			return false;
		}

		// Turn off the auto-heading feature since it's doubtful we
		// will want headings from a one-dimensional array
		$this->autoHeading = false;

		if ($columnLimit === 0)
		{
			return $array;
		}

		$new = [];
		do
		{
			$temp = array_splice($array, 0, $columnLimit);

			if (count($temp) < $columnLimit)
			{
				for ($i = count($temp); $i < $columnLimit; $i ++)
				{
					$temp[] = ' ';
				}
			}

			$new[] = $temp;
		}
		while (count($array) > 0);

		return $new;
	}

Set columns. Takes a one-dimensional array as input and creates
a multi-dimensional array with a depth equal to the number of
columns. This allows a single array with many elements to be
displayed in a table that has a fixed column count.

@param  array   $array
@param  integer $columnLimit
@return array

Set columns . Takes a one - dimensional array as input and creates a multi - dimensional array with a depth equal to the number of columns . This allows a single array with many elements to be displayed in a table that has a fixed column count .


public function clear()
	{
		$this->rows        = [];
		$this->heading     = [];
		$this->footing     = [];
		$this->autoHeading = true;
		$this->caption     = null;
		return $this;
	}

public function clear ( ) { $ this -> rows = [ ] ; $ this -> heading = [ ] ; $ this -> footing = [ ] ; $ this -> autoHeading = true ; $ this -> caption = null ; return $ this ; }

Clears the table arrays.  Useful if multiple tables are being generated

@return Table

Clears the table arrays . Useful if multiple tables are being generated


protected function _setFromDBResult($object)
	{
		// First generate the headings from the table column names
		if ($this->autoHeading === true && empty($this->heading))
		{
			$this->heading = $this->_prepArgs($object->getFieldNames());
		}

		foreach ($object->getResultArray() as $row)
		{
			$this->rows[] = $this->_prepArgs($row);
		}
	}

Set table data from a database result object

@param  BaseResult $object Database result object
@return void


protected function _setFromArray($data)
	{
		if ($this->autoHeading === true && empty($this->heading))
		{
			$this->heading = $this->_prepArgs(array_shift($data));
		}

		foreach ($data as &$row)
		{
			$this->rows[] = $this->_prepArgs($row);
		}
	}

protected function _setFromArray ( $ data ) { if ( $ this -> autoHeading === true && empty ( $ this -> heading ) ) { $ this -> heading = $ this -> _prepArgs ( array_shift ( $ data ) ) ; } foreach ( $ data as & $ row ) { $ this -> rows [ ] = $ this -> _prepArgs ( $ row ) ; } }

Set table data from an array

@param  array $data
@return void


protected function setPath(string $path): string
	{
		if (! is_dir($path))
		{
			mkdir($path, 0777, true);
			//create the index.html file
			if (! is_file($path . 'index.html'))
			{
				$file = fopen($path . 'index.html', 'x+');
				fclose($file);
			}
		}
		return $path;
	}

protected
function
setPath
(
string
$
path
)
:
string
{
if
(
!
is_dir
(
$
path
)
)
{
mkdir
(
$
path
,
0777
,
true
)
;
//create the index.html file
if
(
!
is_file
(
$
path
.
'index.html'
)
)
{
$
file
=
fopen
(
$
path
.
'index.html'
,
'x+'
)
;
fclose
(
$
file
)
;
}
}
return
$
path
;
}

create file target path if
the set path does not exist

@param string $path

@return string The path set or created.


public function getErrorString(): string
	{
		$errors = [
			UPLOAD_ERR_OK         => lang('HTTP.uploadErrOk'),
			UPLOAD_ERR_INI_SIZE   => lang('HTTP.uploadErrIniSize'),
			UPLOAD_ERR_FORM_SIZE  => lang('HTTP.uploadErrFormSize'),
			UPLOAD_ERR_PARTIAL    => lang('HTTP.uploadErrPartial'),
			UPLOAD_ERR_NO_FILE    => lang('HTTP.uploadErrNoFile'),
			UPLOAD_ERR_CANT_WRITE => lang('HTTP.uploadErrCantWrite'),
			UPLOAD_ERR_NO_TMP_DIR => lang('HTTP.uploadErrNoTmpDir'),
			UPLOAD_ERR_EXTENSION  => lang('HTTP.uploadErrExtension'),
		];

		$error = is_null($this->error) ? UPLOAD_ERR_OK : $this->error;

		return sprintf($errors[$error] ?? lang('HTTP.uploadErrUnknown'), $this->getName());
	}

public function getErrorString ( ) : string { $ errors = [ UPLOAD_ERR_OK => lang ( 'HTTP.uploadErrOk' ) , UPLOAD_ERR_INI_SIZE => lang ( 'HTTP.uploadErrIniSize' ) , UPLOAD_ERR_FORM_SIZE => lang ( 'HTTP.uploadErrFormSize' ) , UPLOAD_ERR_PARTIAL => lang ( 'HTTP.uploadErrPartial' ) , UPLOAD_ERR_NO_FILE => lang ( 'HTTP.uploadErrNoFile' ) , UPLOAD_ERR_CANT_WRITE => lang ( 'HTTP.uploadErrCantWrite' ) , UPLOAD_ERR_NO_TMP_DIR => lang ( 'HTTP.uploadErrNoTmpDir' ) , UPLOAD_ERR_EXTENSION => lang ( 'HTTP.uploadErrExtension' ) , ] ; $ error = is_null ( $ this -> error ) ? UPLOAD_ERR_OK : $ this -> error ; return sprintf ( $ errors [ $ error ] ?? lang ( 'HTTP.uploadErrUnknown' ) , $ this -> getName ( ) ) ; }


public function store(string $folderName = null, string $fileName = null): string
	{
		$folderName = $folderName ?? date('Ymd');
		$fileName   = $fileName ?? $this->getRandomName();

		// Move the uploaded file to a new location.
		return ($this->move(WRITEPATH . 'uploads/' . $folderName, $fileName)) ?
				$folderName . DIRECTORY_SEPARATOR . $this->name : null;
	}

Save the uploaded file to a new location.

By default, upload files are saved in writable/uploads directory. The YYYYMMDD folder
and random file name will be created.

@param  string $folderName the folder name to writable/uploads directory.
@param  string $fileName   the name to rename the file to.
@return string file full path

Save the uploaded file to a new location .


public function max_size(string $blank = null, string $params, array $data): bool
	{
		// Grab the file name off the top of the $params
		// after we split it.
		$params = explode(',', $params);
		$name   = array_shift($params);

		$file = $this->request->getFile($name);

		if (is_null($file))
		{
			return false;
		}
		return $params[0] >= $file->getSize() / 1024;
	}

Verifies if the file's size in Kilobytes is no larger than the parameter.

@param string|null $blank
@param string      $params
@param array       $data

@return boolean

Verifies if the file s size in Kilobytes is no larger than the parameter .


public function is_image(string $blank = null, string $params, array $data): bool
	{
		// Grab the file name off the top of the $params
		// after we split it.
		$params = explode(',', $params);
		$name   = array_shift($params);

		$file = $this->request->getFile($name);

		if (is_null($file))
		{
			return false;
		}

		// We know that our mimes list always has the first mime
		// start with `image` even when then are multiple accepted types.
		$type = \Config\Mimes::guessTypeFromExtension($file->getExtension());

		return mb_strpos($type, 'image') === 0;
	}

Uses the mime config file to determine if a file is considered an "image",
which for our purposes basically means that it's a raster image or svg.

@param string|null $blank
@param string      $params
@param array       $data

@return boolean

Uses the mime config file to determine if a file is considered an image which for our purposes basically means that it s a raster image or svg .


public function mime_in(string $blank = null, string $params, array $data): bool
	{
		// Grab the file name off the top of the $params
		// after we split it.
		$params = explode(',', $params);
		$name   = array_shift($params);

		$file = $this->request->getFile($name);

		if (is_null($file))
		{
			return false;
		}

		return in_array($file->getMimeType(), $params);
	}

Checks to see if an uploaded file's mime type matches one in the parameter.

@param string|null $blank
@param string      $params
@param array       $data

@return boolean

Checks to see if an uploaded file s mime type matches one in the parameter .


public function max_dims(string $blank = null, string $params, array $data): bool
	{
		// Grab the file name off the top of the $params
		// after we split it.
		$params = explode(',', $params);
		$name   = array_shift($params);

		$file = $this->request->getFile($name);

		if (is_null($file))
		{
			return false;
		}

		// Get Parameter sizes
		$allowedWidth  = $params[0] ?? 0;
		$allowedHeight = $params[1] ?? 0;

		// Get uploaded image size
		$info       = getimagesize($file->getTempName());
		$fileWidth  = $info[0];
		$fileHeight = $info[1];

		return $fileWidth <= $allowedWidth && $fileHeight <= $allowedHeight;
	}

Checks an uploaded file to verify that the dimensions are within
a specified allowable dimension.

@param string|null $blank
@param string      $params
@param array       $data

@return boolean

Checks an uploaded file to verify that the dimensions are within a specified allowable dimension .


public function fetchGlobal($method, $index = null, $filter = null, $flags = null)
	{
		$method = strtolower($method);

		if (! isset($this->globals[$method]))
		{
			$this->populateGlobals($method);
		}

		// Null filters cause null values to return.
		if (is_null($filter))
		{
			$filter = FILTER_DEFAULT;
		}

		// Return all values when $index is null
		if (is_null($index))
		{
			$values = [];
			foreach ($this->globals[$method] as $key => $value)
			{
				$values[$key] = is_array($value)
					? $this->fetchGlobal($method, $key, $filter, $flags)
					: filter_var($value, $filter, $flags);
			}

			return $values;
		}

		// allow fetching multiple keys at once
		if (is_array($index))
		{
			$output = [];

			foreach ($index as $key)
			{
				$output[$key] = $this->fetchGlobal($method, $key, $filter, $flags);
			}

			return $output;
		}

		// Does the index contain array notation?
		if (($count = preg_match_all('/(?:^[^\[]+)|\[[^]]*\]/', $index, $matches)) > 1)
		{
			$value = $this->globals[$method];
			for ($i = 0; $i < $count; $i++)
			{
				$key = trim($matches[0][$i], '[]');

				if ($key === '') // Empty notation will return the value as array
				{
					break;
				}

				if (isset($value[$key]))
				{
					$value = $value[$key];
				}
				else
				{
					return null;
				}
			}
		}

		if (! isset($value))
		{
			$value = $this->globals[$method][$index] ?? null;
		}

		// Cannot filter these types of data automatically...
		if (is_array($value) || is_object($value) || is_null($value))
		{
			return $value;
		}

		return filter_var($value, $filter, $flags);
	}

Fetches one or more items from a global, like cookies, get, post, etc.
Can optionally filter the input when you retrieve it by passing in
a filter.

If $type is an array, it must conform to the input allowed by the
filter_input_array method.

http://php.net/manual/en/filter.filters.sanitize.php

@param string            $method Input filter constant
@param string|array|null $index
@param integer|null      $filter Filter constant
@param mixed             $flags

@return mixed

Fetches one or more items from a global like cookies get post etc . Can optionally filter the input when you retrieve it by passing in a filter .


protected function populateGlobals(string $method)
	{
		if (! isset($this->globals[$method]))
		{
			$this->globals[$method] = [];
		}

		// Don't populate ENV as it might contain
		// sensitive data that we don't want to get logged.
		switch($method)
		{
			case 'get':
				$this->globals['get'] = $_GET;
				break;
			case 'post':
				$this->globals['post'] = $_POST;
				break;
			case 'request':
				$this->globals['request'] = $_REQUEST;
				break;
			case 'cookie':
				$this->globals['cookie'] = $_COOKIE;
				break;
			case 'server':
				$this->globals['server'] = $_SERVER;
				break;
		}
	}

Saves a copy of the current state of one of several PHP globals
so we can retrieve them later.

@param string $method

Saves a copy of the current state of one of several PHP globals so we can retrieve them later .


public function run(array $params = [])
	{
		$runner = Services::migrations();

		// Get the version number
		$version = array_shift($params);

		if (is_null($version))
		{
			$version = CLI::prompt(lang('Migrations.version'));
		}

		if (is_null($version))
		{
			CLI::error(lang('Migrations.invalidVersion'));
			exit();
		}

		CLI::write(sprintf(lang('Migrations.toVersionPH'), $version), 'yellow');

		$namespace = $params['-n'] ?? CLI::getOption('n');
		$group     = $params['-g'] ?? CLI::getOption('g');

		try
		{
			$runner->version($version, $namespace, $group);
			CLI::write('Done');
		}
		catch (\Exception $e)
		{
			$this->showError($e);
		}
	}

public
function
run
(
array
$
params
=
[
]
)
{
$
runner
=
Services
::
migrations
(
)
;
// Get the version number
$
version
=
array_shift
(
$
params
)
;
if
(
is_null
(
$
version
)
)
{
$
version
=
CLI
::
prompt
(
lang
(
'Migrations.version'
)
)
;
}
if
(
is_null
(
$
version
)
)
{
CLI
::
error
(
lang
(
'Migrations.invalidVersion'
)
)
;
exit
(
)
;
}
CLI
::
write
(
sprintf
(
lang
(
'Migrations.toVersionPH'
)
,
$
version
)
,
'yellow'
)
;
$
namespace
=
$
params
[
'-n'
]
??
CLI
::
getOption
(
'n'
)
;
$
group
=
$
params
[
'-g'
]
??
CLI
::
getOption
(
'g'
)
;
try
{
$
runner
->
version
(
$
version
,
$
namespace
,
$
group
)
;
CLI
::
write
(
'Done'
)
;
}
catch
(
\
Exception
$
e
)
{
$
this
->
showError
(
$
e
)
;
}
}

Migrates the database up or down to get to the specified version.

@param array $params

Migrates the database up or down to get to the specified version .


public function fromTable(string $table)
	{
		$this->prefixedTableName = $table;

		// Remove the prefix, if any, since it's
		// already been added by the time we get here...
		$prefix = $this->db->DBPrefix;
		if (! empty($prefix))
		{
			if (strpos($table, $prefix) === 0)
			{
				$table = substr($table, strlen($prefix));
			}
		}

		if (! $this->db->tableExists($this->prefixedTableName))
		{
			throw DataException::forTableNotFound($this->prefixedTableName);
		}

		$this->tableName = $table;

		$this->fields = $this->formatFields($this->db->getFieldData($table));

		$this->keys = array_merge($this->keys, $this->formatKeys($this->db->getIndexData($table)));

		$this->foreignKeys = $this->db->getForeignKeyData($table);

		return $this;
	}

Reads an existing database table and
collects all of the information needed to
recreate this table.

@param string $table

@return \CodeIgniter\Database\SQLite3\Table

Reads an existing database table and collects all of the information needed to recreate this table .


public function run(): bool
	{
		$this->db->query('PRAGMA foreign_keys = OFF');

		$this->db->transStart();

		$this->forge->renameTable($this->tableName, "temp_{$this->tableName}");

		$this->forge->reset();

		$this->createTable();

		$this->copyData();

		$this->forge->dropTable("temp_{$this->tableName}");

		$success = $this->db->transComplete();

		$this->db->query('PRAGMA foreign_keys = ON');

		return $success;
	}

public
function
run
(
)
:
bool
{
$
this
->
db
->
query
(
'PRAGMA foreign_keys = OFF'
)
;
$
this
->
db
->
transStart
(
)
;
$
this
->
forge
->
renameTable
(
$
this
->
tableName
,
"temp_{$this->tableName}"
)
;
$
this
->
forge
->
reset
(
)
;
$
this
->
createTable
(
)
;
$
this
->
copyData
(
)
;
$
this
->
forge
->
dropTable
(
"temp_{$this->tableName}"
)
;
$
success
=
$
this
->
db
->
transComplete
(
)
;
$
this
->
db
->
query
(
'PRAGMA foreign_keys = ON'
)
;
return
$
success
;
}

Called after `fromTable` and any actions, like `dropColumn`, etc,
to finalize the action. It creates a temp table, creates the new
table with modifications, and copies the data over to the new table.

@return boolean

Called after fromTable and any actions like dropColumn etc to finalize the action . It creates a temp table creates the new table with modifications and copies the data over to the new table .


public function modifyColumn(array $field)
	{
		$field = $field[0];

		$oldName = $field['name'];
		unset($field['name']);

		$this->fields[$oldName] = $field;

		return $this;
	}

public function modifyColumn ( array $ field ) { $ field = $ field [ 0 ] ; $ oldName = $ field [ 'name' ] ; unset ( $ field [ 'name' ] ) ; $ this -> fields [ $ oldName ] = $ field ; return $ this ; }

Modifies a field, including changing data type,
renaming, etc.

@param array $field

@return \CodeIgniter\Database\SQLite3\Table

Modifies a field including changing data type renaming etc .


protected function createTable()
	{
		$this->dropIndexes();
		$this->db->resetDataCache();

		// Handle any modified columns.
		$fields = [];
		foreach ($this->fields as $name => $field)
		{
			if (isset($field['new_name']))
			{
				$fields[$field['new_name']] = $field;
				continue;
			}

			$fields[$name] = $field;
		}

		$this->forge->addField($fields);

		// Unique/Index keys
		if (is_array($this->keys))
		{
			foreach ($this->keys as $key)
			{
				switch ($key['type'])
				{
					case 'primary':
						$this->forge->addPrimaryKey($key['fields']);
						break;
					case 'unique':
						$this->forge->addUniqueKey($key['fields']);
						break;
					case 'index':
						$this->forge->addKey($key['fields']);
						break;
				}
			}
		}

		// Foreign Keys

		return $this->forge->createTable($this->tableName);
	}

protected
function
createTable
(
)
{
$
this
->
dropIndexes
(
)
;
$
this
->
db
->
resetDataCache
(
)
;
// Handle any modified columns.
$
fields
=
[
]
;
foreach
(
$
this
->
fields
as
$
name
=>
$
field
)
{
if
(
isset
(
$
field
[
'new_name'
]
)
)
{
$
fields
[
$
field
[
'new_name'
]
]
=
$
field
;
continue
;
}
$
fields
[
$
name
]
=
$
field
;
}
$
this
->
forge
->
addField
(
$
fields
)
;
// Unique/Index keys
if
(
is_array
(
$
this
->
keys
)
)
{
foreach
(
$
this
->
keys
as
$
key
)
{
switch
(
$
key
[
'type'
]
)
{
case
'primary'
:
$
this
->
forge
->
addPrimaryKey
(
$
key
[
'fields'
]
)
;
break
;
case
'unique'
:
$
this
->
forge
->
addUniqueKey
(
$
key
[
'fields'
]
)
;
break
;
case
'index'
:
$
this
->
forge
->
addKey
(
$
key
[
'fields'
]
)
;
break
;
}
}
}
// Foreign Keys
return
$
this
->
forge
->
createTable
(
$
this
->
tableName
)
;
}

Creates the new table based on our current fields.

@return mixed

Creates the new table based on our current fields .


protected function copyData()
	{
		$exFields  = [];
		$newFields = [];

		foreach ($this->fields as $name => $details)
		{
			// Are we modifying the column?
			if (isset($details['new_name']))
			{
				$newFields[] = $details['new_name'];
			}
			else
			{
				$newFields[] = $name;
			}

			$exFields[] = $name;
		}

		$exFields  = implode(', ', $exFields);
		$newFields = implode(', ', $newFields);

		$this->db->query("INSERT INTO {$this->prefixedTableName}({$newFields}) SELECT {$exFields} FROM {$this->db->DBPrefix}temp_{$this->tableName}");
	}

Copies data from our old table to the new one,
taking care map data correctly based on any columns
that have been renamed.

@return void

Copies data from our old table to the new one taking care map data correctly based on any columns that have been renamed .


protected function formatFields($fields)
	{
		if (! is_array($fields))
		{
			return $fields;
		}

		$return = [];

		foreach ($fields as $field)
		{
			$return[$field->name] = [
				'type'     => $field->type,
				'default'  => $field->default,
				'nullable' => $field->nullable,
			];

			if ($field->primary_key)
			{
				$this->keys[$field->name] = [
					'fields' => [$field->name],
					'type'   => 'primary',
				];
			}
		}

		return $return;
	}

protected function formatFields ( $ fields ) { if ( ! is_array ( $ fields ) ) { return $ fields ; } $ return = [ ] ; foreach ( $ fields as $ field ) { $ return [ $ field -> name ] = [ 'type' => $ field -> type , 'default' => $ field -> default , 'nullable' => $ field -> nullable , ] ; if ( $ field -> primary_key ) { $ this -> keys [ $ field -> name ] = [ 'fields' => [ $ field -> name ] , 'type' => 'primary' , ] ; } } return $ return ; }

Converts fields retrieved from the database to
the format needed for creating fields with Forge.

@param array|boolean $fields

@return mixed

Converts fields retrieved from the database to the format needed for creating fields with Forge .


protected function formatKeys($keys)
	{
		if (! is_array($keys))
		{
			return $keys;
		}

		$return = [];

		foreach ($keys as $name => $key)
		{
			$return[$name] = [
				'fields' => $key->fields,
				'type'   => 'index',
			];
		}

		return $return;
	}

protected function formatKeys ( $ keys ) { if ( ! is_array ( $ keys ) ) { return $ keys ; } $ return = [ ] ; foreach ( $ keys as $ name => $ key ) { $ return [ $ name ] = [ 'fields' => $ key -> fields , 'type' => 'index' , ] ; } return $ return ; }

Converts keys retrieved from the database to
the format needed to create later.

@param mixed $keys

@return mixed

Converts keys retrieved from the database to the format needed to create later .


protected function dropIndexes()
	{
		if (! is_array($this->keys) || ! count($this->keys))
		{
			return;
		}

		foreach ($this->keys as $name => $key)
		{
			if ($key['type'] === 'primary' || $key['type'] === 'unique')
			{
				continue;
			}

			$this->db->query("DROP INDEX IF EXISTS '{$name}'");
		}
	}

protected
function
dropIndexes
(
)
{
if
(
!
is_array
(
$
this
->
keys
)
||
!
count
(
$
this
->
keys
)
)
{
return
;
}
foreach
(
$
this
->
keys
as
$
name
=>
$
key
)
{
if
(
$
key
[
'type'
]
===
'primary'
||
$
key
[
'type'
]
===
'unique'
)
{
continue
;
}
$
this
->
db
->
query
(
"DROP INDEX IF EXISTS '{$name}'"
)
;
}
}

Attempts to drop all indexes and constraints
from the database for this table.

@return null|void

Attempts to drop all indexes and constraints from the database for this table .


public function CSRFSetCookie(RequestInterface $request)
	{
		$expire        = time() + $this->CSRFExpire;
		$secure_cookie = (bool) $this->cookieSecure;

		if ($secure_cookie && ! $request->isSecure())
		{
			return false;
		}

		setcookie(
				$this->CSRFCookieName, $this->CSRFHash, $expire, $this->cookiePath, $this->cookieDomain, $secure_cookie, true                // Enforce HTTP only cookie for security
		);

		log_message('info', 'CSRF cookie sent');

		return $this;
	}

CSRF Set Cookie

@codeCoverageIgnore

@param RequestInterface|\CodeIgniter\HTTP\IncomingRequest $request

@return Security|false


protected function CSRFSetHash(): string
	{
		if ($this->CSRFHash === null)
		{
			// If the cookie exists we will use its value.
			// We don't necessarily want to regenerate it with
			// each page load since a page could contain embedded
			// sub-pages causing this feature to fail
			if (isset($_COOKIE[$this->CSRFCookieName]) && is_string($_COOKIE[$this->CSRFCookieName]) && preg_match('#^[0-9a-f]{32}$#iS', $_COOKIE[$this->CSRFCookieName]) === 1
			)
			{
				return $this->CSRFHash = $_COOKIE[$this->CSRFCookieName];
			}

			$rand           = random_bytes(16);
			$this->CSRFHash = bin2hex($rand);
		}

		return $this->CSRFHash;
	}

Sets the CSRF Hash and cookie.

@return string
@throws \Exception


public static function now($timezone = null, string $locale = null)
	{
		return new Time(null, $timezone, $locale);
	}

public static function now ( $ timezone = null , string $ locale = null ) { return new Time ( null , $ timezone , $ locale ) ; }

Returns a new Time instance with the timezone set.

@param string|DateTimeZone|null $timezone
@param string|null              $locale

@return \CodeIgniter\I18n\Time
@throws \Exception

Returns a new Time instance with the timezone set .


public static function parse(string $datetime, $timezone = null, string $locale = null)
	{
		return new Time($datetime, $timezone, $locale);
	}

public static function parse ( string $ datetime , $ timezone = null , string $ locale = null ) { return new Time ( $ datetime , $ timezone , $ locale ) ; }

Returns a new Time instance while parsing a datetime string.

Example:
$time = Time::parse('first day of December 2008');

@param string      $datetime
@param string|null $timezone
@param string|null $locale

@return \CodeIgniter\I18n\Time
@throws \Exception

Returns a new Time instance while parsing a datetime string .


public static function today($timezone = null, string $locale = null)
	{
		return new Time(date('Y-m-d 00:00:00'), $timezone, $locale);
	}

public
static
function
today
(
$
timezone
=
,
string
$
locale
=
)
{
return
new
Time
(
date
(
'Y-m-d 00:00:00'
)
,
$
timezone
,
$
locale
)
;
}

Return a new time with the time set to midnight.

@param null        $timezone
@param string|null $locale

@return \CodeIgniter\I18n\Time
@throws \Exception

Return a new time with the time set to midnight .


public static function yesterday($timezone = null, string $locale = null)
	{
		return new Time(date('Y-m-d 00:00:00', strtotime('-1 day')), $timezone, $locale);
	}

public
static
function
yesterday
(
$
timezone
=
,
string
$
locale
=
)
{
return
new
Time
(
date
(
'Y-m-d 00:00:00'
,
strtotime
(
'-1 day'
)
)
,
$
timezone
,
$
locale
)
;
}

Returns an instance set to midnight yesterday morning.

@param null        $timezone
@param string|null $locale

@return \CodeIgniter\I18n\Time
@throws \Exception

Returns an instance set to midnight yesterday morning .


public static function tomorrow($timezone = null, string $locale = null)
	{
		return new Time(date('Y-m-d 00:00:00', strtotime('+1 day')), $timezone, $locale);
	}

public
static
function
tomorrow
(
$
timezone
=
,
string
$
locale
=
)
{
return
new
Time
(
date
(
'Y-m-d 00:00:00'
,
strtotime
(
'+1 day'
)
)
,
$
timezone
,
$
locale
)
;
}

Returns an instance set to midnight tomorrow morning.

@param null        $timezone
@param string|null $locale

@return \CodeIgniter\I18n\Time
@throws \Exception

Returns an instance set to midnight tomorrow morning .


public static function createFromDate(int $year = null, int $month = null, int $day = null, $timezone = null, string $locale = null)
	{
		return static::create($year, $month, $day, null, null, null, $timezone, $locale);
	}

public static function createFromDate ( int $ year = null , int $ month = null , int $ day = null , $ timezone = null , string $ locale = null ) { return static :: create ( $ year , $ month , $ day , null , null , null , $ timezone , $ locale ) ; }

Returns a new instance based on the year, month and day. If any of those three
are left empty, will default to the current value.

@param integer|null $year
@param integer|null $month
@param integer|null $day
@param null         $timezone
@param string       $locale

@return \CodeIgniter\I18n\Time
@throws \Exception

Returns a new instance based on the year month and day . If any of those three are left empty will default to the current value .


public static function createFromTime(int $hour = null, int $minutes = null, int $seconds = null, $timezone = null, string $locale = null)
	{
		return static::create(null, null, null, $hour, $minutes, $seconds, $timezone, $locale);
	}

public static function createFromTime ( int $ hour = null , int $ minutes = null , int $ seconds = null , $ timezone = null , string $ locale = null ) { return static :: create ( null , null , null , $ hour , $ minutes , $ seconds , $ timezone , $ locale ) ; }

Returns a new instance with the date set to today, and the time set to the values passed in.

@param integer|null $hour
@param integer|null $minutes
@param integer|null $seconds
@param null         $timezone
@param string|null  $locale

@return \CodeIgniter\I18n\Time
@throws \Exception

Returns a new instance with the date set to today and the time set to the values passed in .


public static function create(int $year = null, int $month = null, int $day = null, int $hour = null, int $minutes = null, int $seconds = null, $timezone = null, string $locale = null)
	{
		$year    = is_null($year) ? date('Y') : $year;
		$month   = is_null($month) ? date('m') : $month;
		$day     = is_null($day) ? date('d') : $day;
		$hour    = empty($hour) ? 0 : $hour;
		$minutes = empty($minutes) ? 0 : $minutes;
		$seconds = empty($seconds) ? 0 : $seconds;

		return new Time(date('Y-m-d H:i:s', strtotime("{$year}-{$month}-{$day} {$hour}:{$minutes}:{$seconds}")), $timezone, $locale);
	}

Returns a new instance with the date time values individually set.

@param integer|null $year
@param integer|null $month
@param integer|null $day
@param integer|null $hour
@param integer|null $minutes
@param integer|null $seconds
@param null         $timezone
@param string|null  $locale

@return \CodeIgniter\I18n\Time
@throws \Exception

Returns a new instance with the date time values individually set .


public static function createFromFormat($format, $datetime, $timeZone = null)
	{
		$date = parent::createFromFormat($format, $datetime);

		return new Time($date->format('Y-m-d H:i:s'), $timeZone);
	}

public
static
function
createFromFormat
(
$
format
,
$
datetime
,
$
timeZone
=
)
{
$
date
=
parent
::
createFromFormat
(
$
format
,
$
datetime
)
;
return
new
Time
(
$
date
->
format
(
'Y-m-d H:i:s'
)
,
$
timeZone
)
;
}

Provides a replacement for DateTime's own createFromFormat function, that provides
more flexible timeZone handling

@param string                $format
@param string                $datetime
@param DateTimeZone|string   $timeZone

@return \CodeIgniter\I18n\Time
@throws \Exception

Provides a replacement for DateTime s own createFromFormat function that provides more flexible timeZone handling


public static function createFromTimestamp(int $timestamp, $timeZone = null, string $locale = null)
	{
		return new Time(date('Y-m-d H:i:s', $timestamp), $timeZone, $locale);
	}

public
static
function
createFromTimestamp
(
int
$
timestamp
,
$
timeZone
=
,
string
$
locale
=
)
{
return
new
Time
(
date
(
'Y-m-d H:i:s'
,
$
timestamp
)
,
$
timeZone
,
$
locale
)
;
}

Returns a new instance with the datetime set based on the provided UNIX timestamp.

@param integer      $timestamp
@param DateTimeZone $timeZone
@param string|null  $locale

@return \CodeIgniter\I18n\Time
@throws \Exception

Returns a new instance with the datetime set based on the provided UNIX timestamp .


public static function instance(DateTime $dateTime, string $locale = null)
	{
		$date     = $dateTime->format('Y-m-d H:i:s');
		$timezone = $dateTime->getTimezone();

		return new Time($date, $timezone, $locale);
	}

public
static
function
instance
(
DateTime
$
dateTime
,
string
$
locale
=
)
{
$
date
=
$
dateTime
->
format
(
'Y-m-d H:i:s'
)
;
$
timezone
=
$
dateTime
->
getTimezone
(
)
;
return
new
Time
(
$
date
,
$
timezone
,
$
locale
)
;
}

Takes an instance of DateTime and returns an instance of Time with it's same values.

@param \DateTime   $dateTime
@param string|null $locale

@return \CodeIgniter\I18n\Time
@throws \Exception

Takes an instance of DateTime and returns an instance of Time with it s same values .


public function toDateTime()
	{
		$dateTime = new DateTime(null, $this->getTimezone());
		$dateTime->setTimestamp(parent::getTimestamp());

		return $dateTime;
	}

public function toDateTime ( ) { $ dateTime = new DateTime ( null , $ this -> getTimezone ( ) ) ; $ dateTime -> setTimestamp ( parent :: getTimestamp ( ) ) ; return $ dateTime ; }

Converts the current instance to a mutable DateTime object.

@return \DateTime
@throws \Exception

Converts the current instance to a mutable DateTime object .


public function getAge()
	{
		$now  = Time::now()->getTimestamp();
		$time = $this->getTimestamp();

		// future dates have no age
		return max(0, date('Y', $now) - date('Y', $time));
	}

public
function
getAge
(
)
{
$
now
=
Time
::
now
(
)
->
getTimestamp
(
)
;
$
time
=
$
this
->
getTimestamp
(
)
;
// future dates have no age
return
max
(
0
,
date
(
'Y'
,
$
now
)
date
(
'Y'
,
$
time
)
)
;
}

Returns the age in years from the "current" date and 'now'
@throws \Exception

Returns the age in years from the current date and now


public function getDst(): bool
	{
		// grab the transactions that would affect today
		$start       = strtotime('-1 year', $this->getTimestamp());
		$end         = strtotime('+2 year', $start);
		$transitions = $this->timezone->getTransitions($start, $end);

		$daylightSaving = false;
		foreach ($transitions as $transition)
		{
			if ($transition['time'] > $this->format('U'))
			{
				$daylightSaving = (bool) $transition['isdst'] ?? $daylightSaving;
			}
		}
		return $daylightSaving;
	}

Are we in daylight savings time currently?

@return boolean


public function setMonth($value)
	{
		if (is_numeric($value) && $value < 1 || $value > 12)
		{
			throw I18nException::forInvalidMonth($value);
		}

		if (is_string($value) && ! is_numeric($value))
		{
			$value = date('m', strtotime("{$value} 1 2017"));
		}

		return $this->setValue('month', $value);
	}

public
function
setMonth
(
$
value
)
{
if
(
is_numeric
(
$
value
)
&&
$
value
<
1
||
$
value
>
12
)
{
throw
I18nException
::
forInvalidMonth
(
$
value
)
;
}
if
(
is_string
(
$
value
)
&&
!
is_numeric
(
$
value
)
)
{
$
value
=
date
(
'm'
,
strtotime
(
"{$value} 1 2017"
)
)
;
}
return
$
this
->
setValue
(
'month'
,
$
value
)
;
}

Sets the month of the year.

@param $value

@return \CodeIgniter\I18n\Time
@throws \Exception


public function setDay($value)
	{
		if ($value < 1 || $value > 31)
		{
			throw I18nException::forInvalidDay($value);
		}

		$date    = $this->getYear() . '-' . $this->getMonth();
		$lastDay = date('t', strtotime($date));
		if ($value > $lastDay)
		{
			throw I18nException::forInvalidOverDay($lastDay, $value);
		}

		return $this->setValue('day', $value);
	}

public function setDay ( $ value ) { if ( $ value < 1 || $ value > 31 ) { throw I18nException :: forInvalidDay ( $ value ) ; } $ date = $ this -> getYear ( ) . '-' . $ this -> getMonth ( ) ; $ lastDay = date ( 't' , strtotime ( $ date ) ) ; if ( $ value > $ lastDay ) { throw I18nException :: forInvalidOverDay ( $ lastDay , $ value ) ; } return $ this -> setValue ( 'day' , $ value ) ; }

Sets the day of the month.

@param $value

@return \CodeIgniter\I18n\Time
@throws \Exception


public function setMinute($value)
	{
		if ($value < 0 || $value > 59)
		{
			throw I18nException::forInvalidMinutes($value);
		}

		return $this->setValue('minute', $value);
	}

public function setMinute ( $ value ) { if ( $ value < 0 || $ value > 59 ) { throw I18nException :: forInvalidMinutes ( $ value ) ; } return $ this -> setValue ( 'minute' , $ value ) ; }

Sets the minute of the hour

@param $value

@return \CodeIgniter\I18n\Time
@throws \Exception


public function setSecond($value)
	{
		if ($value < 0 || $value > 59)
		{
			throw I18nException::forInvalidSeconds($value);
		}

		return $this->setValue('second', $value);
	}

public function setSecond ( $ value ) { if ( $ value < 0 || $ value > 59 ) { throw I18nException :: forInvalidSeconds ( $ value ) ; } return $ this -> setValue ( 'second' , $ value ) ; }

Sets the second of the minute.

@param $value

@return \CodeIgniter\I18n\Time
@throws \Exception


protected function setValue(string $name, $value)
	{
		list($year, $month, $day, $hour, $minute, $second) = explode('-', $this->format('Y-n-j-G-i-s'));
		$$name                                             = $value;

		return Time::create($year, $month, $day, $hour, $minute, $second, $this->getTimezoneName(), $this->locale);
	}

protected function setValue ( string $ name , $ value ) { list ( $ year , $ month , $ day , $ hour , $ minute , $ second ) = explode ( '-' , $ this -> format ( 'Y-n-j-G-i-s' ) ) ; $ $ name = $ value ; return Time :: create ( $ year , $ month , $ day , $ hour , $ minute , $ second , $ this -> getTimezoneName ( ) , $ this -> locale ) ; }

Helper method to do the heavy lifting of the 'setX' methods.

@param string $name
@param $value

@return \CodeIgniter\I18n\Time
@throws \Exception

Helper method to do the heavy lifting of the setX methods .


public function setTimestamp($timestamp)
	{
		$time = date('Y-m-d H:i:s', $timestamp);

		return Time::parse($time, $this->timezone, $this->locale);
	}

public
function
setTimestamp
(
$
timestamp
)
{
$
time
=
date
(
'Y-m-d H:i:s'
,
$
timestamp
)
;
return
Time
::
parse
(
$
time
,
$
this
->
timezone
,
$
this
->
locale
)
;
}

Returns a new instance with the date set to the new timestamp.

@param integer $timestamp

@return \CodeIgniter\I18n\Time
@throws \Exception

Returns a new instance with the date set to the new timestamp .


public function equals($testTime, string $timezone = null): bool
	{
		$testTime = $this->getUTCObject($testTime, $timezone);

		$ourTime = $this->toDateTime()
				->setTimezone(new DateTimeZone('UTC'))
				->format('Y-m-d H:i:s');

		return $testTime->format('Y-m-d H:i:s') === $ourTime;
	}

public
function
equals
(
$
testTime
,
string
$
timezone
=
)
:
bool
{
$
testTime
=
$
this
->
getUTCObject
(
$
testTime
,
$
timezone
)
;
$
ourTime
=
$
this
->
toDateTime
(
)
->
setTimezone
(
new
DateTimeZone
(
'UTC'
)
)
->
format
(
'Y-m-d H:i:s'
)
;
return
$
testTime
->
format
(
'Y-m-d H:i:s'
)
===
$
ourTime
;
}

Determines if the datetime passed in is equal to the current instance.
Equal in this case means that they represent the same moment in time,
and are not required to be in the same timezone, as both times are
converted to UTC and compared that way.

@param Time|DateTime|string $testTime
@param string|null          $timezone

@return boolean
@throws \Exception

Determines if the datetime passed in is equal to the current instance . Equal in this case means that they represent the same moment in time and are not required to be in the same timezone as both times are converted to UTC and compared that way .


public function sameAs($testTime, string $timezone = null): bool
	{
		if ($testTime instanceof DateTime)
		{
			$testTime = $testTime->format('Y-m-d H:i:s');
		}
		else if (is_string($testTime))
		{
			$timezone = $timezone ?: $this->timezone;
			$timezone = $timezone instanceof DateTimeZone ? $timezone : new DateTimeZone($timezone);
			$testTime = new DateTime($testTime, $timezone);
			$testTime = $testTime->format('Y-m-d H:i:s');
		}

		$ourTime = $this->toDateTimeString();

		return $testTime === $ourTime;
	}

public
function
sameAs
(
$
testTime
,
string
$
timezone
=
)
:
bool
{
if
(
$
testTime
instanceof
DateTime
)
{
$
testTime
=
$
testTime
->
format
(
'Y-m-d H:i:s'
)
;
}
else
if
(
is_string
(
$
testTime
)
)
{
$
timezone
=
$
timezone
:
$
this
->
timezone
;
$
timezone
=
$
timezone
instanceof
DateTimeZone
$
timezone
:
new
DateTimeZone
(
$
timezone
)
;
$
testTime
=
new
DateTime
(
$
testTime
,
$
timezone
)
;
$
testTime
=
$
testTime
->
format
(
'Y-m-d H:i:s'
)
;
}
$
ourTime
=
$
this
->
toDateTimeString
(
)
;
return
$
testTime
===
$
ourTime
;
}

Ensures that the times are identical, taking timezone into account.

@param Time|DateTime|string $testTime
@param string|null          $timezone

@return boolean
@throws \Exception

Ensures that the times are identical taking timezone into account .


public function getUTCObject($time, string $timezone = null)
	{
		if ($time instanceof Time)
		{
			$time = $time->toDateTime()
					->setTimezone(new DateTimeZone('UTC'));
		}
		else if ($time instanceof DateTime)
		{
			$time = $time->setTimezone(new DateTimeZone('UTC'));
		}
		else if (is_string($time))
		{
			$timezone = $timezone ?: $this->timezone;
			$timezone = $timezone instanceof DateTimeZone ? $timezone : new DateTimeZone($timezone);
			$time     = new DateTime($time, $timezone);
			$time     = $time->setTimezone(new DateTimeZone('UTC'));
		}

		return $time;
	}

public function getUTCObject ( $ time , string $ timezone = null ) { if ( $ time instanceof Time ) { $ time = $ time -> toDateTime ( ) -> setTimezone ( new DateTimeZone ( 'UTC' ) ) ; } else if ( $ time instanceof DateTime ) { $ time = $ time -> setTimezone ( new DateTimeZone ( 'UTC' ) ) ; } else if ( is_string ( $ time ) ) { $ timezone = $ timezone ? : $ this -> timezone ; $ timezone = $ timezone instanceof DateTimeZone ? $ timezone : new DateTimeZone ( $ timezone ) ; $ time = new DateTime ( $ time , $ timezone ) ; $ time = $ time -> setTimezone ( new DateTimeZone ( 'UTC' ) ) ; } return $ time ; }

Returns a Time instance with the timezone converted to UTC.

@param $time
@param string|null $timezone

@return \DateTime|static
@throws \Exception

Returns a Time instance with the timezone converted to UTC .


protected function jsMatcher($matches)
    {
        $chr = $matches[0];
        if (strlen($chr) == 1) {
            return sprintf('\\x%02X', ord($chr));
        }
        $chr = $this->convertEncoding($chr, 'UTF-16BE', 'UTF-8');
        $hex = strtoupper(bin2hex($chr));
        if (strlen($hex) <= 4) {
            return sprintf('\\u%04s', $hex);
        }
        $highSurrogate = substr($hex, 0, 4);
        $lowSurrogate = substr($hex, 4, 4);
        return sprintf('\\u%04s\\u%04s', $highSurrogate, $lowSurrogate);
    }

protected function jsMatcher ( $ matches ) { $ chr = $ matches [ 0 ] ; if ( strlen ( $ chr ) == 1 ) { return sprintf ( '\\x%02X' , ord ( $ chr ) ) ; } $ chr = $ this -> convertEncoding ( $ chr , 'UTF-16BE' , 'UTF-8' ) ; $ hex = strtoupper ( bin2hex ( $ chr ) ) ; if ( strlen ( $ hex ) <= 4 ) { return sprintf ( '\\u%04s' , $ hex ) ; } $ highSurrogate = substr ( $ hex , 0 , 4 ) ; $ lowSurrogate = substr ( $ hex , 4 , 4 ) ; return sprintf ( '\\u%04s\\u%04s' , $ highSurrogate , $ lowSurrogate ) ; }

Callback function for preg_replace_callback that applies Javascript
escaping to all matches.

@param array $matches
@return string

Callback function for preg_replace_callback that applies Javascript escaping to all matches .


protected function cssMatcher($matches)
    {
        $chr = $matches[0];
        if (strlen($chr) == 1) {
            $ord = ord($chr);
        } else {
            $chr = $this->convertEncoding($chr, 'UTF-32BE', 'UTF-8');
            $ord = hexdec(bin2hex($chr));
        }
        return sprintf('\\%X ', $ord);
    }

protected
function
cssMatcher
(
$
matches
)
{
$
chr
=
$
matches
[
0
]
;
if
(
strlen
(
$
chr
)
==
1
)
{
$
ord
=
ord
(
$
chr
)
;
}
else
{
$
chr
=
$
this
->
convertEncoding
(
$
chr
,
'UTF-32BE'
,
'UTF-8'
)
;
$
ord
=
hexdec
(
bin2hex
(
$
chr
)
)
;
}
return
sprintf
(
'\\%X '
,
$
ord
)
;
}

Callback function for preg_replace_callback that applies CSS
escaping to all matches.

@param array $matches
@return string

Callback function for preg_replace_callback that applies CSS escaping to all matches .


protected function toUtf8($string)
    {
        if ($this->getEncoding() === 'utf-8') {
            $result = $string;
        } else {
            $result = $this->convertEncoding($string, 'UTF-8', $this->getEncoding());
        }

        if (! $this->isUtf8($result)) {
            throw new Exception\RuntimeException(
                sprintf('String to be escaped was not valid UTF-8 or could not be converted: %s', $result)
            );
        }

        return $result;
    }

Converts a string to UTF-8 from the base encoding. The base encoding is set via this
class' constructor.

@param string $string
@throws Exception\RuntimeException
@return string

Converts a string to UTF - 8 from the base encoding . The base encoding is set via this class constructor .


protected function fromUtf8($string)
    {
        if ($this->getEncoding() === 'utf-8') {
            return $string;
        }

        return $this->convertEncoding($string, $this->getEncoding(), 'UTF-8');
    }

protected function fromUtf8 ( $ string ) { if ( $ this -> getEncoding ( ) === 'utf-8' ) { return $ string ; } return $ this -> convertEncoding ( $ string , $ this -> getEncoding ( ) , 'UTF-8' ) ; }

Converts a string from UTF-8 to the base encoding. The base encoding is set via this
class' constructor.
@param string $string
@return string

Converts a string from UTF - 8 to the base encoding . The base encoding is set via this class constructor .


public function getFile(string $name)
	{
		$this->populateFiles();

		if ($this->hasFile($name))
		{
			if (strpos($name, '.') !== false)
			{
				$name         = explode('.', $name);
				$uploadedFile = $this->getValueDotNotationSyntax($name, $this->files);
				return ($uploadedFile instanceof UploadedFile) ?
					 $uploadedFile : null;
			}

			if (array_key_exists($name, $this->files))
			{
				$uploadedFile = $this->files[$name];
				return  ($uploadedFile instanceof UploadedFile) ?
					$uploadedFile : null;
			}
		}

		return null;
	}

public function getFile ( string $ name ) { $ this -> populateFiles ( ) ; if ( $ this -> hasFile ( $ name ) ) { if ( strpos ( $ name , '.' ) !== false ) { $ name = explode ( '.' , $ name ) ; $ uploadedFile = $ this -> getValueDotNotationSyntax ( $ name , $ this -> files ) ; return ( $ uploadedFile instanceof UploadedFile ) ? $ uploadedFile : null ; } if ( array_key_exists ( $ name , $ this -> files ) ) { $ uploadedFile = $ this -> files [ $ name ] ; return ( $ uploadedFile instanceof UploadedFile ) ? $ uploadedFile : null ; } } return null ; }

Attempts to get a single file from the collection of uploaded files.

@param string $name

@return UploadedFile|null

Attempts to get a single file from the collection of uploaded files .


protected function createFileObject(array $array)
	{
		if (! isset($array['name']))
		{
			$output = [];

			foreach ($array as $key => $values)
			{
				if (! is_array($values))
				{
					continue;
				}

				$output[$key] = $this->createFileObject($values);
			}

			return $output;
		}

		return new UploadedFile(
				$array['tmp_name'] ?? null, $array['name'] ?? null, $array['type'] ?? null, $array['size'] ?? null, $array['error'] ?? null
		);
	}

protected function createFileObject ( array $ array ) { if ( ! isset ( $ array [ 'name' ] ) ) { $ output = [ ] ; foreach ( $ array as $ key => $ values ) { if ( ! is_array ( $ values ) ) { continue ; } $ output [ $ key ] = $ this -> createFileObject ( $ values ) ; } return $ output ; } return new UploadedFile ( $ array [ 'tmp_name' ] ?? null , $ array [ 'name' ] ?? null , $ array [ 'type' ] ?? null , $ array [ 'size' ] ?? null , $ array [ 'error' ] ?? null ) ; }

Given a file array, will create UploadedFile instances. Will
loop over an array and create objects for each.

@param array $array

@return array|UploadedFile

Given a file array will create UploadedFile instances . Will loop over an array and create objects for each .


protected function getValueDotNotationSyntax(array $index, array $value)
	{
		if (is_array($index) && ! empty($index))
		{
			$current_index = array_shift($index);
		}
		if (is_array($index) && $index && is_array($value[$current_index]) && $value[$current_index])
		{
			return $this->getValueDotNotationSyntax($index, $value[$current_index]);
		}

		return (isset($value[$current_index])) ? $value[$current_index] : null;
	}

protected function getValueDotNotationSyntax ( array $ index , array $ value ) { if ( is_array ( $ index ) && ! empty ( $ index ) ) { $ current_index = array_shift ( $ index ) ; } if ( is_array ( $ index ) && $ index && is_array ( $ value [ $ current_index ] ) && $ value [ $ current_index ] ) { return $ this -> getValueDotNotationSyntax ( $ index , $ value [ $ current_index ] ) ; } return ( isset ( $ value [ $ current_index ] ) ) ? $ value [ $ current_index ] : null ; }

Navigate through a array looking for a particular index

@param array $index The index sequence we are navigating down
@param array $value The portion of the array to process

@return mixed


public function setBinary(string $binary)
	{
		if ($this->file !== null)
		{
			throw DownloadException::forCannotSetBinary();
		}

		$this->binary = $binary;
	}

public function setBinary ( string $ binary ) { if ( $ this -> file !== null ) { throw DownloadException :: forCannotSetBinary ( ) ; } $ this -> binary = $ binary ; }

set download for binary string.

@param string $binary


public function setFilePath(string $filepath)
	{
		if ($this->binary !== null)
		{
			throw DownloadException::forCannotSetFilePath($filepath);
		}

		$this->file = new File($filepath, true);
	}

public function setFilePath ( string $ filepath ) { if ( $ this -> binary !== null ) { throw DownloadException :: forCannotSetFilePath ( $ filepath ) ; } $ this -> file = new File ( $ filepath , true ) ; }

set download for file.

@param string $filepath


public function getContentLength() : int
	{
		if (is_string($this->binary))
		{
			return strlen($this->binary);
		}
		elseif ($this->file instanceof File)
		{
			return $this->file->getSize();
		}

		return 0;
	}

public function getContentLength ( ) : int { if ( is_string ( $ this -> binary ) ) { return strlen ( $ this -> binary ) ; } elseif ( $ this -> file instanceof File ) { return $ this -> file -> getSize ( ) ; } return 0 ; }


private function setContentTypeByMimeType()
	{
		$mime    = null;
		$charset = '';

		if ($this->setMime === true)
		{
			if (($last_dot_position = strrpos($this->filename, '.')) !== false)
			{
				$mime    = Mimes::guessTypeFromExtension(substr($this->filename, $last_dot_position + 1));
				$charset = $this->charset;
			}
		}

		if (! is_string($mime))
		{
			// Set the default MIME type to send
			$mime    = 'application/octet-stream';
			$charset = '';
		}

		$this->setContentType($mime, $charset);
	}

private
function
setContentTypeByMimeType
(
)
{
$
mime
=
;
$
charset
=
''
;
if
(
$
this
->
setMime
===
true
)
{
if
(
(
$
last_dot_position
=
strrpos
(
$
this
->
filename
,
'.'
)
)
!==
false
)
{
$
mime
=
Mimes
::
guessTypeFromExtension
(
substr
(
$
this
->
filename
,
$
last_dot_position
+
1
)
)
;
$
charset
=
$
this
->
charset
;
}
}
if
(
!
is_string
(
$
mime
)
)
{
// Set the default MIME type to send
$
mime
=
'application/octet-stream'
;
$
charset
=
''
;
}
$
this
->
setContentType
(
$
mime
,
$
charset
)
;
}

Set content type by guessing mime type from file extension


private function getDownloadFileName(): string
	{
		$filename  = $this->filename;
		$x         = explode('.', $this->filename);
		$extension = end($x);

		/* It was reported that browsers on Android 2.1 (and possibly older as well)
		 * need to have the filename extension upper-cased in order to be able to
		 * download it.
		 *
		 * Reference: http://digiblog.de/2011/04/19/android-and-the-download-file-headers/
		 */
		// @todo: depend super global
		if (count($x) !== 1 && isset($_SERVER['HTTP_USER_AGENT'])
				&& preg_match('/Android\s(1|2\.[01])/', $_SERVER['HTTP_USER_AGENT']))
		{
			$x[count($x) - 1] = strtoupper($extension);
			$filename         = implode('.', $x);
		}

		return $filename;
	}


private function getContentDisposition() : string
	{
		$download_filename = $this->getDownloadFileName();

		$utf8_filename = $download_filename;

		if (strtoupper($this->charset) !== 'UTF-8')
		{
			$utf8_filename = mb_convert_encoding($download_filename, 'UTF-8', $this->charset);
		}

		$result = sprintf('attachment; filename="%s"', $download_filename);

		if (isset($utf8_filename))
		{
			$result .= '; filename*=UTF-8\'\'' . rawurlencode($utf8_filename);
		}

		return $result;
	}

private
function
getContentDisposition
(
)
:
string
{
$
download_filename
=
$
this
->
getDownloadFileName
(
)
;
$
utf8_filename
=
$
download_filename
;
if
(
strtoupper
(
$
this
->
charset
)
!==
'UTF-8'
)
{
$
utf8_filename
=
mb_convert_encoding
(
$
download_filename
,
'UTF-8'
,
$
this
->
charset
)
;
}
$
result
=
sprintf
(
'attachment; filename="%s"'
,
$
download_filename
)
;
if
(
isset
(
$
utf8_filename
)
)
{
$
result
.=
'; filename*=UTF-8\'\''
.
rawurlencode
(
$
utf8_filename
)
;
}
return
$
result
;
}

get Content-Disposition Header string.

@return string

get Content - Disposition Header string .


public function buildHeaders()
	{
		if (! $this->hasHeader('Content-Type'))
		{
			$this->setContentTypeByMimeType();
		}

		$this->setHeader('Content-Disposition', $this->getContentDisposition());
		$this->setHeader('Expires-Disposition', '0');
		$this->setHeader('Content-Transfer-Encoding', 'binary');
		$this->setHeader('Content-Length', (string)$this->getContentLength());
		$this->noCache();
	}

public function buildHeaders ( ) { if ( ! $ this -> hasHeader ( 'Content-Type' ) ) { $ this -> setContentTypeByMimeType ( ) ; } $ this -> setHeader ( 'Content-Disposition' , $ this -> getContentDisposition ( ) ) ; $ this -> setHeader ( 'Expires-Disposition' , '0' ) ; $ this -> setHeader ( 'Content-Transfer-Encoding' , 'binary' ) ; $ this -> setHeader ( 'Content-Length' , ( string ) $ this -> getContentLength ( ) ) ; $ this -> noCache ( ) ; }


public function sendBody()
	{
		if ($this->binary !== null)
		{
			return $this->sendBodyByBinary();
		}
		elseif ($this->file !== null)
		{
			return $this->sendBodyByFilePath();
		}

		throw DownloadException::forNotFoundDownloadSource();
	}

public function sendBody ( ) { if ( $ this -> binary !== null ) { return $ this -> sendBodyByBinary ( ) ; } elseif ( $ this -> file !== null ) { return $ this -> sendBodyByFilePath ( ) ; } throw DownloadException :: forNotFoundDownloadSource ( ) ; }

output download file text.

@throws DownloadException

@return DownloadResponse


private function sendBodyByFilePath()
	{
		$spl_file_object = $this->file->openFile('rb');

		// Flush 1MB chunks of data
		while (! $spl_file_object->eof() && ($data = $spl_file_object->fread(1048576)) !== false)
		{
			echo $data;
		}

		return $this;
	}

private
function
sendBodyByFilePath
(
)
{
$
spl_file_object
=
$
this
->
file
->
openFile
(
'rb'
)
;
// Flush 1MB chunks of data
while
(
!
$
spl_file_object
->
eof
(
)
&&
(
$
data
=
$
spl_file_object
->
fread
(
1048576
)
)
!==
false
)
{
echo
$
data
;
}
return
$
this
;
}

output download text by file.

@return DownloadResponse


public function _remap($method, ...$params)
	{
		// The first param is usually empty, so scrap it.
		if (empty($params[0]))
		{
			array_shift($params);
		}

		$this->index($params);
	}

We map all un-routed CLI methods through this function
so we have the chance to look for a Command first.

@param string $method
@param array  ...$params

@throws \ReflectionException

We map all un - routed CLI methods through this function so we have the chance to look for a Command first .


protected function runCommand(string $command, array $params)
	{
		if (! isset($this->commands[$command]))
		{
			CLI::error(lang('CLI.commandNotFound', [$command]));
			CLI::newLine();
			return;
		}

		// The file would have already been loaded during the
		// createCommandList function...
		$className = $this->commands[$command]['class'];
		$class     = new $className($this->logger, $this);

		return $class->run($params);
	}

Actually runs the command.

@param string $command
@param array  $params

@return mixed


protected function createCommandList()
	{
		$files = Services::locator()->listFiles('Commands/');

		// If no matching command files were found, bail
		if (empty($files))
		{
			// This should never happen in unit testing.
			// if it does, we have far bigger problems!
			// @codeCoverageIgnoreStart
			return;
			// @codeCoverageIgnoreEnd
		}

		// Loop over each file checking to see if a command with that
		// alias exists in the class. If so, return it. Otherwise, try the next.
		foreach ($files as $file)
		{
			$className = Services::locator()->findQualifiedNameFromPath($file);
			if (empty($className) || ! class_exists($className))
			{
				continue;
			}

			$class = new \ReflectionClass($className);

			if (! $class->isInstantiable() || ! $class->isSubclassOf(BaseCommand::class))
			{
				continue;
			}

			$class = new $className($this->logger, $this);

			// Store it!
			if ($class->group !== null)
			{
				$this->commands[$class->name] = [
					'class'       => $className,
					'file'        => $file,
					'group'       => $class->group,
					'description' => $class->description,
				];
			}

			$class = null;
			unset($class);
		}

		asort($this->commands);
	}

Scans all Commands directories and prepares a list
of each command with it's group and file.

@throws \ReflectionException

Scans all Commands directories and prepares a list of each command with it s group and file .


public static function connect($group = null, bool $getShared = true)
	{
		// If a DB connection is passed in, just pass it back
		if ($group instanceof BaseConnection)
		{
			return $group;
		}

		if (is_array($group))
		{
			$config = $group;
			$group  = 'custom-' . md5(json_encode($config));
		}

		$config = $config ?? new \Config\Database();

		if (empty($group))
		{
			$group = ENVIRONMENT === 'testing' ? 'tests' : $config->defaultGroup;
		}

		if (is_string($group) && ! isset($config->$group) && strpos($group, 'custom-') !== 0)
		{
			throw new \InvalidArgumentException($group . ' is not a valid database connection group.');
		}

		if ($getShared && isset(static::$instances[$group]))
		{
			return static::$instances[$group];
		}

		static::ensureFactory();

		if (isset($config->$group))
		{
			$config = $config->$group;
		}

		$connection = static::$factory->load($config, $group);

		static::$instances[$group] = & $connection;

		return $connection;
	}

Creates the default

@param string|array $group     The name of the connection group to use,
or an array of configuration settings.
@param boolean      $getShared Whether to return a shared instance of the connection.

@return BaseConnection


public static function seeder(string $group = null)
	{
		$config = config('Database');

		return new Seeder($config, static::connect($group));
	}

public static function seeder ( string $ group = null ) { $ config = config ( 'Database' ) ; return new Seeder ( $ config , static :: connect ( $ group ) ) ; }

Returns a new instance of the Database Seeder.

@param string|null $group

@return Seeder

Returns a new instance of the Database Seeder .


private function isAllNamespace(array $params): bool
	{
		if (array_search('-all', $params) !== false)
		{
			return true;
		}

		return ! is_null(CLI::getOption('all'));
	}

private function isAllNamespace ( array $ params ) : bool { if ( array_search ( '-all' , $ params ) !== false ) { return true ; } return ! is_null ( CLI :: getOption ( 'all' ) ) ; }

To migrate all namespaces to the latest migration

Demo:
1. command line: php spark migrate:latest -all
2. command file: $this->call('migrate:latest', ['-g' => 'test','-all']);

@param  array $params
@return boolean


public function add(string $name, \Closure $closure)
	{
		$name = strtolower($name);

		$this->tests[$name] = $closure;

		return $this;
	}

public function add ( string $ name , \ Closure $ closure ) { $ name = strtolower ( $ name ) ; $ this -> tests [ $ name ] = $ closure ; return $ this ; }

Adds a test to run.

Tests are simply closures that the user can define any sequence of
things to happen during the test.

@param string    $name
@param \Closure  $closure

@return $this


public function run(int $iterations = 1000, bool $output = true)
	{
		foreach ($this->tests as $name => $test)
		{
			// clear memory before start
			gc_collect_cycles();

			$start     = microtime(true);
			$start_mem = $max_memory = memory_get_usage(true);

			for ($i = 0; $i < $iterations; $i ++)
			{
				$result = $test();

				$max_memory = max($max_memory, memory_get_usage(true));

				unset($result);
			}

			$this->results[$name] = [
				'time'   => microtime(true) - $start,
				'memory' => $max_memory - $start_mem,
				'n'      => $iterations,
			];
		}

		if ($output)
		{
			return $this->getReport();
		}

		return null;
	}

public
function
run
(
int
$
iterations
=
1000
,
bool
$
output
=
true
)
{
foreach
(
$
this
->
tests
as
$
name
=>
$
test
)
{
// clear memory before start
gc_collect_cycles
(
)
;
$
start
=
microtime
(
true
)
;
$
start_mem
=
$
max_memory
=
memory_get_usage
(
true
)
;
for
(
$
i
=
0
;
$
i
<
$
iterations
;
$
i
++
)
{
$
result
=
$
test
(
)
;
$
max_memory
=
max
(
$
max_memory
,
memory_get_usage
(
true
)
)
;
unset
(
$
result
)
;
}
$
this
->
results
[
$
name
]
=
[
'time'
=>
microtime
(
true
)
$
start
,
'memory'
=>
$
max_memory
$
start_mem
,
'n'
=>
$
iterations
,
]
;
}
if
(
$
output
)
{
return
$
this
->
getReport
(
)
;
}
return
;
}

Runs through all of the tests that have been added, recording
time to execute the desired number of iterations, and the approximate
memory usage used during those iterations.

@param integer $iterations
@param boolean $output

@return string|null

Runs through all of the tests that have been added recording time to execute the desired number of iterations and the approximate memory usage used during those iterations .


public function getReport(): string
	{
		if (empty($this->results))
		{
			return 'No results to display.';
		}

		helper('number');

		// Template
		$tpl = '

					Test
					Time
					Memory

				{rows}

';

		$rows = '';

		foreach ($this->results as $name => $result)
		{
			$memory = number_to_size($result['memory'], 4);

			$rows .= "

				{$name}
				" . number_format($result['time'], 4) . "
				{$memory}

";
		}

		$tpl = str_replace('{rows}', $rows, $tpl);

		return $tpl . '
';
	}

'

					Test
					Time
					Memory

				{rows}

'


public function setQuery(string $sql, $binds = null, bool $setEscape = true)
	{
		$this->originalQueryString = $sql;

		if (! is_null($binds))
		{
			if (! is_array($binds))
			{
				$binds = [$binds];
			}

			if ($setEscape)
			{
				array_walk($binds, function (&$item) {
					$item = [
						$item,
						true,
					];
				});
			}
			$this->binds = $binds;
		}

		return $this;
	}

public function setQuery ( string $ sql , $ binds = null , bool $ setEscape = true ) { $ this -> originalQueryString = $ sql ; if ( ! is_null ( $ binds ) ) { if ( ! is_array ( $ binds ) ) { $ binds = [ $ binds ] ; } if ( $ setEscape ) { array_walk ( $ binds , function ( & $ item ) { $ item = [ $ item , true , ] ; } ) ; } $ this -> binds = $ binds ; } return $ this ; }

Sets the raw query string to use for this statement.

@param string  $sql
@param mixed   $binds
@param boolean $setEscape

@return $this

Sets the raw query string to use for this statement .


public function getQuery(): string
	{
		if (empty($this->finalQueryString))
		{
			$this->finalQueryString = $this->originalQueryString;
		}

		$this->compileBinds();

		return $this->finalQueryString;
	}

public function getQuery ( ) : string { if ( empty ( $ this -> finalQueryString ) ) { $ this -> finalQueryString = $ this -> originalQueryString ; } $ this -> compileBinds ( ) ; return $ this -> finalQueryString ; }

Returns the final, processed query string after binding, etal
has been performed.

@return string

Returns the final processed query string after binding etal has been performed .


public function getStartTime(bool $returnRaw = false, int $decimals = 6): string
	{
		if ($returnRaw)
		{
			return $this->startTime;
		}

		return number_format($this->startTime, $decimals);
	}

public function getStartTime ( bool $ returnRaw = false , int $ decimals = 6 ) : string { if ( $ returnRaw ) { return $ this -> startTime ; } return number_format ( $ this -> startTime , $ decimals ) ; }

Returns the start time in seconds with microseconds.

@param boolean $returnRaw
@param integer $decimals

@return string

Returns the start time in seconds with microseconds .


public function getDuration(int $decimals = 6): string
	{
		return number_format(($this->endTime - $this->startTime), $decimals);
	}

public function getDuration ( int $ decimals = 6 ) : string { return number_format ( ( $ this -> endTime - $ this -> startTime ) , $ decimals ) ; }

Returns the duration of this query during execution, or null if
the query has not been executed yet.

@param integer $decimals The accuracy of the returned time.

@return string

Returns the duration of this query during execution or null if the query has not been executed yet .


public function setError(int $code, string $error)
	{
		$this->errorCode   = $code;
		$this->errorString = $error;

		return $this;
	}

public function setError ( int $ code , string $ error ) { $ this -> errorCode = $ code ; $ this -> errorString = $ error ; return $ this ; }

Stores the error description that happened for this query.

@param integer $code
@param string  $error

@return $this

Stores the error description that happened for this query .


public function swapPrefix(string $orig, string $swap)
	{
		$sql = empty($this->finalQueryString) ? $this->originalQueryString : $this->finalQueryString;

		$this->finalQueryString = preg_replace('/(\W)' . $orig . '(\S+?)/', '\\1' . $swap . '\\2', $sql);

		return $this;
	}

public function swapPrefix ( string $ orig , string $ swap ) { $ sql = empty ( $ this -> finalQueryString ) ? $ this -> originalQueryString : $ this -> finalQueryString ; $ this -> finalQueryString = preg_replace ( '/(\W)' . $ orig . '(\S+?)/' , '\\1' . $ swap . '\\2' , $ sql ) ; return $ this ; }

Swaps out one table prefix for a new one.

@param string $orig
@param string $swap

@return $this

Swaps out one table prefix for a new one .


protected function compileBinds()
	{
		$sql = $this->finalQueryString;

		$hasNamedBinds = strpos($sql, ':') !== false;

		if (empty($this->binds) || empty($this->bindMarker) ||
				(strpos($sql, $this->bindMarker) === false &&
				$hasNamedBinds === false)
		)
		{
			return;
		}

		if (! is_array($this->binds))
		{
			$binds     = [$this->binds];
			$bindCount = 1;
		}
		else
		{
			$binds     = $this->binds;
			$bindCount = count($binds);
		}

		// Reverse the binds so that duplicate named binds
		// will be processed prior to the original binds.
		if (! is_numeric(key(array_slice($binds, 0, 1))))
		{
			$binds = array_reverse($binds);
		}

		// We'll need marker length later
		$ml = strlen($this->bindMarker);

		if ($hasNamedBinds)
		{
			$sql = $this->matchNamedBinds($sql, $binds);
		}
		else
		{
			$sql = $this->matchSimpleBinds($sql, $binds, $bindCount, $ml);
		}

		$this->finalQueryString = $sql;
	}

Escapes and inserts any binds into the finalQueryString object.

@return null|void

Escapes and inserts any binds into the finalQueryString object .


protected function loadHelpers()
	{
		if (empty($this->helpers))
		{
			return;
		}

		foreach ($this->helpers as $helper)
		{
			helper($helper);
		}
	}

protected function loadHelpers ( ) { if ( empty ( $ this -> helpers ) ) { return ; } foreach ( $ this -> helpers as $ helper ) { helper ( $ helper ) ; } }


public function register()
	{
		// Since the default file extensions are searched
		// in order of .inc then .php, but we always use .php,
		// put the .php extension first to eek out a bit
		// better performance.
		// http://php.net/manual/en/function.spl-autoload.php#78053
		spl_autoload_extensions('.php,.inc');

		// Prepend the PSR4  autoloader for maximum performance.
		spl_autoload_register([$this, 'loadClass'], true, true);

		// Now prepend another loader for the files in our class map.
		$config = is_array($this->classmap) ? $this->classmap : [];

		spl_autoload_register(function ($class) use ($config) {
			if (empty($config[$class]))
			{
				return false;
			}

			include_once $config[$class];
		}, true, // Throw exception
			true // Prepend
		);
	}

Register the loader with the SPL autoloader stack.

Register the loader with the SPL autoloader stack .


public function addNamespace($namespace, string $path = null)
	{
		if (is_array($namespace))
		{
			foreach ($namespace as $prefix => $path)
			{
				$prefix = trim($prefix, '\\');

				if (is_array($path))
				{
					foreach ($path as $dir)
					{
						$this->prefixes[$prefix][] = rtrim($dir, '/') . '/';
					}

					continue;
				}

				$this->prefixes[$prefix][] = rtrim($path, '/') . '/';
			}
		}
		else
		{
			$this->prefixes[trim($namespace, '\\')][] = rtrim($path, '/') . '/';
		}

		return $this;
	}

public function addNamespace ( $ namespace , string $ path = null ) { if ( is_array ( $ namespace ) ) { foreach ( $ namespace as $ prefix => $ path ) { $ prefix = trim ( $ prefix , '\\' ) ; if ( is_array ( $ path ) ) { foreach ( $ path as $ dir ) { $ this -> prefixes [ $ prefix ] [ ] = rtrim ( $ dir , '/' ) . '/' ; } continue ; } $ this -> prefixes [ $ prefix ] [ ] = rtrim ( $ path , '/' ) . '/' ; } } else { $ this -> prefixes [ trim ( $ namespace , '\\' ) ] [ ] = rtrim ( $ path , '/' ) . '/' ; } return $ this ; }

Registers namespaces with the autoloader.

@param array|string $namespace
@param string       $path

@return Autoloader

Registers namespaces with the autoloader .


public function getNamespace(string $prefix = null)
	{
		if ($prefix === null)
		{
			return $this->prefixes;
		}

		return $this->prefixes[trim($prefix, '\\')] ?? [];
	}

public function getNamespace ( string $ prefix = null ) { if ( $ prefix === null ) { return $ this -> prefixes ; } return $ this -> prefixes [ trim ( $ prefix , '\\' ) ] ?? [ ] ; }

Get namespaces with prefixes as keys and paths as values.

If a prefix param is set, returns only paths to the given prefix.

@var string|null $prefix

@return array

Get namespaces with prefixes as keys and paths as values .


protected function requireFile(string $file)
	{
		$file = $this->sanitizeFilename($file);

		if (is_file($file))
		{
			require_once $file;

			return $file;
		}

		return false;
	}

protected function requireFile ( string $ file ) { $ file = $ this -> sanitizeFilename ( $ file ) ; if ( is_file ( $ file ) ) { require_once $ file ; return $ file ; } return false ; }

A central way to require a file is loaded. Split out primarily
for testing purposes.

@param string $file

@return string|false The filename on success, false if the file is not loaded

A central way to require a file is loaded . Split out primarily for testing purposes .


public function sanitizeFilename(string $filename): string
	{
		// Only allow characters deemed safe for POSIX portable filenames.
		// Plus the forward slash for directory separators since this might
		// be a path.
		// http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_278
		// Modified to allow backslash and colons for on Windows machines.
		$filename = preg_replace('/[^a-zA-Z0-9\s\/\-\_\.\:\\\\]/', '', $filename);

		// Clean up our filename edges.
		$filename = trim($filename, '.-_');

		return $filename;
	}

Sanitizes a filename, replacing spaces with dashes.

Removes special characters that are illegal in filenames on certain
operating systems and special characters requiring special escaping
to manipulate at the command line. Replaces spaces and consecutive
dashes with a single dash. Trim period, dash and underscore from beginning
and end of filename.

@param string $filename

@return string       The sanitized filename

Sanitizes a filename replacing spaces with dashes .


protected function discoverComposerNamespaces()
	{
		if (! is_file(COMPOSER_PATH))
		{
			return false;
		}

		$composer = include COMPOSER_PATH;

		$paths = $composer->getPrefixesPsr4();
		unset($composer);

		// Get rid of CodeIgniter so we don't have duplicates
		if (isset($paths['CodeIgniter\\']))
		{
			unset($paths['CodeIgniter\\']);
		}

		// Composer stores paths with trailng slash. We don't.
		$newPaths = [];
		foreach ($paths as $key => $value)
		{
			$newPaths[rtrim($key, '\\ ')] = $value;
		}

		$this->prefixes = array_merge($this->prefixes, $newPaths);
	}

Locates all PSR4 compatible namespaces from Composer.

Locates all PSR4 compatible namespaces from Composer .


public static function date_modify($value, string $adjustment): string
	{
		$value = static::date($value, 'Y-m-d H:i:s');

		return strtotime($adjustment, strtotime($value));
	}

public
static
function
date_modify
(
$
value
,
string
$
adjustment
)
:
string
{
$
value
=
static
::
date
(
$
value
,
'Y-m-d H:i:s'
)
;
return
strtotime
(
$
adjustment
,
strtotime
(
$
value
)
)
;
}

Given a string or DateTime object, will return the date modified
by the given value. Returns the value as a unix timestamp

Example:
my_date|date_modify(+1 day)

@param $value
@param string $adjustment

@return   string
@internal param string $format

Given a string or DateTime object will return the date modified by the given value . Returns the value as a unix timestamp


public static function excerpt(string $value, string $phrase, int $radius = 100): string
	{
		helper('text');

		return excerpt($value, $phrase, $radius);
	}

public static function excerpt ( string $ value , string $ phrase , int $ radius = 100 ) : string { helper ( 'text' ) ; return excerpt ( $ value , $ phrase , $ radius ) ; }

Returns an excerpt of the given string.

@param string  $value
@param string  $phrase
@param integer $radius

@return string

Returns an excerpt of the given string .


protected function sanitizeValue(string $value): string
	{
		if (! $value)
		{
			return $value;
		}

		// Does it begin with a quote?
		if (strpbrk($value[0], '"\'') !== false)
		{
			// value starts with a quote
			$quote        = $value[0];
			$regexPattern = sprintf(
					'/^
					%1$s          # match a quote at the start of the value
					(             # capturing sub-pattern used
								  (?:          # we do not need to capture this
								   [^%1$s\\\\] # any character other than a quote or backslash
								   |\\\\\\\\   # or two backslashes together
								   |\\\\%1$s   # or an escaped quote e.g \"
								  )*           # as many characters that match the previous rules
					)             # end of the capturing sub-pattern
					%1$s          # and the closing quote
					.*$           # and discard any string after the closing quote
					/mx', $quote
			);
			$value        = preg_replace($regexPattern, '$1', $value);
			$value        = str_replace("\\$quote", $quote, $value);
			$value        = str_replace('\\\\', '\\', $value);
		}
		else
		{
			$parts = explode(' #', $value, 2);

			$value = trim($parts[0]);

			// Unquoted values cannot contain whitespace
			if (preg_match('/\s+/', $value) > 0)
			{
				throw new \InvalidArgumentException('.env values containing spaces must be surrounded by quotes.');
			}
		}

		return $value;
	}

Strips quotes from the environment variable value.

This was borrowed from the excellent phpdotenv with very few changes.
https://github.com/vlucas/phpdotenv

@param string $value

@return string
@throws \InvalidArgumentException

Strips quotes from the environment variable value .


protected function resolveNestedVariables(string $value): string
	{
		if (strpos($value, '$') !== false)
		{
			$loader = $this;

			$value = preg_replace_callback(
				'/\${([a-zA-Z0-9_]+)}/',
				function ($matchedPatterns) use ($loader) {
					$nestedVariable = $loader->getVariable($matchedPatterns[1]);

					if (is_null($nestedVariable))
					{
						return $matchedPatterns[0];
					}

					return $nestedVariable;
				},
				$value
			);
		}

		return $value;
	}

protected function resolveNestedVariables ( string $ value ) : string { if ( strpos ( $ value , '$' ) !== false ) { $ loader = $ this ; $ value = preg_replace_callback ( '/\${([a-zA-Z0-9_]+)}/' , function ( $ matchedPatterns ) use ( $ loader ) { $ nestedVariable = $ loader -> getVariable ( $ matchedPatterns [ 1 ] ) ; if ( is_null ( $ nestedVariable ) ) { return $ matchedPatterns [ 0 ] ; } return $ nestedVariable ; } , $ value ) ; } return $ value ; }

Resolve the nested variables.

Look for ${varname} patterns in the variable value and replace with an existing
environment variable.

This was borrowed from the excellent phpdotenv with very few changes.
https://github.com/vlucas/phpdotenv

@param $value

@return string


public function setDatabase(string $databaseName): bool
	{
		if ($databaseName === '')
		{
			$databaseName = $this->database;
		}

		if (empty($this->connID))
		{
			$this->initialize();
		}

		if ($this->connID->select_db($databaseName))
		{
			$this->database = $databaseName;

			return true;
		}

		return false;
	}

public function setDatabase ( string $ databaseName ) : bool { if ( $ databaseName === '' ) { $ databaseName = $ this -> database ; } if ( empty ( $ this -> connID ) ) { $ this -> initialize ( ) ; } if ( $ this -> connID -> select_db ( $ databaseName ) ) { $ this -> database = $ databaseName ; return true ; } return false ; }

Select a specific database table to use.

@param string $databaseName

@return boolean

Select a specific database table to use .


public function execute(string $sql)
	{
		while ($this->connID->more_results())
		{
			$this->connID->next_result();
			if ($res = $this->connID->store_result())
			{
				$res->free();
			}
		}

		return $this->connID->query($this->prepQuery($sql));
	}

public function execute ( string $ sql ) { while ( $ this -> connID -> more_results ( ) ) { $ this -> connID -> next_result ( ) ; if ( $ res = $ this -> connID -> store_result ( ) ) { $ res -> free ( ) ; } } return $ this -> connID -> query ( $ this -> prepQuery ( $ sql ) ) ; }

Executes the query against the database.

@param string $sql

@return mixed

Executes the query against the database .


protected function prepQuery(string $sql): string
	{
		// mysqli_affected_rows() returns 0 for "DELETE FROM TABLE" queries. This hack
		// modifies the query so that it a proper number of affected rows is returned.
		if ($this->deleteHack === true && preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i', $sql))
		{
			return trim($sql) . ' WHERE 1=1';
		}

		return $sql;
	}

Prep the query

If needed, each database adapter can prep the query string

@param string $sql an SQL query

@return string


public function error(): array
	{
		if (! empty($this->mysqli->connect_errno))
		{
			return [
				'code'    => $this->mysqli->connect_errno,
				'message' => $this->mysqli->connect_error,
			];
		}

		return [
			'code'    => $this->connID->errno,
			'message' => $this->connID->error,
		];
	}

public function error ( ) : array { if ( ! empty ( $ this -> mysqli -> connect_errno ) ) { return [ 'code' => $ this -> mysqli -> connect_errno , 'message' => $ this -> mysqli -> connect_error , ] ; } return [ 'code' => $ this -> connID -> errno , 'message' => $ this -> connID -> error , ] ; }

Returns the last error code and message.

Must return an array with keys 'code' and 'message':

return ['code' => null, 'message' => null);

@return array

Returns the last error code and message .


public function execute(string $sql)
	{
		return $this->isWriteType($sql)
			? $this->connID->exec($sql)
			: $this->connID->query($sql);
	}

public function execute ( string $ sql ) { return $ this -> isWriteType ( $ sql ) ? $ this -> connID -> exec ( $ sql ) : $ this -> connID -> query ( $ sql ) ; }

Execute the query

@param string $sql

@return mixed    \SQLite3Result object or bool


public function getFieldNames(string $table)
	{
		// Is there a cached result?
		if (isset($this->dataCache['field_names'][$table]))
		{
			return $this->dataCache['field_names'][$table];
		}

		if (empty($this->connID))
		{
			$this->initialize();
		}

		if (false === ($sql = $this->_listColumns($table)))
		{
			if ($this->DBDebug)
			{
				throw new DatabaseException(lang('Database.featureUnavailable'));
			}

			return false;
		}

		$query                                  = $this->query($sql);
		$this->dataCache['field_names'][$table] = [];

		foreach ($query->getResultArray() as $row)
		{
			// Do we know from where to get the column's name?
			if (! isset($key))
			{
				if (isset($row['column_name']))
				{
					$key = 'column_name';
				}
				elseif (isset($row['COLUMN_NAME']))
				{
					$key = 'COLUMN_NAME';
				}
				elseif (isset($row['name']))
				{
					$key = 'name';
				}
				else
				{
					// We have no other choice but to just get the first element's key.
					$key = key($row);
				}
			}

			$this->dataCache['field_names'][$table][] = $row[$key];
		}

		return $this->dataCache['field_names'][$table];
	}

Fetch Field Names

@param string $table Table name

@return array|false
@throws DatabaseException


public static function cache(Cache $config = null, bool $getShared = true)
	{
		if ($getShared)
		{
			return static::getSharedInstance('cache', $config);
		}

		if (! is_object($config))
		{
			$config = new Cache();
		}

		return CacheFactory::getHandler($config);
	}

public static function cache ( Cache $ config = null , bool $ getShared = true ) { if ( $ getShared ) { return static :: getSharedInstance ( 'cache' , $ config ) ; } if ( ! is_object ( $ config ) ) { $ config = new Cache ( ) ; } return CacheFactory :: getHandler ( $ config ) ; }

The cache class provides a simple way to store and retrieve
complex data for later.

@param \Config\Cache $config
@param boolean       $getShared

@return \CodeIgniter\Cache\CacheInterface

The cache class provides a simple way to store and retrieve complex data for later .


public static function clirequest(App $config = null, bool $getShared = true)
	{
		if ($getShared)
		{
			return static::getSharedInstance('clirequest', $config);
		}

		if (! is_object($config))
		{
			$config = config(App::class);
		}

		return new CLIRequest($config);
	}

public static function clirequest ( App $ config = null , bool $ getShared = true ) { if ( $ getShared ) { return static :: getSharedInstance ( 'clirequest' , $ config ) ; } if ( ! is_object ( $ config ) ) { $ config = config ( App :: class ) ; } return new CLIRequest ( $ config ) ; }

The CLI Request class provides for ways to interact with
a command line request.

@param \Config\App $config
@param boolean     $getShared

@return \CodeIgniter\HTTP\CLIRequest

The CLI Request class provides for ways to interact with a command line request .


public static function curlrequest(array $options = [], ResponseInterface $response = null, App $config = null, bool $getShared = true)
	{
		if ($getShared === true)
		{
			return static::getSharedInstance('curlrequest', $options, $response, $config);
		}

		if (! is_object($config))
		{
			$config = config(App::class);
		}

		if (! is_object($response))
		{
			$response = new Response($config);
		}

		return new CURLRequest(
			$config,
			new URI($options['base_uri'] ?? null),
			$response,
			$options
		);
	}

public static function curlrequest ( array $ options = [ ] , ResponseInterface $ response = null , App $ config = null , bool $ getShared = true ) { if ( $ getShared === true ) { return static :: getSharedInstance ( 'curlrequest' , $ options , $ response , $ config ) ; } if ( ! is_object ( $ config ) ) { $ config = config ( App :: class ) ; } if ( ! is_object ( $ response ) ) { $ response = new Response ( $ config ) ; } return new CURLRequest ( $ config , new URI ( $ options [ 'base_uri' ] ?? null ) , $ response , $ options ) ; }

The CURL Request class acts as a simple HTTP client for interacting
with other servers, typically through APIs.

@param array                               $options
@param \CodeIgniter\HTTP\ResponseInterface $response
@param \Config\App                         $config
@param boolean                             $getShared

@return \CodeIgniter\HTTP\CURLRequest

The CURL Request class acts as a simple HTTP client for interacting with other servers typically through APIs .


public static function honeypot(BaseConfig $config = null, bool $getShared = true)
	{
		if ($getShared)
		{
			return static::getSharedInstance('honeypot', $config);
		}

		if (is_null($config))
		{
			$config = new \Config\Honeypot();
		}

		return new Honeypot($config);
	}

public static function honeypot ( BaseConfig $ config = null , bool $ getShared = true ) { if ( $ getShared ) { return static :: getSharedInstance ( 'honeypot' , $ config ) ; } if ( is_null ( $ config ) ) { $ config = new \ Config \ Honeypot ( ) ; } return new Honeypot ( $ config ) ; }

The Honeypot provides a secret input on forms that bots should NOT
fill in, providing an additional safeguard when accepting user input.

@param \CodeIgniter\Config\BaseConfig|null $config
@param boolean                             $getShared

@return \CodeIgniter\Honeypot\Honeypot|mixed

The Honeypot provides a secret input on forms that bots should NOT fill in providing an additional safeguard when accepting user input .


public static function language(string $locale = null, bool $getShared = true)
	{
		if ($getShared)
		{
			return static::getSharedInstance('language', $locale)
					   ->setLocale($locale);
		}

		$locale = ! empty($locale)
			? $locale
			: static::request()
				  ->getLocale();

		return new Language($locale);
	}

public static function language ( string $ locale = null , bool $ getShared = true ) { if ( $ getShared ) { return static :: getSharedInstance ( 'language' , $ locale ) -> setLocale ( $ locale ) ; } $ locale = ! empty ( $ locale ) ? $ locale : static :: request ( ) -> getLocale ( ) ; return new Language ( $ locale ) ; }

Responsible for loading the language string translations.

@param string  $locale
@param boolean $getShared

@return \CodeIgniter\Language\Language

Responsible for loading the language string translations .


public static function logger(bool $getShared = true)
	{
		if ($getShared)
		{
			return static::getSharedInstance('logger');
		}

		return new \CodeIgniter\Log\Logger(new Logger());
	}

public static function logger ( bool $ getShared = true ) { if ( $ getShared ) { return static :: getSharedInstance ( 'logger' ) ; } return new \ CodeIgniter \ Log \ Logger ( new Logger ( ) ) ; }

The Logger class is a PSR-3 compatible Logging class that supports
multiple handlers that process the actual logging.

@param boolean $getShared

@return \CodeIgniter\Log\Logger

The Logger class is a PSR - 3 compatible Logging class that supports multiple handlers that process the actual logging .


public static function negotiator(RequestInterface $request = null, bool $getShared = true)
	{
		if ($getShared)
		{
			return static::getSharedInstance('negotiator', $request);
		}

		if (is_null($request))
		{
			$request = static::request();
		}

		return new Negotiate($request);
	}

public static function negotiator ( RequestInterface $ request = null , bool $ getShared = true ) { if ( $ getShared ) { return static :: getSharedInstance ( 'negotiator' , $ request ) ; } if ( is_null ( $ request ) ) { $ request = static :: request ( ) ; } return new Negotiate ( $ request ) ; }

The Negotiate class provides the content negotiation features for
working the request to determine correct language, encoding, charset,
and more.

@param \CodeIgniter\HTTP\RequestInterface $request
@param boolean                            $getShared

@return \CodeIgniter\HTTP\Negotiate

The Negotiate class provides the content negotiation features for working the request to determine correct language encoding charset and more .


public static function parser(string $viewPath = null, $config = null, bool $getShared = true)
	{
		if ($getShared)
		{
			return static::getSharedInstance('parser', $viewPath, $config);
		}

		if (is_null($config))
		{
			$config = new \Config\View();
		}

		if (is_null($viewPath))
		{
			$paths    = config('Paths');
			$viewPath = $paths->viewDirectory;
		}

		return new Parser($config, $viewPath, static::locator(true), CI_DEBUG, static::logger(true));
	}

public static function parser ( string $ viewPath = null , $ config = null , bool $ getShared = true ) { if ( $ getShared ) { return static :: getSharedInstance ( 'parser' , $ viewPath , $ config ) ; } if ( is_null ( $ config ) ) { $ config = new \ Config \ View ( ) ; } if ( is_null ( $ viewPath ) ) { $ paths = config ( 'Paths' ) ; $ viewPath = $ paths -> viewDirectory ; } return new Parser ( $ config , $ viewPath , static :: locator ( true ) , CI_DEBUG , static :: logger ( true ) ) ; }

The Parser is a simple template parser.

@param string  $viewPath
@param mixed   $config
@param boolean $getShared

@return \CodeIgniter\View\Parser

The Parser is a simple template parser .


public static function request(App $config = null, bool $getShared = true)
	{
		if ($getShared)
		{
			return static::getSharedInstance('request', $config);
		}

		if (! is_object($config))
		{
			$config = config(App::class);
		}

		return new IncomingRequest(
			$config,
			new URI(),
			'php://input',
			new UserAgent()
		);
	}

public static function request ( App $ config = null , bool $ getShared = true ) { if ( $ getShared ) { return static :: getSharedInstance ( 'request' , $ config ) ; } if ( ! is_object ( $ config ) ) { $ config = config ( App :: class ) ; } return new IncomingRequest ( $ config , new URI ( ) , 'php://input' , new UserAgent ( ) ) ; }

The Request class models an HTTP request.

@param \Config\App $config
@param boolean     $getShared

@return \CodeIgniter\HTTP\IncomingRequest

The Request class models an HTTP request .


public static function response(App $config = null, bool $getShared = true)
	{
		if ($getShared)
		{
			return static::getSharedInstance('response', $config);
		}

		if (! is_object($config))
		{
			$config = config(App::class);
		}

		return new Response($config);
	}

public static function response ( App $ config = null , bool $ getShared = true ) { if ( $ getShared ) { return static :: getSharedInstance ( 'response' , $ config ) ; } if ( ! is_object ( $ config ) ) { $ config = config ( App :: class ) ; } return new Response ( $ config ) ; }

The Response class models an HTTP response.

@param \Config\App $config
@param boolean     $getShared

@return \CodeIgniter\HTTP\Response

The Response class models an HTTP response .


public static function redirectResponse(App $config = null, bool $getShared = true)
	{
		if ($getShared)
		{
			return static::getSharedInstance('redirectResponse', $config);
		}

		if (! is_object($config))
		{
			$config = config(App::class);
		}

		$response = new RedirectResponse($config);
		$response->setProtocolVersion(static::request()
										  ->getProtocolVersion());

		return $response;
	}

public static function redirectResponse ( App $ config = null , bool $ getShared = true ) { if ( $ getShared ) { return static :: getSharedInstance ( 'redirectResponse' , $ config ) ; } if ( ! is_object ( $ config ) ) { $ config = config ( App :: class ) ; } $ response = new RedirectResponse ( $ config ) ; $ response -> setProtocolVersion ( static :: request ( ) -> getProtocolVersion ( ) ) ; return $ response ; }

The Redirect class provides nice way of working with redirects.

@param \Config\App $config
@param boolean     $getShared

@return \CodeIgniter\HTTP\Response

The Redirect class provides nice way of working with redirects .


public static function router(RouteCollectionInterface $routes = null, bool $getShared = true)
	{
		if ($getShared)
		{
			return static::getSharedInstance('router', $routes);
		}

		if (empty($routes))
		{
			$routes = static::routes(true);
		}

		return new Router($routes);
	}

public static function router ( RouteCollectionInterface $ routes = null , bool $ getShared = true ) { if ( $ getShared ) { return static :: getSharedInstance ( 'router' , $ routes ) ; } if ( empty ( $ routes ) ) { $ routes = static :: routes ( true ) ; } return new Router ( $ routes ) ; }

The Router class uses a RouteCollection's array of routes, and determines
the correct Controller and Method to execute.

@param \CodeIgniter\Router\RouteCollectionInterface $routes
@param boolean                                      $getShared

@return \CodeIgniter\Router\Router

The Router class uses a RouteCollection s array of routes and determines the correct Controller and Method to execute .


public static function security(App $config = null, bool $getShared = true)
	{
		if ($getShared)
		{
			return static::getSharedInstance('security', $config);
		}

		if (! is_object($config))
		{
			$config = config(App::class);
		}

		return new Security($config);
	}

public static function security ( App $ config = null , bool $ getShared = true ) { if ( $ getShared ) { return static :: getSharedInstance ( 'security' , $ config ) ; } if ( ! is_object ( $ config ) ) { $ config = config ( App :: class ) ; } return new Security ( $ config ) ; }

The Security class provides a few handy tools for keeping the site
secure, most notably the CSRF protection tools.

@param \Config\App $config
@param boolean     $getShared

@return \CodeIgniter\Security\Security

The Security class provides a few handy tools for keeping the site secure most notably the CSRF protection tools .


public static function uri(string $uri = null, bool $getShared = true)
	{
		if ($getShared)
		{
			return static::getSharedInstance('uri', $uri);
		}

		return new URI($uri);
	}

public static function uri ( string $ uri = null , bool $ getShared = true ) { if ( $ getShared ) { return static :: getSharedInstance ( 'uri' , $ uri ) ; } return new URI ( $ uri ) ; }

The URI class provides a way to model and manipulate URIs.

@param string  $uri
@param boolean $getShared

@return \CodeIgniter\HTTP\URI

The URI class provides a way to model and manipulate URIs .


public static function validation(\Config\Validation $config = null, bool $getShared = true)
	{
		if ($getShared)
		{
			return static::getSharedInstance('validation', $config);
		}

		if (is_null($config))
		{
			$config = config('Validation');
		}

		return new Validation($config, static::renderer());
	}

public static function validation ( \ Config \ Validation $ config = null , bool $ getShared = true ) { if ( $ getShared ) { return static :: getSharedInstance ( 'validation' , $ config ) ; } if ( is_null ( $ config ) ) { $ config = config ( 'Validation' ) ; } return new Validation ( $ config , static :: renderer ( ) ) ; }

The Validation class provides tools for validating input data.

@param \Config\Validation $config
@param boolean            $getShared

@return \CodeIgniter\Validation\Validation

The Validation class provides tools for validating input data .


protected function describeCommands(array $commands = [])
	{
		ksort($commands);

		// Sort into buckets by group
		$sorted         = [];
		$maxTitleLength = 0;

		foreach ($commands as $title => $command)
		{
			if (! isset($sorted[$command['group']]))
			{
				$sorted[$command['group']] = [];
			}

			$sorted[$command['group']][$title] = $command;

			$maxTitleLength = max($maxTitleLength, strlen($title));
		}

		ksort($sorted);

		// Display it all...
		foreach ($sorted as $group => $items)
		{
			CLI::newLine();
			CLI::write($group);

			foreach ($items as $title => $item)
			{
				$title = $this->padTitle($title, $maxTitleLength, 2, 2);

				$out = CLI::color($title, 'yellow');

				if (isset($item['description']))
				{
					$out .= CLI::wrap($item['description'], 125, strlen($title));
				}

				CLI::write($out);
			}
		}
	}

protected
function
describeCommands
(
array
$
commands
=
[
]
)
{
ksort
(
$
commands
)
;
// Sort into buckets by group
$
sorted
=
[
]
;
$
maxTitleLength
=
0
;
foreach
(
$
commands
as
$
title
=>
$
command
)
{
if
(
!
isset
(
$
sorted
[
$
command
[
'group'
]
]
)
)
{
$
sorted
[
$
command
[
'group'
]
]
=
[
]
;
}
$
sorted
[
$
command
[
'group'
]
]
[
$
title
]
=
$
command
;
$
maxTitleLength
=
max
(
$
maxTitleLength
,
strlen
(
$
title
)
)
;
}
ksort
(
$
sorted
)
;
// Display it all...
foreach
(
$
sorted
as
$
group
=>
$
items
)
{
CLI
::
newLine
(
)
;
CLI
::
write
(
$
group
)
;
foreach
(
$
items
as
$
title
=>
$
item
)
{
$
title
=
$
this
->
padTitle
(
$
title
,
$
maxTitleLength
,
2
,
2
)
;
$
out
=
CLI
::
color
(
$
title
,
'yellow'
)
;
if
(
isset
(
$
item
[
'description'
]
)
)
{
$
out
.=
CLI
::
wrap
(
$
item
[
'description'
]
,
125
,
strlen
(
$
title
)
)
;
}
CLI
::
write
(
$
out
)
;
}
}
}

Displays the commands on the CLI.

@param array $commands


protected function padTitle(string $item, int $max, int $extra = 2, int $indent = 0): string
	{
		$max += $extra + $indent;

		$item = str_repeat(' ', $indent) . $item;
		$item = str_pad($item, $max);

		return $item;
	}

protected
function
padTitle
(
string
$
item
,
int
$
max
,
int
$
extra
=
2
,
int
$
indent
=
0
)
:
string
{
$
max
+=
$
extra
+
$
indent
;
$
item
=
str_repeat
(
' '
,
$
indent
)
.
$
item
;
$
item
=
str_pad
(
$
item
,
$
max
)
;
return
$
item
;
}

Pads our string out so that all titles are the same length to nicely line up descriptions.

@param string  $item
@param integer $max
@param integer $extra  // How many extra spaces to add at the end
@param integer $indent

@return string

Pads our string out so that all titles are the same length to nicely line up descriptions .


public function getCSVFromResult(ResultInterface $query, string $delim = ',', string $newline = "\n", string $enclosure = '"')
	{
		$out = '';
		// First generate the headings from the table column names
		foreach ($query->getFieldNames() as $name)
		{
			$out .= $enclosure . str_replace($enclosure, $enclosure . $enclosure, $name) . $enclosure . $delim;
		}

		$out = substr($out, 0, -strlen($delim)) . $newline;

		// Next blast through the result array and build out the rows
		while ($row = $query->getUnbufferedRow('array'))
		{
			$line = [];
			foreach ($row as $item)
			{
				$line[] = $enclosure . str_replace($enclosure, $enclosure . $enclosure, $item) . $enclosure;
			}
			$out .= implode($delim, $line) . $newline;
		}

		return $out;
	}

Generate CSV from a query result object

@param ResultInterface $query     Query result object
@param string          $delim     Delimiter (default: ,)
@param string          $newline   Newline character (default: \n)
@param string          $enclosure Enclosure (default: ")

@return string