Files
wiosna-dev_common-library/src/Utilities/Miscellaneous.php
2019-03-05 10:18:45 +01:00

1351 lines
40 KiB
PHP

<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\Common\Utilities;
use Gedmo\Sluggable\Util\Urlizer;
use Transliterator;
/**
* Miscellaneous methods (only static functions)
*
* @author Meritoo <github@meritoo.pl>
* @copyright Meritoo <http://www.meritoo.pl>
*/
class Miscellaneous
{
/**
* Returns directory's content (names of directories and files)
*
* @param string $directoryPath Path of directory who content should be returned
* @param bool $recursive (optional) If is set to true, sub-directories are also searched for content.
* Otherwise - only content of given directory is returned.
* @param int $maxFilesCount (optional) Maximum files that will be returned. If it's null, all files are
* returned.
* @return array|null
*/
public static function getDirectoryContent($directoryPath, $recursive = false, $maxFilesCount = null)
{
/*
* Path of directory is unknown or does not exist and is not readable?
* Nothing to do
*/
if (empty($directoryPath) || !is_readable($directoryPath)) {
return null;
}
$files = [];
$startFileName = '';
if (self::isFilePath($directoryPath)) {
$startDirectoryPath = dirname($directoryPath);
$startFileName = str_replace($startDirectoryPath, '', $directoryPath);
$directoryPath = $startDirectoryPath;
}
$count = 0;
$startFileFound = false;
if (!Regex::endsWith($directoryPath, '/')) {
$directoryPath .= '/';
}
if (Regex::startsWith($startFileName, '/')) {
$startFileName = mb_substr($startFileName, 1);
}
$directoryContent = scandir($directoryPath, SCANDIR_SORT_ASCENDING);
if (!empty($directoryContent)) {
foreach ($directoryContent as $fileName) {
if ('.' !== $fileName && '..' !== $fileName) {
$content = null;
if (!empty($startFileName) && !$startFileFound) {
if ($fileName === $startFileName) {
$startFileFound = true;
}
continue;
}
if ($recursive && is_dir($directoryPath . $fileName)) {
$content = self::getDirectoryContent($directoryPath . $fileName, true, $maxFilesCount - $count);
}
if (null !== $content) {
$files[$fileName] = $content;
if (null !== $maxFilesCount) {
$count += Arrays::getNonArrayElementsCount($content);
}
} else {
$files[] = $fileName;
if (null !== $maxFilesCount) {
++$count;
}
}
if (null !== $maxFilesCount && $count >= $maxFilesCount) {
break;
}
}
}
}
return $files;
}
/**
* Returns information if given path it's a file's path, if the path contains file name
*
* @param string $path The path to check
* @return bool
*/
public static function isFilePath($path)
{
$info = pathinfo($path);
return isset($info['extension']) && !empty($info['extension']);
}
/**
* Converts checkbox value to boolean
*
* @param string $checkboxValue Checkbox value
* @return bool
*/
public static function checkboxValue2Boolean($checkboxValue)
{
$mapping = [
'on' => true,
'off' => false,
];
$clearValue = strtolower(trim($checkboxValue));
if (isset($mapping[$clearValue])) {
return $mapping[$clearValue];
}
return false;
}
/**
* Converts checkbox value to integer
*
* @param string $checkboxValue Checkbox value
* @return int
*/
public static function checkboxValue2Integer($checkboxValue)
{
return (int)self::checkboxValue2Boolean($checkboxValue);
}
/**
* Returns name of file with given extension after verification if it contains the extension
*
* @param string $fileName The file name to verify
* @param string $extension The extension to verify and include
* @return string
*/
public static function includeFileExtension($fileName, $extension)
{
$fileExtension = self::getFileExtension($fileName, true);
/*
* File has given extension?
* Nothing to do
*/
if ($fileExtension === strtolower($extension)) {
return $fileName;
}
return sprintf('%s.%s', $fileName, $extension);
}
/**
* Returns file extension
*
* @param string $fileName File name
* @param bool $asLowerCase (optional) if true extension is returned as lowercase string
* @return string
*/
public static function getFileExtension($fileName, $asLowerCase = false)
{
$extension = '';
$matches = [];
if (preg_match('|(.+)\.(.+)|', $fileName, $matches)) {
$extension = end($matches);
}
if ($asLowerCase) {
return strtolower($extension);
}
return $extension;
}
/**
* Returns file name from given path
*
* @param string $path A path that contains file name
* @return string
*/
public static function getFileNameFromPath($path)
{
$matches = [];
$pattern = sprintf('|([^\%s.]+\.[A-Za-z0-9.]+)$|', DIRECTORY_SEPARATOR);
if ((bool)preg_match($pattern, $path, $matches)) {
return $matches[1];
}
return '';
}
/**
* Returns unique name for file based on given original name
*
* @param string $originalFileName Original name of the file
* @param int $objectId (optional) Object ID, the ID of database's row. May be included into the
* generated / unique name.
* @return string
*/
public static function getUniqueFileName($originalFileName, $objectId = 0)
{
/*
* Get parts of the file name:
* - without extension
* - and... the extension
*/
$withoutExtension = self::getFileNameWithoutExtension($originalFileName);
$extension = self::getFileExtension($originalFileName, true);
/*
* Let's clear name of file
*
* Attention.
* The name without extension may be cleared / urlized only to avoid incorrect name by replacing "." with "-".
*/
$withoutExtension = Urlizer::urlize($withoutExtension);
/*
* Now I have to complete the template used to build / generate unique name
*/
$template = '%s-%s.%s'; // [file's name]-[unique key].[file's extension]
/*
* Add some uniqueness
*/
$unique = self::getUniqueString(mt_rand());
/*
* Finally build and return the unique name
*/
if ($objectId > 0) {
$template = '%s-%s-%s.%s'; // [file's name]-[unique key]-[object ID].[file's extension]
return sprintf($template, $withoutExtension, $unique, $objectId, $extension);
}
return sprintf($template, $withoutExtension, $unique, $extension);
}
/**
* Returns file name without extension
*
* @param string $fileName The file name
* @return string
*/
public static function getFileNameWithoutExtension($fileName)
{
$matches = [];
if (is_string($fileName) && (bool)preg_match('|(.+)\.(.+)|', $fileName, $matches)) {
return $matches[1];
}
return '';
}
/**
* Converts value to non-negative integer (element of the set {0, 1, 2, 3, ...})
*
* @param mixed $value Value to convert
* @param int $negativeReplacement (optional) Replacement for negative value
* @return int
*/
public static function value2NonNegativeInteger($value, $negativeReplacement = 0)
{
$effect = (int)$value;
if ($effect < 0) {
return $negativeReplacement;
}
return $effect;
}
/**
* Returns information if given PHP module is compiled and loaded
*
* @param string $phpModuleName PHP module name
* @return bool
*/
public static function isPhpModuleLoaded($phpModuleName)
{
$phpModulesArray = get_loaded_extensions();
return in_array($phpModuleName, $phpModulesArray, false);
}
/**
* Converts given string characters to latin characters
*
* @param string $string String to convert
* @param bool $lowerCaseHuman (optional) If is set to true, converted string is returned as lowercase and
* human-readable. Otherwise - as original.
* @param string $replacementChar (optional) Replacement character for all non-latin characters and uppercase
* letters, if 2nd argument is set to true
* @return string
*/
public static function toLatin($string, $lowerCaseHuman = true, $replacementChar = '-')
{
if (is_string($string)) {
$string = trim($string);
}
/*
* Empty value?
* Nothing to do
*/
if (empty($string)) {
return '';
}
$converter = Transliterator::create('Latin-ASCII;');
/*
* Oops, cannot instantiate converter
* Nothing to do
*/
if (null === $converter) {
return '';
}
$converted = $converter->transliterate($string);
/*
* Make the string lowercase and human-readable
*/
if ($lowerCaseHuman) {
$matches = [];
$matchCount = preg_match_all('|[A-Z]{1}[^A-Z]*|', $converted, $matches);
if ($matchCount > 0) {
$parts = $matches[0];
$converted = mb_strtolower(implode($replacementChar, $parts));
}
}
/*
* Let's replace special characters to spaces
* ...and finally spaces to $replacementChar
*/
$replaced = preg_replace('|[^a-zA-Z0-9]|', ' ', $converted);
return preg_replace('| +|', $replacementChar, trim($replaced));
}
/**
* Returns unique string
*
* @param string $prefix (optional) Prefix of the unique string. May be used while generating the unique
* string simultaneously on several hosts at the same microsecond.
* @param bool $hashed (optional) If is set to true, the unique string is hashed additionally. Otherwise - not.
* @return string
*/
public static function getUniqueString($prefix = '', $hashed = false)
{
$unique = uniqid($prefix, true);
if ($hashed) {
return sha1($unique);
}
return $unique;
}
/**
* Replaces part of string with other string or strings.
* There is a few combination of what should be searched and with what it should be replaced.
*
* @param string|array $subject The string or an array of strings to search and replace
* @param string|array $search String or pattern or array of patterns to find. It may be: string, an array
* of strings or an array of patterns.
* @param string|array $replacement The string or an array of strings to replace. It may be: string or an array
* of strings.
* @param bool $quoteStrings (optional) If is set to true, strings are surrounded with single quote sign
* @return string
*
* Example:
* a) an array of strings to search
* $subject = [
* 'Lorem ipsum dolor sit amet.',
* 'Etiam ullamcorper. Suspendisse a pellentesque dui, non felis.',
* ];
*
* b) an array of patterns
* $search = [
* '|ipsum|',
* '|pellentesque|',
* ];
*
* c) an array of strings to replace
* $replacement = [
* 'commodo',
* 'interdum',
* ];
*
* The result:
* [
* 'Lorem commodo dolor sit amet.',
* 'Etiam ullamcorper. Suspendisse a interdum dui, non felis.',
* ];
*/
public static function replace($subject, $search, $replacement, $quoteStrings = false)
{
/*
* Unknown source or item to find or replacement is an empty array?
* Nothing to do
*/
if (empty($subject) || empty($search) || [] === $replacement) {
return $subject;
}
$effect = $subject;
$searchIsString = is_string($search);
$searchIsArray = is_array($search);
/*
* Value to find is neither a string nor an array OR it's an empty string?
* Nothing to do
*/
if ((!$searchIsString && !$searchIsArray) || ($searchIsString && '' === $search)) {
return $effect;
}
$replacementIsString = is_string($replacement);
$replacementIsArray = is_array($replacement);
$bothAreStrings = $searchIsString && $replacementIsString;
$bothAreArrays = $searchIsArray && $replacementIsArray;
if ($quoteStrings) {
if ($replacementIsString) {
$replacement = '\'' . $replacement . '\'';
} elseif ($replacementIsArray) {
foreach ($replacement as &$item) {
if (is_string($item)) {
$item = '\'' . $item . '\'';
}
}
unset($item);
}
}
/*
* 1st step: replace strings, simple operation with strings
*/
if ($bothAreStrings) {
$effect = str_replace($search, $replacement, $subject);
}
/*
* 2nd step: replace with regular expressions.
* Attention. Searched and replacement value should be the same type: strings or arrays.
*/
if ($effect === $subject && ($bothAreStrings || $bothAreArrays)) {
/*
* I have to avoid string that contains spaces only, e.g. " ".
* It's required to avoid bug: preg_replace(): Empty regular expression.
*/
if ($searchIsArray || ($searchIsString && !empty(trim($search)))) {
$replaced = @preg_replace($search, $replacement, $subject);
if (null !== $replaced && [] !== $replaced) {
$effect = $replaced;
}
}
}
/*
* 3rd step: complex replace of the replacement defined as an array.
* It may be useful when you want to search for a one string and replace the string with multiple values.
*/
if ($effect === $subject && $searchIsString && $replacementIsArray) {
$subjectIsArray = is_array($subject);
$effect = '';
if ($subjectIsArray) {
$effect = [];
}
/*
* I have to make the subject an array...
*/
$subject = Arrays::makeArray($subject);
/*
* ...and use iterate through the subjects,
* because explode() function expects strings as both arguments (1st and 2nd)
*/
foreach ($subject as $subSubject) {
$subEffect = '';
$exploded = explode($search, $subSubject);
$explodedCount = count($exploded);
foreach ($exploded as $key => $item) {
$subEffect .= $item;
/*
* The replacement shouldn't be included when the searched string was not found
*/
if ($explodedCount > 1 && $key < $explodedCount - 1 && isset($replacement[$key])) {
$subEffect .= $replacement[$key];
}
}
if ($subjectIsArray) {
$effect[] = $subEffect;
continue;
}
$effect .= $subEffect;
}
}
return $effect;
}
/**
* Returns new file name after adding prefix or suffix (or both of them) to the name
*
* @param string $fileName The file name
* @param string $prefix File name prefix
* @param string $suffix File name suffix
* @return string
*/
public static function getNewFileName($fileName, $prefix, $suffix)
{
$effect = $fileName;
if (!empty($fileName) && (!empty($prefix) || !empty($suffix))) {
$name = self::getFileNameWithoutExtension($fileName);
$extension = self::getFileExtension($fileName);
$effect = sprintf('%s%s%s.%s', $prefix, $name, $suffix, $extension);
}
return $effect;
}
/**
* Returns operating system name PHP is running on
*
* @return string
*/
public static function getOperatingSystemNameServer()
{
return PHP_OS;
/*
* Previous version:
* return php_uname('s');
*/
}
/**
* Returns part of string preserving words
*
* @param string $text The string / text
* @param int $maxLength Maximum length of given string
* @param string $suffix (optional) The suffix to add at the end of string
* @return string
*/
public static function substringToWord($text, $maxLength, $suffix = '...')
{
$effect = $text;
$textLength = mb_strlen($text, 'utf-8');
$suffixLength = mb_strlen($suffix, 'utf-8');
$maxLength -= $suffixLength;
if ($textLength > $maxLength) {
$effect = mb_substr($text, 0, $maxLength, 'utf-8');
$lastSpacePosition = mb_strrpos($effect, ' ', 'utf-8');
if (false !== $lastSpacePosition) {
$effect = mb_substr($effect, 0, $lastSpacePosition, 'utf-8');
}
$effect .= $suffix;
}
return $effect;
}
/**
* Breaks long text
*
* @param string $text The text to check and break
* @param int $perLine (optional) Characters count per line. Default: 100.
* @param string $separator (optional) Separator that is placed between lines. Default: "<br>".
* @param string $encoding (optional) Character encoding. Used by mb_substr(). Default: "UTF-8".
* @param int $proportionalAberration (optional) Proportional aberration for chars (percent value). Default: 20.
* @return string
*/
public static function breakLongText(
$text,
$perLine = 100,
$separator = '<br>',
$encoding = 'utf-8',
$proportionalAberration = 20
) {
$effect = $text;
$textLength = mb_strlen($text);
if (!empty($text) && $textLength > $perLine) {
/*
* The html_entity_decode() function is used here, because while operating
* on string that contains only special characters the string is divided
* incorrectly, e.g. "<<<<<" -> "&lt;&lt;&lt;&lt;&<br />lt;".
*/
//$text = htmlspecialchars_decode($text);
$text = html_entity_decode($text, ENT_QUOTES);
$effect = '';
$currentPosition = 0;
$charsAberration = ceil($perLine * ($proportionalAberration / 100));
$charsPerLineDefault = $perLine;
while ($currentPosition <= $textLength) {
$insertSeparator = false;
/*
* Looking for spaces before and after current position. It was done, because text wasn't
* broken properly and some words were breaked and placed into two lines.
*/
if ($charsAberration > 0) {
$length = $perLine + $charsAberration;
$lineWithAberration = mb_substr($text, $currentPosition, $length, $encoding);
if (!Regex::contains($lineWithAberration, ' ')) {
$length = $perLine - $charsAberration;
$lineWithAberration = mb_substr($text, $currentPosition, $length, $encoding);
}
if (Regex::startsWith($lineWithAberration, ' ')) {
++$currentPosition;
$lineWithAberration = ltrim($lineWithAberration);
}
$spacePosition = mb_strrpos($lineWithAberration, ' ', 0, $encoding);
if (false !== $spacePosition && 0 < $spacePosition) {
/* @var int $spacePosition */
$perLine = $spacePosition;
$insertSeparator = true;
}
}
$charsOneLine = mb_substr($text, $currentPosition, $perLine, $encoding);
/*
* The htmlspecialchars() function is used here, because...
* Reason and comment the same as above for html_entity_decode() function.
*/
$effect .= htmlspecialchars($charsOneLine);
//$effect .= $charsOneLine;
$currentPosition += $perLine;
$oneLineContainsSpace = Regex::contains($charsOneLine, ' ');
if (($insertSeparator || !$oneLineContainsSpace) && $currentPosition <= $textLength) {
$effect .= $separator;
}
$perLine = $charsPerLineDefault;
}
}
return $effect;
}
/**
* Removes the directory.
* If not empty, removes also contents.
*
* @param string $directoryPath Directory path
* @param bool $contentOnly (optional) If is set to true, only content of the directory is removed, not
* directory itself. Otherwise - directory is removed too (default behaviour).
* @return bool|null
*/
public static function removeDirectory($directoryPath, $contentOnly = false)
{
/*
* Directory does not exist?
* Nothing to do
*/
if (!file_exists($directoryPath)) {
return null;
}
/*
* It's not a directory?
* Let's treat it like file
*/
if (!is_dir($directoryPath)) {
return unlink($directoryPath);
}
foreach (scandir($directoryPath, SCANDIR_SORT_ASCENDING) as $item) {
if ('.' === $item || '..' === $item) {
continue;
}
if (!self::removeDirectory($directoryPath . DIRECTORY_SEPARATOR . $item)) {
return false;
}
}
/*
* Directory should be removed too?
*/
if (!$contentOnly) {
return rmdir($directoryPath);
}
return true;
}
/**
* Returns information if value is decimal
*
* @param mixed $value The value to check
* @return bool
*/
public static function isDecimal($value)
{
return is_scalar($value) && floor($value) !== (float)$value;
}
/**
* Returns the string in camel case
*
* @param string $string The string to convert e.g. this-is-eXamplE (return: thisIsExample)
* @param string $separator (optional) Separator used to find parts of the string, e.g. '-' or ','
* @return string
*/
public static function getCamelCase($string, $separator = ' ')
{
if (empty($string)) {
return '';
}
$effect = '';
$members = explode($separator, $string);
foreach ($members as $key => $value) {
$value = mb_strtolower($value);
if (0 === $key) {
$effect .= self::lowercaseFirst($value);
} else {
$effect .= self::uppercaseFirst($value);
}
}
return $effect;
}
/**
* Make a string's first character lowercase
*
* @param string $text The text to get first character lowercase
* @param bool|null $restLowercase (optional) Information that to do with rest of given string
* @return string
*
* Values of the $restLowercase argument:
* - null (default): nothing is done with the string
* - true: the rest of string is lowercased
* - false: the rest of string is uppercased
*/
public static function lowercaseFirst($text, $restLowercase = null)
{
if (empty($text)) {
return '';
}
$effect = $text;
if ($restLowercase) {
$effect = mb_strtolower($effect);
} elseif (false === $restLowercase) {
$effect = mb_strtoupper($effect);
}
return lcfirst($effect);
}
/**
* Make a string's first character uppercase
*
* @param string $text The text to get uppercase
* @param bool|null $restLowercase (optional) Information that to do with rest of given string
* @return string
*
* Values of the $restLowercase argument:
* - null (default): nothing is done with the string
* - true: the rest of string is lowercased
* - false: the rest of string is uppercased
*/
public static function uppercaseFirst($text, $restLowercase = null)
{
if (empty($text)) {
return '';
}
$effect = $text;
if ($restLowercase) {
$effect = mb_strtolower($effect);
} elseif (false === $restLowercase) {
$effect = mb_strtoupper($effect);
}
return ucfirst($effect);
}
/**
* Quotes given value with apostrophes or quotation marks
*
* @param mixed $value The value to quote
* @param bool $useApostrophe (optional) If is set to true, apostrophes are used. Otherwise - quotation marks.
* @return string
*/
public static function quoteValue($value, $useApostrophe = true)
{
if (is_string($value)) {
$quotes = '"';
if ($useApostrophe) {
$quotes = '\'';
}
$value = sprintf('%s%s%s', $quotes, $value, $quotes);
}
return $value;
}
/**
* Returns size (of file or directory) in human readable format
*
* @param int $sizeInBytes The size in bytes
* @return string
*/
public static function getHumanReadableSize($sizeInBytes)
{
$units = [
'B',
'KB',
'MB',
'GB',
'TB',
'PB',
];
$index = floor(log($sizeInBytes, 1024));
$size = round($sizeInBytes / (1024 ** $index), 2);
$unit = $units[(int)$index];
return sprintf('%s %s', $size, $unit);
}
/**
* Returns string without the last element.
* The string should contain given separator.
*
* @param string $string The string to check
* @param string $separator The separator which divides elements of string
* @return string
*/
public static function getStringWithoutLastElement($string, $separator)
{
$elements = self::getStringElements($string, $separator);
$lastKey = Arrays::getLastKey($elements);
unset($elements[$lastKey]);
return implode($separator, $elements);
}
/**
* Returns elements of given string divided by given separator
*
* @param string $string The string to check
* @param string $separator The separator which divides elements of string
* @return array
*/
public static function getStringElements($string, $separator)
{
$matches = [];
$pattern = sprintf('|[^\%s]+|', $separator);
$matchCount = preg_match_all($pattern, $string, $matches);
if ($matchCount > 1) {
return $matches[0];
}
return [];
}
/**
* Returns the last element of given string divided by given separator
*
* @param string $string The string to check
* @param string $separator The separator which divides elements of string
* @return string|null
*/
public static function getLastElementOfString($string, $separator)
{
$elements = self::getStringElements($string, $separator);
/*
* No elements?
* Nothing to do
*/
if (empty($elements)) {
return null;
}
$element = Arrays::getLastElement($elements);
return trim($element);
}
/**
* Returns smartly trimmed string.
* If the string is empty, contains only spaces, e.g. " ", nothing is done and the original string is returned.
*
* @param string $string The string to trim
* @return string
*/
public static function trimSmart($string)
{
$trimmed = trim($string);
if (empty($trimmed)) {
return $string;
}
return $trimmed;
}
/**
* Returns concatenated given paths
*
* The paths may be passed as:
* - an array of paths / strings
* - strings passed as following arguments
*
* Examples:
* - concatenatePaths(['path/first', 'path/second', 'path/third']);
* - concatenatePaths('path/first', 'path/second', 'path/third');
*
* @param string|array $paths Paths co concatenate. As described above: an array of paths / strings or strings
* passed as following arguments.
* @return string
*/
public static function concatenatePaths($paths)
{
/*
* If paths are not provided as array, get the paths from methods' arguments
*/
if (!is_array($paths)) {
$paths = func_get_args();
}
/*
* No paths provided?
* Nothing to do
*/
if (empty($paths)) {
return '';
}
/*
* Some useful variables
*/
$concatenated = '';
$firstWindowsBased = false;
$separator = DIRECTORY_SEPARATOR;
foreach ($paths as $path) {
$path = trim($path);
/*
* Empty paths are useless
*/
if (empty($path)) {
continue;
}
/*
* Does the first path is a Windows-based path?
*/
if (Arrays::isFirstElement($paths, $path)) {
$firstWindowsBased = Regex::isWindowsBasedPath($path);
if ($firstWindowsBased) {
$separator = '\\';
}
}
/*
* Remove the starting / beginning directory's separator
*/
$path = self::removeStartingDirectorySeparator($path, $separator);
/*
* Removes the ending directory's separator
*/
$path = self::removeEndingDirectorySeparator($path, $separator);
/*
* If OS is Windows, first part of the concatenated path should be the first passed path,
* because in Windows paths starts with drive letter, e.g. "C:", and the directory separator is not
* necessary at the beginning.
*/
if ($firstWindowsBased && empty($concatenated)) {
$concatenated = $path;
continue;
}
/*
* Concatenate the paths / strings with OS-related directory separator between them (slash or backslash)
*/
$concatenated = sprintf('%s%s%s', $concatenated, $separator, $path);
}
return $concatenated;
}
/**
* Removes the starting / beginning directory's separator
*
* @param string $text Text that may contain a directory's separator at the start / beginning
* @param string $separator (optional) The directory's separator, e.g. "/". If is empty (not provided), separator
* provided by operating system will be used.
* @return string
*/
public static function removeStartingDirectorySeparator($text, $separator = '')
{
/*
* Not a string?
* Nothing to do
*/
if (!is_string($text)) {
return '';
}
if (empty($separator)) {
$separator = DIRECTORY_SEPARATOR;
}
$effect = trim($text);
if (Regex::startsWithDirectorySeparator($effect, $separator)) {
$effect = mb_substr($effect, mb_strlen($separator));
}
return $effect;
}
/**
* Removes the ending directory's separator
*
* @param string $text Text that may contain a directory's separator at the end
* @param string $separator (optional) The directory's separator, e.g. "/". If is empty (not provided), system's
* separator is used.
* @return string
*/
public static function removeEndingDirectorySeparator($text, $separator = '')
{
/*
* Not a string?
* Nothing to do
*/
if (!is_string($text)) {
return '';
}
if (empty($separator)) {
$separator = DIRECTORY_SEPARATOR;
}
$effect = trim($text);
if (Regex::endsWithDirectorySeparator($effect, $separator)) {
$effect = mb_substr($effect, 0, mb_strlen($effect) - mb_strlen($separator));
}
return $effect;
}
/**
* Returns safely value of global variable, found in one of the global arrays / variables, e.g. $_GET
*
* @param int $globalSourceType Represents the global array / variable. One of constants: INPUT_GET, INPUT_POST,
* INPUT_COOKIE, INPUT_SERVER, or INPUT_ENV.
* @param string $variableName Name of the variable to return value
* @return mixed
*/
public static function getSafelyGlobalVariable($globalSourceType, $variableName)
{
$value = filter_input($globalSourceType, $variableName);
if (null === $value) {
$globalSource = null;
switch ($globalSourceType) {
case INPUT_GET:
$globalSource = $_GET;
break;
case INPUT_POST:
$globalSource = $_POST;
break;
case INPUT_COOKIE:
$globalSource = $_COOKIE;
break;
case INPUT_SERVER:
$globalSource = $_SERVER;
break;
case INPUT_ENV:
$globalSource = $_ENV;
break;
}
if (null !== $globalSource && isset($globalSource[$variableName])) {
$value = $globalSource[$variableName];
}
}
return $value;
}
/**
* Adds missing the "0" characters to given number until given length is reached
*
* Example:
* - number: 201
* - length: 6
* - will be returned: 000201
*
* If "before" parameter is false, zeros will be inserted after given number. If given number is longer than
* given length the number will be returned as it was given to the method.
*
* @param mixed $number Number for who the "0" characters should be inserted
* @param int $length Wanted length of final number
* @param bool $before (optional) If false, 0 characters will be inserted after given number
* @return string
*/
public static function fillMissingZeros($number, $length, $before = true)
{
/*
* It's not a number? Empty string is not a number too.
* Nothing to do
*/
if (!is_numeric($number)) {
return '';
}
$text = trim($number);
$textLength = mb_strlen($text);
if ($length <= $textLength) {
return $text;
}
for ($i = ($length - $textLength); 0 < $i; --$i) {
if ($before) {
$text = '0' . $text;
continue;
}
$text .= '0';
}
return $text;
}
/**
* Returns information if given value is located in interval between given utmost left and right values
*
* @param int|float $value Value to verify
* @param int|float $left Left utmost value of interval
* @param int|float $right Right utmost value of interval
* @return bool
*/
public static function isBetween($value, $left, $right)
{
return $value > $left && $value < $right;
}
/**
* Returns type of given variable.
* If it's an object, full class name is returned.
*
* @param mixed $variable Variable who type should be returned
* @return string
*/
public static function getType($variable)
{
if (is_object($variable)) {
return Reflection::getClassName($variable);
}
return gettype($variable);
}
/**
* Returns valid value of color's component (e.g. red).
* If given value is greater than 0, returns the value. Otherwise - 0.
*
* @param int $colorComponent Color's component to verify. Decimal value, e.g. 255.
* @param bool $asHexadecimal (optional) If is set to true, hexadecimal value is returned (default behaviour).
* Otherwise - decimal.
* @return int|string
*/
public static function getValidColorComponent($colorComponent, $asHexadecimal = true)
{
$colorComponent = (int)$colorComponent;
if ($colorComponent < 0 || $colorComponent > 255) {
$colorComponent = 0;
}
if ($asHexadecimal) {
$hexadecimal = dechex($colorComponent);
if (1 === strlen($hexadecimal)) {
return sprintf('0%s', $hexadecimal);
}
return $hexadecimal;
}
return $colorComponent;
}
/**
* Returns inverted value of color for given color
*
* @param string $color Hexadecimal value of color to invert (with or without hash), e.g. "dd244c" or "#22a5fe"
* @return string
*/
public static function getInvertedColor($color)
{
/*
* Prepare the color for later usage
*/
$color = trim($color);
$withHash = Regex::startsWith($color, '#');
/*
* Verify and get valid value of color.
* An exception will be thrown if the value is not a color.
*/
$validColor = Regex::getValidColorHexValue($color);
/*
* Grab color's components
*/
$red = hexdec(substr($validColor, 0, 2));
$green = hexdec(substr($validColor, 2, 2));
$blue = hexdec(substr($validColor, 4, 2));
/*
* Calculate inverted color's components
*/
$redInverted = self::getValidColorComponent(255 - $red);
$greenInverted = self::getValidColorComponent(255 - $green);
$blueInverted = self::getValidColorComponent(255 - $blue);
/*
* Voila, here is the inverted color
*/
$invertedColor = sprintf('%s%s%s', $redInverted, $greenInverted, $blueInverted);
if ($withHash) {
return sprintf('#%s', $invertedColor);
}
return $invertedColor;
}
/**
* Returns project's root path.
* Looks for directory that contains composer.json.
*
* @return string
*/
public static function getProjectRootPath()
{
$projectRootPath = '';
$fileName = 'composer.json';
$directoryPath = __DIR__;
/*
* Path of directory it's not the path of last directory?
*/
while (DIRECTORY_SEPARATOR !== $directoryPath) {
$filePath = static::concatenatePaths($directoryPath, $fileName);
/*
* Is here file we are looking for?
* Maybe it's a project's root path
*/
if (file_exists($filePath)) {
$projectRootPath = $directoryPath;
}
$directoryPath = dirname($directoryPath);
}
return $projectRootPath;
}
}