{"id":18773126,"url":"https://github.com/webfactory/webfactorylegacyintegrationbundle","last_synced_at":"2025-04-13T09:07:16.025Z","repository":{"id":12616468,"uuid":"15287622","full_name":"webfactory/WebfactoryLegacyIntegrationBundle","owner":"webfactory","description":"A battle-proven approach to facilitate the incremental migration of legacy applications to the Symfony2 stack.","archived":false,"fork":false,"pushed_at":"2024-03-14T15:56:04.000Z","size":115,"stargazers_count":16,"open_issues_count":0,"forks_count":3,"subscribers_count":12,"default_branch":"master","last_synced_at":"2025-04-13T09:07:15.941Z","etag":null,"topics":["bundle","legacy","php","symfony"],"latest_commit_sha":null,"homepage":null,"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/webfactory.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2013-12-18T16:06:09.000Z","updated_at":"2022-11-16T07:23:52.000Z","dependencies_parsed_at":"2024-03-14T12:40:26.256Z","dependency_job_id":"76a5a939-a55e-4e91-b5ee-56dc812a7c7c","html_url":"https://github.com/webfactory/WebfactoryLegacyIntegrationBundle","commit_stats":{"total_commits":126,"total_committers":9,"mean_commits":14.0,"dds":0.626984126984127,"last_synced_commit":"56e0217fa08abba6b1a8224d593f92c4b3deeb78"},"previous_names":[],"tags_count":49,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/webfactory%2FWebfactoryLegacyIntegrationBundle","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/webfactory%2FWebfactoryLegacyIntegrationBundle/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/webfactory%2FWebfactoryLegacyIntegrationBundle/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/webfactory%2FWebfactoryLegacyIntegrationBundle/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/webfactory","download_url":"https://codeload.github.com/webfactory/WebfactoryLegacyIntegrationBundle/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248688568,"owners_count":21145766,"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":["bundle","legacy","php","symfony"],"created_at":"2024-11-07T19:32:55.483Z","updated_at":"2025-04-13T09:07:16.005Z","avatar_url":"https://github.com/webfactory.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"WebfactoryLegacyIntegrationBundle\n===================================\n\nThis bundle provides an approach to integrate existing legacy applications with\nSymfony2.\n\nIn brief, the approach is to run a particular event listener on the kernel.controller\nevent. This event listener will decide whether and how to run the legacy application.\nThe response generated by the legacy application will then be captured.\n\nLater, after the Symfony2 Controller has been executed and a Twig template is being\nrendered, fragments of the \"legacy response\" can be retrieved and be used as part\nof the output.\n\nThat way, you can start with your legacy application and Symfony2 in coexistence\nnext to each other. You can then incrementally start to shift functionality over\nto the Symfony2 stack while maintaining a coherent user experience.\n\nBecause Symfony2 is driving this process and Twig templates have the control\nauthority of which parts of the legacy response are being used, this approach\nwill naturally \"grow\" away from the legacy application towards the Symfony2 stack.\n\n*Take care:* This bundle currently uses webfactory/dom, a small set of utilities\n  on top of PHP's DOM extension, to process the legacy application's repsonse and\n  provide XPath-based access to it. It will only work if your old application\n  returns well-formed XHTML or Polyglot HTML5.\n\nTo learn more about this concept, its benefits and caveats, use your time-machine\nand visit the [Symfony2 User Group Colone meeting on 2013-12-18](http://de.slideshare.net/webfactory/marry-me-public).\n\nInstallation\n---\n\nJust like any other Symfony2 bundle, left as an exercise to the reader.\n\nConfiguration\n---\n\n```\nwebfactory_legacy_integration:\n    # Whether your legacy application returns text/html as XHTML 1.0 or Polyglot HTML5.\n    parsingMode: xhtml10|html5\n    # Bootstrap file for the legacy application (see next section)\n    legacyApplicationBootstrapFile: www/index-legacy.php\n```\n\nThe legacy \"bootstrap\" file\n---\n\nYou must provide a single file that can be `include()`ed in order to run your\nlegacy application. Typically you will already have this - it should be your\nlegacy application's front controller.\n\nIf you are running PHP \u003c 5.4, this file should _return_ the HTTP status code\nsent by the legacy application. Starting with PHP 5.4, `http_response_code()`\nwill be used to detect it.\n\nAlso, as this bundle will try to capture the response including headers using\noutput buffering, you must not flush the response body or headers\nto the client.\n\nUsing it\n---\n\nOnce you're set up, use the @Dispatch annotation on your controller to run the\nlegacy application before your controller - like so:\n\n```php\n\u003c?php\nnamespace Acme\\My\\Bundle\\Controller;\n\nuse Webfactory\\Bundle\\LegacyIntegrationBundle\\Integration\\Annotation as Legacy;\nuse ...\n\nclass MyController ...\n{\n    /**\n     * @Legacy\\Dispatch\n     */\n    public function myAction()\n    {\n        return ...\n    }\n}\n```\n\nThis will run your legacy application before entering the controller. The entire output including\nHTTP headers (repeat after me: including HTTP headers) will be captured and saved. *Nothing* will\nbe sent to the client unless you take care of doing so. \n\nRegarding the legacy response body, there are two ways of mixing your legacy world with your new world: Either you create a new layout and embed parts of\nthe legacy application, or you retain your old layout and embed new parts in it. The following sections \nexplain both of them.\n\nRegarding HTTP headers and especially cookies sent by the legacy application make sure\nyou don't miss the filters explained further below. For example, if your legacy code uses `session_start()`\nyou probably need to forward the session cookie.\n\n### Using XPath to embed parts of the legacy response in your new layout\n\nThis is the way we recommend in general. If you're doing your legacy integration for a frontend redesign or if it's not\ntoo hard to rewrite your layout in the Symfony world, you should do that.\n\nOnly with this approach you can implement new functionality on the Symfony 2 stack \nthat can be executed without running the legacy application at all.\n\nFor the use cases that need to be run (partially) in legacy, you can use the Twig global `legacyApplication`\nprovided by the bundle to access parts of the response and place it in your views.\n\n```twig\n{# you_template.html.twig #}\n\u003chtml\u003e\n    ...\n    \u003cbody\u003e\n        ...\n        \u003cdiv id=\"content\"\u003e\n            {{ legacyApplication.xpath('//*[@id=\"content\"]/*') | raw }}\n        \u003c/div\u003e\n        ...\n    \u003c/body\u003e\n\u003c/html\u003e\n```\n\n### Replacing arbitrary placeholders in the legacy response with markup generated by Twig\n\nSometimes you will have to focus on delivering new functionality on the Symfony 2 stack and you will be\nstuck with a page layout generated in the legacy application.\n\nThis has the disadvantage of having to run the legacy application on every request just to get this layout, \nwhich is a penalty performance-wise. Even completely new functionality will need to run the legacy application every time.\n\nThe two Twig functions `webfactoy_legacy_integration_embed()` and `webfactory_legacy_integration_embed_result()`\nhelp with this style of integration.\n\n* `webfactory_legacy_integration_embed(placeholder, replacement)` will search for arbitrary `placeholder` strings \n  in the legacy application's response. It will then replace those with `replacement`. This function cann be used \n  several times for different replacements.\n\n* `webfactory_legacy_integration_embed_result()` will return the final result after one or more substitutions have\n  been performed.\n\nThese replacements are best kept in a base layout template in Twig and mapped to Twig blocks, like so:\n\n```twig\n{# baseLayout.html.twig #}\n{{ webfactory_legacy_integration_embed('\u003c!-- MAIN_CONTENT --\u003e', block('main_content')) }}\n{{ webfactory_legacy_integration_embed_result() }}\n```\n\nThis layout template performs no other output than the one provided by `webfactory_legacy_integration_embed_result()`. \nIt can then be extended like this:\n\n```twig\n{# new-functionality.html.twig #}\n{% extends 'baseLayout.html.twig' %}\n{% block main_content %}\n    your new content here\n{% end block %}\n```\n\nThis has the benefit of isolating the `new-functionality.html.twig` template from the way it is integrated with the legacy\napplication. Once you shift the page layout over to the Symfony 2 stack, you can update the `baseLayout.html.twig` template\n(of course it should output the `main_content` block as well!) and stop dispatching the legacy application for the new\nfunctionality.\n\nFilters\n---\n\nThe `LegacyApplicationDispatchingEventListener` can take a set of _Filters_ which\nmust implement the Webfactory\\Bundle\\LegacyIntegrationBundle\\Integration\\Filter interface.\n\nOnce the legacy application has been executed, all registered filters are passed\nthe `ControllerEvent` which triggered the event listener as well as the\n`Response` object that was created for the legacy application.\n\nThe primary use case for this is to be able to examine the response and choose\nto send it to the client as-is, bypassing execution of the Symfony2 controller.\nThat way, you can have routes/controllers in Symfony2 to trigger (or allow) the\nexecution of particular use-cases in your legacy application while still returning\nits response unmodified initially.\n\nYou can use the `webfactory_legacy_integration.filter` tag to add more filters.\nA more convenient way is the use of additional annotations as follows.\n\n### Filter annotations\n\nThe `Webfactory\\Bundle\\LegacyIntegrationBundle\\Integration\\Annotation` namespace\ncontains a few annotations you can use in addition to the `@Legacy\\Dispatch` annotation\ndescribed earlier.\n\nIn particular,\n\n- @Legacy\\Passthru will send the legacy application's response as-is, so the controller itself will never be run\n- @Legacy\\IgnoreRedirect will bypass the controller if the legacy application sent a Location: redirect header.\n- @Legacy\\IgnoreHeader(\"some-name\") will bypass the controller if the legacy application sent \"Some-Name:\" header. This can be used to make the legacy application control execution of the Symfony2 controller (use with caution).\n- @Legacy\\KeepHeaders will apply *all* HTTP headers found in the legacy response and add them to the response created by Symfony controller. You can also selectively pick headers via `@Legacy\\KeepHeaders({\"X-Some-Header\", \"X-Some-Other\"})` \n- @Legacy\\KeepCookies works like `KeepHeaders` but peeks at cookie names.   \n\nBugs\n---\n\nWe've used this bundle successfully to slowly migrate a couple of applications\nand projects to the Symfony2 stack. Yet it deserves a little more love, fine-polishing,\nand documentation. Feel free to open PRs or open issues for it to express your\ninterest in it.\n\nOh, and unit tests would be fine :)\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwebfactory%2Fwebfactorylegacyintegrationbundle","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwebfactory%2Fwebfactorylegacyintegrationbundle","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwebfactory%2Fwebfactorylegacyintegrationbundle/lists"}