{"id":22814443,"url":"https://github.com/68publishers/smart-nette-component","last_synced_at":"2025-04-22T18:38:37.230Z","repository":{"id":56236239,"uuid":"191016508","full_name":"68publishers/smart-nette-component","owner":"68publishers","description":":bulb: Features for Nette Components and Presenters. Authorization via attributes, template resolving and overloading etc. ...","archived":false,"fork":false,"pushed_at":"2022-12-12T01:35:53.000Z","size":86,"stargazers_count":2,"open_issues_count":1,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-11-13T14:35:04.907Z","etag":null,"topics":["nette"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/68publishers.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-06-09T14:29:37.000Z","updated_at":"2022-12-12T09:21:59.000Z","dependencies_parsed_at":"2023-01-27T09:46:32.784Z","dependency_job_id":null,"html_url":"https://github.com/68publishers/smart-nette-component","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/68publishers%2Fsmart-nette-component","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/68publishers%2Fsmart-nette-component/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/68publishers%2Fsmart-nette-component/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/68publishers%2Fsmart-nette-component/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/68publishers","download_url":"https://codeload.github.com/68publishers/smart-nette-component/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":229388360,"owners_count":18065252,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["nette"],"created_at":"2024-12-12T13:08:56.655Z","updated_at":"2024-12-12T13:08:57.229Z","avatar_url":"https://github.com/68publishers.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003eSmart Nette Component\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003eThis package adds some useful features for Nette Presenters and Components, such as authorization for Presenters, their actions and signals using PHP8 attributes, authorization for component signals using attributes, and resolving of component template files.\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n\u003ca href=\"https://github.com/68publishers/smart-nette-component/actions\"\u003e\u003cimg alt=\"Checks\" src=\"https://badgen.net/github/checks/68publishers/smart-nette-component/master\"\u003e\u003c/a\u003e\n\u003ca href=\"https://coveralls.io/github/68publishers/smart-nette-component?branch=master\"\u003e\u003cimg alt=\"Coverage Status\" src=\"https://coveralls.io/repos/github/68publishers/smart-nette-component/badge.svg?branch=master\"\u003e\u003c/a\u003e\n\u003ca href=\"https://packagist.org/packages/68publishers/smart-nette-component\"\u003e\u003cimg alt=\"Total Downloads\" src=\"https://badgen.net/packagist/dt/68publishers/smart-nette-component\"\u003e\u003c/a\u003e\n\u003ca href=\"https://packagist.org/packages/68publishers/smart-nette-component\"\u003e\u003cimg alt=\"Latest Version\" src=\"https://badgen.net/packagist/v/68publishers/smart-nette-component\"\u003e\u003c/a\u003e\n\u003ca href=\"https://packagist.org/packages/68publishers/smart-nette-component\"\u003e\u003cimg alt=\"PHP Version\" src=\"https://badgen.net/packagist/php/68publishers/smart-nette-component\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n## Installation\n\nThe best way to install 68publishers/smart-nette-component is using Composer:\n\n```sh\n$ composer require 68publishers/smart-nette-component\n```\n\n## Authorization attributes\n\nTo use the authorization attributes, you need to register a compiler extension.\n\n```neon\nextensions:\n    component_authorization: SixtyEightPublishers\\SmartNetteComponent\\Bridge\\Nette\\DI\\ComponentAuthorizationExtension\n\n# The default configuration (you don't need to define it) is as follows:\ncomponent_authorization:\n    cache: %debugMode%\n    scanDirs:\n    \t- %appDir%\n    scanComposer: yes\n    scanFilters:\n    \t- *Presenter\n    \t- *Control\n    \t- *Component\n```\n\nAttributes can be cached when folding the DI container to avoid using reflection at runtime.\nThe extension will create a classmap and a map of all attributes automatically, it just needs to know where to look for Presenters and Components.\nThis is done with the `scanDirs`, `scanComposer` and `scanFilters` options, which behave similarly to [nette/application](https://doc.nette.org/en/application/configuration#toc-automatic-registration-of-presenters).\n\nNow add the following trait to your `BasePresenter` and `BaseControl`:\n\n```php\nuse Nette\\Application\\UI\\Presenter;\nuse SixtyEightPublishers\\SmartNetteComponent\\Bridge\\Nette\\Application\\AuthorizationTrait;\n\nabstract class BasePresenter extends Presenter\n{\n    use AuthorizationTrait;\n}\n```\n\n```php\nuse Nette\\Application\\UI\\Control;\nuse SixtyEightPublishers\\SmartNetteComponent\\Bridge\\Nette\\Application\\AuthorizationTrait;\n\nabstract class BaseControl extends Control\n{\n    use AuthorizationTrait;\n}\n```\n\nFrom now, you can use authorization attributes in your Presenters and Components:\n\n```php\nuse SixtyEightPublishers\\SmartNetteComponent\\Attribute\\LoggedIn;\nuse SixtyEightPublishers\\SmartNetteComponent\\Attribute\\Allowed;\n\n#[LoggedIn]\nfinal class AdminProductPresenter extends BasePresenter\n{\n    #[Allowed('product_resource', 'add')]\n    public function actionAdd(): void {}\n\n    #[Allowed('product_resource', 'delete')]\n    public function handleDelete(): void {}\n}\n```\n\n```php\nuse SixtyEightPublishers\\SmartNetteComponent\\Attribute\\LoggedIn;\nuse SixtyEightPublishers\\SmartNetteComponent\\Attribute\\Allowed;\n\nfinal class EditOrderControl extends BaseControl\n{\n    #[Allowed('order_resource', 'delete_item')]\n    public function handleDeleteItem(): void {}\n}\n```\n\nThe Presenter/Component throws the exception `SixtyEightPublishers\\SmartNetteComponent\\Exception\\ForbiddenRequestException` if any of the conditions in the attributes are not met.\n\nThe package includes the following attributes:\n\n- `Allowed`\n- `InRole`\n- `LoggedIn`\n- `LoggedOut`\n\nIf you would like to react somehow to the thrown exception, you can overwrite the `onForbiddenRequest()` method in a Presenter/Component.\n\n```php\nprotected function onForbiddenRequest(ForbiddenRequestException $exception): void\n{\n    # `$exception-\u003erule` contains failed attribute\n    \n    $this-\u003eflashMessage('You don\\'t have access here!', 'error');\n    $this-\u003eredirect('Homepage:');\n}\n```\n\n### Custom authorization attributes\n\nYou can register your own attributes in the following way:\n\n```php\nuse SixtyEightPublishers\\SmartNetteComponent\\Attribute\\AttributeInterface;\nuse SixtyEightPublishers\\SmartNetteComponent\\Authorization\\RuleInterface;\nuse SixtyEightPublishers\\SmartNetteComponent\\Authorization\\RuleHandlerInterface;\nuse SixtyEightPublishers\\SmartNetteComponent\\Exception\\ForbiddenRequestException;\n\nfinal class CustomRule implements AttributeInterface, RuleInterface\n{\n    # ...\n}\n\nfinal class CustomRuleHandler implements RuleHandlerInterface\n{\n    public function canHandle(RuleInterface $rule): bool\n    {\n        return $rule instanceof CustomRule;\n    }\n\n    public function __invoke(RuleInterface $rule): void\n    {\n        assert($rule instanceof CustomRule);\n\n        if (...) {\n            throw new ForbiddenRequestException($rule);\n        }\n    }\n}\n```\n\n```neon\nservices:\n    -\n        autowired: no\n        factory: CustomRuleHandler\n```\n\n## Template resolving\n\nYou don't need to register any compiler extension to use this feature, just use the `TemplateResolverTrait` trait in your BaseControl.\n\n```php\nuse Nette\\Application\\UI\\Control;\nuse SixtyEightPublishers\\SmartNetteComponent\\Bridge\\Nette\\Application\\TemplateResolverTrait;\n\nabstract class BaseControl extends Control\n{\n    use TemplateResolverTrait;\n}\n```\n\nThe base `render()` method is already declared in the trait.\nTo assign variables to the template, we can use the `beforeRender()` method.\nYou can also define custom `render*()` methods that are called for rendering using `{control myControl:foo}`.\n\n```php\nfinal class MyControl extends BaseControl\n{\n    protected function beforeRender(): void\n    {\n        # assign variables into the template here\n    }\n\n    public function renderFoo(): void\n    {\n        $this-\u003edoRender('foo');\n    }\n}\n```\n\nThe template for the base render method will be resolved as `COMPONENT_DIRECTORY/templates/myControl.latte` or `COMPONENT_DIRECTORY/templates/MyControl.latte`.\n\nThe template for the `foo` render method will be resolved as `COMPONENT_DIRECTORY/templates/foo.myControl.latte` or `COMPONENT_DIRECTORY/templates/foo.MyControl.latte`.\n\nOf course, you can set a template file manually:\n\n```php\nfinal class MyPresenter extends BasePresenter\n{\n    protected function createComponentMyControl() : FooControl\n    {\n        $control = $this-\u003emyControlFactory-\u003ecreate();\n\n        $control-\u003esetFile(__DIR__ . '/path/to/file.latte');\n        # or relatively from a component's directory:\n        $control-\u003esetRelativeFile('templates/new/myControl.latte');\n\n        # you can change the template for a specific render type:\n        $control-\u003esetFile(__DIR__ . '/path/to/myControl.latte', 'foo'); # template for `renderFoo()`\n\n        return $control;\n    }\n}\n```\n\n## Contributing\n\nBefore opening a pull request, please check your changes using the following commands\n\n```bash\n$ make init # to pull and start all docker images\n\n$ make cs.check\n$ make stan\n$ make tests.all\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F68publishers%2Fsmart-nette-component","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F68publishers%2Fsmart-nette-component","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F68publishers%2Fsmart-nette-component/lists"}