diff --git a/src/Application/PresenterFactory.php b/src/Application/PresenterFactory.php index 00a8bb513..1c3208141 100644 --- a/src/Application/PresenterFactory.php +++ b/src/Application/PresenterFactory.php @@ -91,15 +91,59 @@ public function getPresenterClass(& $name) /** * Sets mapping as pairs [module => mask] + * @param array * @return self */ public function setMapping(array $mapping) { + $prefixPattern = '\\\\?([\w\\\\]*\\\\)?'; + $modulePattern = '[\w\\\\]*?\*\w*?\\\\'; + $presenterPattern = '([\w\\\\]*\*\w*)'; + foreach ($mapping as $module => $mask) { - if (!preg_match('#^\\\\?([\w\\\\]*\\\\)?(\w*\*\w*?\\\\)?([\w\\\\]*\*\w*)\z#', $mask, $m)) { - throw new Nette\InvalidStateException("Invalid mapping mask '$mask'."); + if (is_array($mask)) { + + $prefixPart = ''; + $modulePart = ''; + + if (count($mask) === 3) { + $prefixPart = $mask[0]; + $modulePart = $mask[1]; + $presenterPart = $mask[2]; + } elseif (count($mask) === 2) { + if (preg_match("#^{$prefixPattern}\\z#", $mask[0])) { + $prefixPart = $mask[0]; + $modulePart = ''; + } elseif (preg_match("#^{$modulePattern}\\z#", $mask[0])) { + $prefixPart = ''; + $modulePart = $mask[0]; + } + $presenterPart = $mask[1]; + } elseif (count($mask) === 1) { + $presenterPart = $mask[0]; + } else { + throw new Nette\InvalidStateException("Invalid length of mask array."); + } + + if (!preg_match("#^{$prefixPattern}\\z#", $prefixPart)) { + throw new Nette\InvalidStateException("Invalid prefix part of mask."); + } + + if (!preg_match("#^({$modulePattern})?\\z#", $modulePart)) { + throw new Nette\InvalidStateException("Invalid module part of mask."); + } + + if (!preg_match("#^{$presenterPattern}\\z#", $presenterPart)) { + throw new Nette\InvalidStateException("Invalid presenter part of mask."); + } + + $this->mapping[$module] = [$prefixPart, $modulePart, $presenterPart]; + } else { + if (!preg_match("#^{$prefixPattern}({$modulePattern})?{$presenterPattern}\\z#", $mask, $m)) { + throw new Nette\InvalidStateException("Invalid mapping mask '$mask'."); + } + $this->mapping[$module] = [$m[1], $m[2] ?: '*Module\\', $m[3]]; } - $this->mapping[$module] = [$m[1], $m[2] ?: '*Module\\', $m[3]]; } return $this; } diff --git a/tests/Application/PresenterFactory.formatPresenterClass.array.phpt b/tests/Application/PresenterFactory.formatPresenterClass.array.phpt new file mode 100644 index 000000000..53769408d --- /dev/null +++ b/tests/Application/PresenterFactory.formatPresenterClass.array.phpt @@ -0,0 +1,74 @@ +setMapping([ + '*' => ['App\\', 'Module\*\\', 'Presenter\*'], + ]); + Assert::same('App\Module\Jupiter\Presenter\RedDwarf', $factory->formatPresenterClass('Jupiter:RedDwarf')); + Assert::same('App\Module\Universe\Module\Jupiter\Presenter\RedDwarf', $factory->formatPresenterClass('Universe:Jupiter:RedDwarf')); +}); + +test(function () { + $factory = new PresenterFactory; + $factory->setMapping([ + '*' => ['App\\', '*\\', '*'], + ]); + Assert::same('App\Universe\Jupiter\RedDwarf', $factory->formatPresenterClass('Universe:Jupiter:RedDwarf')); +}); + +test(function () { + $factory = new PresenterFactory; + $factory->setMapping([ + '*' => ['*\\', '*'], + ]); + Assert::same('Jupiter\RedDwarf', $factory->formatPresenterClass('Jupiter:RedDwarf')); +}); + +test(function () { + $factory = new PresenterFactory; + $factory->setMapping([ + '*' => ['App\\', '*'], + ]); + Assert::same('App\RedDwarf', $factory->formatPresenterClass('RedDwarf')); +}); + +test(function () { + $factory = new PresenterFactory; + $factory->setMapping([ + '*' => ['App\\', 'Module\*Module\\', 'Presenter\*Presenter'], + ]); + Assert::same( + 'App\Module\JupiterModule\Presenter\RedDwarfPresenter', + $factory->formatPresenterClass('Jupiter:RedDwarf') + ); + Assert::same( + 'App\Module\UniverseModule\Module\JupiterModule\Presenter\RedDwarfPresenter', + $factory->formatPresenterClass('Universe:Jupiter:RedDwarf') + ); +}); + + +test(function () { + $factory = new PresenterFactory; + Assert::exception( + function () use ($factory) { + $factory->setMapping([ + '*' => ['Lister', 'Rimmer', 'Cat', 'Kryton'], + ]); + }, + Nette\InvalidStateException::class, + 'Invalid length of mask array.' + ); +}); diff --git a/tests/Application/PresenterFactory.formatPresenterClass.phpt b/tests/Application/PresenterFactory.formatPresenterClass.string.phpt similarity index 100% rename from tests/Application/PresenterFactory.formatPresenterClass.phpt rename to tests/Application/PresenterFactory.formatPresenterClass.string.phpt diff --git a/tests/Application/PresenterFactory.unformatPresenterClass.phpt b/tests/Application/PresenterFactory.unformatPresenterClass.string.phpt similarity index 100% rename from tests/Application/PresenterFactory.unformatPresenterClass.phpt rename to tests/Application/PresenterFactory.unformatPresenterClass.string.phpt