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.
848 lines
30 KiB
848 lines
30 KiB
<?php
|
|
|
|
/**
|
|
* This file is part of the Carbon package.
|
|
*
|
|
* (c) Brian Nesbitt <brian@nesbot.com>
|
|
*
|
|
* For the full copyright and license information, please view the LICENSE
|
|
* file that was distributed with this source code.
|
|
*/
|
|
|
|
use Carbon\Carbon;
|
|
use Carbon\CarbonImmutable;
|
|
use Carbon\CarbonInterface;
|
|
use Carbon\Factory;
|
|
use Carbon\FactoryImmutable;
|
|
|
|
$tags = [
|
|
'property',
|
|
'property-read',
|
|
'property-write',
|
|
PHP_EOL,
|
|
'mode',
|
|
['call', 'is'],
|
|
['call', 'isDayOfWeek'],
|
|
['call', 'isSameUnit'],
|
|
['call', 'setUnit'],
|
|
['call', 'addUnit'],
|
|
['call', 'addUTCUnit'],
|
|
['call', 'roundUnit'],
|
|
['call', 'diffForHumans'],
|
|
];
|
|
$nativeMethods = [
|
|
'getOffset' => 'int',
|
|
'getTimestamp' => 'int',
|
|
];
|
|
$modes = [];
|
|
$autoDocLines = [];
|
|
$carbon = __DIR__.'/src/Carbon/Carbon.php';
|
|
$immutable = __DIR__.'/src/Carbon/CarbonImmutable.php';
|
|
$interface = __DIR__.'/src/Carbon/CarbonInterface.php';
|
|
$phpLevel = 7.1;
|
|
file_put_contents($interface, preg_replace('/(\/\/ <methods[\s\S]*>)([\s\S]+)(<\/methods>)/mU', "$1\n\n // $3", file_get_contents($interface), 1));
|
|
require_once __DIR__.'/vendor/autoload.php';
|
|
$trait = __DIR__.'/src/Carbon/Traits/Date.php';
|
|
$code = '';
|
|
$overrideTyping = [
|
|
$carbon => [
|
|
// 'createFromImmutable' => ['static Carbon', 'DateTimeImmutable $dateTime', 'Create a new Carbon object from an immutable date.'],
|
|
// 'createFromFormat' => ['static static', 'string $format, string $time, DateTimeZone|string|false|null $timezone = null', 'Parse a string into a new Carbon object according to the specified format.'],
|
|
// '__set_state' => ['static static', 'array $array', 'https://php.net/manual/en/datetime.set-state.php'],
|
|
],
|
|
$immutable => [
|
|
// 'createFromMutable' => ['static CarbonImmutable', 'DateTime $dateTime', 'Create a new CarbonImmutable object from an immutable date.'],
|
|
// 'createFromFormat' => ['static static', 'string $format, string $time, DateTimeZone|string|false|null $timezone = null', 'Parse a string into a new CarbonImmutable object according to the specified format.'],
|
|
// '__set_state' => ['static static', 'array $array', 'https://php.net/manual/en/datetime.set-state.php'],
|
|
],
|
|
];
|
|
|
|
foreach (glob(__DIR__.'/src/Carbon/Traits/*.php') as $file) {
|
|
$code .= file_get_contents($file);
|
|
}
|
|
|
|
function unitName($unit)
|
|
{
|
|
return match ($unit) {
|
|
'milli' => 'millisecond',
|
|
'micro' => 'microsecond',
|
|
default => $unit,
|
|
};
|
|
}
|
|
|
|
function pluralize($word)
|
|
{
|
|
if (preg_match('/(millenni)um$/i', $word)) {
|
|
return preg_replace('/(millenni)um$/i', '$1a', $word);
|
|
}
|
|
|
|
return preg_replace('/(centur)y$/i', '$1ie', $word).'s';
|
|
}
|
|
|
|
function dumpValue($value)
|
|
{
|
|
if ($value === null) {
|
|
return 'null';
|
|
}
|
|
|
|
if ($value === CarbonInterface::TRANSLATE_ALL) {
|
|
return 'CarbonInterface::TRANSLATE_ALL';
|
|
}
|
|
|
|
$value = preg_replace('/^array\s*\(\s*\)$/', '[]', var_export($value, true));
|
|
$value = preg_replace('/^array\s*\(([\s\S]+)\)$/', '[$1]', $value);
|
|
|
|
return $value;
|
|
}
|
|
|
|
function cleanClassName($name)
|
|
{
|
|
if ($name === 'CarbonInterval') {
|
|
throw new \Exception('stop');
|
|
}
|
|
|
|
if (preg_match('/^[A-Z]/', $name)) {
|
|
$name = "\\$name";
|
|
}
|
|
|
|
if ($name === '\\Symfony\\Contracts\\Translation\\TranslatorInterface') {
|
|
return 'TranslatorInterface';
|
|
}
|
|
|
|
return preg_replace('/^\\\\(Date(?:Time(?:Immutable|Interface|Zone)?|Interval)|[a-z]*Exception|Closure)$/i', '$1', preg_replace('/^\\\\Carbon\\\\/', '', $name));
|
|
}
|
|
|
|
function dumpType(ReflectionType $type, bool $deep = true, bool $allowsNull = false): string
|
|
{
|
|
if ($type instanceof ReflectionUnionType) {
|
|
return ($deep ? '(' : '').implode('|', array_map(
|
|
dumpType(...),
|
|
$type->getTypes(),
|
|
)).($deep ? ')' : '');
|
|
}
|
|
|
|
if ($type instanceof ReflectionIntersectionType) {
|
|
return ($deep ? '(' : '').implode('&', array_map(
|
|
dumpType(...),
|
|
$type->getTypes(),
|
|
)).($deep ? ')' : '');
|
|
}
|
|
|
|
$name = cleanClassName($type instanceof ReflectionNamedType ? $type->getName() : (string) $type);
|
|
$nullable = $allowsNull && $name !== 'mixed';
|
|
|
|
return (!$deep && $nullable ? '?' : '').
|
|
$name.
|
|
($deep && $nullable ? '|null' : '');
|
|
}
|
|
|
|
function dumpParameter(string $method, ReflectionParameter $parameter): string
|
|
{
|
|
global $defaultValues;
|
|
|
|
$name = $parameter->getName();
|
|
$output = '$'.$name;
|
|
|
|
if ($parameter->isVariadic()) {
|
|
$output = "...$output";
|
|
}
|
|
|
|
if ($parameter->hasType()) {
|
|
$output = dumpType($parameter->getType(), false, $parameter->allowsNull())." $output";
|
|
}
|
|
|
|
if (isset($defaultValues[$method])) {
|
|
if (isset($defaultValues[$method][$name])) {
|
|
$output .= ' = '.dumpValue($defaultValues[$method][$name]);
|
|
}
|
|
|
|
return $output;
|
|
}
|
|
|
|
if ($parameter->isDefaultValueAvailable()) {
|
|
$output .= ' = '.dumpValue($parameter->getDefaultValue());
|
|
}
|
|
|
|
return $output;
|
|
}
|
|
|
|
$deprecated = [];
|
|
|
|
foreach ($tags as $tag) {
|
|
if (\is_array($tag)) {
|
|
[$tag, $pattern] = $tag;
|
|
}
|
|
|
|
$pattern ??= '\S+';
|
|
|
|
if ($tag === PHP_EOL) {
|
|
$autoDocLines[] = '';
|
|
|
|
continue;
|
|
}
|
|
|
|
$unitOfUnit = [];
|
|
preg_match_all('/\/\/ @'.$tag.'\s+(?<type>'.$pattern.')(?:\s+\$(?<name>\S+)(?:[^\S\n](?<description>.*))?\n|(?:[^\S\n](?<description2>.*))?\n(?<comments>(?:[ \t]+\/\/[^\n]*\n)*)[^\']*\'(?<name2>[^\']+)\')/', $code, $oneLine, PREG_SET_ORDER);
|
|
preg_match_all('/\/\* *@'.$tag.'\s+(?<type>'.$pattern.') *\*\/[^\']*\'(?<name2>[^\']+)\'/', $code, $multiLine, PREG_SET_ORDER);
|
|
|
|
foreach ([...$oneLine, ...$multiLine] as $match) {
|
|
$vars = (object) $match;
|
|
$deprecation = null;
|
|
|
|
if (isset($vars->comments) && preg_match(
|
|
'`^[ \t]+(//|/*|#)[ \t]*@deprecated(?:\s(?<deprecation>[\s\S]*))?$`',
|
|
$vars->comments,
|
|
$comments
|
|
)) {
|
|
['deprecation' => $deprecation] = $comments;
|
|
$deprecation = preg_replace('/^\s*(\/\/|#|\*) {0,3}/m', '', trim($deprecation));
|
|
|
|
if (preg_match('/^(?:[a-z]+:[^\n]+\n)+$/', "$deprecation\n")) {
|
|
$data = [];
|
|
|
|
foreach (explode("\n", $deprecation) as $line) {
|
|
[$name, $value] = array_map('trim', explode(':', $line, 2));
|
|
|
|
$data[$name] = $value;
|
|
}
|
|
|
|
$deprecation = $data;
|
|
} else {
|
|
$deprecation = ['reason' => $deprecation];
|
|
}
|
|
}
|
|
|
|
$vars->name = ($vars->name ?? null) ?: ($vars->name2 ?? '');
|
|
$vars->description = ($vars->description ?? null) ?: ($vars->description2 ?? '');
|
|
|
|
if ($tag === 'mode') {
|
|
$modes[$vars->type] ??= [];
|
|
$modes[$vars->type][] = $vars->name;
|
|
|
|
continue;
|
|
}
|
|
|
|
if ($tag === 'call') {
|
|
switch ($vars->type) {
|
|
case 'diffForHumans':
|
|
foreach ($modes[$vars->type] as $mode) {
|
|
$autoDocLines[] = [
|
|
'@method',
|
|
'string',
|
|
"$mode{$vars->name}DiffForHumans(DateTimeInterface \$other = null, int \$parts = 1)",
|
|
"Get the difference ($mode format, '{$vars->name}' mode) in a human readable format in the current locale. (\$other and \$parts parameters can be swapped.)",
|
|
];
|
|
}
|
|
|
|
break;
|
|
|
|
case 'isDayOfWeek':
|
|
$autoDocLines[] = [
|
|
'@method',
|
|
'bool',
|
|
'is'.ucFirst($vars->name).'()',
|
|
'Checks if the instance day is '.unitName(strtolower($vars->name)).'.',
|
|
];
|
|
|
|
break;
|
|
|
|
case 'is':
|
|
$autoDocLines[] = [
|
|
'@method',
|
|
'bool',
|
|
'is'.ucFirst($vars->name).'()',
|
|
$vars->description,
|
|
];
|
|
|
|
break;
|
|
|
|
case 'isSameUnit':
|
|
$unit = $vars->name;
|
|
$unitName = unitName($unit);
|
|
$method = 'isSame'.ucFirst($unit);
|
|
|
|
if (!method_exists(Carbon::class, $method)) {
|
|
$autoDocLines[] = [
|
|
'@method',
|
|
'bool',
|
|
$method.'(DateTimeInterface|string $date)',
|
|
"Checks if the given date is in the same $unitName as the instance. If null passed, compare to now (with the same timezone).",
|
|
];
|
|
}
|
|
|
|
$autoDocLines[] = [
|
|
'@method',
|
|
'bool',
|
|
'isCurrent'.ucFirst($unit).'()',
|
|
"Checks if the instance is in the same $unitName as the current moment.",
|
|
];
|
|
$autoDocLines[] = [
|
|
'@method',
|
|
'bool',
|
|
'isNext'.ucFirst($unit).'()',
|
|
"Checks if the instance is in the same $unitName as the current moment next $unitName.",
|
|
];
|
|
$autoDocLines[] = [
|
|
'@method',
|
|
'bool',
|
|
'isLast'.ucFirst($unit).'()',
|
|
"Checks if the instance is in the same $unitName as the current moment last $unitName.",
|
|
];
|
|
|
|
break;
|
|
|
|
case 'setUnit':
|
|
$unit = $vars->name;
|
|
$unitName = unitName($unit);
|
|
$plUnit = pluralize($unit);
|
|
$enums = $unitName === 'month' ? 'Month|' : '';
|
|
$autoDocLines[] = [
|
|
'@method',
|
|
'self',
|
|
"$plUnit({$enums}int \$value)",
|
|
"Set current instance $unitName to the given value.",
|
|
];
|
|
$autoDocLines[] = [
|
|
'@method',
|
|
'self',
|
|
"$unit({$enums}int \$value)",
|
|
"Set current instance $unitName to the given value.",
|
|
];
|
|
$autoDocLines[] = [
|
|
'@method',
|
|
'self',
|
|
'set'.ucfirst($plUnit)."({$enums}int \$value)",
|
|
"Set current instance $unitName to the given value.",
|
|
];
|
|
$autoDocLines[] = [
|
|
'@method',
|
|
'self',
|
|
'set'.ucfirst($unit)."({$enums}int \$value)",
|
|
"Set current instance $unitName to the given value.",
|
|
];
|
|
|
|
break;
|
|
|
|
case 'addUnit':
|
|
$unit = $vars->name;
|
|
$unitName = unitName($unit);
|
|
$plUnit = pluralize($unit);
|
|
$plUnitName = pluralize($unitName);
|
|
$autoDocLines[] = [
|
|
'@method',
|
|
'self',
|
|
'add'.ucFirst($plUnit).'(int|float $value = 1)',
|
|
"Add $plUnitName (the \$value count passed in) to the instance (using date interval).",
|
|
];
|
|
$autoDocLines[] = [
|
|
'@method',
|
|
'self',
|
|
'add'.ucFirst($unit).'()',
|
|
"Add one $unitName to the instance (using date interval).",
|
|
];
|
|
$autoDocLines[] = [
|
|
'@method',
|
|
'self',
|
|
'sub'.ucFirst($plUnit).'(int|float $value = 1)',
|
|
"Sub $plUnitName (the \$value count passed in) to the instance (using date interval).",
|
|
];
|
|
$autoDocLines[] = [
|
|
'@method',
|
|
'self',
|
|
'sub'.ucFirst($unit).'()',
|
|
"Sub one $unitName to the instance (using date interval).",
|
|
];
|
|
|
|
if (\in_array($unit, [
|
|
'month',
|
|
'quarter',
|
|
'year',
|
|
'decade',
|
|
'century',
|
|
'millennium',
|
|
])) {
|
|
$autoDocLines[] = [
|
|
'@method',
|
|
'self',
|
|
'add'.ucFirst($plUnit).'WithOverflow(int|float $value = 1)',
|
|
"Add $plUnitName (the \$value count passed in) to the instance (using date interval) with overflow explicitly allowed.",
|
|
];
|
|
$autoDocLines[] = [
|
|
'@method',
|
|
'self',
|
|
'add'.ucFirst($unit).'WithOverflow()',
|
|
"Add one $unitName to the instance (using date interval) with overflow explicitly allowed.",
|
|
];
|
|
$autoDocLines[] = [
|
|
'@method',
|
|
'self',
|
|
'sub'.ucFirst($plUnit).'WithOverflow(int|float $value = 1)',
|
|
"Sub $plUnitName (the \$value count passed in) to the instance (using date interval) with overflow explicitly allowed.",
|
|
];
|
|
$autoDocLines[] = [
|
|
'@method',
|
|
'self',
|
|
'sub'.ucFirst($unit).'WithOverflow()',
|
|
"Sub one $unitName to the instance (using date interval) with overflow explicitly allowed.",
|
|
];
|
|
|
|
foreach (['WithoutOverflow', 'WithNoOverflow', 'NoOverflow'] as $alias) {
|
|
$autoDocLines[] = [
|
|
'@method',
|
|
'self',
|
|
'add'.ucFirst($plUnit)."$alias(int|float \$value = 1)",
|
|
"Add $plUnitName (the \$value count passed in) to the instance (using date interval) with overflow explicitly forbidden.",
|
|
];
|
|
$autoDocLines[] = [
|
|
'@method',
|
|
'self',
|
|
'add'.ucFirst($unit)."$alias()",
|
|
"Add one $unitName to the instance (using date interval) with overflow explicitly forbidden.",
|
|
];
|
|
$autoDocLines[] = [
|
|
'@method',
|
|
'self',
|
|
'sub'.ucFirst($plUnit)."$alias(int|float \$value = 1)",
|
|
"Sub $plUnitName (the \$value count passed in) to the instance (using date interval) with overflow explicitly forbidden.",
|
|
];
|
|
$autoDocLines[] = [
|
|
'@method',
|
|
'self',
|
|
'sub'.ucFirst($unit)."$alias()",
|
|
"Sub one $unitName to the instance (using date interval) with overflow explicitly forbidden.",
|
|
];
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
break;
|
|
|
|
case 'addUTCUnit':
|
|
$unit = $vars->name;
|
|
$unitName = unitName($unit);
|
|
$plUnit = pluralize($unit);
|
|
$plUnitName = pluralize($unitName);
|
|
$autoDocLines[] = [
|
|
'@method',
|
|
'self',
|
|
'addUTC'.ucFirst($plUnit).'(int|float $value = 1)',
|
|
"Add $plUnitName (the \$value count passed in) to the instance (using timestamp).",
|
|
];
|
|
$autoDocLines[] = [
|
|
'@method',
|
|
'self',
|
|
'addUTC'.ucFirst($unit).'()',
|
|
"Add one $unitName to the instance (using timestamp).",
|
|
];
|
|
$autoDocLines[] = [
|
|
'@method',
|
|
'self',
|
|
'subUTC'.ucFirst($plUnit).'(int|float $value = 1)',
|
|
"Sub $plUnitName (the \$value count passed in) to the instance (using timestamp).",
|
|
];
|
|
$autoDocLines[] = [
|
|
'@method',
|
|
'self',
|
|
'subUTC'.ucFirst($unit).'()',
|
|
"Sub one $unitName to the instance (using timestamp).",
|
|
];
|
|
$autoDocLines[] = [
|
|
'@method',
|
|
'CarbonPeriod',
|
|
$plUnit.'Until($endDate = null, int|float $factor = 1)',
|
|
"Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each $unitName or every X $plUnitName if a factor is given.",
|
|
];
|
|
$autoDocLines[] = [
|
|
'@method',
|
|
'float',
|
|
'diffInUTC'.ucFirst($plUnit).'(DateTimeInterface|string|null $date, bool $absolute = false)',
|
|
"Convert current and given date in UTC timezone and return a floating number of $plUnitName.",
|
|
];
|
|
|
|
break;
|
|
|
|
case 'roundUnit':
|
|
$unit = $vars->name;
|
|
$unitName = unitName($unit);
|
|
$plUnit = pluralize($unit);
|
|
$autoDocLines[] = [
|
|
'@method',
|
|
'self',
|
|
'round'.ucFirst($unit).'(float $precision = 1, string $function = "round")',
|
|
"Round the current instance $unitName with given precision using the given function.",
|
|
];
|
|
$autoDocLines[] = [
|
|
'@method',
|
|
'self',
|
|
'round'.ucFirst($plUnit).'(float $precision = 1, string $function = "round")',
|
|
"Round the current instance $unitName with given precision using the given function.",
|
|
];
|
|
$autoDocLines[] = [
|
|
'@method',
|
|
'self',
|
|
'floor'.ucFirst($unit).'(float $precision = 1)',
|
|
"Truncate the current instance $unitName with given precision.",
|
|
];
|
|
$autoDocLines[] = [
|
|
'@method',
|
|
'self',
|
|
'floor'.ucFirst($plUnit).'(float $precision = 1)',
|
|
"Truncate the current instance $unitName with given precision.",
|
|
];
|
|
$autoDocLines[] = [
|
|
'@method',
|
|
'self',
|
|
'ceil'.ucFirst($unit).'(float $precision = 1)',
|
|
"Ceil the current instance $unitName with given precision.",
|
|
];
|
|
$autoDocLines[] = [
|
|
'@method',
|
|
'self',
|
|
'ceil'.ucFirst($plUnit).'(float $precision = 1)',
|
|
"Ceil the current instance $unitName with given precision.",
|
|
];
|
|
|
|
break;
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
$description = trim($vars->description);
|
|
$variable = $vars->name;
|
|
|
|
if (str_starts_with($description, '$')) {
|
|
[$variable, $description] = explode(' ', $description, 2);
|
|
$variable = ltrim($variable, '$');
|
|
$description = ltrim($description);
|
|
}
|
|
|
|
if ($deprecation !== null) {
|
|
$deprecated[$tag] = $deprecated[$tag] ?? [];
|
|
$deprecated[$tag][] = [
|
|
'deprecation' => $deprecation,
|
|
'type' => $vars->type,
|
|
'variable' => $variable,
|
|
'description' => $description ?: '',
|
|
];
|
|
|
|
continue;
|
|
}
|
|
|
|
if (
|
|
\in_array($tag, ['property', 'property-read'], true) &&
|
|
preg_match('/^[a-z]{2,}(?<operator>In|Of)[A-Z][a-z]+$/', $vars->name, $match)
|
|
) {
|
|
$unitOfUnit[$vars->name] = [
|
|
'@'.($match['operator'] === 'Of' ? 'property' : 'property-read'),
|
|
$vars->type,
|
|
'$'.$variable,
|
|
$description ?: '',
|
|
];
|
|
|
|
continue;
|
|
}
|
|
|
|
$autoDocLines[] = [
|
|
'@'.$tag,
|
|
$vars->type,
|
|
'$'.$variable,
|
|
$description ?: '',
|
|
];
|
|
}
|
|
|
|
if ($tag === 'property') {
|
|
$units = ['microseconds', 'milliseconds', 'seconds', 'minutes', 'hours', 'days', 'weeks', 'months', 'quarters', 'years', 'decades', 'centuries', 'millennia'];
|
|
|
|
foreach ($units as $small) {
|
|
array_shift($units);
|
|
|
|
foreach ($units as $big) {
|
|
$singularSmall = Carbon::singularUnit($small);
|
|
$singularBig = Carbon::singularUnit($big);
|
|
$name = $singularSmall.'Of'.ucfirst($singularBig);
|
|
$unitOfUnit[$name] ??= [
|
|
'@property',
|
|
'int',
|
|
'$'.$name,
|
|
'The value of the '.$singularSmall.' starting from the beginning of the current '.$singularBig,
|
|
];
|
|
}
|
|
}
|
|
|
|
ksort($unitOfUnit);
|
|
|
|
array_push($autoDocLines, ...array_values($unitOfUnit));
|
|
}
|
|
|
|
if ($tag === 'property-read') {
|
|
$units = ['microseconds', 'milliseconds', 'seconds', 'minutes', 'hours', 'days', 'weeks', 'months', 'quarters', 'years', 'decades', 'centuries', 'millennia'];
|
|
|
|
foreach ($units as $small) {
|
|
array_shift($units);
|
|
|
|
foreach ($units as $big) {
|
|
$singularSmall = Carbon::singularUnit($small);
|
|
$singularBig = Carbon::singularUnit($big);
|
|
$name = $small.'In'.ucfirst($singularBig);
|
|
$unitOfUnit[$name] ??= [
|
|
'@property-read',
|
|
'int',
|
|
'$'.$name,
|
|
'The number of '.$small.' contained in the current '.$singularBig,
|
|
];
|
|
}
|
|
}
|
|
|
|
ksort($unitOfUnit);
|
|
|
|
array_push($autoDocLines, ...array_values($unitOfUnit));
|
|
}
|
|
}
|
|
|
|
$units = ['microseconds', 'milliseconds', 'seconds', 'minutes', 'hours', 'days', 'weeks', 'months', 'quarters', 'years', 'decades', 'centuries', 'millennia'];
|
|
$unitOfUnit = [
|
|
'dayOfYear' => false,
|
|
'weeksInYear' => false,
|
|
];
|
|
|
|
foreach ($units as $small) {
|
|
array_shift($units);
|
|
|
|
foreach ($units as $big) {
|
|
$singularSmall = Carbon::singularUnit($small);
|
|
$singularBig = Carbon::singularUnit($big);
|
|
$name = $singularSmall.'Of'.ucfirst($singularBig);
|
|
$unitOfUnit[$name] ??= [
|
|
'@method',
|
|
'int|static',
|
|
$name.'(?int $'.$singularSmall.' = null)',
|
|
'Return the value of the '.$singularSmall.' starting from the beginning of the current '.$singularBig.' when called with no parameters, change the current '.$singularSmall.' when called with an integer value',
|
|
];
|
|
$name = $small.'In'.ucfirst($singularBig);
|
|
$unitOfUnit[$name] ??= [
|
|
'@method',
|
|
'int',
|
|
$name.'()',
|
|
'Return the number of '.$small.' contained in the current '.$singularBig,
|
|
];
|
|
}
|
|
}
|
|
|
|
ksort($unitOfUnit);
|
|
|
|
array_push($autoDocLines, ...array_values(array_filter($unitOfUnit)));
|
|
|
|
$propertyTemplate = '
|
|
/**
|
|
* %description%
|
|
*
|
|
* @var %type%
|
|
*
|
|
* @deprecated %line1%
|
|
* %line2%
|
|
*/
|
|
public $%variable%;
|
|
';
|
|
|
|
$lineGlue = preg_replace('/^[\s\S]*%line1%([\s\S]*)%line2%[\s\S]*$/', '$1', $propertyTemplate);
|
|
$propertyTemplate = preg_replace('/(%line1%[\s\S]*%line2%)/', '%deprecation%', $propertyTemplate);
|
|
|
|
function compileDoc($autoDocLines, $file)
|
|
{
|
|
$class = 'CarbonInterface';
|
|
|
|
if (preg_match('`[\\\\/](Carbon\w*)\.php$`', $file, $match)) {
|
|
$class = $match[1];
|
|
}
|
|
|
|
$autoDoc = '';
|
|
$columnsMaxLengths = [];
|
|
|
|
foreach ($autoDocLines as &$editableLine) {
|
|
if (\is_array($editableLine)) {
|
|
if (($editableLine[1] ?? '') === 'self') {
|
|
$editableLine[1] = $class === 'Carbon' ? '$this' : $class;
|
|
}
|
|
|
|
foreach ($editableLine as $column => $text) {
|
|
$length = \strlen($text);
|
|
$max = $columnsMaxLengths[$column] ?? 0;
|
|
|
|
if ($length > $max) {
|
|
$columnsMaxLengths[$column] = $length;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach ($autoDocLines as $line) {
|
|
$autoDoc .= "\n *";
|
|
if (\is_string($line)) {
|
|
if (!empty($line)) {
|
|
$autoDoc .= " $line";
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
$computedLine = ' ';
|
|
foreach ($line as $column => $text) {
|
|
$computedLine .= str_pad($text, $columnsMaxLengths[$column] + 1, ' ', STR_PAD_RIGHT);
|
|
}
|
|
|
|
$autoDoc .= rtrim($computedLine);
|
|
}
|
|
|
|
return $autoDoc;
|
|
}
|
|
|
|
$files = new stdClass();
|
|
|
|
foreach ([$trait, $carbon, $immutable, $interface] as $file) {
|
|
$content = file_get_contents($file);
|
|
$files->$file = preg_replace_callback('/(<autodoc[\s\S]*>)([\s\S]+)(<\/autodoc>)/mU', function ($matches) use ($file, $autoDocLines, $overrideTyping) {
|
|
foreach (($overrideTyping[$file] ?? []) as $method => $line) {
|
|
$line[1] = $method.'('.$line[1].')';
|
|
array_unshift($line, '@method');
|
|
$autoDocLines[] = $line;
|
|
}
|
|
|
|
$autoDoc = compileDoc($autoDocLines, $file);
|
|
|
|
return $matches[1]."\n *$autoDoc\n *\n * ".$matches[3];
|
|
}, $content, 1);
|
|
}
|
|
|
|
$staticMethods = [];
|
|
$staticImmutableMethods = [];
|
|
$methods = '';
|
|
$carbonMethods = get_class_methods(Carbon::class);
|
|
sort($carbonMethods);
|
|
|
|
function getMethodReturnType(ReflectionMethod $method): string
|
|
{
|
|
$type = $method->getReturnType();
|
|
$type = $type ? dumpType($type, false, $type->allowsNull()) : null;
|
|
|
|
return $type ? ': '.$type : '';
|
|
}
|
|
|
|
foreach ($carbonMethods as $method) {
|
|
if (!method_exists(CarbonImmutable::class, $method) ||
|
|
method_exists(DateTimeInterface::class, $method) ||
|
|
\in_array($method, ['diff', 'createFromInterface'], true)
|
|
) {
|
|
continue;
|
|
}
|
|
|
|
$function = new ReflectionMethod(Carbon::class, $method);
|
|
$static = $function->isStatic() ? ' static' : '';
|
|
$parameters = implode(', ', array_map(function (ReflectionParameter $parameter) use ($method) {
|
|
return dumpParameter($method, $parameter);
|
|
}, $function->getParameters()));
|
|
$methodDocBlock = $function->getDocComment() ?: '';
|
|
|
|
if (!str_starts_with($method, '__') && $function->isStatic()) {
|
|
$doc = preg_replace('/^\/\*+\n([\s\S]+)\s*\*\//', '$1', $methodDocBlock);
|
|
$doc = preg_replace('/^\s*\*\s?/m', '', $doc);
|
|
$doc = explode("\n@", $doc, 2);
|
|
$doc = preg_split('/(\r\n|\r|\n)/', trim($doc[0]));
|
|
$returnType = $function->getReturnType();
|
|
|
|
if ($returnType instanceof ReflectionType) {
|
|
$returnType = dumpType($returnType, false, $returnType->allowsNull());
|
|
}
|
|
|
|
if (!$returnType && preg_match('/\*\s*@returns?\s+(\S+)/', $methodDocBlock, $match)) {
|
|
$returnType = $match[1];
|
|
}
|
|
|
|
$returnType = str_replace('static|CarbonInterface', 'static', $returnType ?: 'static');
|
|
if (!method_exists(Factory::class, $method)) {
|
|
$staticMethods[] = [
|
|
'@method',
|
|
str_replace(['self', 'static'], 'Carbon', $returnType),
|
|
"$method($parameters)",
|
|
$doc[0],
|
|
];
|
|
|
|
for ($i = 1; $i < \count($doc); $i++) {
|
|
$staticMethods[] = ['', '', '', $doc[$i]];
|
|
}
|
|
}
|
|
|
|
if (!method_exists(FactoryImmutable::class, $method)) {
|
|
$staticImmutableMethods[] = [
|
|
'@method',
|
|
str_replace(['self', 'static'], 'CarbonImmutable', $returnType),
|
|
"$method($parameters)",
|
|
$doc[0],
|
|
];
|
|
|
|
for ($i = 1; $i < \count($doc); $i++) {
|
|
$staticImmutableMethods[] = ['', '', '', $doc[$i]];
|
|
}
|
|
}
|
|
}
|
|
|
|
$return = getMethodReturnType($function);
|
|
|
|
if (!empty($methodDocBlock)) {
|
|
$methodDocBlock = "\n $methodDocBlock";
|
|
} elseif (isset($nativeMethods[$method])) {
|
|
$link = strtolower($method);
|
|
$methodDocBlock = "\n /**\n".
|
|
" * Calls DateTime::$method if mutable or DateTimeImmutable::$method else.\n".
|
|
" *\n".
|
|
" * @see https://php.net/manual/en/datetime.$link.php\n".
|
|
' */';
|
|
}
|
|
|
|
if (str_contains($return, 'self') && $phpLevel < 7.4) {
|
|
$return = '';
|
|
}
|
|
|
|
if ($method === '__toString' && $phpLevel < 8) {
|
|
$return = '';
|
|
}
|
|
|
|
if (method_exists($function, 'getAttributes') && ($attributes = $function->getAttributes())) {
|
|
foreach ($attributes as $attribute) {
|
|
$methodDocBlock .= "\n #[".$attribute->getName().']';
|
|
}
|
|
}
|
|
|
|
$methods .= "\n$methodDocBlock\n public$static function $method($parameters)$return;";
|
|
}
|
|
|
|
$files->$interface = strtr(preg_replace_callback(
|
|
'/(\/\/ <methods[\s\S]*>)([\s\S]+)(<\/methods>)/mU',
|
|
static fn ($matches) => "{$matches[1]}$methods\n\n // {$matches[3]}",
|
|
$files->$interface,
|
|
1,
|
|
), [
|
|
'|CarbonInterface' => '|self',
|
|
'CarbonInterface::TRANSLATE_ALL' => 'self::TRANSLATE_ALL',
|
|
]);
|
|
|
|
$factories = [
|
|
__DIR__.'/src/Carbon/Factory.php' => $staticMethods,
|
|
__DIR__.'/src/Carbon/FactoryImmutable.php' => $staticImmutableMethods,
|
|
];
|
|
|
|
foreach ($factories as $file => $methods) {
|
|
$autoDoc = compileDoc($methods, $file);
|
|
$content = file_get_contents($file);
|
|
$files->$file = preg_replace_callback(
|
|
'/(<autodoc[\s\S]*>)([\s\S]+)(<\/autodoc>)/mU',
|
|
static fn ($matches) => "{$matches[1]}\n *$autoDoc\n *\n * {$matches[3]}",
|
|
$content,
|
|
1,
|
|
);
|
|
}
|
|
|
|
foreach ($files as $file => $contents) {
|
|
file_put_contents($file, $contents);
|
|
}
|
|
|