123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909 |
- <?php
- namespace Dcat\Admin\Support;
- use Dcat\Admin\Admin;
- use Dcat\Admin\Grid;
- use Dcat\Laravel\Database\WhereHasInServiceProvider;
- use Illuminate\Contracts\Support\Arrayable;
- use Illuminate\Contracts\Support\Htmlable;
- use Illuminate\Contracts\Support\Jsonable;
- use Illuminate\Contracts\Support\Renderable;
- use Illuminate\Http\Request;
- use Illuminate\Support\Arr;
- use Illuminate\Support\Collection;
- use Illuminate\Support\Facades\File;
- use Illuminate\Support\Str;
- use Symfony\Component\Process\Process;
- class Helper
- {
- /**
- * @var array
- */
- public static $fileTypes = [
- 'image' => 'png|jpg|jpeg|tmp|gif',
- 'word' => 'doc|docx',
- 'excel' => 'xls|xlsx|csv',
- 'powerpoint' => 'ppt|pptx',
- 'pdf' => 'pdf',
- 'code' => 'php|js|java|python|ruby|go|c|cpp|sql|m|h|json|html|aspx',
- 'archive' => 'zip|tar\.gz|rar|rpm',
- 'txt' => 'txt|pac|log|md',
- 'audio' => 'mp3|wav|flac|3pg|aa|aac|ape|au|m4a|mpc|ogg',
- 'video' => 'mkv|rmvb|flv|mp4|avi|wmv|rm|asf|mpeg',
- ];
- /**
- * 把给定的值转化为数组.
- *
- * @param $value
- * @param bool $filter
- *
- * @return array
- */
- public static function array($value, bool $filter = true): array
- {
- if (! $value) {
- return [];
- }
- if ($value instanceof \Closure) {
- $value = $value();
- }
- if (is_array($value)) {
- } elseif ($value instanceof Jsonable) {
- $value = json_decode($value->toJson(), true);
- } elseif ($value instanceof Arrayable) {
- $value = $value->toArray();
- } elseif (is_string($value)) {
- $array = null;
- try {
- $array = json_decode($value, true);
- } catch (\Throwable $e) {
- }
- $value = is_array($array) ? $array : explode(',', $value);
- } else {
- $value = (array) $value;
- }
- return $filter ? array_filter($value, function ($v) {
- return $v !== '' && $v !== null;
- }) : $value;
- }
- /**
- * 把给定的值转化为字符串.
- *
- * @param string|Grid|\Closure|Renderable|Htmlable $value
- * @param array $params
- * @param object $newThis
- *
- * @return string
- */
- public static function render($value, $params = [], $newThis = null): string
- {
- if (is_string($value)) {
- return $value;
- }
- if ($value instanceof \Closure) {
- $newThis && ($value = $value->bindTo($newThis));
- $value = $value(...(array) $params);
- }
- if ($value instanceof Grid) {
- return (string) $value->render();
- }
- if ($value instanceof Renderable) {
- return (string) $value->render();
- }
- if ($value instanceof Htmlable) {
- return (string) $value->toHtml();
- }
- return (string) $value;
- }
- /**
- * @param array $attributes
- *
- * @return string
- */
- public static function buildHtmlAttributes($attributes)
- {
- $html = '';
- foreach ((array) $attributes as $key => &$value) {
- if (is_array($value)) {
- $value = implode(' ', $value);
- }
- if (is_numeric($key)) {
- $key = $value;
- }
- $element = '';
- if ($value !== null) {
- $element = $key.'="'.htmlentities($value, ENT_QUOTES, 'UTF-8').'"';
- }
- $html .= $element;
- }
- return $html;
- }
- /**
- * @param string $url
- * @param array $query
- *
- * @return string
- */
- public static function urlWithQuery(?string $url, array $query = [])
- {
- if (! $url || ! $query) {
- return $url;
- }
- $array = explode('?', $url);
- $url = $array[0];
- parse_str($array[1] ?? '', $originalQuery);
- return $url.'?'.http_build_query(array_merge($originalQuery, $query));
- }
- /**
- * @param string $url
- * @param string|array|Arrayable $keys
- *
- * @return string
- */
- public static function urlWithoutQuery($url, $keys)
- {
- if (! Str::contains($url, '?') || ! $keys) {
- return $url;
- }
- if ($keys instanceof Arrayable) {
- $keys = $keys->toArray();
- }
- $keys = (array) $keys;
- $urlInfo = parse_url($url);
- parse_str($urlInfo['query'], $query);
- Arr::forget($query, $keys);
- $baseUrl = explode('?', $url)[0];
- return $query
- ? $baseUrl.'?'.http_build_query($query)
- : $baseUrl;
- }
- /**
- * @param Arrayable|array|string $keys
- *
- * @return string
- */
- public static function fullUrlWithoutQuery($keys)
- {
- return static::urlWithoutQuery(request()->fullUrl(), $keys);
- }
- /**
- * @param string $url
- * @param string|array $keys
- *
- * @return bool
- */
- public static function urlHasQuery(string $url, $keys)
- {
- $value = explode('?', $url);
- if (empty($value[1])) {
- return false;
- }
- parse_str($value[1], $query);
- foreach ((array) $keys as $key) {
- if (Arr::has($query, $key)) {
- return true;
- }
- }
- return false;
- }
- /**
- * 匹配请求路径.
- *
- * @example
- * Helper::matchRequestPath(admin_base_path('auth/user'))
- * Helper::matchRequestPath(admin_base_path('auth/user*'))
- * Helper::matchRequestPath(admin_base_path('auth/user/* /edit'))
- * Helper::matchRequestPath('GET,POST:auth/user')
- *
- * @param string $path
- * @param null|string $current
- *
- * @return bool
- */
- public static function matchRequestPath($path, ?string $current = null)
- {
- $request = request();
- $current = $current ?: $request->decodedPath();
- if (Str::contains($path, ':')) {
- [$methods, $path] = explode(':', $path);
- $methods = array_map('strtoupper', explode(',', $methods));
- if (! empty($methods) && ! in_array($request->method(), $methods)) {
- return false;
- }
- }
- // 判断路由名称
- if ($request->routeIs($path)) {
- return true;
- }
- if (! Str::contains($path, '*')) {
- return $path === $current;
- }
- $path = str_replace(['*', '/'], ['([0-9a-z-_,])*', "\/"], $path);
- return preg_match("/$path/i", $current);
- }
- /**
- * 生成层级数据.
- *
- * @param array $nodes
- * @param int $parentId
- * @param string|null $primaryKeyName
- * @param string|null $parentKeyName
- * @param string|null $childrenKeyName
- *
- * @return array
- */
- public static function buildNestedArray(
- $nodes = [],
- $parentId = 0,
- ?string $primaryKeyName = null,
- ?string $parentKeyName = null,
- ?string $childrenKeyName = null
- ) {
- $branch = [];
- $primaryKeyName = $primaryKeyName ?: 'id';
- $parentKeyName = $parentKeyName ?: 'parent_id';
- $childrenKeyName = $childrenKeyName ?: 'children';
- $parentId = is_numeric($parentId) ? (int) $parentId : $parentId;
- foreach ($nodes as $node) {
- $pk = $node[$parentKeyName];
- $pk = is_numeric($pk) ? (int) $pk : $pk;
- if ($pk === $parentId) {
- $children = static::buildNestedArray(
- $nodes,
- $node[$primaryKeyName],
- $primaryKeyName,
- $parentKeyName,
- $childrenKeyName
- );
- if ($children) {
- $node[$childrenKeyName] = $children;
- }
- $branch[] = $node;
- }
- }
- return $branch;
- }
- /**
- * @param string $name
- * @param string $symbol
- *
- * @return mixed
- */
- public static function slug(string $name, string $symbol = '-')
- {
- $text = preg_replace_callback('/([A-Z])/', function ($text) use ($symbol) {
- return $symbol.strtolower($text[1]);
- }, $name);
- return str_replace('_', $symbol, ltrim($text, $symbol));
- }
- /**
- * @param array $array
- * @param int $level
- *
- * @return string
- */
- public static function exportArray(array &$array, $level = 1)
- {
- $start = '[';
- $end = ']';
- $txt = "$start\n";
- foreach ($array as $k => &$v) {
- if (is_array($v)) {
- $pre = is_string($k) ? "'$k' => " : "$k => ";
- $txt .= str_repeat(' ', $level * 4).$pre.static::exportArray($v, $level + 1).",\n";
- continue;
- }
- $t = $v;
- if ($v === true) {
- $t = 'true';
- } elseif ($v === false) {
- $t = 'false';
- } elseif ($v === null) {
- $t = 'null';
- } elseif (is_string($v)) {
- $v = str_replace("'", "\\'", $v);
- $t = "'$v'";
- }
- $pre = is_string($k) ? "'$k' => " : "$k => ";
- $txt .= str_repeat(' ', $level * 4)."{$pre}{$t},\n";
- }
- return $txt.str_repeat(' ', ($level - 1) * 4).$end;
- }
- /**
- * @param array $array
- *
- * @return string
- */
- public static function exportArrayPhp(array $array)
- {
- return "<?php \nreturn ".static::exportArray($array).";\n";
- }
- /**
- * 删除数组中的元素.
- *
- * @param array $array
- * @param mixed $value
- */
- public static function deleteByValue(&$array, $value)
- {
- $value = (array) $value;
- foreach ($array as $index => $item) {
- if (in_array($item, $value)) {
- unset($array[$index]);
- }
- }
- }
- /**
- * 颜色转亮.
- *
- * @param string $color
- * @param int $amt
- *
- * @return string
- */
- public static function colorLighten(string $color, int $amt)
- {
- if (! $amt) {
- return $color;
- }
- $hasPrefix = false;
- if (mb_strpos($color, '#') === 0) {
- $color = mb_substr($color, 1);
- $hasPrefix = true;
- }
- [$red, $blue, $green] = static::colorToRBG($color, $amt);
- return ($hasPrefix ? '#' : '').dechex($green + ($blue << 8) + ($red << 16));
- }
- /**
- * 颜色转暗.
- *
- * @param string $color
- * @param int $amt
- *
- * @return string
- */
- public static function colorDarken(string $color, int $amt)
- {
- return static::colorLighten($color, -$amt);
- }
- /**
- * 颜色透明度.
- *
- * @param string $color
- * @param float|string $alpha
- *
- * @return string
- */
- public static function colorAlpha(string $color, $alpha)
- {
- if ($alpha >= 1) {
- return $color;
- }
- if (mb_strpos($color, '#') === 0) {
- $color = mb_substr($color, 1);
- }
- [$red, $blue, $green] = static::colorToRBG($color);
- return "rgba($red, $blue, $green, $alpha)";
- }
- /**
- * @param string $color
- * @param int $amt
- *
- * @return array
- */
- public static function colorToRBG(string $color, int $amt = 0)
- {
- $format = function ($value) {
- if ($value > 255) {
- return 255;
- }
- if ($value < 0) {
- return 0;
- }
- return $value;
- };
- $num = hexdec($color);
- $red = $format(($num >> 16) + $amt);
- $blue = $format((($num >> 8) & 0x00FF) + $amt);
- $green = $format(($num & 0x0000FF) + $amt);
- return [$red, $blue, $green];
- }
- /**
- * 验证扩展包名称.
- *
- * @param string $name
- *
- * @return int
- */
- public static function validateExtensionName($name)
- {
- return preg_match('/^[\w\-_]+\/[\w\-_]+$/', $name);
- }
- /**
- * Get file icon.
- *
- * @param string $file
- *
- * @return string
- */
- public static function getFileIcon($file = '')
- {
- $extension = File::extension($file);
- foreach (static::$fileTypes as $type => $regex) {
- if (preg_match("/^($regex)$/i", $extension) !== 0) {
- return "fa fa-file-{$type}-o";
- }
- }
- return 'fa fa-file-o';
- }
- /**
- * 判断是否是ajax请求.
- *
- * @param Request $request
- *
- * @return bool
- */
- public static function isAjaxRequest(?Request $request = null)
- {
- /* @var Request $request */
- $request = $request ?: request();
- return $request->ajax() && ! $request->pjax();
- }
- /**
- * 判断是否是IE浏览器.
- *
- * @return false|int
- */
- public static function isIEBrowser()
- {
- return (bool) preg_match('/Mozilla\/5\.0 \(Windows NT 10\.0; WOW64; Trident\/7\.0; rv:[0-9\.]*\) like Gecko/i', $_SERVER['HTTP_USER_AGENT'] ?? '');
- }
- /**
- * 判断是否QQ浏览器.
- *
- * @return bool
- */
- public static function isQQBrowser()
- {
- return mb_strpos(mb_strtolower($_SERVER['HTTP_USER_AGENT'] ?? ''), 'qqbrowser') !== false;
- }
- /**
- * @param string $url
- *
- * @return void
- */
- public static function setPreviousUrl($url)
- {
- session()->flash('admin.prev.url', static::urlWithoutQuery((string) $url, '_pjax'));
- }
- /**
- * @return string
- */
- public static function getPreviousUrl()
- {
- return (string) (session()->get('admin.prev.url') ? url(session()->get('admin.prev.url')) : url()->previous());
- }
- /**
- * @param mixed $command
- * @param int $timeout
- * @param null $input
- * @param null $cwd
- *
- * @return Process
- */
- public static function process($command, $timeout = 100, $input = null, $cwd = null)
- {
- $parameters = [
- $command,
- $cwd,
- [],
- $input,
- $timeout,
- ];
- return is_string($command)
- ? Process::fromShellCommandline(...$parameters)
- : new Process(...$parameters);
- }
- /**
- * 判断两个值是否相等.
- *
- * @param $value1
- * @param $value2
- *
- * @return bool
- */
- public static function equal($value1, $value2)
- {
- if ($value1 === null || $value2 === null) {
- return false;
- }
- if (! is_scalar($value1) || ! is_scalar($value2)) {
- return $value1 === $value2;
- }
- return (string) $value1 === (string) $value2;
- }
- /**
- * 判断给定的数组是是否包含给定元素.
- *
- * @param mixed $value
- * @param array $array
- *
- * @return bool
- */
- public static function inArray($value, array $array)
- {
- $array = array_map(function ($v) {
- if (is_scalar($v) || $v === null) {
- $v = (string) $v;
- }
- return $v;
- }, $array);
- return in_array((string) $value, $array, true);
- }
- /**
- * Limit the number of characters in a string.
- *
- * @param string $value
- * @param int $limit
- * @param string $end
- * @return string
- */
- public static function strLimit($value, $limit = 100, $end = '...')
- {
- if (mb_strlen($value, 'UTF-8') <= $limit) {
- return $value;
- }
- return rtrim(mb_substr($value, 0, $limit, 'UTF-8')).$end;
- }
- /**
- * 获取类名或对象的文件路径.
- *
- * @param string|object $class
- *
- * @return string
- *
- * @throws \ReflectionException
- */
- public static function guessClassFileName($class)
- {
- if (is_object($class)) {
- $class = get_class($class);
- }
- try {
- if (class_exists($class)) {
- return (new \ReflectionClass($class))->getFileName();
- }
- } catch (\Throwable $e) {
- }
- $class = trim($class, '\\');
- $composer = Composer::parse(base_path('composer.json'));
- $map = collect($composer->autoload['psr-4'] ?? [])->mapWithKeys(function ($path, $namespace) {
- $namespace = trim($namespace, '\\').'\\';
- return [$namespace => [$namespace, $path]];
- })->sortBy(function ($_, $namespace) {
- return strlen($namespace);
- }, SORT_REGULAR, true);
- $prefix = explode($class, '\\')[0];
- if ($map->isEmpty()) {
- if (Str::startsWith($class, 'App\\')) {
- $values = ['App\\', 'app/'];
- }
- } else {
- $values = $map->filter(function ($_, $k) use ($class) {
- return Str::startsWith($class, $k);
- })->first();
- }
- if (empty($values)) {
- $values = [$prefix.'\\', self::slug($prefix).'/'];
- }
- [$namespace, $path] = $values;
- return base_path(str_replace([$namespace, '\\'], [$path, '/'], $class)).'.php';
- }
- /**
- * Is input data is has-one relation.
- *
- * @param Collection $fields
- * @param array $input
- */
- public static function prepareHasOneRelation(Collection $fields, array &$input)
- {
- $relations = [];
- $fields->each(function ($field) use (&$relations) {
- $column = $field->column();
- if (is_array($column)) {
- foreach ($column as $v) {
- if (Str::contains($v, '.')) {
- $first = explode('.', $v)[0];
- $relations[$first] = null;
- }
- }
- return;
- }
- if (Str::contains($column, '.')) {
- $first = explode('.', $column)[0];
- $relations[$first] = null;
- }
- });
- foreach ($relations as $first => $v) {
- if (isset($input[$first])) {
- foreach ($input[$first] as $key => $value) {
- if (is_array($value)) {
- $input["$first.$key"] = $value;
- }
- }
- $input = array_merge($input, Arr::dot([$first => $input[$first]]));
- }
- }
- }
- /**
- * 设置查询条件.
- *
- * @param mixed $model
- * @param string $column
- * @param string $query
- * @param mixed array $params
- *
- * @return void
- */
- public static function withQueryCondition($model, ?string $column, string $query, array $params)
- {
- if (! Str::contains($column, '.')) {
- $model->$query($column, ...$params);
- return;
- }
- $method = $query === 'orWhere' ? 'orWhere' : 'where';
- $subQuery = $query === 'orWhere' ? 'where' : $query;
- $model->$method(function ($q) use ($column, $subQuery, $params) {
- static::withRelationQuery($q, $column, $subQuery, $params);
- });
- }
- /**
- * 设置关联关系查询条件.
- *
- * @param mixed $model
- * @param string $column
- * @param string $query
- * @param mixed ...$params
- *
- * @return void
- */
- public static function withRelationQuery($model, ?string $column, string $query, array $params)
- {
- $column = explode('.', $column);
- array_unshift($params, array_pop($column));
- // 增加对whereHasIn的支持
- $method = class_exists(WhereHasInServiceProvider::class) ? 'whereHasIn' : 'whereHas';
- $model->$method(implode('.', $column), function ($relation) use ($params, $query) {
- $relation->$query(...$params);
- });
- }
- /**
- * Html转义.
- *
- * @param array|string $item
- *
- * @return mixed
- */
- public static function htmlEntityEncode($item)
- {
- if (is_array($item)) {
- array_walk_recursive($item, function (&$value) {
- $value = htmlentities($value);
- });
- } else {
- $item = htmlentities($item);
- }
- return $item;
- }
- /**
- * 格式化表单元素 name 属性.
- *
- * @param string|array $name
- *
- * @return mixed|string
- */
- public static function formatElementName($name)
- {
- if (! $name) {
- return $name;
- }
- if (is_array($name)) {
- foreach ($name as &$v) {
- $v = static::formatElementName($v);
- }
- return $name;
- }
- $name = explode('.', $name);
- if (count($name) == 1) {
- return $name[0];
- }
- $html = array_shift($name);
- foreach ($name as $piece) {
- $html .= "[$piece]";
- }
- return $html;
- }
- /**
- * Set an array item to a given value using "dot" notation.
- *
- * If no key is given to the method, the entire array will be replaced.
- *
- * @param array|\ArrayAccess $array
- * @param string $key
- * @param mixed $value
- * @return array
- */
- public static function arraySet(&$array, $key, $value)
- {
- if (is_null($key)) {
- return $array = $value;
- }
- $keys = explode('.', $key);
- $default = null;
- while (count($keys) > 1) {
- $key = array_shift($keys);
- if (! isset($array[$key]) || (! is_array($array[$key]) && ! $array[$key] instanceof \ArrayAccess)) {
- $array[$key] = [];
- }
- if (is_array($array)) {
- $array = &$array[$key];
- } else {
- if (is_object($array[$key])) {
- $array[$key] = static::arraySet($array[$key], implode('.', $keys), $value);
- } else {
- $mid = $array[$key];
- $array[$key] = static::arraySet($mid, implode('.', $keys), $value);
- }
- }
- }
- $array[array_shift($keys)] = $value;
- return $array;
- }
- }
|