Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/Bag/Casts/CollectionOf.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ public function __construct(public string $valueClassname)
public function set(Collection $propertyTypes, string $propertyName, LaravelCollection $properties): mixed
{
/** @var class-string<LaravelCollection<array-key,mixed>> $propertyType */
$propertyType = $propertyTypes->first();
$propertyType = $propertyTypes->firstWhere(fn ($type) => $type === LaravelCollection::class || \is_subclass_of($type, LaravelCollection::class, true));

if ($propertyType !== LaravelCollection::class && ! \is_subclass_of($propertyType, LaravelCollection::class, true)) {
if ($propertyType === null) {
throw new InvalidCollection(sprintf('The property "%s" must be a subclass of %s', $propertyName, LaravelCollection::class));
}

Expand Down
87 changes: 65 additions & 22 deletions src/Bag/Console/Commands/MakeBagCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@
use Bag\Collection;
use Bag\Factory;
use Bag\Internal\Reflection;
use Bag\Internal\Util;
use Bag\Traits\HasFactory;
use Brick\Money\Money;
use DateTimeInterface;
use Illuminate\Console\Command;
use Illuminate\Contracts\Console\PromptsForMissingInput;
use Illuminate\Support\Collection as LaravelCollection;
use Illuminate\Support\Str;
use function Laravel\Prompts\outro;
use function Laravel\Prompts\text;
Expand All @@ -27,7 +29,6 @@
use Nette\PhpGenerator\TraitType;
use PrinsFrank\Standards\Currency\CurrencyAlpha3;
use ReflectionClass;
use ReflectionNamedType;

class MakeBagCommand extends Command implements PromptsForMissingInput
{
Expand Down Expand Up @@ -183,12 +184,14 @@ protected function updateBag(string $namespace, string $name, string $classFile,

/** @var class-string $fullyQualifiedName */
$fullyQualifiedName = $classNamespace->getName() . '\\' . $name;
$reflectionClass = new ReflectionClass($fullyQualifiedName);

if ($factory !== null) {
$classNamespace->addUse(FactoryAttribute::class);
$classNamespace->addUse(HasFactory::class);
$classNamespace->addUse($namespace . '\\Factories\\' . $factory);

if (count((new ReflectionClass($fullyQualifiedName))->getAttributes(FactoryAttribute::class)) > 0) {
if (count($reflectionClass->getAttributes(FactoryAttribute::class)) > 0) {
$attributes = $class->getAttributes();
foreach ($attributes as $key => $attribute) {
if ($attribute->getName() === FactoryAttribute::class) {
Expand All @@ -205,7 +208,7 @@ protected function updateBag(string $namespace, string $name, string $classFile,
}

if ($collection !== null) {
if (count((new ReflectionClass($fullyQualifiedName))->getAttributes(CollectionAttribute::class)) > 0) {
if (count($reflectionClass->getAttributes(CollectionAttribute::class)) > 0) {
$attributes = $class->getAttributes();
foreach ($attributes as $key => $attribute) {
if ($attribute->getName() === CollectionAttribute::class) {
Expand All @@ -229,49 +232,89 @@ protected function updateBag(string $namespace, string $name, string $classFile,

/** @var class-string $fullyQualifiedName */
$fullyQualifiedName = $namespace . '\\' . $name;
$parameters = (new ReflectionClass($fullyQualifiedName))->getMethod('__construct')->getParameters();
$parameters = $reflectionClass->getConstructor()?->getParameters() ?? [];
foreach ($parameters as $parameter) {
/** @var ReflectionNamedType $parameterType */
$parameterType = $parameter->getType();
$parameterTypeName = $parameterType->getName();
/** @var Collection<string> $types */
$types = Util::getPropertyTypes($parameter)->map(
// @phpstan-ignore argument.type
function (string $type) use ($parameter, $classNamespace): string {
if (!\class_exists($type)) {
return $type;
}

if (!$parameterType->isBuiltin()) {
$classNamespace->addUse($parameterTypeName);
$classNamespace->addUse($type);

$collectionOf = '';
if ($parameterTypeName === Collection::class || \is_subclass_of($parameterTypeName, Collection::class, true)) {
$castAttribute = Reflection::getAttribute($parameter, Cast::class);
$typeName = \class_basename($type);
$collectionOf = '';

if ($castAttribute !== null && $castAttribute->getArguments()[0] === CollectionOf::class && $castAttribute->getArguments()[1] !== null) {
$classNamespace->addUse($castAttribute->getArguments()[1]);
if ($type === LaravelCollection::class || \is_subclass_of($type, LaravelCollection::class, true)) {
$castAttribute = Reflection::getAttribute($parameter, Cast::class);

$collectionOf = '<' . \class_basename($castAttribute->getArguments()[1]) . '>';
if ($castAttribute !== null && $castAttribute->getArguments()[0] === CollectionOf::class && $castAttribute->getArguments()[1] !== null) {
$classNamespace->addUse($castAttribute->getArguments()[1]);
$collectionOf = '<' . \class_basename($castAttribute->getArguments()[1]) . '>';
}
}

return $typeName . $collectionOf;
}
);

$parameterTypeName = class_basename($parameterTypeName) . $collectionOf;
if ($types->count() === 2 && $types->contains('null')) {
$type = $types->first(fn ($type) => $type !== 'null');
if ($type === 'mixed') {
$types = collect(['mixed']);
} else {
/** @var string $type */
$types = collect(['?' . $type]);
}
}

if ($parameterType->allowsNull() && $parameterType->getName() !== 'mixed') {
$parameterTypeName = '?' . $parameterTypeName;
$parameterTypeName = $types->implode('|');

if ($parameter->isVariadic()) {
$parameterTypeName = ' ...';
}

$args[] = $parameterTypeName . ' $' . $parameter->getName();
$parameterDefinition = $parameterTypeName . ' $' . $parameter->getName();
if ($parameter->isDefaultValueAvailable()) {
if ($parameter->isDefaultValueConstant()) {
$args[count($args) - 1] .= ' = ' . $parameter->getDefaultValueConstantName();
$parameterDefinition .= ' = ' . $parameter->getDefaultValueConstantName();
} else {
$args[count($args) - 1] .= ' = ' . Str::of(var_export($parameter->getDefaultValue(), true))
$parameterDefinition .= ' = ' . Str::of(var_export($parameter->getDefaultValue(), true))
->replace(['NULL', 'FALSE', 'TRUE'], ['null', 'false', 'true']);
}
}

$args[] = $parameterDefinition;
}

$comment = Str::of($class->getComment() ?? '')
->replaceMatches('/^@method static static from\(.*$/', '')
->replaceMatches('/@method static .*? from\(.*/', '')
->append("\n@method static static from(" . implode(', ', $args) . ')')
->ltrim("\n");

$collectionAttributes = $reflectionClass->getAttributes(CollectionAttribute::class);
if (count($collectionAttributes) > 0) {
$collectionAttribute = $collectionAttributes[0];
$collectionClass = $collectionAttribute->getArguments()[0];
$comment = $comment
->replaceMatches('/@method static .*? collect\(.*/', '')
->append("\n@method static " . \class_basename($collectionClass) . '<' . $name . '> collect(iterable $items)')
->ltrim("\n");
}


$factoryAttributes = $reflectionClass->getAttributes(FactoryAttribute::class);
if (count($factoryAttributes) > 0) {
$factoryAttributes = $factoryAttributes[0];
$factoryClass = $factoryAttributes->getArguments()[0];
$comment = $comment
->replaceMatches('/@method static .*? factory\(.*/', '')
->append("\n@method static " . \class_basename($factoryClass) . '<' . $name . '> factory(Collection|array|int $data = [])')
->ltrim("\n");
}

$class->setComment($comment->toString());
}

Expand Down