You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

104 lines
2.3 KiB

3 years ago
  1. <?php
  2. /**
  3. * This file is part of the Nette Framework (https://nette.org)
  4. * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
  5. */
  6. declare(strict_types=1);
  7. namespace Nette\Schema;
  8. use Nette;
  9. use Nette\Utils\Reflection;
  10. /**
  11. * @internal
  12. */
  13. final class Helpers
  14. {
  15. use Nette\StaticClass;
  16. public const PREVENT_MERGING = '_prevent_merging';
  17. /**
  18. * Merges dataset. Left has higher priority than right one.
  19. * @return array|string
  20. */
  21. public static function merge($value, $base)
  22. {
  23. if (is_array($value) && isset($value[self::PREVENT_MERGING])) {
  24. unset($value[self::PREVENT_MERGING]);
  25. return $value;
  26. }
  27. if (is_array($value) && is_array($base)) {
  28. $index = 0;
  29. foreach ($value as $key => $val) {
  30. if ($key === $index) {
  31. $base[] = $val;
  32. $index++;
  33. } else {
  34. $base[$key] = static::merge($val, $base[$key] ?? null);
  35. }
  36. }
  37. return $base;
  38. } elseif ($value === null && is_array($base)) {
  39. return $base;
  40. } else {
  41. return $value;
  42. }
  43. }
  44. public static function getPropertyType(\ReflectionProperty $prop): ?string
  45. {
  46. if ($types = Reflection::getPropertyTypes($prop)) {
  47. return implode('|', $types);
  48. } elseif ($type = preg_replace('#\s.*#', '', (string) self::parseAnnotation($prop, 'var'))) {
  49. $class = Reflection::getPropertyDeclaringClass($prop);
  50. return preg_replace_callback('#[\w\\\\]+#', function ($m) use ($class) {
  51. return Reflection::expandClassName($m[0], $class);
  52. }, $type);
  53. }
  54. return null;
  55. }
  56. /**
  57. * Returns an annotation value.
  58. * @param \ReflectionProperty $ref
  59. */
  60. public static function parseAnnotation(\Reflector $ref, string $name): ?string
  61. {
  62. if (!Reflection::areCommentsAvailable()) {
  63. throw new Nette\InvalidStateException('You have to enable phpDoc comments in opcode cache.');
  64. }
  65. $re = '#[\s*]@' . preg_quote($name, '#') . '(?=\s|$)(?:[ \t]+([^@\s]\S*))?#';
  66. if ($ref->getDocComment() && preg_match($re, trim($ref->getDocComment(), '/*'), $m)) {
  67. return $m[1] ?? '';
  68. }
  69. return null;
  70. }
  71. /**
  72. * @param mixed $value
  73. */
  74. public static function formatValue($value): string
  75. {
  76. if (is_object($value)) {
  77. return 'object ' . get_class($value);
  78. } elseif (is_string($value)) {
  79. return "'" . Nette\Utils\Strings::truncate($value, 15, '...') . "'";
  80. } elseif (is_scalar($value)) {
  81. return var_export($value, true);
  82. } else {
  83. return strtolower(gettype($value));
  84. }
  85. }
  86. }