├── tests ├── Pest │ └── .gitkeep ├── Unit │ └── .gitkeep └── Playwright │ ├── fixtures │ ├── frontend │ │ ├── guest.js │ │ └── customer.js │ ├── adminhtml │ │ └── admin.js │ └── webapi_rest │ │ ├── self.js │ │ └── anonymous.js │ ├── .gitignore │ ├── playwright.config.js │ ├── helpers │ └── messages.js │ ├── README.md │ └── tests │ └── directives.spec.js ├── src ├── view │ ├── base │ │ ├── templates │ │ │ ├── magewire │ │ │ │ ├── flakes │ │ │ │ │ └── .gitkeep │ │ │ │ ├── features │ │ │ │ │ └── .gitkeep │ │ │ │ ├── utils │ │ │ │ │ └── icons │ │ │ │ │ │ └── loading.phtml │ │ │ │ └── ui-components │ │ │ │ │ └── notifier │ │ │ │ │ └── activity-state.phtml │ │ │ └── js │ │ │ │ ├── alpinejs │ │ │ │ ├── directives │ │ │ │ │ └── .gitkeep │ │ │ │ └── magewire.phtml │ │ │ │ └── magewire │ │ │ │ ├── state.phtml │ │ │ │ └── script.phtml │ │ └── web │ │ │ └── js │ │ │ └── manifest.json │ └── frontend │ │ ├── templates │ │ ├── magewire │ │ │ ├── utils │ │ │ │ └── .gitkeep │ │ │ ├── ui-components │ │ │ │ └── .gitkeep │ │ │ └── tests │ │ │ │ └── playwright │ │ │ │ └── directives │ │ │ │ ├── area │ │ │ │ ├── escape.phtml │ │ │ │ ├── render │ │ │ │ │ ├── child-child.phtml │ │ │ │ │ └── child.phtml │ │ │ │ └── render.phtml │ │ │ │ ├── scope.phtml │ │ │ │ └── base.phtml │ │ └── js │ │ │ ├── magewire │ │ │ ├── features │ │ │ │ └── .gitkeep │ │ │ └── directives │ │ │ │ └── .gitkeep │ │ │ ├── alpinejs │ │ │ └── directives │ │ │ │ └── .gitkeep │ │ │ └── alpinejs.phtml │ │ ├── tailwind │ │ └── tailwind.config.js │ │ └── layout │ │ └── default.xml ├── etc │ ├── module.xml │ ├── adminhtml │ │ ├── system.xml │ │ └── system │ │ │ ├── magewire │ │ │ ├── features.xml │ │ │ └── debug.xml │ │ │ └── magewire.xml │ ├── frontend │ │ ├── routes.xml │ │ └── events.xml │ ├── cache.xml │ ├── acl.xml │ ├── config.xml │ └── events.xml ├── Model │ ├── View │ │ ├── UtilsInterface.php │ │ ├── Fragment │ │ │ ├── Style.php │ │ │ ├── Javascript.php │ │ │ ├── Exceptions │ │ │ │ ├── EmptyFragmentException.php │ │ │ │ └── FragmentValidationException.php │ │ │ ├── Modifier │ │ │ │ └── Developer.php │ │ │ └── Script.php │ │ ├── Utils │ │ │ ├── Tailwind.php │ │ │ ├── Alpine.php │ │ │ ├── Application.php │ │ │ ├── Environment.php │ │ │ ├── Magewire │ │ │ │ ├── Builder.php │ │ │ │ └── Features.php │ │ │ ├── Security.php │ │ │ ├── Csp.php │ │ │ └── Fragment.php │ │ └── FragmentModifier.php │ ├── Magento │ │ └── System │ │ │ └── ConfigMagewireGroup.php │ ├── Magewire │ │ └── Notifier │ │ │ ├── NotificationTypeEnum.php │ │ │ └── NotificationStateEnum.php │ └── App │ │ ├── ExceptionHandler.php │ │ └── AbstractExceptionHandler.php ├── i18n │ └── en_US.csv ├── Exceptions │ ├── AcceptableException.php │ ├── RequestException.php │ ├── SilentException.php │ ├── BuilderException.php │ └── MagewirePageExpiredBecauseNewDeploymentHasSignificantEnoughChanges.php ├── Magewire │ └── Playwright │ │ └── Directives │ │ ├── Base.php │ │ ├── Scope.php │ │ └── Render.php ├── Controller │ ├── Playwright │ │ ├── Directives.php │ │ └── Resolvers.php │ ├── MagewireUpdateRouteFrontend.php │ └── Router.php ├── Observer │ └── ControllerActionPredispatch.php ├── registration.php └── Setup │ └── Patch │ └── Data │ └── EnableCache.php ├── .release-please-manifest.json ├── themes ├── Hyva │ ├── view │ │ └── frontend │ │ │ ├── tailwind │ │ │ ├── ui-components │ │ │ │ └── notifier.css │ │ │ ├── tailwind-source.css │ │ │ └── tailwind.config.js │ │ │ └── templates │ │ │ └── js │ │ │ ├── magewire │ │ │ ├── script.phtml │ │ │ └── features │ │ │ │ └── support-magento-flash-messages │ │ │ │ └── support-magento-flash-messages.phtml │ │ │ └── disable-alpinejs.phtml │ ├── etc │ │ ├── module.xml │ │ └── frontend │ │ │ └── events.xml │ ├── registration.php │ └── Magewire │ │ └── Features │ │ └── SupportMagewireCompiling │ │ └── View │ │ ├── Directive │ │ └── Hyva │ │ │ ├── Dialog.php │ │ │ └── SvgHeroIcon.php │ │ └── Action │ │ └── Hyva │ │ └── SvgIconViewAction.php ├── Luma │ ├── etc │ │ └── module.xml │ └── registration.php ├── Backend │ ├── etc │ │ └── module.xml │ └── registration.php └── Breeze │ ├── etc │ └── module.xml │ └── registration.php ├── .github ├── FUNDING.yml ├── workflows │ ├── release-please.yml │ └── portman.yml └── dependabot.yml ├── package.json ├── portman └── Livewire │ ├── Features │ ├── SupportRedirects │ │ ├── HandlesRedirects.php │ │ ├── Redirector.php │ │ └── SupportRedirects.php │ ├── SupportStreaming │ │ └── HandlesStreaming.php │ ├── SupportEvents │ │ └── Event.php │ └── SupportLocales │ │ └── SupportLocales.php │ ├── ComponentHook.php │ ├── Mechanisms │ └── ComponentRegistry.php │ ├── Drawer │ └── BaseUtils.php │ └── Concerns │ └── InteractsWithProperties.php ├── CHANGELOG.md ├── .gitignore ├── styles ├── magewire.css └── ui-component │ └── notifier.css ├── captainhook.json ├── lib ├── Magewire │ ├── Containers.php │ ├── Support │ │ ├── Str.php │ │ ├── Contracts │ │ │ └── DataTransferObjectInterface.php │ │ ├── Conditions │ │ │ └── ConditionEnum.php │ │ ├── DataScope │ │ │ ├── InvalidDataScopeException.php │ │ │ └── Compiler.php │ │ ├── Parser.php │ │ ├── Random.php │ │ ├── Concerns │ │ │ └── WithFactory.php │ │ └── Parser │ │ │ └── DomElementParser.php │ ├── Features │ │ ├── SupportMagewireRateLimiting │ │ │ ├── HandlesRateLimiting.php │ │ │ ├── Exceptions │ │ │ │ └── TooManyRequestsException.php │ │ │ ├── RateLimiterCache.php │ │ │ ├── RateLimiterStorageInterface.php │ │ │ ├── Config │ │ │ │ └── Source │ │ │ │ │ ├── RequestsScope.php │ │ │ │ │ └── RateLimitingVariant.php │ │ │ ├── RateLimiterExceptionHandler.php │ │ │ └── Storage │ │ │ │ └── RateLimiterCacheStorage.php │ │ ├── SupportMagewireCompiling │ │ │ ├── View │ │ │ │ ├── ViewAction.php │ │ │ │ ├── Precompiler.php │ │ │ │ ├── Action │ │ │ │ │ ├── Magewire.php │ │ │ │ │ └── Magento │ │ │ │ │ │ └── Auth.php │ │ │ │ ├── Directive │ │ │ │ │ ├── Parser │ │ │ │ │ │ ├── ConditionExpressionParser.php │ │ │ │ │ │ ├── IterationClauseExpressionParser.php │ │ │ │ │ │ └── ExpressionParser.php │ │ │ │ │ ├── Magento │ │ │ │ │ │ ├── Escape.php │ │ │ │ │ │ ├── Block.php │ │ │ │ │ │ └── Auth.php │ │ │ │ │ ├── Script.php │ │ │ │ │ ├── Base.php │ │ │ │ │ ├── Json.php │ │ │ │ │ └── Fragment.php │ │ │ │ ├── ScopeDirectiveChain.php │ │ │ │ ├── Management │ │ │ │ │ ├── CompileManager.php │ │ │ │ │ └── StubsManager.php │ │ │ │ ├── ScopeDirectiveParser.php │ │ │ │ ├── ViewStub.php │ │ │ │ ├── FunctionDirective.php │ │ │ │ └── ScopeDirective.php │ │ │ ├── Exception │ │ │ │ └── DirectiveExpressionParseException.php │ │ │ ├── HandlesMagewireCompiling.php │ │ │ └── MagewireUnderscoreViewModel.php │ │ ├── SupportMagewireViewInstructions │ │ │ ├── Handler │ │ │ │ ├── Type │ │ │ │ │ ├── FormHandler.php │ │ │ │ │ ├── FormInputHandler.php │ │ │ │ │ ├── DispatchHandler.php │ │ │ │ │ ├── DocumentHandler.php │ │ │ │ │ └── DomNodeHandler.php │ │ │ │ ├── TypeContext │ │ │ │ │ ├── HandlerTypeListeners.php │ │ │ │ │ ├── HandlerTypeMetaData.php │ │ │ │ │ ├── HandlerTypeTargets.php │ │ │ │ │ └── HandlerTypeInteractions.php │ │ │ │ └── HandlerTypeContext.php │ │ │ ├── ViewInstructionDoesNotExistException.php │ │ │ ├── Concern │ │ │ │ ├── WithNaming.php │ │ │ │ └── WithStacking.php │ │ │ ├── HandlesMagewireViewInstructions.php │ │ │ ├── Instructions │ │ │ │ ├── Action.php │ │ │ │ ├── Magento │ │ │ │ │ └── FlashMessage.php │ │ │ │ └── Notification.php │ │ │ └── ViewInstructionFactory.php │ │ ├── SupportMagentoLayouts │ │ │ └── SupportMagentoLayouts.php │ │ ├── SupportMagewireNotifications │ │ │ ├── SupportMagewireNotifications.php │ │ │ └── MagewireNotificationsFacade.php │ │ ├── SupportMagentoFlashMessages │ │ │ ├── FlashMessageType.php │ │ │ ├── FlashMessage.php │ │ │ └── SupportMagentoFlashMessages.php │ │ ├── SupportMagewireFlakes │ │ │ └── View │ │ │ │ ├── Fragment │ │ │ │ └── FlakeFragment.php │ │ │ │ └── Directive │ │ │ │ └── FlakeDirective.php │ │ ├── SupportMagewireLoaders │ │ │ ├── HandlesMagewireLoaders.php │ │ │ └── SupportMagewireLoaders.php │ │ ├── SupportMagewireViewModel │ │ │ ├── HandlesMagewireViewModel.php │ │ │ └── MagewireViewModel.php │ │ ├── SupportMagewireExceptionHandling │ │ │ └── SupportMagewireExceptionHandling.php │ │ └── SupportMagentoObserverEvents │ │ │ └── DTO │ │ │ └── ListenerDataTransferObject.php │ ├── Mechanisms │ │ ├── ResolveComponents │ │ │ ├── ComponentArguments │ │ │ │ ├── BlockMagewireArguments.php │ │ │ │ └── LayoutBlockArguments.php │ │ │ ├── ComponentResolverNotFoundException.php │ │ │ ├── ResolversCache.php │ │ │ └── ResolveComponentsViewModel.php │ │ ├── HandleComponents │ │ │ ├── DynamicPropertyProviderInterface.php │ │ │ ├── ComponentContext │ │ │ │ ├── Memo.php │ │ │ │ └── Effects.php │ │ │ └── CorruptComponentPayloadException.php │ │ ├── HandleRequests │ │ │ ├── ComponentContext │ │ │ │ └── EffectsInterface.php │ │ │ └── HandleRequestFacade.php │ │ └── FrontendAssets │ │ │ ├── FrontendAssetsFacade.php │ │ │ └── FrontendAssetsViewModel.php │ ├── Exceptions │ │ ├── ComponentNotFoundException.php │ │ └── RootTagMissingFromViewException.php │ ├── Mechanisms.php │ ├── Containers │ │ ├── Livewire.php │ │ └── Redirect.php │ ├── Features.php │ └── Concerns │ │ └── WithTagging.php ├── MagewireBc │ ├── Exception │ │ ├── ValidationException.php │ │ ├── AcceptableException.php │ │ └── MagewireException.php │ ├── Features │ │ └── SupportMagewireBackwardsCompatibility │ │ │ ├── HandlesFormComponentBackwardsCompatibility.php │ │ │ ├── SupportMagewireBackwardsCompatibility.php │ │ │ └── HandlesComponentBackwardsCompatibility.php │ └── Model │ │ ├── Concern │ │ └── BrowserEvent.php │ │ └── HydratorInterface.php ├── Symfony │ └── Component │ │ └── Console │ │ └── Command │ │ └── MagewireCommand.php └── Magento │ ├── Framework │ ├── Reflection │ │ └── TypeProcessor.php │ └── View │ │ └── BlockRenderingRegistry.php │ └── App │ └── Cache │ ├── Type │ └── Magewire.php │ └── MagewireCacheSection.php ├── release-please-config.json ├── dist ├── Exceptions │ ├── BypassViewHandler.php │ ├── ComponentNotFoundException.php │ ├── NonPublicComponentMethodCall.php │ ├── MethodNotFoundException.php │ ├── PropertyNotFoundException.php │ ├── MissingRulesException.php │ ├── ComponentAttributeMissingOnDynamicComponentException.php │ └── PublicPropertyNotFoundException.php ├── Features │ ├── SupportAttributes │ │ ├── AttributeLevel.php │ │ └── HandlesAttributes.php │ ├── SupportValidation │ │ └── BaseRule.php │ ├── SupportLockedProperties │ │ ├── CannotUpdateLockedPropertyException.php │ │ └── BaseLocked.php │ ├── SupportFormObjects │ │ └── HandlesFormObjects.php │ ├── SupportStreaming │ │ └── HandlesStreaming.php │ ├── SupportEvents │ │ ├── HandlesEvents.php │ │ ├── BaseOn.php │ │ └── Event.php │ ├── SupportLifecycleHooks │ │ └── DirectlyCallingLifecycleHooksNotAllowedException.php │ ├── SupportRedirects │ │ ├── HandlesRedirects.php │ │ └── Redirector.php │ └── SupportLocales │ │ └── SupportLocales.php ├── Attributes │ ├── Locked.php │ └── On.php ├── Mechanisms │ ├── Mechanism.php │ └── HandleComponents │ │ └── Synthesizers │ │ ├── IntSynth.php │ │ ├── FloatSynth.php │ │ ├── StdClassSynth.php │ │ └── EnumSynth.php ├── Transparency.php └── Pipe.php ├── SECURITY.md ├── rector.php └── LICENSE.md /tests/Pest/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/Unit/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/Playwright/fixtures/frontend/guest.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/view/base/templates/magewire/flakes/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/Playwright/fixtures/adminhtml/admin.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/Playwright/fixtures/webapi_rest/self.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/view/base/templates/magewire/features/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/view/frontend/templates/magewire/utils/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/Playwright/fixtures/webapi_rest/anonymous.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/view/base/templates/js/alpinejs/directives/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/view/frontend/templates/js/magewire/features/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.release-please-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | ".": "3.0.0-beta1" 3 | } -------------------------------------------------------------------------------- /src/view/frontend/templates/js/alpinejs/directives/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/view/frontend/templates/js/magewire/directives/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/view/frontend/templates/magewire/ui-components/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /themes/Hyva/view/frontend/tailwind/ui-components/notifier.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/view/base/web/js/manifest.json: -------------------------------------------------------------------------------- 1 | 2 | {"/magewire.js":"df3a17f2"} 3 | -------------------------------------------------------------------------------- /tests/Playwright/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | test-results/ 3 | .env 4 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: wpoortman 4 | -------------------------------------------------------------------------------- /src/view/frontend/templates/magewire/tests/playwright/directives/area/escape.phtml: -------------------------------------------------------------------------------- 1 |
2 | -------------------------------------------------------------------------------- /themes/Hyva/view/frontend/tailwind/tailwind-source.css: -------------------------------------------------------------------------------- 1 | @import url(ui-components/notifier.css); 2 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "@tailwindcss/cli": "^4.1.8", 4 | "tailwindcss": "^4.1.8" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /portman/Livewire/Features/SupportRedirects/HandlesRedirects.php: -------------------------------------------------------------------------------- 1 | 2 | Child's Child 3 | 4 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## [3.0.0-beta1](https://github.com/magewirephp/magewire/compare/main...v3.0.0-beta1) (2025-06-02) 4 | 5 | -------------------------------------------------------------------------------- /src/view/frontend/templates/magewire/tests/playwright/directives/area/render.phtml: -------------------------------------------------------------------------------- 1 |
2 | Parent 3 | 4 | @renderChild(alias: 'child') 5 |
6 | -------------------------------------------------------------------------------- /src/view/frontend/templates/magewire/tests/playwright/directives/area/render/child.phtml: -------------------------------------------------------------------------------- 1 |
2 | Child 3 | 4 | @renderChild(alias: 'child-child') 5 |
6 | -------------------------------------------------------------------------------- /themes/Hyva/view/frontend/tailwind/tailwind.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | content: [ 3 | '../../../../themes/Hyva/view/frontend/templates/**/*.phtml' 4 | ] 5 | }; 6 | -------------------------------------------------------------------------------- /portman/Livewire/Features/SupportRedirects/Redirector.php: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/etc/adminhtml/system.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /styles/magewire.css: -------------------------------------------------------------------------------- 1 | /* Minimal Tailwind CSS layers */ 2 | @import "tailwindcss" layer(utilities); 3 | 4 | /* UI Components */ 5 | @import "./ui-component/notifier.css"; 6 | 7 | /* Purge Sources */ 8 | @source "../src/view/base/templates/**/*.{phtml,js}"; 9 | @source "../src/view/frontend/templates/**/*.{phtml,js}"; 10 | -------------------------------------------------------------------------------- /src/view/frontend/tailwind/tailwind.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | content: [ 3 | '../../../../src/view/base/layout/**/*.xml', 4 | '../../../../src/view/base/templates/**/*.phtml', 5 | '../../../../src/view/frontend/layout/**/*.xml', 6 | '../../../../src/view/frontend/templates/**/*.phtml', 7 | ] 8 | }; 9 | -------------------------------------------------------------------------------- /captainhook.json: -------------------------------------------------------------------------------- 1 | { 2 | "commit-msg": { 3 | "enabled": true, 4 | "actions": [ 5 | { 6 | "action": "\\Ramsey\\CaptainHook\\ValidateConventionalCommit" 7 | } 8 | ] 9 | }, 10 | "pre-commit": { 11 | "enabled": true, 12 | "actions": [ 13 | { 14 | "action": "vendor/bin/portman build" 15 | } 16 | ] 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /lib/Magewire/Containers.php: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/etc/cache.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | Magewire cache 8 | 9 | 10 | -------------------------------------------------------------------------------- /themes/Luma/etc/module.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /lib/MagewireBc/Exception/ValidationException.php: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /themes/Breeze/etc/module.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /release-please-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "packages": { 3 | ".": { 4 | "changelog-path": "CHANGELOG.md", 5 | "bump-minor-pre-major": true, 6 | "release-type": "php", 7 | "bump-patch-for-minor-pre-major": false, 8 | "draft": false, 9 | "prerelease": true 10 | } 11 | }, 12 | "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json" 13 | } 14 | -------------------------------------------------------------------------------- /src/Exceptions/AcceptableException.php: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /lib/Magewire/Features/SupportMagewireCompiling/View/ViewAction.php: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /lib/Magewire/Features/SupportMagewireViewInstructions/Handler/Type/FormHandler.php: -------------------------------------------------------------------------------- 1 | stream($to, $content, $replace); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /lib/Magewire/Features/SupportMagewireRateLimiting/Exceptions/TooManyRequestsException.php: -------------------------------------------------------------------------------- 1 | 13 | 18 | -------------------------------------------------------------------------------- /lib/Magewire/Features/SupportMagewireNotifications/SupportMagewireNotifications.php: -------------------------------------------------------------------------------- 1 | instance(static::class, $this); 17 | } 18 | function boot() 19 | { 20 | // 21 | } 22 | } -------------------------------------------------------------------------------- /lib/Magewire/Features/SupportMagewireRateLimiting/RateLimiterCache.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /lib/Magewire/Features/SupportMagewireNotifications/MagewireNotificationsFacade.php: -------------------------------------------------------------------------------- 1 | items as $accessor => $mechanism) { 20 | $this->items[$accessor]['type']->boot(); 21 | } 22 | 23 | return $this; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/etc/adminhtml/system/magewire/features.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/etc/frontend/events.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /dist/Exceptions/NonPublicComponentMethodCall.php: -------------------------------------------------------------------------------- 1 | config; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /lib/Magewire/Features/SupportMagewireCompiling/View/Directive/Parser/ConditionExpressionParser.php: -------------------------------------------------------------------------------- 1 | $expression]; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /lib/Magewire/Features/SupportMagewireLoaders/HandlesMagewireLoaders.php: -------------------------------------------------------------------------------- 1 | loader; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Controller/Playwright/Directives.php: -------------------------------------------------------------------------------- 1 | $expression]; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /lib/Magewire/Features/SupportMagewireCompiling/View/ScopeDirectiveChain.php: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /dist/Exceptions/ComponentAttributeMissingOnDynamicComponentException.php: -------------------------------------------------------------------------------- 1 | property . ']'); 17 | } 18 | } -------------------------------------------------------------------------------- /lib/MagewireBc/Model/Concern/BrowserEvent.php: -------------------------------------------------------------------------------- 1 | dispatchQueue; 20 | } 21 | 22 | public function dispatchBrowserEvent($event, $data = null): void 23 | { 24 | $this->dispatchQueue[] = compact('event', 'data'); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/etc/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 0 10 | 11 | 12 | 0 13 | 4 14 | 5 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /dist/Exceptions/PublicPropertyNotFoundException.php: -------------------------------------------------------------------------------- 1 | getName()); 19 | } 20 | } -------------------------------------------------------------------------------- /lib/Magewire/Exceptions/RootTagMissingFromViewException.php: -------------------------------------------------------------------------------- 1 | component; 18 | } 19 | 20 | public function callMagewireConstruct(...$params): void 21 | { 22 | if (method_exists($this, 'magewireConstruct')) { 23 | $this->magewireConstruct(...$params); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | If you discover a security issue, please bring it to our attention right away! 4 | 5 | ## Reporting a Vulnerability 6 | 7 | Please **DO NOT** file a public issue to report a security vulberability, instead send your report privately to `magewirephp@wpoortman.nl`. This will help ensure that any vulnerabilities that are found can be [disclosed responsibly](https://en.wikipedia.org/wiki/Responsible_disclosure) to any affected parties. 8 | 9 | ## Supported Versions 10 | 11 | Project versions that are currently being supported with security updates vary per project. 12 | Please see specific project repositories for details. 13 | If nothing is specified, only the latest major versions are supported. -------------------------------------------------------------------------------- /lib/Magewire/Features/SupportMagewireCompiling/View/Management/CompileManager.php: -------------------------------------------------------------------------------- 1 | directiveManager; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /lib/Magewire/Support/Concerns/WithFactory.php: -------------------------------------------------------------------------------- 1 | create(static::class, $arguments); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /themes/Hyva/Magewire/Features/SupportMagewireCompiling/View/Directive/Hyva/Dialog.php: -------------------------------------------------------------------------------- 1 | name = $name; 20 | 21 | return $this; 22 | } 23 | 24 | public function getName(): ?string 25 | { 26 | return $this->name; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /dist/Features/SupportFormObjects/HandlesFormObjects.php: -------------------------------------------------------------------------------- 1 | all() as $key => $value) { 18 | if ($value instanceof Form) { 19 | $forms[] = $value; 20 | } 21 | } 22 | return $forms; 23 | } 24 | } -------------------------------------------------------------------------------- /themes/Hyva/view/frontend/templates/js/magewire/script.phtml: -------------------------------------------------------------------------------- 1 | getData('view_model'); 14 | $magewireUtility = $magewireViewModel->utils()->magewire(); 15 | ?> 16 | 21 | -------------------------------------------------------------------------------- /lib/Magewire/Features/SupportMagewireCompiling/View/ScopeDirectiveParser.php: -------------------------------------------------------------------------------- 1 | viewInstructions ??= ObjectManager::getInstance()->create(ViewInstructions::class); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Model/Magewire/Notifier/NotificationTypeEnum.php: -------------------------------------------------------------------------------- 1 | value; 23 | } 24 | 25 | public function getCssClass(): string 26 | { 27 | return 'notification-' . $this->value; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/etc/adminhtml/system/magewire.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 |
12 | 13 | advanced 14 | Magewirephp_Magewire::magewire 15 | 16 | 17 | 18 |
19 |
20 | -------------------------------------------------------------------------------- /themes/Hyva/view/frontend/templates/js/magewire/features/support-magento-flash-messages/support-magento-flash-messages.phtml: -------------------------------------------------------------------------------- 1 | getData('view_model'); 12 | $magewireFragment = $magewireViewModel->utils()->fragment(); 13 | ?> 14 | make()->script()->start() ?> 15 | 20 | end() ?> 21 | -------------------------------------------------------------------------------- /lib/Magewire/Mechanisms/HandleComponents/ComponentContext/Memo.php: -------------------------------------------------------------------------------- 1 | viewModel ??= ObjectManager::getInstance()->get(MagewireViewModel::class); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /dist/Features/SupportStreaming/HandlesStreaming.php: -------------------------------------------------------------------------------- 1 | stream($to, $content, $replace); 20 | } 21 | } -------------------------------------------------------------------------------- /src/view/frontend/templates/magewire/tests/playwright/directives/scope.phtml: -------------------------------------------------------------------------------- 1 |
2 |

3 | Scope 4 |

5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | @foreach(['a', 'b', 'c'] as $key => $value) 16 | 17 | 18 | 19 | 20 | @endforeach 21 | 22 |
KeyValue
23 |
24 | -------------------------------------------------------------------------------- /src/Exceptions/MagewirePageExpiredBecauseNewDeploymentHasSignificantEnoughChanges.php: -------------------------------------------------------------------------------- 1 | { 8 | await page.goto('/customer/account/login'); 9 | 10 | await page.fill('#email', process.env.ACCOUNT_EMAIL); 11 | await page.fill('#pass', process.env.ACCOUNT_PASSWORD); 12 | 13 | const button = page.locator('button[type="submit"]', { hasText: 'Sign In' }); 14 | await button.click(); 15 | 16 | await page.waitForURL('/customer/account/'); 17 | 18 | await use(page); 19 | } 20 | }); 21 | 22 | export { test }; 23 | -------------------------------------------------------------------------------- /dist/Features/SupportEvents/HandlesEvents.php: -------------------------------------------------------------------------------- 1 | listeners; 19 | } 20 | public function dispatch($event, ...$params) 21 | { 22 | $event = new Event($event, $params); 23 | store($this)->push('dispatched', $event); 24 | return $event; 25 | } 26 | } -------------------------------------------------------------------------------- /dist/Features/SupportLifecycleHooks/DirectlyCallingLifecycleHooksNotAllowedException.php: -------------------------------------------------------------------------------- 1 | handler()->data()->push('listeners', fn () => ['options' => $options], $event); 20 | 21 | return $this; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /styles/ui-component/notifier.css: -------------------------------------------------------------------------------- 1 | .magewire-notifier { 2 | @apply space-y-2 z-50 w-full fixed bottom-4 left-6 md:max-w-xs ml-2 mb-2 flex flex-col; 3 | } 4 | 5 | .magewire-notifier__notification { 6 | @apply pointer-events-auto relative w-full py-2 px-5 max-w-sm rounded-lg drop-shadow-md bg-white border-l-6 border-l-gray-600; 7 | } 8 | 9 | .magewire-notifier__notification-content { 10 | @apply flex items-center justify-between; 11 | } 12 | 13 | .magewire-notifier__notification-before { 14 | @apply flex items-center space-x-3; 15 | } 16 | 17 | .magewire-notifier__notification-text { 18 | 19 | } 20 | 21 | .magewire-notifier__notification-title { 22 | 23 | } 24 | 25 | .magewire-notifier__notification-message { 26 | 27 | } 28 | 29 | .magewire-notifier__notification-after { 30 | @apply flex items-center space-x-3; 31 | } 32 | -------------------------------------------------------------------------------- /lib/Magewire/Containers/Livewire.php: -------------------------------------------------------------------------------- 1 | message); 27 | } 28 | 29 | function getType(): FlashMessageType 30 | { 31 | return $this->type; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /lib/Magewire/Features/SupportMagewireCompiling/HandlesMagewireCompiling.php: -------------------------------------------------------------------------------- 1 | compiler = $compiler; 24 | } 25 | 26 | return $this->compiler; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/Magewire/Mechanisms/ResolveComponents/ResolveComponentsViewModel.php: -------------------------------------------------------------------------------- 1 | renderLifecycleManager->getLifecycle()) > 0; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /lib/Magewire/Features/SupportMagewireCompiling/View/Management/StubsManager.php: -------------------------------------------------------------------------------- 1 | collector->collect(); 26 | 27 | return $stubs[$namespace] ?? null; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /lib/Magewire/Features/SupportMagewireExceptionHandling/SupportMagewireExceptionHandling.php: -------------------------------------------------------------------------------- 1 | self::ISOLATED, 'label' => 'Isolated'], 24 | ['value' => self::SHARED, 'label' => 'Shared'] 25 | ]; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Observer/ControllerActionPredispatch.php: -------------------------------------------------------------------------------- 1 | magewireServiceProvider->setup(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/etc/adminhtml/system/magewire/debug.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 12 | 13 | 14 | 21 | 22 | Magento\Config\Model\Config\Source\Yesno 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /portman/Livewire/Features/SupportEvents/Event.php: -------------------------------------------------------------------------------- 1 | $this->name, 'params' => $this->params]; 20 | 21 | if ($this->self) { 22 | $output['self'] = true; 23 | } 24 | if ($this->component) { 25 | $output['to'] = app(ComponentRegistry::class)->getName($this->component); 26 | } 27 | 28 | return $output; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /lib/Magewire/Features/SupportMagewireViewModel/MagewireViewModel.php: -------------------------------------------------------------------------------- 1 | utils->$name($arguments) : $this->utils; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /rector.php: -------------------------------------------------------------------------------- 1 | withPaths([ 11 | realpath('dist'), 12 | ]) 13 | ->withRules([ 14 | ClassPropertyAssignToConstructorPromotionRector::class, 15 | ArraySpreadInsteadOfArrayMergeRector::class 16 | ]) 17 | ->withPhpSets( 18 | php82: true 19 | ) 20 | ->withPreparedSets( 21 | deadCode: true, 22 | codeQuality: true, 23 | codingStyle: true, 24 | typeDeclarations: true, 25 | ) 26 | ->withNoDiffs() 27 | //->withTypeCoverageLevel(Level::PHP_82) 28 | ->withImportNames( 29 | removeUnusedImports: true 30 | ); 31 | -------------------------------------------------------------------------------- /lib/Magewire/Mechanisms/HandleComponents/CorruptComponentPayloadException.php: -------------------------------------------------------------------------------- 1 | setData('application_state', $this->state); 27 | 28 | return $block; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /themes/Hyva/Magewire/Features/SupportMagewireCompiling/View/Action/Hyva/SvgIconViewAction.php: -------------------------------------------------------------------------------- 1 | icons->renderHtml($icon); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/Magewire/Features/SupportMagewireViewInstructions/Concern/WithStacking.php: -------------------------------------------------------------------------------- 1 | stackPosition = $position; 20 | 21 | return $this; 22 | } 23 | 24 | public function getStackPosition(): int 25 | { 26 | return $this->stackPosition; 27 | } 28 | 29 | public function resetStackPosition(): static 30 | { 31 | return $this->withStackPosition(100); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /lib/Magewire/Mechanisms/HandleRequests/ComponentContext/EffectsInterface.php: -------------------------------------------------------------------------------- 1 | 24 | getChildHtml() ?> 25 | -------------------------------------------------------------------------------- /dist/Features/SupportRedirects/HandlesRedirects.php: -------------------------------------------------------------------------------- 1 | set('redirect', $url); 19 | if ($navigate) { 20 | store($this)->set('redirectUsingNavigate', true); 21 | } 22 | $shouldSkipRender = !config('livewire.render_on_redirect', false); 23 | $shouldSkipRender && $this->skipRender(); 24 | } 25 | } -------------------------------------------------------------------------------- /lib/Magewire/Features.php: -------------------------------------------------------------------------------- 1 | items as $accessor => $feature) { 27 | $this->componentHookRegistry::register($this->items[$accessor]['type']); 28 | } 29 | 30 | $this->componentHookRegistry::boot(); 31 | return $this; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /lib/Magewire/Features/SupportMagentoObserverEvents/DTO/ListenerDataTransferObject.php: -------------------------------------------------------------------------------- 1 | */ 18 | private array $listeners = []; 19 | 20 | public function with(callable $callback): static 21 | { 22 | $this->listeners[] = $callback; 23 | 24 | return $this; 25 | } 26 | 27 | public function listeners(): array 28 | { 29 | return $this->listeners; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /lib/Magewire/Mechanisms/FrontendAssets/FrontendAssetsFacade.php: -------------------------------------------------------------------------------- 1 | mechanism->returnJavaScriptAsFile(); 26 | } 27 | 28 | function getMagewireScriptAttributes(): array 29 | { 30 | return $this->mechanism->getDataByPath('script.html_attributes', []); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/view/base/templates/js/magewire/state.phtml: -------------------------------------------------------------------------------- 1 | getData('view_model'); 14 | $magewireFragment = $magewireViewModel->utils()->fragment(); 15 | 16 | $state = $block->getData('state') ? 'active' : 'inactive'; 17 | 18 | /** @internal Do not modify to ensure Magewire continues to function correctly. */ 19 | ?> 20 | make()->script()->start() ?> 21 | 28 | end() ?> 29 | -------------------------------------------------------------------------------- /lib/Magewire/Features/SupportMagewireViewInstructions/Instructions/Action.php: -------------------------------------------------------------------------------- 1 | action = $action; 32 | 33 | return $this; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /portman/Livewire/Features/SupportLocales/SupportLocales.php: -------------------------------------------------------------------------------- 1 | localeResolver->getLocale(); 31 | $locale = strstr($code, '_', true); 32 | 33 | $context->addMemo('locale', $locale); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /dist/Features/SupportLocales/SupportLocales.php: -------------------------------------------------------------------------------- 1 | localeResolver->getLocale(); 23 | $locale = strstr($code, '_', true); 24 | $context->addMemo('locale', $locale); 25 | } 26 | function __construct(private readonly LocaleResolver $localeResolver) 27 | { 28 | // 29 | } 30 | } -------------------------------------------------------------------------------- /lib/Magewire/Features/SupportMagewireCompiling/View/Directive/Magento/Escape.php: -------------------------------------------------------------------------------- 1 | escapeUrl({$url}) ?>"; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /lib/Magewire/Features/SupportMagewireCompiling/View/ViewStub.php: -------------------------------------------------------------------------------- 1 | stub->getName(), '.stub')); 29 | } 30 | 31 | public function getContent(): string 32 | { 33 | return $this->content ??= file_get_contents($this->stub->getFilename()); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Model/View/Utils/Environment.php: -------------------------------------------------------------------------------- 1 | applicationState->getMode() === ApplicationState::MODE_DEVELOPER; 27 | } 28 | 29 | public function isProductionMode(): bool 30 | { 31 | return $this->applicationState->getMode() === ApplicationState::MODE_PRODUCTION; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/etc/events.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 9 | 10 | 11 | 12 | 15 | 16 | 17 | 18 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /lib/Magewire/Features/SupportMagewireCompiling/View/Directive/Script.php: -------------------------------------------------------------------------------- 1 | var('fragment')} = \$__magewire->utils()->fragment()->make()->script()->start() ?>"; 22 | } 23 | 24 | public function endscript(): string 25 | { 26 | return "var('fragment')}->end() ?>"; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/Magewire/Features/SupportMagewireRateLimiting/Config/Source/RateLimitingVariant.php: -------------------------------------------------------------------------------- 1 | self::COMPONENTS_ONLY, 'label' => 'Components only'], 25 | ['value' => self::REQUESTS_ONLY, 'label' => 'Requests only'], 26 | ['value' => self::NONE, 'label' => 'None'] 27 | ]; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /lib/Magewire/Features/SupportMagewireViewInstructions/Instructions/Magento/FlashMessage.php: -------------------------------------------------------------------------------- 1 | data()->set('args.text', $message->render()); 31 | return $this; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /.github/workflows/portman.yml: -------------------------------------------------------------------------------- 1 | name: 'Portman Build' 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - main 7 | paths: 8 | - 'portman/**' 9 | - 'src/**' 10 | - 'lib/**' 11 | 12 | permissions: 13 | contents: write 14 | pull-requests: write 15 | 16 | jobs: 17 | 18 | portman: 19 | runs-on: ubuntu-latest 20 | steps: 21 | - name: Checkout 22 | uses: actions/checkout@v4 23 | with: 24 | ref: ${{ github.head_ref }} 25 | token: ${{ secrets.MY_TOKEN }} 26 | 27 | - name: Setup php 28 | uses: shivammathur/setup-php@v2 29 | with: 30 | php-version: '8.2' 31 | 32 | - name: Install composer 33 | uses: ramsey/composer-install@v3 34 | with: 35 | composer-options: "--no-scripts" 36 | 37 | - name: Portman build 38 | run: ./vendor/bin/portman build 39 | 40 | - uses: stefanzweifel/git-auto-commit-action@v5 41 | with: 42 | commit_message: 'chore(portman) build' 43 | -------------------------------------------------------------------------------- /lib/Magewire/Features/SupportMagewireCompiling/View/Directive/Magento/Block.php: -------------------------------------------------------------------------------- 1 | getChildBlock({$alias}) ? \$block->getChildBlock({$alias})->toHtml() : '' ?>"; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /lib/Magewire/Features/SupportMagewireViewInstructions/Handler/TypeContext/HandlerTypeMetaData.php: -------------------------------------------------------------------------------- 1 | alias = $alias; 22 | 23 | return $this; 24 | } 25 | 26 | public function getAlias(): string|null 27 | { 28 | return $this->alias; 29 | } 30 | 31 | public function hasAlias(): bool 32 | { 33 | return is_string($this->alias); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /lib/Magewire/Containers/Redirect.php: -------------------------------------------------------------------------------- 1 | component = $component; 38 | 39 | return $this; 40 | } 41 | 42 | public function response($to) 43 | { 44 | // 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /lib/Magewire/Mechanisms/HandleComponents/ComponentContext/Effects.php: -------------------------------------------------------------------------------- 1 | setData($key, $value); 32 | } 33 | 34 | function exclude($key): static 35 | { 36 | return $this->unsetData($key); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Model/View/Utils/Magewire/Builder.php: -------------------------------------------------------------------------------- 1 | httpContext->getValue(Context::CONTEXT_AUTH); 28 | } 29 | 30 | public function isGuest(): bool 31 | { 32 | return ! $this->isCustomer(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /dist/Features/SupportEvents/BaseOn.php: -------------------------------------------------------------------------------- 1 | event) as $event) { 25 | store($this->component)->push('listenersFromAttributes', $this->getName() ?? '$refresh', $event); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /dist/Features/SupportAttributes/HandlesAttributes.php: -------------------------------------------------------------------------------- 1 | attributes ??= AttributeCollection::fromComponent($this); 18 | } 19 | function setPropertyAttribute($property, $attribute) 20 | { 21 | $attribute->__boot($this, AttributeLevel::PROPERTY, $property); 22 | $this->mergeOutsideAttributes(new AttributeCollection([$attribute])); 23 | } 24 | function mergeOutsideAttributes(AttributeCollection $attributes) 25 | { 26 | $this->attributes = $this->getAttributes()->concat($attributes); 27 | } 28 | } -------------------------------------------------------------------------------- /src/Model/View/Fragment/Modifier/Developer.php: -------------------------------------------------------------------------------- 1 | applicationState->getMode() === ApplicationState::MODE_DEVELOPER) { 28 | $fragment->withAttribute('magewire-fragment'); 29 | } 30 | 31 | return $fragment; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /lib/Magewire/Support/DataScope/Compiler.php: -------------------------------------------------------------------------------- 1 | $uses */ 18 | protected array $uses = []; 19 | 20 | abstract public function compile(DataScope $data): array|string; 21 | 22 | /** 23 | * Assign an additional dependency to be used by callable values requiring 24 | * access to global variables that are otherwise inaccessible during injection. 25 | */ 26 | public function use(string $name, object $object): static 27 | { 28 | $this->uses[$name] = $object; 29 | 30 | return $this; 31 | } 32 | 33 | protected function uses(): array 34 | { 35 | return $this->uses; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /lib/Magewire/Features/SupportMagewireCompiling/View/Directive/Base.php: -------------------------------------------------------------------------------- 1 | escapeHtml(__({$value})) ?>"; 24 | } 25 | 26 | return ""; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # MIT License 2 | 3 | Copyright © Willem Poortman 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /portman/Livewire/Features/SupportRedirects/SupportRedirects.php: -------------------------------------------------------------------------------- 1 | component($this->component); 17 | } 18 | 19 | public function dehydrate($context) 20 | { 21 | $to = $this->storeGet('redirect'); 22 | $usingNavigate = $this->storeGet('redirectUsingNavigate'); 23 | 24 | if ($to) { 25 | $context->addEffect('redirect', $to); 26 | } 27 | 28 | $usingNavigate && $context->addEffect('redirectUsingNavigate', true); 29 | 30 | if (! $context->isMounting()) { 31 | static::$atLeastOneMountedComponentHasRedirected = true; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /dist/Mechanisms/HandleComponents/Synthesizers/IntSynth.php: -------------------------------------------------------------------------------- 1 | getChildBlock('loader') 13 | ?> 14 |
15 |
16 |
17 | 18 | 19 |
22 | toHtml() ?> 23 |
24 | 25 |
26 |
27 |
28 | -------------------------------------------------------------------------------- /src/view/base/templates/js/alpinejs/magewire.phtml: -------------------------------------------------------------------------------- 1 | getData('view_model'); 12 | $magewireFragment = $magewireViewModel->utils()->fragment(); 13 | 14 | /** 15 | * AlpineJS - Global 16 | * 17 | * @internal Do not modify to ensure Magewire continues to function correctly. 18 | */ 19 | ?> 20 | make()->script()->start() ?> 21 | 32 | end() ?> 33 | -------------------------------------------------------------------------------- /tests/Playwright/helpers/messages.js: -------------------------------------------------------------------------------- 1 | import process from "process"; 2 | 3 | /** 4 | * Verifies whether the specified message was displayed as a flash message. 5 | */ 6 | export async function has(page, message) { 7 | await hasAny(page).then(async result => { 8 | if (result) { 9 | const messages = await page.$$eval('.messages div', elements => 10 | elements.map(el => el.textContent.trim()) 11 | ); 12 | 13 | if (messages.some(text => text.includes(message))) { 14 | return true; 15 | } 16 | } 17 | }) 18 | 19 | return false; 20 | } 21 | 22 | /** 23 | * Verifies whether there are any messages been shown. 24 | */ 25 | export async function hasAny(page) { 26 | const messages = page.locator('#messages'); 27 | 28 | if (messages.isVisible()) { 29 | const messages = await page.$$eval('.messages div', elements => 30 | elements.map(el => el.textContent.trim()) 31 | ); 32 | 33 | return messages.length !== 0; 34 | } 35 | 36 | return false; 37 | } 38 | -------------------------------------------------------------------------------- /dist/Mechanisms/HandleComponents/Synthesizers/FloatSynth.php: -------------------------------------------------------------------------------- 1 | getData('view_model'); 12 | $magewireFragment = $magewireViewModel->utils()->fragment(); 13 | ?> 14 | make()->script()->start() ?> 15 | 25 | end() ?> 26 | -------------------------------------------------------------------------------- /lib/Magewire/Mechanisms/HandleRequests/HandleRequestFacade.php: -------------------------------------------------------------------------------- 1 | mechanism->handleUpdate(); 32 | } 33 | 34 | function getUpdateUri(): string 35 | { 36 | return $this->mechanism->getUpdateUri(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /lib/MagewireBc/Features/SupportMagewireBackwardsCompatibility/HandlesComponentBackwardsCompatibility.php: -------------------------------------------------------------------------------- 1 | formKey->getFormKey(); 31 | } catch (LocalizedException $exception) { 32 | $this->logger->critical($exception->getMessage(), ['exception' => $exception]); 33 | } 34 | 35 | return 'unknown-csrf-token'; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Model/Magewire/Notifier/NotificationStateEnum.php: -------------------------------------------------------------------------------- 1 | value; 27 | } 28 | 29 | public function getCssClass(): string 30 | { 31 | return 'state-' . $this->value; 32 | } 33 | 34 | public function getLevel(): int 35 | { 36 | $level = array_search($this, self::cases(), true); 37 | return $level !== false ? $level : 0; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /tests/Playwright/README.md: -------------------------------------------------------------------------------- 1 | # Playwright 2 | 3 | ## Requirements 4 | 5 | - Magento Sample Data 6 | 7 | ## Install 8 | 9 | To run the Magewire Playwright tests, follow these steps: 10 | 11 | 1. Navigate into the Playwright tests directory: 12 | ```sh 13 | cd tests/Playwright 14 | ``` 15 | 16 | 2. Install all dev-dependencies 17 | ```sh 18 | npm install 19 | ``` 20 | 21 | 3. Create a `.env` config file in the root `Playwright` folder using the following variables: 22 | ```text 23 | BASE_URL=https://local.test/ 24 | 25 | ENVIRONMENT=local 26 | ACCOUNT_FIRSTNAME=Veronica 27 | ACCOUNT_LASTNAME=Costello 28 | ACCOUNT_EMAIL=roni_cost@example.com 29 | ACCOUNT_PASSWORD=roni_cost3@example.com 30 | ``` 31 | _Set the `BASE_URL` value with the `base-url` of your Magento instance._ 32 | 33 | 34 | 4. Run tests 35 | ```sh 36 | npm run test 37 | ``` 38 | 39 | 5. Run tests manually (optional) 40 | ```sh 41 | npx playwright test --ui 42 | ``` 43 | 44 | ## More details 45 | 46 | For more information about Playwright, please refer to [the documentation](https://playwright.dev/docs/intro). 47 | -------------------------------------------------------------------------------- /src/registration.php: -------------------------------------------------------------------------------- 1 | parser(ExpressionParserType::FUNCTION_ARGUMENTS)->parse($expression); 22 | 23 | // TODO: should handle exceptions, logging them and return an empty string when so. 24 | return method_exists($this, $directive) ? $this->$directive(...$parsed->arguments()->all()) : ''; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /lib/Magento/App/Cache/Type/Magewire.php: -------------------------------------------------------------------------------- 1 | get(self::TYPE_IDENTIFIER), self::CACHE_TAG); 27 | } 28 | 29 | public function load($identifier) 30 | { 31 | $data = parent::load($identifier); 32 | 33 | return is_string($data) ? $this->serializer->unserialize($data) : $data; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /lib/Magewire/Features/SupportMagewireViewInstructions/Handler/HandlerTypeContext.php: -------------------------------------------------------------------------------- 1 | handler(); 26 | } 27 | 28 | public function return(): HandlerType 29 | { 30 | return $this->also(); 31 | } 32 | 33 | public function only(array $arguments = []): HandlerType 34 | { 35 | return ObjectManager::getInstance()->create(get_class($this->handler()), $arguments); 36 | } 37 | 38 | protected function handler(): HandlerType 39 | { 40 | return $this->handler; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Model/App/AbstractExceptionHandler.php: -------------------------------------------------------------------------------- 1 | getMessage(), $exception->getCode(), $exception->getPrevious()); 22 | } 23 | 24 | return $exception; 25 | } 26 | 27 | function handleWithBlock(AbstractBlock $block, Exception $exception, bool $subsequent = false): AbstractBlock 28 | { 29 | if ($block instanceof Template) { 30 | $block->setTemplate('Magewirephp_Magewire::magewire/exception.phtml'); 31 | } 32 | 33 | return $block; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Model/View/Utils/Csp.php: -------------------------------------------------------------------------------- 1 | csp->isCspAvailable() 28 | ? $this->csp->getMagentoCspNonceProvider()->generateNonce() 29 | : ''; 30 | } 31 | 32 | public function generateNonceAttribute(string $format = ' %s'): string 33 | { 34 | return $this->csp->isCspAvailable() 35 | ? sprintf(sprintf($format, 'nonce="%s"'), $this->escaper->escapeHtmlAttr($this->generateNonce())) 36 | : ''; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /lib/Magento/Framework/View/BlockRenderingRegistry.php: -------------------------------------------------------------------------------- 1 | current = $block; 25 | $this->blocks[] = $block; 26 | 27 | return $this; 28 | } 29 | 30 | public function pop(): static 31 | { 32 | $this->previous = array_pop($this->blocks); 33 | 34 | return $this; 35 | } 36 | 37 | public function previous(): BlockInterface|null 38 | { 39 | return $this->previous; 40 | } 41 | 42 | public function current(): BlockInterface|null 43 | { 44 | return $this->current; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /lib/Magewire/Features/SupportMagewireCompiling/View/Directive/Parser/ExpressionParser.php: -------------------------------------------------------------------------------- 1 | arguments()->merge( 28 | strlen($content) === 0 ? [] : $this->parseArguments($content) 29 | ); 30 | 31 | return $this; 32 | } 33 | 34 | abstract protected function parseArguments(string $expression): array; 35 | 36 | public function arguments(): Arguments 37 | { 38 | return $this->arguments ??= $this->argumentsFactory->create(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /lib/Magewire/Features/SupportMagewireCompiling/View/Directive/Json.php: -------------------------------------------------------------------------------- 1 | parser(Directive\Parser\ExpressionParserType::FUNCTION_ARGUMENTS)->parse($expression)->arguments(); 25 | 26 | $value = $arguments->get('value', $arguments->get('default', [])); 27 | $flags = $arguments->get('flags', $this->encodingOptions); 28 | $depth = $arguments->get('depth', 512); 29 | 30 | return ""; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/view/frontend/templates/magewire/tests/playwright/directives/base.phtml: -------------------------------------------------------------------------------- 1 | 2 |
3 |

4 | Basics 5 |

6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 |
DirectiveInputResultExpected
translatefoo@translate(value: 'foo', escape: false)foo
translate (escaped)bar@translate(value: 'bar')bar
33 |
34 | -------------------------------------------------------------------------------- /src/Controller/MagewireUpdateRouteFrontend.php: -------------------------------------------------------------------------------- 1 | fn (Request $request): bool => $request->isPost(), 24 | 'update_uri' => fn (Request $request): bool => str_starts_with($request->getPathInfo(), '/magewire/update'), 25 | 'content_type' => fn (Request $request): bool => $request->getHeader('Content-Type') === 'application/json' 26 | ]; 27 | } 28 | 29 | public function createAction(RequestInterface $request): ActionInterface 30 | { 31 | return $this->actionFactory()->create(Update::class); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /dist/Transparency.php: -------------------------------------------------------------------------------- 1 | target; 19 | } 20 | function offsetExists(mixed $offset): bool 21 | { 22 | return isset($this->target[$offset]); 23 | } 24 | function offsetGet(mixed $offset): mixed 25 | { 26 | return $this->target[$offset]; 27 | } 28 | function offsetSet(mixed $offset, mixed $value): void 29 | { 30 | $this->target[$offset] = $value; 31 | } 32 | function offsetUnset(mixed $offset): void 33 | { 34 | unset($this->target[$offset]); 35 | } 36 | function getIterator(): Traversable 37 | { 38 | return (function () { 39 | foreach ($this->target as $key => $value) { 40 | yield $key => $value; 41 | } 42 | })(); 43 | } 44 | } -------------------------------------------------------------------------------- /portman/Livewire/Mechanisms/ComponentRegistry.php: -------------------------------------------------------------------------------- 1 | getNameAndClass($nameOrClass); 18 | 19 | $component = new $class; 20 | 21 | $component->setId($id ?: str()->random(20)); 22 | 23 | $component->setName($name); 24 | 25 | // // Parameters passed in automatically set public properties by the same name... 26 | // foreach ($params as $key => $value) { 27 | // if (! property_exists($component, $key)) continue; 28 | 29 | // // Typed properties shouldn't be set back to "null". It will throw an error... 30 | // if ((new \ReflectionProperty($component, $key))->getType() && is_null($value)) continue; 31 | 32 | // $component->$key = $value; 33 | // } 34 | 35 | return $component; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /lib/Magewire/Features/SupportMagewireRateLimiting/RateLimiterExceptionHandler.php: -------------------------------------------------------------------------------- 1 | setBody('Too Many Requests.'); 25 | $response->setHttpResponseCode(429); 26 | 27 | return $response; 28 | }; 29 | } 30 | 31 | return $exception; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /dist/Pipe.php: -------------------------------------------------------------------------------- 1 | target = $target; 18 | } 19 | function __invoke(...$params) 20 | { 21 | if (empty($params)) { 22 | return $this->target; 23 | } 24 | [$before, $through, $after] = [[], null, []]; 25 | foreach ($params as $key => $param) { 26 | if (!$through) { 27 | if (is_callable($param)) { 28 | $through = $param; 29 | } else { 30 | $before[$key] = $param; 31 | } 32 | } else { 33 | $after[$key] = $param; 34 | } 35 | } 36 | $params = [...$before, $this->target, ...$after]; 37 | $this->target = $through(...$params); 38 | return $this; 39 | } 40 | } -------------------------------------------------------------------------------- /lib/Magewire/Features/SupportMagewireCompiling/View/Directive/Magento/Auth.php: -------------------------------------------------------------------------------- 1 | action('magento.auth')->execute('is_customer')): ?>"; 22 | } 23 | 24 | public function endauth(): string 25 | { 26 | return parent::endif(); 27 | } 28 | 29 | #[ScopeDirectiveChain(methods: ['endguest'])] 30 | public function guest(): string 31 | { 32 | return "action('magento.auth')->execute('is_guest')): ?>"; 33 | } 34 | 35 | public function endguest(): string 36 | { 37 | return parent::endif(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Model/View/Fragment/Script.php: -------------------------------------------------------------------------------- 1 | withValidator(fn ($script) => str_starts_with($script, 'withValidator(fn ($script) => str_ends_with($script, '')); 23 | } 24 | 25 | /** 26 | * Returns the content between the script tags. 27 | */ 28 | public function getScriptCode(): string 29 | { 30 | if (is_string($this->code)) { 31 | return $this->code; 32 | } 33 | 34 | $start = strpos($this->raw, '>'); 35 | $end = strrpos($this->raw, '<'); 36 | 37 | if ($start !== false && $end !== false && $start < $end) { 38 | $this->code = trim(substr($this->raw, $start + 1, $end - $start - 1)); 39 | } 40 | 41 | return $this->code ?? ''; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /dist/Mechanisms/HandleComponents/Synthesizers/StdClassSynth.php: -------------------------------------------------------------------------------- 1 | $child) { 24 | $data[$key] = $dehydrateChild($key, $child); 25 | } 26 | return [$data, []]; 27 | } 28 | function hydrate($value, $meta, $hydrateChild) 29 | { 30 | $obj = new stdClass(); 31 | foreach ($value as $key => $child) { 32 | $obj->{$key} = $hydrateChild($key, $child); 33 | } 34 | return $obj; 35 | } 36 | function set(&$target, $key, $value) 37 | { 38 | $target->{$key} = $value; 39 | } 40 | } -------------------------------------------------------------------------------- /lib/Magewire/Features/SupportMagewireCompiling/View/Directive/Fragment.php: -------------------------------------------------------------------------------- 1 | var('fragment')} = \$__magewire->utils()->fragment()->make({$type})->start() ?>"; 25 | } 26 | 27 | public function endfragment(): string 28 | { 29 | return "var('fragment')}->end() ?>"; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/view/frontend/layout/default.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 18 | 19 | 20 | 21 | 22 | 23 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /themes/Hyva/Magewire/Features/SupportMagewireCompiling/View/Directive/Hyva/SvgHeroIcon.php: -------------------------------------------------------------------------------- 1 | parser(ExpressionParserType::FUNCTION_ARGUMENTS)->parse($expression); 23 | 24 | $arguments = $parsed->arguments()->unset('type'); 25 | $arguments->default('version', 'outlined'); 26 | 27 | return "action('hyva.svg-icons')->execute('heroicon', {$arguments->renderAsNamed()}) ?>"; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /lib/Magewire/Features/SupportMagewireCompiling/MagewireUnderscoreViewModel.php: -------------------------------------------------------------------------------- 1 | actionManager->load($class); 31 | } 32 | 33 | public function arguments(): DataScope 34 | { 35 | return $this->arguments; 36 | } 37 | 38 | public function utils(): Utils 39 | { 40 | return $this->utils; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /lib/Magewire/Features/SupportMagewireViewInstructions/Handler/TypeContext/HandlerTypeTargets.php: -------------------------------------------------------------------------------- 1 | query = $this->builder?->__toString(); 28 | // 29 | // return $this; 30 | // } 31 | 32 | // public function query(): QueryBuilder 33 | // { 34 | // return $this->builder ??= ObjectManager::getInstance()->create(QueryBuilder::class, [ 35 | // 'context' => $this 36 | // ]); 37 | // } 38 | 39 | public function __toString(): string 40 | { 41 | return $this->query ?? ''; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /dist/Mechanisms/HandleComponents/Synthesizers/EnumSynth.php: -------------------------------------------------------------------------------- 1 | value, ['class' => get_class($target)]]; 33 | } 34 | function hydrate($value, $meta) 35 | { 36 | if ($value === null || $value === '') { 37 | return null; 38 | } 39 | $class = $meta['class']; 40 | return $class::from($value); 41 | } 42 | } -------------------------------------------------------------------------------- /lib/Magewire/Features/SupportMagewireCompiling/View/ScopeDirective.php: -------------------------------------------------------------------------------- 1 | scopeResponsibilities[$directive] ?? null)) { 25 | $reflection = new ReflectionClass($this); 26 | 27 | foreach ($reflection->getMethods() as $method) { 28 | $attributes = $method->getAttributes(ScopeDirectiveChain::class); 29 | $attribute = ($attributes[0] ?? null) ? $attributes[0]->newInstance() : null; 30 | 31 | if ($attribute) { 32 | $this->scopeResponsibilities[$method->getName()] = $attribute->methods; 33 | } 34 | } 35 | } 36 | 37 | return $this->scopeResponsibilities[$directive] ?? []; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /lib/Magewire/Features/SupportMagewireViewInstructions/ViewInstructionFactory.php: -------------------------------------------------------------------------------- 1 | $instructions 19 | */ 20 | public function __construct( 21 | private readonly array $instructions = [] 22 | ) { 23 | // 24 | } 25 | 26 | /** 27 | * @template T of ViewInstruction 28 | * @param class-string $instruction 29 | * @return T 30 | * @throws ViewInstructionDoesNotExistException 31 | */ 32 | public function create(string $instruction): ViewInstruction 33 | { 34 | if (array_key_exists($instruction, $this->instructions)) { 35 | return $this->instructions[$instruction]; 36 | } 37 | if (class_exists($instruction)) { 38 | return ObjectManager::getInstance()->create($instruction); 39 | } 40 | 41 | throw new ViewInstructionDoesNotExistException(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /portman/Livewire/Drawer/BaseUtils.php: -------------------------------------------------------------------------------- 1 | getDeclaringClass()->getName() !== \Magewirephp\Magewire\Component::class; 19 | }); 20 | } 21 | 22 | static function getPublicMethodsDefinedBySubClass($target) 23 | { 24 | $methods = array_filter((new \ReflectionObject($target))->getMethods(), function ($method) { 25 | $isInBaseComponentClass = $method->getDeclaringClass()->getName() === \Livewire\Component::class; 26 | 27 | return $method->isPublic() 28 | && ! $method->isStatic() 29 | && ! $isInBaseComponentClass; 30 | }); 31 | 32 | return array_map(function ($method) { 33 | return $method->getName(); 34 | }, $methods); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /lib/Magewire/Features/SupportMagewireViewInstructions/Handler/TypeContext/HandlerTypeInteractions.php: -------------------------------------------------------------------------------- 1 | handler()->listen()->for('click'); 21 | 22 | return $this; 23 | } 24 | 25 | public function onDoubleClick(): static 26 | { 27 | $this->handler()->listen()->for('dblclick'); 28 | 29 | return $this; 30 | } 31 | 32 | public function onMouseOver(): static 33 | { 34 | $this->handler()->listen()->for('mouseover'); 35 | 36 | return $this; 37 | } 38 | 39 | public function onMouseOut(): static 40 | { 41 | $this->handler()->listen()->for('mouseout'); 42 | 43 | return $this; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /lib/Magewire/Features/SupportMagewireFlakes/View/Directive/FlakeDirective.php: -------------------------------------------------------------------------------- 1 | action('magewire.flake')->execute( 28 | 'create', 29 | flake: \$decoded['flake'], 30 | data: \$decoded['data'] ?? [], 31 | metadata: \$decoded['metadata'] ?? [], 32 | variables: \$variables 33 | ); 34 | 35 | unset(\$decoded, \$fragment, \$variables); 36 | ?> 37 | DIRECTIVE; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Setup/Patch/Data/EnableCache.php: -------------------------------------------------------------------------------- 1 | cacheManager->setEnabled( 41 | array_intersect($this->cacheManager->getAvailableTypes(), [MagewireCacheType::TYPE_IDENTIFIER]), 42 | true 43 | ); 44 | 45 | $this->cacheManager->clean($enableMagewireCache); 46 | return $this; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /lib/Magento/App/Cache/MagewireCacheSection.php: -------------------------------------------------------------------------------- 1 | tags)) { 33 | $this->tags[] = $this->identifier; 34 | } 35 | 36 | return $this->magewireCacheType->save($this->serializer->serialize($data), $this->identifier, $this->tags, $ttl ?? $this->ttl); 37 | } 38 | 39 | public function fetch(): array 40 | { 41 | $data = $this->magewireCacheType->load($this->identifier); 42 | 43 | return ! $data ? [] : $data; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /lib/Magewire/Features/SupportMagentoFlashMessages/SupportMagentoFlashMessages.php: -------------------------------------------------------------------------------- 1 | component->hasFlashMessages()) { 21 | $context->pushEffect('dispatches', [ 22 | 'name' => 'magewire:flash-messages:dispatch', 23 | 'params' => $this->mapFlashMessages($this->component->getFlashMessages()) 24 | ]); 25 | } 26 | } 27 | 28 | /** 29 | * @param array $messages 30 | */ 31 | private function mapFlashMessages(array $messages): array 32 | { 33 | return array_map(static function (FlashMessage $message) { 34 | return [ 35 | 'text' => $message->getMessage()->render(), 36 | 'type' => $message->getType() 37 | ]; 38 | }, $messages); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Model/View/Utils/Magewire/Features.php: -------------------------------------------------------------------------------- 1 | featuresServiceType->viewModel($utility); 35 | } catch (NotFoundException $exception) { 36 | $this->logger->critical($exception->getMessage(), ['exception' => $exception]); 37 | 38 | throw new BadMethodCallException( 39 | sprintf('Feature view model "%1" does not exist.', $utility) 40 | ); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /dist/Features/SupportRedirects/Redirector.php: -------------------------------------------------------------------------------- 1 | component->redirect($this->generator->to($path, [], $secure)); 20 | return $this; 21 | } 22 | public function away($path, $status = 302, $headers = []) 23 | { 24 | return $this->to($path, $status, $headers); 25 | } 26 | public function with($key, $value = null) 27 | { 28 | $key = is_array($key) ? $key : [$key => $value]; 29 | foreach ($key as $k => $v) { 30 | $this->session->flash($k, $v); 31 | } 32 | return $this; 33 | } 34 | public function component(Component $component) 35 | { 36 | $this->component = $component; 37 | return $this; 38 | } 39 | public function response($to) 40 | { 41 | return $this->createRedirect($to, 302, []); 42 | } 43 | } -------------------------------------------------------------------------------- /lib/Magewire/Mechanisms/FrontendAssets/FrontendAssetsViewModel.php: -------------------------------------------------------------------------------- 1 | frontendAssetsMechanism->returnJavaScriptAsFile(); 29 | } 30 | 31 | function getScriptAttributes(): string 32 | { 33 | $attributes = $this->frontendAssetsMechanism->getDataByPath('script.html_attributes', []); 34 | 35 | return implode(' ', array_map(function ($attribute, ?string $expression) { 36 | return $expression === null ? $attribute : sprintf('%s="%s"', $attribute, $this->escaper->escapeHtmlAttr($expression)); 37 | }, array_keys($attributes), array_values($attributes))); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /lib/Magewire/Features/SupportMagewireLoaders/SupportMagewireLoaders.php: -------------------------------------------------------------------------------- 1 | component->getLoader(); 22 | 23 | if ($loader) { 24 | if (is_array($loader)) { 25 | $loader = map_with_keys(function ($value, $key) { 26 | if (is_string($value)) { 27 | $value = [$value]; 28 | } 29 | if (is_array($value)) { 30 | $value = array_map('__', array_filter($value, 'is_string')); 31 | } 32 | 33 | return [$key => $value]; 34 | }, $loader); 35 | } elseif (is_string($loader)) { 36 | $loader = __($loader); 37 | } 38 | 39 | $context->pushEffect('loader', $loader); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Controller/Router.php: -------------------------------------------------------------------------------- 1 | matchesMagewireSpecifics($request)) { 33 | foreach (array_filter($this->routes) as $route) { 34 | if ($result = $route->match($request)) { 35 | return $result; 36 | } 37 | } 38 | } 39 | 40 | return null; 41 | } 42 | 43 | private function matchesMagewireSpecifics(RequestInterface $request): bool 44 | { 45 | return $request instanceof Request && $this->magewireRouteValidator->validate($request); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /portman/Livewire/Concerns/InteractsWithProperties.php: -------------------------------------------------------------------------------- 1 | {Utils::beforeFirstDot($name)}; 26 | 27 | if (Utils::containsDots($name)) { 28 | return data_get($value, Utils::afterFirstDot($name)); 29 | } 30 | 31 | return $value; 32 | } 33 | 34 | function fill($values) 35 | { 36 | $publicProperties = array_keys($this->all()); 37 | 38 | if ($values instanceof DataObject) { 39 | $values = $values->toArray(); 40 | } 41 | 42 | foreach ($values as $key => $value) { 43 | if (in_array(Utils::beforeFirstDot($key), $publicProperties)) { 44 | data_set($this, $key, $value); 45 | } 46 | } 47 | } 48 | 49 | function all() 50 | { 51 | return Utils::getPublicPropertiesDefinedOnSubclass($this); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /tests/Playwright/tests/directives.spec.js: -------------------------------------------------------------------------------- 1 | import { expect } from '@playwright/test' 2 | import { test } from '../fixtures/frontend/customer.js'; 3 | import { logout } from "../helpers/customer/account"; 4 | 5 | test.describe('Directives', () => { 6 | /* 7 | * Runs before each individual test. 8 | */ 9 | test.beforeEach(async ({ page, magentoCustomerDashboard }) => { 10 | const pageVersion = Math.floor(Math.random() * 10000); 11 | 12 | await magentoCustomerDashboard.goto(`/magewire/playwright/directives?v=${pageVersion}`); 13 | }); 14 | 15 | /* 16 | * Runs after each individual test. 17 | */ 18 | test.afterEach(async ({ page }) => { 19 | await logout(page) 20 | }); 21 | 22 | test('Check Page Title', async ({ page }) => { 23 | const title = page.locator('[data-ui-id="page-title-wrapper"]'); 24 | 25 | await expect(title).toHaveText('Magewire / Playwright / Directives'); 26 | }) 27 | 28 | test('Check Base Directives', async ({ page }) => { 29 | const table = page.locator('[wire\\:id="magewire.playwright.directives.base"]'); 30 | await expect(table).toBeVisible(); 31 | 32 | const rows = await table.locator('tbody tr').all(); 33 | expect(rows).toHaveLength(2) 34 | 35 | for (const row of rows) { 36 | const cells = await row.locator('td').allInnerTexts(); 37 | 38 | expect(cells[2]).toBe(cells[3]); 39 | } 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /lib/Magewire/Features/SupportMagewireRateLimiting/Storage/RateLimiterCacheStorage.php: -------------------------------------------------------------------------------- 1 | cache->fetch(); 29 | 30 | return $storage[$key] ?? []; 31 | } 32 | 33 | public function set(string $key, array $data, int|null $ttl = null): bool 34 | { 35 | $storage = $this->cache->fetch(); 36 | $storage[$key] = $data; 37 | 38 | return $this->cache->save($storage, $ttl); 39 | } 40 | 41 | public function unset(string $key): bool 42 | { 43 | $storage = $this->cache->fetch(); 44 | unset($storage[$key]); 45 | 46 | return $this->cache->save($storage); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /lib/Magewire/Features/SupportMagewireViewInstructions/Instructions/Notification.php: -------------------------------------------------------------------------------- 1 | data()->set('args.text', $message->render()); 31 | return $this; 32 | } 33 | 34 | public function withDelay(int|null $delay): static 35 | { 36 | $this->data()->set('args.delay', $delay); 37 | return $this; 38 | } 39 | 40 | public function withTitle(Phrase|null $title): static 41 | { 42 | $this->data()->set('args.title', $title); 43 | return $this; 44 | } 45 | 46 | public function withType(string|null $type): static 47 | { 48 | $this->data()->set('args.type', $type); 49 | return $this; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/Model/View/Utils/Fragment.php: -------------------------------------------------------------------------------- 1 | types (e.g., 'header', 'footer') 30 | * 2. Direct class names 31 | * 32 | * @param string|null $name 33 | * @return \Magewirephp\Magewire\Model\View\Fragment|FragmentFactory 34 | * @throws InvalidArgumentException 35 | * 36 | * @see FragmentFactory::$types For registering custom fragment types via DI 37 | */ 38 | public function make(string|null $name = null): FragmentFactory|\Magewirephp\Magewire\Model\View\Fragment 39 | { 40 | if ($name) { 41 | return $this->fragmentFactory->custom($name); 42 | } 43 | 44 | return $this->fragmentFactory; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /lib/Magewire/Concerns/WithTagging.php: -------------------------------------------------------------------------------- 1 | */ 16 | private array $tags = []; 17 | 18 | /** 19 | * Tag a fragment with a recognizable name. 20 | */ 21 | public function tag(string $name): static 22 | { 23 | $sanitized = preg_replace('/[^a-z0-9]/', '', strtolower($name)); 24 | 25 | if ($sanitized !== '') { 26 | $this->tags[] = $sanitized; 27 | } 28 | 29 | return $this; 30 | } 31 | 32 | /** 33 | * Clears all tags either completely or by a provided filter callback. 34 | */ 35 | public function clearTags(callable|null $filter = null): static 36 | { 37 | $this->tags = $filter ? array_filter($this->tags, $filter) : []; 38 | 39 | return $this; 40 | } 41 | 42 | /** 43 | * Returns if the given tag exists. 44 | */ 45 | public function hasTag(string $name): bool 46 | { 47 | return is_string($this->tags[$name] ?? null); 48 | } 49 | 50 | /** 51 | * Returns if any tags were set. 52 | */ 53 | public function hasTags(): bool 54 | { 55 | return count($this->tags) > 0; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /lib/Magewire/Support/Parser/DomElementParser.php: -------------------------------------------------------------------------------- 1 | attributes()->set($match[1], $match[3]); 41 | } 42 | 43 | return $this; 44 | } 45 | 46 | public function attributes(): DataArray 47 | { 48 | return $this->attributes ??= $this->attributesFactory->create(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /dist/Features/SupportEvents/Event.php: -------------------------------------------------------------------------------- 1 | name = $name; 23 | $this->params = $params; 24 | } 25 | public function self() 26 | { 27 | $this->self = true; 28 | return $this; 29 | } 30 | public function component($name) 31 | { 32 | $this->component = $name; 33 | return $this; 34 | } 35 | public function to($name) 36 | { 37 | return $this->component($name); 38 | } 39 | public function serialize() 40 | { 41 | $output = ['name' => $this->name, 'params' => $this->params]; 42 | if ($this->self) { 43 | $output['self'] = true; 44 | } 45 | if ($this->component) { 46 | $output['to'] = app(ComponentRegistry::class)->getName($this->component); 47 | } 48 | return $output; 49 | } 50 | } --------------------------------------------------------------------------------