### Describe the Proposal Right now, code like this: ```php df() ->extract(/* */) ->partitionBy('order-year', 'order-month', 'order-name') ->load( to_csv(__DIR__.'/output/{order-name}.csv') ); ``` Would fail because `Path` doesn't allow patterns. ### API Adjustments ```php # UnixPath.php public function addPartitions(Partition $partition, Partition ...$partitions) : self { /** @var Partition[] $partitions */ $partitions = [$partition, ...$partitions]; // Here are first changes if ($this->isPathPattern($this->path) && [] === $partitions) { throw new InvalidArgumentException("Can't use partitions with non-pattern path."); } $pathInfo = \pathinfo($this->path); $dirname = $pathInfo['dirname'] ?? ''; $filename = $pathInfo['filename'] ?? ''; $extension = $pathInfo['extension'] ?? ''; // Here lies most of the "magic" if (str_starts_with($filename, '{') && str_ends_with($filename, '}')) { foreach ($partitions as $index => $partition) { if (!str_contains($filename, $partition->name)) { continue; } $filename = $partition->value; unset($partitions[$index]); } } $basename = $filename . '.' . $extension; if ($this->isPathPattern($basename)) { throw new InvalidArgumentException("Can't resolve path pattern."); } $partitionsString = \implode('/', \array_map(static fn (Partition $p) => $p->name . '=' . $p->value, $partitions)); return match ($dirname) { '', '.' => new self($this->protocol->scheme() . '/' . $partitionsString . '/' . $basename, $this->options), '/', '\\' => new self($this->protocol->scheme() . '/' . $partitionsString . '/' . $basename, $this->options), default => new self($this->protocol->scheme() . $dirname . '/' . $partitionsString . '/' . $basename, $this->options), }; } ``` ### Are you intending to also work on proposed change? Yes ### Are you interested in sponsoring this change? None ### Integration & Dependencies _No response_