Helper.php 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002
  1. <?php
  2. namespace Dcat\Admin\Support;
  3. use Dcat\Admin\Grid;
  4. use Dcat\Laravel\Database\WhereHasInServiceProvider;
  5. use Illuminate\Contracts\Support\Arrayable;
  6. use Illuminate\Contracts\Support\Htmlable;
  7. use Illuminate\Contracts\Support\Jsonable;
  8. use Illuminate\Contracts\Support\Renderable;
  9. use Illuminate\Http\Request;
  10. use Illuminate\Support\Arr;
  11. use Illuminate\Support\Collection;
  12. use Illuminate\Support\Facades\File;
  13. use Illuminate\Support\Facades\URL;
  14. use Illuminate\Support\Str;
  15. use Symfony\Component\Process\Process;
  16. class Helper
  17. {
  18. /**
  19. * @var array
  20. */
  21. public static $fileTypes = [
  22. 'image' => 'png|jpg|jpeg|tmp|gif',
  23. 'word' => 'doc|docx',
  24. 'excel' => 'xls|xlsx|csv',
  25. 'powerpoint' => 'ppt|pptx',
  26. 'pdf' => 'pdf',
  27. 'code' => 'php|js|java|python|ruby|go|c|cpp|sql|m|h|json|html|aspx',
  28. 'archive' => 'zip|tar\.gz|rar|rpm',
  29. 'txt' => 'txt|pac|log|md',
  30. 'audio' => 'mp3|wav|flac|3pg|aa|aac|ape|au|m4a|mpc|ogg',
  31. 'video' => 'mkv|rmvb|flv|mp4|avi|wmv|rm|asf|mpeg',
  32. ];
  33. protected static $controllerNames = [];
  34. /**
  35. * 把给定的值转化为数组.
  36. *
  37. * @param $value
  38. * @param bool $filter
  39. * @return array
  40. */
  41. public static function array($value, bool $filter = true): array
  42. {
  43. if ($value === null || $value === '' || $value === []) {
  44. return [];
  45. }
  46. if ($value instanceof \Closure) {
  47. $value = $value();
  48. }
  49. if (is_array($value)) {
  50. } elseif ($value instanceof Jsonable) {
  51. $value = json_decode($value->toJson(), true);
  52. } elseif ($value instanceof Arrayable) {
  53. $value = $value->toArray();
  54. } elseif (is_string($value)) {
  55. $array = null;
  56. try {
  57. $array = json_decode($value, true);
  58. } catch (\Throwable $e) {
  59. }
  60. $value = is_array($array) ? $array : explode(',', $value);
  61. } else {
  62. $value = (array) $value;
  63. }
  64. return $filter ? array_filter($value, function ($v) {
  65. return $v !== '' && $v !== null;
  66. }) : $value;
  67. }
  68. /**
  69. * 把给定的值转化为字符串.
  70. *
  71. * @param string|Grid|\Closure|Renderable|Htmlable $value
  72. * @param array $params
  73. * @param object $newThis
  74. * @return string
  75. */
  76. public static function render($value, $params = [], $newThis = null): string
  77. {
  78. if (is_string($value)) {
  79. return $value;
  80. }
  81. if ($value instanceof \Closure) {
  82. $newThis && ($value = $value->bindTo($newThis));
  83. $value = $value(...(array) $params);
  84. }
  85. if ($value instanceof Renderable) {
  86. return (string) $value->render();
  87. }
  88. if ($value instanceof Htmlable) {
  89. return (string) $value->toHtml();
  90. }
  91. return (string) $value;
  92. }
  93. /**
  94. * 获取当前控制器名称.
  95. *
  96. * @return mixed|string
  97. */
  98. public static function getControllerName()
  99. {
  100. $router = app('router');
  101. if (! $router->current()) {
  102. return 'undefined';
  103. }
  104. $actionName = $router->current()->getActionName();
  105. if (! isset(static::$controllerNames[$actionName])) {
  106. $controller = class_basename(explode('@', $actionName)[0]);
  107. static::$controllerNames[$actionName] = str_replace('Controller', '', $controller);
  108. }
  109. return static::$controllerNames[$actionName];
  110. }
  111. /**
  112. * @param array $attributes
  113. * @return string
  114. */
  115. public static function buildHtmlAttributes($attributes)
  116. {
  117. $html = '';
  118. foreach ((array) $attributes as $key => &$value) {
  119. if (is_array($value)) {
  120. $value = implode(' ', $value);
  121. }
  122. if (is_numeric($key)) {
  123. $key = $value;
  124. }
  125. $element = '';
  126. if ($value !== null) {
  127. $element = $key.'="'.htmlentities($value, ENT_QUOTES, 'UTF-8').'" ';
  128. }
  129. $html .= $element;
  130. }
  131. return $html;
  132. }
  133. /**
  134. * @param string $url
  135. * @param array $query
  136. * @return string
  137. */
  138. public static function urlWithQuery(?string $url, array $query = [])
  139. {
  140. if (! $url || ! $query) {
  141. return $url;
  142. }
  143. $array = explode('?', $url);
  144. $url = $array[0];
  145. parse_str($array[1] ?? '', $originalQuery);
  146. return $url.'?'.http_build_query(array_merge($originalQuery, $query));
  147. }
  148. /**
  149. * @param string $url
  150. * @param string|array|Arrayable $keys
  151. * @return string
  152. */
  153. public static function urlWithoutQuery($url, $keys)
  154. {
  155. if (! Str::contains($url, '?') || ! $keys) {
  156. return $url;
  157. }
  158. if ($keys instanceof Arrayable) {
  159. $keys = $keys->toArray();
  160. }
  161. $keys = (array) $keys;
  162. $urlInfo = parse_url($url);
  163. parse_str($urlInfo['query'], $query);
  164. Arr::forget($query, $keys);
  165. $baseUrl = explode('?', $url)[0];
  166. return $query
  167. ? $baseUrl.'?'.http_build_query($query)
  168. : $baseUrl;
  169. }
  170. /**
  171. * @param Arrayable|array|string $keys
  172. * @return string
  173. */
  174. public static function fullUrlWithoutQuery($keys)
  175. {
  176. return static::urlWithoutQuery(request()->fullUrl(), $keys);
  177. }
  178. /**
  179. * @param string $url
  180. * @param string|array $keys
  181. * @return bool
  182. */
  183. public static function urlHasQuery(string $url, $keys)
  184. {
  185. $value = explode('?', $url);
  186. if (empty($value[1])) {
  187. return false;
  188. }
  189. parse_str($value[1], $query);
  190. foreach ((array) $keys as $key) {
  191. if (Arr::has($query, $key)) {
  192. return true;
  193. }
  194. }
  195. return false;
  196. }
  197. /**
  198. * 匹配请求路径.
  199. *
  200. * @example
  201. * Helper::matchRequestPath(admin_base_path('auth/user'))
  202. * Helper::matchRequestPath(admin_base_path('auth/user*'))
  203. * Helper::matchRequestPath(admin_base_path('auth/user/* /edit'))
  204. * Helper::matchRequestPath('GET,POST:auth/user')
  205. *
  206. * @param string $path
  207. * @param null|string $current
  208. * @return bool
  209. */
  210. public static function matchRequestPath($path, ?string $current = null)
  211. {
  212. $request = request();
  213. $current = $current ?: $request->decodedPath();
  214. if (Str::contains($path, ':')) {
  215. [$methods, $path] = explode(':', $path);
  216. $methods = array_map('strtoupper', explode(',', $methods));
  217. if (! empty($methods) && ! in_array($request->method(), $methods)) {
  218. return false;
  219. }
  220. }
  221. // 判断路由名称
  222. if ($request->routeIs($path) || $request->routeIs(admin_route_name($path))) {
  223. return true;
  224. }
  225. if (! Str::contains($path, '*')) {
  226. return $path === $current;
  227. }
  228. $path = str_replace(['*', '/'], ['([0-9a-z-_,])*', "\/"], $path);
  229. return preg_match("/$path/i", $current);
  230. }
  231. /**
  232. * 生成层级数据.
  233. *
  234. * @param array $nodes
  235. * @param int $parentId
  236. * @param string|null $primaryKeyName
  237. * @param string|null $parentKeyName
  238. * @param string|null $childrenKeyName
  239. * @return array
  240. */
  241. public static function buildNestedArray(
  242. $nodes = [],
  243. $parentId = 0,
  244. ?string $primaryKeyName = null,
  245. ?string $parentKeyName = null,
  246. ?string $childrenKeyName = null
  247. ) {
  248. $branch = [];
  249. $primaryKeyName = $primaryKeyName ?: 'id';
  250. $parentKeyName = $parentKeyName ?: 'parent_id';
  251. $childrenKeyName = $childrenKeyName ?: 'children';
  252. $parentId = is_numeric($parentId) ? (int) $parentId : $parentId;
  253. foreach ($nodes as $node) {
  254. $pk = $node[$parentKeyName];
  255. $pk = is_numeric($pk) ? (int) $pk : $pk;
  256. if ($pk === $parentId) {
  257. $children = static::buildNestedArray(
  258. $nodes,
  259. $node[$primaryKeyName],
  260. $primaryKeyName,
  261. $parentKeyName,
  262. $childrenKeyName
  263. );
  264. if ($children) {
  265. $node[$childrenKeyName] = $children;
  266. }
  267. $branch[] = $node;
  268. }
  269. }
  270. return $branch;
  271. }
  272. /**
  273. * @param string $name
  274. * @param string $symbol
  275. * @return mixed
  276. */
  277. public static function slug(string $name, string $symbol = '-')
  278. {
  279. $text = preg_replace_callback('/([A-Z])/', function ($text) use ($symbol) {
  280. return $symbol.strtolower($text[1]);
  281. }, $name);
  282. return str_replace('_', $symbol, ltrim($text, $symbol));
  283. }
  284. /**
  285. * @param array $array
  286. * @param int $level
  287. * @return string
  288. */
  289. public static function exportArray(array &$array, $level = 1)
  290. {
  291. $start = '[';
  292. $end = ']';
  293. $txt = "$start\n";
  294. foreach ($array as $k => &$v) {
  295. if (is_array($v)) {
  296. $pre = is_string($k) ? "'$k' => " : "$k => ";
  297. $txt .= str_repeat(' ', $level * 4).$pre.static::exportArray($v, $level + 1).",\n";
  298. continue;
  299. }
  300. $t = $v;
  301. if ($v === true) {
  302. $t = 'true';
  303. } elseif ($v === false) {
  304. $t = 'false';
  305. } elseif ($v === null) {
  306. $t = 'null';
  307. } elseif (is_string($v)) {
  308. $v = str_replace("'", "\\'", $v);
  309. $t = "'$v'";
  310. }
  311. $pre = is_string($k) ? "'$k' => " : "$k => ";
  312. $txt .= str_repeat(' ', $level * 4)."{$pre}{$t},\n";
  313. }
  314. return $txt.str_repeat(' ', ($level - 1) * 4).$end;
  315. }
  316. /**
  317. * @param array $array
  318. * @return string
  319. */
  320. public static function exportArrayPhp(array $array)
  321. {
  322. return "<?php \nreturn ".static::exportArray($array).";\n";
  323. }
  324. /**
  325. * 删除数组中的元素.
  326. *
  327. * @param array $array
  328. * @param mixed $value
  329. * @param bool $strict
  330. */
  331. public static function deleteByValue(&$array, $value, bool $strict = false)
  332. {
  333. $value = (array) $value;
  334. foreach ($array as $index => $item) {
  335. if (in_array($item, $value, $strict)) {
  336. unset($array[$index]);
  337. }
  338. }
  339. }
  340. /**
  341. * @param array $array
  342. * @param mixed $value
  343. */
  344. public static function deleteContains(&$array, $value)
  345. {
  346. $value = (array) $value;
  347. foreach ($array as $index => $item) {
  348. foreach ($value as $v) {
  349. if (Str::contains($item, $v)) {
  350. unset($array[$index]);
  351. }
  352. }
  353. }
  354. }
  355. /**
  356. * 颜色转亮.
  357. *
  358. * @param string $color
  359. * @param int $amt
  360. * @return string
  361. */
  362. public static function colorLighten(string $color, int $amt)
  363. {
  364. if (! $amt) {
  365. return $color;
  366. }
  367. $hasPrefix = false;
  368. if (mb_strpos($color, '#') === 0) {
  369. $color = mb_substr($color, 1);
  370. $hasPrefix = true;
  371. }
  372. [$red, $blue, $green] = static::colorToRBG($color, $amt);
  373. return ($hasPrefix ? '#' : '').dechex($green + ($blue << 8) + ($red << 16));
  374. }
  375. /**
  376. * 颜色转暗.
  377. *
  378. * @param string $color
  379. * @param int $amt
  380. * @return string
  381. */
  382. public static function colorDarken(string $color, int $amt)
  383. {
  384. return static::colorLighten($color, -$amt);
  385. }
  386. /**
  387. * 颜色透明度.
  388. *
  389. * @param string $color
  390. * @param float|string $alpha
  391. * @return string
  392. */
  393. public static function colorAlpha(string $color, $alpha)
  394. {
  395. if ($alpha >= 1) {
  396. return $color;
  397. }
  398. if (mb_strpos($color, '#') === 0) {
  399. $color = mb_substr($color, 1);
  400. }
  401. [$red, $blue, $green] = static::colorToRBG($color);
  402. return "rgba($red, $blue, $green, $alpha)";
  403. }
  404. /**
  405. * @param string $color
  406. * @param int $amt
  407. * @return array
  408. */
  409. public static function colorToRBG(string $color, int $amt = 0)
  410. {
  411. $format = function ($value) {
  412. if ($value > 255) {
  413. return 255;
  414. }
  415. if ($value < 0) {
  416. return 0;
  417. }
  418. return $value;
  419. };
  420. $num = hexdec($color);
  421. $red = $format(($num >> 16) + $amt);
  422. $blue = $format((($num >> 8) & 0x00FF) + $amt);
  423. $green = $format(($num & 0x0000FF) + $amt);
  424. return [$red, $blue, $green];
  425. }
  426. /**
  427. * 验证扩展包名称.
  428. *
  429. * @param string $name
  430. * @return int
  431. */
  432. public static function validateExtensionName($name)
  433. {
  434. return preg_match('/^[\w\-_]+\/[\w\-_]+$/', $name);
  435. }
  436. /**
  437. * Get file icon.
  438. *
  439. * @param string $file
  440. * @return string
  441. */
  442. public static function getFileIcon($file = '')
  443. {
  444. $extension = File::extension($file);
  445. foreach (static::$fileTypes as $type => $regex) {
  446. if (preg_match("/^($regex)$/i", $extension) !== 0) {
  447. return "fa fa-file-{$type}-o";
  448. }
  449. }
  450. return 'fa fa-file-o';
  451. }
  452. /**
  453. * 判断是否是ajax请求.
  454. *
  455. * @param Request $request
  456. * @return bool
  457. */
  458. public static function isAjaxRequest(?Request $request = null)
  459. {
  460. /* @var Request $request */
  461. $request = $request ?: request();
  462. return $request->ajax() && ! $request->pjax();
  463. }
  464. /**
  465. * 判断是否是IE浏览器.
  466. *
  467. * @return false|int
  468. */
  469. public static function isIEBrowser()
  470. {
  471. 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'] ?? '');
  472. }
  473. /**
  474. * 判断是否QQ浏览器.
  475. *
  476. * @return bool
  477. */
  478. public static function isQQBrowser()
  479. {
  480. return mb_strpos(mb_strtolower($_SERVER['HTTP_USER_AGENT'] ?? ''), 'qqbrowser') !== false;
  481. }
  482. /**
  483. * @param string $url
  484. * @return void
  485. */
  486. public static function setPreviousUrl($url)
  487. {
  488. session()->flash('admin.prev.url', static::urlWithoutQuery((string) $url, '_pjax'));
  489. }
  490. /**
  491. * @return string
  492. */
  493. public static function getPreviousUrl()
  494. {
  495. return (string) (session()->get('admin.prev.url') ? url(session()->get('admin.prev.url')) : url()->previous());
  496. }
  497. /**
  498. * @param mixed $command
  499. * @param int $timeout
  500. * @param null $input
  501. * @param null $cwd
  502. * @return Process
  503. */
  504. public static function process($command, $timeout = 100, $input = null, $cwd = null)
  505. {
  506. $parameters = [
  507. $command,
  508. $cwd,
  509. [],
  510. $input,
  511. $timeout,
  512. ];
  513. return is_string($command)
  514. ? Process::fromShellCommandline(...$parameters)
  515. : new Process(...$parameters);
  516. }
  517. /**
  518. * 判断两个值是否相等.
  519. *
  520. * @param $value1
  521. * @param $value2
  522. * @return bool
  523. */
  524. public static function equal($value1, $value2)
  525. {
  526. if ($value1 === null || $value2 === null) {
  527. return false;
  528. }
  529. if (! is_scalar($value1) || ! is_scalar($value2)) {
  530. return $value1 === $value2;
  531. }
  532. return (string) $value1 === (string) $value2;
  533. }
  534. /**
  535. * 判断给定的数组是是否包含给定元素.
  536. *
  537. * @param mixed $value
  538. * @param array $array
  539. * @return bool
  540. */
  541. public static function inArray($value, array $array)
  542. {
  543. $array = array_map(function ($v) {
  544. if (is_scalar($v) || $v === null) {
  545. $v = (string) $v;
  546. }
  547. return $v;
  548. }, $array);
  549. return in_array((string) $value, $array, true);
  550. }
  551. /**
  552. * Limit the number of characters in a string.
  553. *
  554. * @param string $value
  555. * @param int $limit
  556. * @param string $end
  557. * @return string
  558. */
  559. public static function strLimit($value, $limit = 100, $end = '...')
  560. {
  561. if (mb_strlen($value, 'UTF-8') <= $limit) {
  562. return $value;
  563. }
  564. return rtrim(mb_substr($value, 0, $limit, 'UTF-8')).$end;
  565. }
  566. /**
  567. * 获取类名或对象的文件路径.
  568. *
  569. * @param string|object $class
  570. * @return string
  571. *
  572. * @throws \ReflectionException
  573. */
  574. public static function guessClassFileName($class)
  575. {
  576. if (is_object($class)) {
  577. $class = get_class($class);
  578. }
  579. try {
  580. if (class_exists($class)) {
  581. return (new \ReflectionClass($class))->getFileName();
  582. }
  583. } catch (\Throwable $e) {
  584. }
  585. $class = trim($class, '\\');
  586. $composer = Composer::parse(base_path('composer.json'));
  587. $map = collect($composer->autoload['psr-4'] ?? [])->mapWithKeys(function ($path, $namespace) {
  588. $namespace = trim($namespace, '\\').'\\';
  589. return [$namespace => [$namespace, $path]];
  590. })->sortBy(function ($_, $namespace) {
  591. return strlen($namespace);
  592. }, SORT_REGULAR, true);
  593. $prefix = explode($class, '\\')[0];
  594. if ($map->isEmpty()) {
  595. if (Str::startsWith($class, 'App\\')) {
  596. $values = ['App\\', 'app/'];
  597. }
  598. } else {
  599. $values = $map->filter(function ($_, $k) use ($class) {
  600. return Str::startsWith($class, $k);
  601. })->first();
  602. }
  603. if (empty($values)) {
  604. $values = [$prefix.'\\', self::slug($prefix).'/'];
  605. }
  606. [$namespace, $path] = $values;
  607. return base_path(str_replace([$namespace, '\\'], [$path, '/'], $class)).'.php';
  608. }
  609. /**
  610. * Is input data is has-one relation.
  611. *
  612. * @param Collection $fields
  613. * @param array $input
  614. */
  615. public static function prepareHasOneRelation(Collection $fields, array &$input)
  616. {
  617. $relations = [];
  618. $fields->each(function ($field) use (&$relations) {
  619. $column = $field->column();
  620. if (is_array($column)) {
  621. foreach ($column as $v) {
  622. if (Str::contains($v, '.')) {
  623. $first = explode('.', $v)[0];
  624. $relations[$first] = null;
  625. }
  626. }
  627. return;
  628. }
  629. if (Str::contains($column, '.')) {
  630. $first = explode('.', $column)[0];
  631. $relations[$first] = null;
  632. }
  633. });
  634. foreach ($relations as $first => $v) {
  635. if (isset($input[$first])) {
  636. foreach ($input[$first] as $key => $value) {
  637. if (is_array($value)) {
  638. $input["$first.$key"] = $value;
  639. }
  640. }
  641. $input = array_merge($input, Arr::dot([$first => $input[$first]]));
  642. }
  643. }
  644. }
  645. /**
  646. * 设置查询条件.
  647. *
  648. * @param mixed $model
  649. * @param string $column
  650. * @param string $query
  651. * @param mixed array $params
  652. * @return void
  653. */
  654. public static function withQueryCondition($model, ?string $column, string $query, array $params)
  655. {
  656. if (! Str::contains($column, '.')) {
  657. $model->$query($column, ...$params);
  658. return;
  659. }
  660. $method = $query === 'orWhere' ? 'orWhere' : 'where';
  661. $subQuery = $query === 'orWhere' ? 'where' : $query;
  662. $model->$method(function ($q) use ($column, $subQuery, $params) {
  663. static::withRelationQuery($q, $column, $subQuery, $params);
  664. });
  665. }
  666. /**
  667. * 设置关联关系查询条件.
  668. *
  669. * @param mixed $model
  670. * @param string $column
  671. * @param string $query
  672. * @param mixed ...$params
  673. * @return void
  674. */
  675. public static function withRelationQuery($model, ?string $column, string $query, array $params)
  676. {
  677. $column = explode('.', $column);
  678. $relColumn = array_pop($column);
  679. // 增加对whereHasIn的支持
  680. $method = class_exists(WhereHasInServiceProvider::class) ? 'whereHasIn' : 'whereHas';
  681. $model->$method(implode('.', $column), function ($relation) use ($relColumn, $params, $query) {
  682. $table = $relation->getModel()->getTable();
  683. $relation->$query("{$table}.{$relColumn}", ...$params);
  684. });
  685. }
  686. /**
  687. * Html转义.
  688. *
  689. * @param array|string $item
  690. * @return mixed
  691. */
  692. public static function htmlEntityEncode($item)
  693. {
  694. if (is_object($item)) {
  695. return $item;
  696. }
  697. if (is_array($item)) {
  698. array_walk_recursive($item, function (&$value) {
  699. $value = htmlentities($value ?? '');
  700. });
  701. } else {
  702. $item = htmlentities($item ?? '');
  703. }
  704. return $item;
  705. }
  706. /**
  707. * 格式化表单元素 name 属性.
  708. *
  709. * @param string|array $name
  710. * @return mixed|string
  711. */
  712. public static function formatElementName($name)
  713. {
  714. if (! $name) {
  715. return $name;
  716. }
  717. if (is_array($name)) {
  718. foreach ($name as &$v) {
  719. $v = static::formatElementName($v);
  720. }
  721. return $name;
  722. }
  723. $name = explode('.', $name);
  724. if (count($name) == 1) {
  725. return $name[0];
  726. }
  727. $html = array_shift($name);
  728. foreach ($name as $piece) {
  729. $html .= "[$piece]";
  730. }
  731. return $html;
  732. }
  733. /**
  734. * Set an array item to a given value using "dot" notation.
  735. *
  736. * If no key is given to the method, the entire array will be replaced.
  737. *
  738. * @param array|\ArrayAccess $array
  739. * @param string $key
  740. * @param mixed $value
  741. * @return array
  742. */
  743. public static function arraySet(&$array, $key, $value)
  744. {
  745. if (is_null($key)) {
  746. return $array = $value;
  747. }
  748. $keys = explode('.', $key);
  749. $default = null;
  750. while (count($keys) > 1) {
  751. $key = array_shift($keys);
  752. if (! isset($array[$key]) || (! is_array($array[$key]) && ! $array[$key] instanceof \ArrayAccess)) {
  753. $array[$key] = [];
  754. }
  755. if (is_array($array)) {
  756. $array = &$array[$key];
  757. } else {
  758. if (is_object($array[$key])) {
  759. $array[$key] = static::arraySet($array[$key], implode('.', $keys), $value);
  760. } else {
  761. $mid = $array[$key];
  762. $array[$key] = static::arraySet($mid, implode('.', $keys), $value);
  763. }
  764. }
  765. }
  766. $array[array_shift($keys)] = $value;
  767. return $array;
  768. }
  769. /**
  770. * 把下划线风格字段名转化为驼峰风格.
  771. *
  772. * @param array $array
  773. * @return array
  774. */
  775. public static function camelArray(array &$array)
  776. {
  777. foreach ($array as $k => $v) {
  778. if (is_array($v)) {
  779. Helper::camelArray($v);
  780. }
  781. $array[Str::camel($k)] = $v;
  782. }
  783. return $array;
  784. }
  785. /**
  786. * 获取文件名称.
  787. *
  788. * @param string $name
  789. * @return array|mixed
  790. */
  791. public static function basename($name)
  792. {
  793. if (! $name) {
  794. return $name;
  795. }
  796. return last(explode('/', $name));
  797. }
  798. /**
  799. * @param string|int $key
  800. * @param array|object $arrayOrObject
  801. * @return bool
  802. */
  803. public static function keyExists($key, $arrayOrObject)
  804. {
  805. if (is_object($arrayOrObject)) {
  806. $arrayOrObject = static::array($arrayOrObject, false);
  807. }
  808. return array_key_exists($key, $arrayOrObject);
  809. }
  810. /**
  811. * 跳转.
  812. *
  813. * @param string $to
  814. * @param int $statusCode
  815. * @param Request $request
  816. * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\JsonResponse|\Illuminate\Http\RedirectResponse|\Illuminate\Http\Response|\Illuminate\Routing\Redirector
  817. */
  818. public static function redirect($to, int $statusCode = 302, $request = null)
  819. {
  820. $request = $request ?: request();
  821. if (! URL::isValidUrl($to)) {
  822. $to = admin_base_path($to);
  823. }
  824. if ($request->ajax() && ! $request->pjax()) {
  825. return response()->json(['redirect' => $to], $statusCode);
  826. }
  827. if ($request->pjax()) {
  828. return response("<script>location.href = '{$to}';</script>");
  829. }
  830. $redirectCodes = [201, 301, 302, 303, 307, 308];
  831. return redirect($to, in_array($statusCode, $redirectCodes, true) ? $statusCode : 302);
  832. }
  833. }