Helper.php 23 KB

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