diff --git a/CHANGELOG.md b/CHANGELOG.md index f933f00..9c74762 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,8 @@ Changelog ========= -## 1.3.* +## 1.4.0 (2020-10-04) + * Added `KeyboardLayoutHelper` * Added `DbSchemaTrait` for migrations * Added `ArrayHelper::diff()` method diff --git a/README.md b/README.md index 24927f8..289111d 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ ![Progress](https://img.shields.io/badge/progress-ready_to_use-green.svg) [![GitHub license](https://img.shields.io/github/license/wdmg/yii2-helpers.svg)](https://github.com/wdmg/yii2-helpers/blob/master/LICENSE) -Yii2 Composite Forms +Custom helpers for Yii2 # Yii2 Helpers Custom helpers for Yii2 @@ -18,59 +18,8 @@ To install the helpers, run the following command in the console: `$ composer require "wdmg/yii2-helpers"` -# Usage -An example of a standalone time difference widget: - - updated_at, null, [ - 'layout' => '[ {datetime} ]', - 'inpastClass' => 'text-danger', // Class for datediff in past time - 'futureClass' => 'text-success', // Class for datediff in future time - ]); - - ?> - -Example of integer amount to string: - - "; - // 1,25K - - echo StringHelper::integerAmount('125763', 2, true) . "
"; - // 125,76K - - echo StringHelper::integerAmount('2525763', 2, false) . "
"; - // 2,52 mill. - - echo StringHelper::integerAmount('1432525763', 2, false) . "
"; - // 1,43 bill. - - ?> - -Example of string trim including full words: - - "; - // Lorem ipsum dolor sit amet, consectetuer adipiscing… - - echo StringHelper::stringShorter('Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.', 55, 25) . "
"; - // Lorem ipsum dolor sit amet, consectetuer adipiscing… ex ea commodo consequat. - - ?> - # Status and version [ready to use] +* v.1.4.0 - Added `KeyboardLayoutHelper` and `DbSchemaTrait` for migrations * v.1.3.6 - Fixed CIDR methods. Added IPv6 methods in `IpAddressHelper` * v.1.3.5 - IpAddressHelper fixed * v.1.3.4 - Added IpAddressHelper diff --git a/composer.json b/composer.json index 1294c6b..ecd1955 100644 --- a/composer.json +++ b/composer.json @@ -4,7 +4,7 @@ "keywords": ["yii", "yii2", "extension", "helper", "array-helper", "daterime-helper", "ip-helper", "string-helper", "text-analyzer", "utilities", "wdmg"], "type": "yii2-extension", "license": "MIT", - "version": "1.3.6", + "version": "1.4.0", "homepage": "https://github.com/wdmg/yii2-helpers", "support": { "source": "https://github.com/wdmg/yii2-helpers", diff --git a/src/ArrayHelper.php b/src/ArrayHelper.php index 31cd79a..9bc6ece 100644 --- a/src/ArrayHelper.php +++ b/src/ArrayHelper.php @@ -6,7 +6,7 @@ * Yii2 Custom array helper * * @category Helpers - * @version 1.3.6 + * @version 1.4.0 * @author Alexsander Vyshnyvetskyy * @link https://github.com/wdmg/yii2-helpers * @copyright Copyright (c) 2019 - 2020 W.D.M.Group, Ukraine @@ -21,6 +21,15 @@ class ArrayHelper extends BaseArrayHelper { + /** + * Returns the path to the parent array and the child array key (separated by a separator) where the search was found + * + * @param $needle + * @param array $array + * @param string $delimiter + * @param bool $searchByKeys + * @return bool|int|string + */ public static function getParents($needle, $array = [], $delimiter = '.', $searchByKeys = true) { foreach ($array as $key => $value) { @@ -37,6 +46,14 @@ public static function getParents($needle, $array = [], $delimiter = '.', $searc return false; } + /** + * Forms an array of values from CSV data for subsequent import + * + * @param null $data + * @param null $delimiter + * @param bool $withColumns + * @return array + */ public static function importCSV($data = null, $delimiter = null, $withColumns = false) { if (is_null($delimiter)) @@ -97,6 +114,15 @@ public static function importCSV($data = null, $delimiter = null, $withColumns = return $array; } + /** + * Forms CSV string data from an array of values for subsequent export + * + * @param null $array + * @param string $columns + * @param null $delimiter + * @param bool $withColumns + * @return string|null + */ public static function exportCSV($array = null, $columns = "*", $delimiter = null, $withColumns = false) { if (is_array($array)) { @@ -138,7 +164,20 @@ public static function exportCSV($array = null, $columns = "*", $delimiter = nul } } + /** + * Uniqueizes a multidimensional array, including specifying a key for uniqueizing values + * + * @param $array + * @param null $columns + * @return array|mixed + */ public static function unique($array, $columns = null) { + + if (!is_array($array)) { + throw new InvalidArgumentException('The `$array` argument must be array.'); + return null; + } + list($temp, $data) = [[],[]]; foreach ($array as $key => $row) { @@ -168,6 +207,13 @@ public static function unique($array, $columns = null) { } } + /** + * Returns the differences of multidimensional arrays. + * + * @param $array1 + * @param $array2 + * @return array|null + */ public static function diff($array1, $array2) { $array = []; @@ -204,6 +250,15 @@ public static function diff($array1, $array2) { return $array; } + /** + * Merges multidimensional arrays. + * + * @param $array1 + * @param $array2 + * @param null $count1 + * @param null $count2 + * @return array|null + */ public static function crossMerging($array1, $array2, $count1 = null, $count2 = null) { $i = 0; $j = 0; @@ -228,24 +283,39 @@ public static function crossMerging($array1, $array2, $count1 = null, $count2 = // Traverse both array while ($i < $count1 && $j < $count2) { - $array[$k++] = $array1[$i++]; - $array[$k++] = $array2[$j++]; + if (isset($array1[$i++])) + $array[$k++] = $array1[$i++]; + + if (isset($array2[$j++])) + $array[$k++] = $array2[$j++]; } // Store remaining elements of first array while ($i < $count1) { - $array[$k++] = $array1[$i++]; + if (isset($array1[$i++])) + $array[$k++] = $array1[$i++]; } // Store remaining elements of second array while($j < $count2) { - $array[$k++] = $array2[$j++]; + if (isset($array2[$j++])) + $array[$k++] = $array2[$j++]; } return $array; } + /** + * Builds an array tree from heirs by keys ʻitems` and `parent_id` + * + * @param array $array + * @param int $parentId + * @param string $parentKey + * @param string $childsKey + * @param int $level + * @return array + */ public static function buildTree(&$array = [], $parentId = 0, $parentKey = 'parent_id', $childsKey = 'items', $level = 1) { $tree = array(); foreach ($array as &$item) { diff --git a/src/DateAndTime.php b/src/DateAndTime.php index 82b46f2..4038c4e 100644 --- a/src/DateAndTime.php +++ b/src/DateAndTime.php @@ -6,7 +6,7 @@ * Yii2 Date and Time helper * * @category Helpers - * @version 1.3.6 + * @version 1.4.0 * @author Alexsander Vyshnyvetskyy * @link https://github.com/wdmg/yii2-helpers * @copyright Copyright (c) 2019 - 2020 W.D.M.Group, Ukraine diff --git a/src/DbSchemaTrait.php b/src/DbSchemaTrait.php index e02a9f7..255fff4 100644 --- a/src/DbSchemaTrait.php +++ b/src/DbSchemaTrait.php @@ -2,6 +2,18 @@ namespace wdmg\helpers; +/** + * Yii2 Extend DB schema + * + * @category Helpers + * @version 1.4.0 + * @author Alexsander Vyshnyvetskyy + * @link https://github.com/wdmg/yii2-helpers + * @copyright Copyright (c) 2019 - 2020 W.D.M.Group, Ukraine + * @license https://opensource.org/licenses/MIT Massachusetts Institute of Technology (MIT) License + * + */ + trait DbSchemaTrait { /** diff --git a/src/FileHelper.php b/src/FileHelper.php index 07ca3b4..10a7f08 100644 --- a/src/FileHelper.php +++ b/src/FileHelper.php @@ -6,7 +6,7 @@ * Yii2 Custom file helper * * @category Helpers - * @version 1.3.6 + * @version 1.4.0 * @author Alexsander Vyshnyvetskyy * @link https://github.com/wdmg/yii2-helpers * @copyright Copyright (c) 2019 - 2020 W.D.M.Group, Ukraine diff --git a/src/IpAddressHelper.php b/src/IpAddressHelper.php index ba3d9e2..3bf20f2 100644 --- a/src/IpAddressHelper.php +++ b/src/IpAddressHelper.php @@ -6,7 +6,7 @@ * Yii2 IP address helper * * @category Helpers - * @version 1.3.6 + * @version 1.4.0 * @author Alexsander Vyshnyvetskyy , Jonavon Wilcox , Manuel Kasper * @see https://gist.github.com/stibiumz/5e6a92a195c50c875649, https://gist.github.com/jonavon/2028872, http://m0n0.ch/wall, https://www.experts-exchange.com/questions/23903322/Need-PHP-code-for-calculating-subnets.html * @link https://github.com/wdmg/yii2-helpers @@ -1157,7 +1157,6 @@ public static function applyNetmask($ip, $netmask) { return long2ip(sprintf('%u', $ip & $netmask)); } - /** * Determines if the passed netmask is valid * @@ -1728,6 +1727,81 @@ public static function ipLookup($ip) { return($results); } + /** + * @return array|null + */ + public static function getArpTable() { + + $results = []; + exec('arp -an', $output); + foreach ($output as $line) { + preg_match('/((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])/i', $line, $match); + $ip = (isset($match[0]) ? $match[0] : null); // ip + + preg_match('/(([a-fA-F0-9]{1,2}\:){5}[a-fA-F0-9]{2})/i', $line, $match); + $mac = (isset($match[0]) ? $match[0] : null); // mac + + preg_match('/on\s+(.+)\[/i', $line, $match); + $scope = (isset($match[1]) ? $match[1] : null); // scope + + preg_match('/\[(\w+)\]/i', $line, $match); + $interface = (isset($match[1]) ? $match[1] : null); // interface + + $results[] = [ + 'ip' => $ip, + 'mac' => $mac, + 'scope' => $scope, + 'interface' => $interface, + ]; + } + + return (!empty($results)) ? $results : null; + } + + /** + * @param $address + * @return bool|mixed + */ + public static function ipMacLookup($address) { + if ($table = self::getArpTable()) { + foreach ($table as $item) { + if ($item['ip'] == $address || $item['mac'] == $address) + return $item; + } + } + + return false; + } + + /** + * @param $address + * @param string $separator + * @return mixed|string|string[]|null + */ + public static function formatMAC($address, $separator = ':') { + + if (preg_match('/^([a-fA-F0-9]{1,2}\:){5}[a-fA-F0-9]{1,2}$/is', $address)) // 70:EF:00:85:36:A9 + return str_replace(':', $separator, $address); + elseif (preg_match('/^([a-fA-F0-9]{1,2}[\:]{2}){5}[a-fA-F0-9]{1,2}$/is', $address)) // 70::EF::00::85::36::A9 + return str_replace('::', $separator, $address); + elseif (preg_match('/^([a-fA-F0-9]{1,2}[\:]{1,2}){5}[a-fA-F0-9]{1,2}$/is', $address)) // 70:EF::00:85::36:A9 + return preg_replace('/[\:]{1,2}/is', $separator, $address); + elseif (preg_match('/^([a-fA-F0-9]{1,2}\-){5}[a-fA-F0-9]{1,2}$/is', $address)) // 70-EF-00-85-36-A9 + return str_replace('-', $separator, $address); + elseif (preg_match('/^([a-fA-F0-9]{2})/is', $address)) // 70EF008536A9 + return rtrim(chunk_split($address, 2, $separator), $separator); + + return $address; + } + + /** + * @param $address + * @return bool + */ + public static function isValidMAC($address) { + return (false === filter_var($address, FILTER_VALIDATE_MAC)) ? false : true; + } + /** * Get list of IP adress by range * diff --git a/src/KeyboardLayoutHelper.php b/src/KeyboardLayoutHelper.php new file mode 100644 index 0000000..1a984e0 --- /dev/null +++ b/src/KeyboardLayoutHelper.php @@ -0,0 +1,169 @@ + + * @link https://github.com/wdmg/yii2-helpers + * @copyright Copyright (c) 2019 - 2020 W.D.M.Group, Ukraine + * @license https://opensource.org/licenses/MIT Massachusetts Institute of Technology (MIT) License + * + */ + +use Yii; +use yii\helpers\BaseStringHelper; +use yii\base\InvalidArgumentException; +use yii\base\InvalidConfigException; + +class KeyboardLayoutHelper extends BaseStringHelper +{ + /** + * @var array, available keyboard layouts grouped under the primary language locale code + */ + private static $layouts = [ + 'en_US' => 'QqWwEeRrTtYyUuIiOoPp{[}]AaSsDdFfGgHhJjKkLl:;"\'|\\ZzXxCcVvBbNnMm<,>.?/~`!1@2#3$4%5^6&7*8(9)0_-+=', + 'ru_RU' => 'ЙйЦцУуКкЕеНнГгШшЩщЗзХхЪъФфЫыВвАаПпРрОоЛлДдЖжЭэ/\\ЯяЧчСсМмИиТтЬьБбЮю,.Ёё!1"2№3;4%5:6?7*8(9)0_-+=', + 'uk_UA' => 'ЙйЦцУуКкЕеНнГгШшЩщЗзХхЇїФфІіВвАаПпРрОоЛлДдЖжЄєҐґЯяЧчСсМмИиТтЬьБбЮю,.~`!1"2№3;4%5:6?7*8(9)0_-+=', + 'be_BY' => 'ЙйЦцУуКкЕеНнГгШшЎўЗзХх\'ФфЫыВвАаПпРрОоЛлДдЖжЭэЁёЯяЧчСсМмІіТтЬьБбЮю?/„“!1"2№3%4:5,6.7;8(9)0_-+=', + 'kk_KZ' => 'ЙйЦцУуКкЕеНнГгШшЩщЗзХхЪъФфЫыВвАаПпРрОоЛлДдЖжЭэЁёЯяЧчСсМмИиТтЬьБбЮю?/[]!"ӘәІіҢңҒғ;,:.ҮүҰұҚқӨөҺһ', + 'pl_PL' => 'QqWwEeRrTtZzUuIiOoPpźó)(AaSsDdFfGgHhJjKkLlŁłęą$;YyXxCcVvBbNnMmś.ń,ć-><§1%2!3?4+5=6:7_8/9"0Żż][', + 'es_ES' => 'QqWwEeRrTtYyUuIiOoPp^``+AaSsDdFfGgHhJjKkLlÑñ¨´´çZzXxCcVvBbNnMm;,:._-> 'QqWwEeRrTtZzUuIiOoPpÜü*+AaSsDdFfGgHhJjKkLlÖöÄä\'#YyXxCcVvBbNnMm;,:._-> 'QqWwEeRrTtYyUuIiOoPpéè*+AaSsDdFfGgHhJjKkLlçò°à§ùZzXxCcVvBbNnMm;,:._-> 'AaZzEeRrTtYyUuIiOoPp¨^^$QqSsDdFfGgHhJjKkLlMm%ù£``wXxCcVvBbNn?,.;/:+=><1&2é3"4\'5(6§7è8!9ç0à°)_-', + 'zn_CH' => 'QㄆWㄊEㄍRㄐTㄔYㄗUㄧIㄛOㄟPㄣ『「』」AㄇSㄋDㄎFㄑGㄕHㄘJㄨKㄜLㄠ:ㄤ“‘|、ZㄈXㄌCㄏVㄒBㄖNㄙMㄩ,ㄝ。ㄡ?ㄥ~`!ㄅ@ㄉ#ˇ$ˋ$ˋ%ㄓ^ˊ&˙*ㄚ(ㄞ)ㄢ_ㄦ+=', + ]; + + + /** + * Configures keyboard layouts (adds a new one). + * + * @param string|null $locale, primary language locale + * @param null $chars, keyboard layout chars string + * @return array|null + */ + public static function setKeyboardLayout($locale = null, $chars = null) { + + if (!isset($chars) || empty($chars) || !is_string($chars)){ + throw new InvalidArgumentException('The `$locale` and `$chars` arguments must be set.'); + return null; + } + + return (self::$layouts = array_merge(self::$layouts, [ + $locale => $chars + ])); + } + + /** + * Returns the keyboard layout that was requested. + * + * @param string|null $locale, primary language locale + * @param integer|bool $format $format, where 1 - as array, 2 - keycode array, false - as pattern string + * @return array|array[]|false|mixed|string[]|null, keyboard layout + */ + public static function getKeyboardLayout($locale = null, $format = false) { + + if (!$locale) { + throw new InvalidArgumentException('The `$locale` argument must be set.'); + return null; + } + + if (!isset(self::$layouts[$locale])) + return null; + + if ($format == 1 || $format == 2) { + $chars = preg_split('!!u', self::$layouts[$locale], null, PREG_SPLIT_NO_EMPTY); + if ($format == 1) { + return $chars; + } elseif ($format == 2 && is_countable($chars)) { + $keycodes = []; + foreach ($chars as $char) { + $keycodes[] = \ord($char); + } + return $keycodes; + } else { + return null; + } + } else { + return self::$layouts[$locale]; + } + } + + /** + * Returns all previously configured language keyboard layouts locales. + * + * @return array|null, of keyboards locales + * @throws InvalidConfigException + */ + public static function getKeyboardLocales() { + + if (!is_array(self::$layouts)) { + throw new InvalidConfigException('The `KeboardLayoutHelper::$layouts` must be configured.'); + return null; + } + + return array_keys(self::$layouts); + } + + /** + * Returns all previously configured keyboard layouts. + * + * @param integer|bool $format, where 1 - as array, 2 - keycode array, false - as pattern string + * @return array of keyboards layouts + * @throws InvalidConfigException + */ + public static function getKeyboardLayouts($format = false) { + + if ($format) { + $layouts = []; + $locales = self::getKeyboardLocales(); + foreach ($locales as $locale) { + $layouts[$locale] = self::getKeyboardLayout($locale, $format); + } + return $layouts; + } + + return self::$layouts; + } + + /** + * Fixes an incorrect keyboard layout for incorrect entries. + * + * Например, + * ```php + * var_export(\wdmg\helpers\KeyboardLayoutHelper::convertKeyboardLayout('Get ыефкеув with щгк сщтеуте ьфтфпук ыныеуь', 'ru_RU', 'en_US')); + * ``` + * will be return: + * ```php + * string(43) "Get started with our content manager system" + * ``` + * + * @param string|null $string, a string that contains invalid entries + * @param string|null $from, incorrect language locale + * @param string|null $to, primary language locale + * @return string|null, fixed string in correct language locale + * @throws InvalidConfigException + */ + public static function convertKeyboardLayout($string = null, $from = null, $to = null) { + + if (!$from || !$to) { + throw new InvalidArgumentException('The `$from` and `$to` locales argument must be set.'); + return null; + } + + + $chunks = explode(' ', $string); + $layouts = self::getKeyboardLayouts(1); + foreach ($chunks as $index => $chunk) { + if ($from !== $to && $from) + $chunks[$index] = str_replace($layouts[$from], $layouts[$to], $chunks[$index]); + } + + return implode(' ', $chunks); + } + +} \ No newline at end of file diff --git a/src/StringHelper.php b/src/StringHelper.php index 4505970..3c3b703 100644 --- a/src/StringHelper.php +++ b/src/StringHelper.php @@ -6,7 +6,7 @@ * Yii2 short integer helper * * @category Helpers - * @version 1.3.6 + * @version 1.4.0 * @author Alexsander Vyshnyvetskyy * @link https://github.com/wdmg/yii2-helpers * @copyright Copyright (c) 2019 - 2020 W.D.M.Group, Ukraine @@ -20,6 +20,14 @@ class StringHelper extends BaseStringHelper { + /** + * Formats the text ending of a numeric value + * + * @param $input + * @param int $decimals + * @param bool $uppercase + * @return string + */ public static function integerAmount($input, $decimals = 2, $uppercase = false) { static::initI18N('app/helpers'); @@ -43,7 +51,14 @@ public static function integerAmount($input, $decimals = 2, $uppercase = false) } } - + /** + * Cuts (replaces) html entities from a substring + * + * @param $input + * @param string $tags + * @param string $replacement + * @return mixed|string|string[]|null + */ public static function stripTags($input, $tags = "a|strong|b|p", $replacement = '') { static::initI18N('app/helpers'); @@ -73,6 +88,16 @@ public static function stripTags($input, $tags = "a|strong|b|p", $replacement = return $input; } + /** + * Truncates a string to a given length without truncating words + * + * @param $input + * @param int $start + * @param int $end + * @param bool $cut + * @param string $ending + * @return string|null + */ public static function stringShorter($input, $start = 55, $end = 0, $cut = true, $ending = '…') { static::initI18N('app/helpers'); @@ -99,7 +124,16 @@ public static function stringShorter($input, $start = 55, $end = 0, $cut = true, return $input; } - private static function mb_wordwrap($str, $length = 75, $break = "\n", $cut = false) { + /** + * Splits a string into substrings with a string termination + * + * @param $str + * @param int $length + * @param string $break + * @param bool $cut + * @return string + */ + public static function mb_wordwrap($str, $length = 75, $break = "\n", $cut = false) { $lines = explode($break, $str); foreach ($lines as &$line) { $line = rtrim($line); diff --git a/src/TextAnalyzer.php b/src/TextAnalyzer.php index 674bb7a..04be67b 100644 --- a/src/TextAnalyzer.php +++ b/src/TextAnalyzer.php @@ -6,7 +6,7 @@ * Yii2 Text analyzer helper * * @category Helpers - * @version 1.3.6 + * @version 1.4.0 * @author Alexsander Vyshnyvetskyy * @link https://github.com/wdmg/yii2-helpers * @copyright Copyright (c) 2019 - 2020 W.D.M.Group, Ukraine