{"id":18773120,"url":"https://github.com/webfactory/webfactoryshortcodebundle","last_synced_at":"2025-08-08T21:16:10.926Z","repository":{"id":32643491,"uuid":"138289815","full_name":"webfactory/WebfactoryShortcodeBundle","owner":"webfactory","description":"Symfony integration for thunderer/Shortcode","archived":false,"fork":false,"pushed_at":"2024-11-20T16:21:04.000Z","size":123,"stargazers_count":5,"open_issues_count":3,"forks_count":5,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-04-13T09:07:29.318Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"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":null,"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}},"created_at":"2018-06-22T10:29:17.000Z","updated_at":"2024-11-20T16:21:07.000Z","dependencies_parsed_at":"2024-03-07T10:49:52.739Z","dependency_job_id":"ab0a4662-b935-41d3-8d56-5c896160c991","html_url":"https://github.com/webfactory/WebfactoryShortcodeBundle","commit_stats":{"total_commits":64,"total_committers":6,"mean_commits":"10.666666666666666","dds":0.515625,"last_synced_commit":"7cfd6f68f85cfe700bd731ca7c589325ab37219b"},"previous_names":[],"tags_count":16,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/webfactory%2FWebfactoryShortcodeBundle","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/webfactory%2FWebfactoryShortcodeBundle/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/webfactory%2FWebfactoryShortcodeBundle/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/webfactory%2FWebfactoryShortcodeBundle/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/webfactory","download_url":"https://codeload.github.com/webfactory/WebfactoryShortcodeBundle/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248688567,"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":[],"created_at":"2024-11-07T19:32:54.070Z","updated_at":"2025-04-13T09:07:35.964Z","avatar_url":"https://github.com/webfactory.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# WebfactoryShortcodeBundle\n\nA Symfony bundle to resolve `[shortcode]` markup in Twig templates, using the [thunderer/Shortcode](https://github.com/thunderer/Shortcode) library.\n\nIt allows you to define shortcodes and their replacements in a jiffy. Shortcodes are special text fragments that can be replaced with other content or markup. E.g. a user could use the following in a comment: \n\n```\n[image url=\"https://upload.wikimedia.org/wikipedia/en/f/f7/RickRoll.png\"]\n[text color=\"red\"]This is red text.[/text]\n```\n\nIn analogy to living style guides, this bundle provides a shortcode guide that lists all registered shortcodes with an optional description and example.\n \n## Installation\n\nAs usual, install via [Composer](https://getcomposer.org/) and register the bundle in your application:\n\n    composer require webfactory/shortcode-bundle\n\n```php\n\u003c?php\n// config/bundles.php\n\npublic function registerBundles()\n{\n    return [\n        // ...\n        Webfactory\\ShortcodeBundle\\WebfactoryShortcodeBundle::class =\u003e ['all' =\u003e true],\n        // ...\n    ];\n    // ...\n}\n```\n\n## Usage\n\n### Twig Filter\n\nThe bundle will set up a `shortcodes` Twig filter. What you pass through this filter will be processed by the `Processor` class (see [docs](https://github.com/thunderer/Shortcode#processing)).\n\n```twig\n{% apply shortcodes %}\n    [image url=\"https://upload.wikimedia.org/wikipedia/en/f/f7/RickRoll.png\"]\n    [text color=\"red\"]This is red text.[/text]\n{% endapply %}\n{{ some_content |shortcodes }}\n```\n\n### Using Controllers as Shortcode Handlers\n\nThis bundle comes with a helper class that allows to use Symfony's [Fragment Sub-Framework](https://symfony.com/blog/new-in-symfony-2-2-the-new-fragment-sub-framework) and the technique of [embedding controllers](https://symfony.com/doc/current/templates.html#embedding-controllers) to have controllers generate the replacement output for shortcodes.\n\nTo give an example, assume the following configuration:\n\n```yaml\n# config.yml\nwebfactory_shortcode:\n    shortcodes:\n        image: AppBundle\\Controller\\EmbeddedImageController::show\n```\n\nThen, when doing something like this in Twig:\n\n```twig\n{{ '[image url=\"https://upload.wikimedia.org/wikipedia/en/f/f7/RickRoll.png\"]' |shortcodes }}\n```\n\n... the `AppBundle\\Controller\\EmbeddedImageController::show()` controller method will be called. Additional shortcode attributes, like `url` in the above example, will be passed as parameters to the controller. The response returned by the controller will be used to replace the shortcode in the given content. The controller can generate the response directly, or use Twig to render a template to create it. \n\n#### Rendering with Edge Side Includes\n\nYou can also use [ESI rendering](https://symfony.com/doc/current/http_cache/esi.html) for particular shortcodes. The advantage of ESI is that single shortcode replacements can be stored in edge caches and/or reverse proxies like Varnish and possibly be reused on multiple pages.\n\n⚠️ Take care: Due to the way ESI works, the (master) `Request` visible to controllers is no longer the one where the shortcode was used. Keep that in mind when you, for example, want to log the URLs where shortcodes are being used.\n\nTo use ESI-based embedding for a particular shortcode, use a configuration like the following:\n\n```yaml\n# config.yml\nwebfactory_shortcodes:\n    shortcodes:\n        image: \n            controller: AppBundle\\Controller\\EmbeddedImageController::showAction\n            method: esi\n```\n\n### Registering Handlers as Services \n\nIn the [thunderer/Shortcode](https://github.com/thunderer/Shortcode) package, _handlers_ transform shortcodes into desired replacements. You can register services from the Symfony Dependency Injection Container to be used as shortcode handlers by tagging them with `webfactory.shortcode` and adding a `shortcode` attribute to the tag indicating the shortcode name.\n\n```yaml\nservices:\n    My\\Shortcode\\Handler\\Service:\n        tags:\n            - { name: 'webfactory.shortcode', shortcode: 'my-shortcode-name' }\n```\n\n### Removing `\u003cp\u003e` Tags around Shortcodes\n\nBy default, the `RemoveWrappingParagraphElementsEventHandler` contained in this bundle will be used to remove `\u003cp\u003e...\u003c/p\u003e` tags around shortcodes, if the shortcode is the only text content in that paragraph. \n\n## Activating the Shortcode Guide\n\nThe optional Shortcode Guide is a controller providing an overview page of all configured shortcodes. For every shortcode, there is also a detail page including a rendered example. \n\nTo use the Shortcode Guide, include the routing configuration from `@WebfactoryShortcodeBundle/Resources/config/guide-routing.xml`.\n\n⚠️ You probably want to do this only for your Symfony `dev` and/or `test` environment, and possibly restrict access in your security configuration in addition to that.\n\n```yaml\n# src/routing.yml\n_shortcode-guide:\n    prefix: /shortcodes\n    resource: \"@WebfactoryShortcodeBundle/Resources/config/guide-routing.xml\"\n```\n\nWith the route prefix defined as above, visit `/shortcodes/` to see a list of all defined shortcodes. If you want to add descriptions to shortcodes and/or provide the example shortcode that shall be rendered on the detail page, you can add this information when configuring shortcodes:\n\n```yaml\n# config.yml\nwebfactory_shortcodes:\n    shortcodes:\n        image: \n            controller: AppBundle\\Controller\\EmbeddedImageController::showAction\n            description: \"Renders an image tag with the {url} as it's source.\"\n            example: \"image url=https://upload.wikimedia.org/wikipedia/en/f/f7/RickRoll.png\"\n```\n\n### Other Configuration Parameters\n\nIn most cases, the default values should work fine. But you might want to configure something else, e.g. if the default\nparser needs too much memory for a large snippet. See thunderer's documentation on [parsing](https://github.com/thunderer/Shortcode#parsing)\nand [configuration](https://github.com/thunderer/Shortcode#configuration) so you understand the advantages,\ndisadvantages and limitations:\n\n```yaml\n# config.yml\n\nwebfactory_shortcode:\n    parser: 'regex'      # default: regular\n    recursion_depth: 2   # default: null\n    max_iterations: 2    # default: null\n```  \n\n## Testing your Shortcodes\n\nThis section provides a few hints and starting pointers on testing your shortcode handlers and bundle configuration.\n\n### Direct Unit Tests\n\nIn general, try to start with unit testing your shortcode handlers directly.\n\nNo matter whether your handler is a simple class implementing the `__invoke` magic method or a Symfony Controller with one or several methods: Direct unit tests are the easiest way to have full control over the handler's (or controller's) input, and to get immediate access to its return value. This allows you to test also a broader range of input parameters and verify the outcomes. In this case, you will typically use Mock Objects to substitute some or all other classes and services your handler depends upon.\n\nIf your shortcode handler produces HTML output, the [Symfony DomCrawler](https://symfony.com/doc/current/components/dom_crawler.html) might be helpful to perform assertions on the HTML structure and content.\n\n### Functional Tests for shortcode-handling Controllers\n\nWhen using a controller to handle a shortcode, and the controller uses Twig for rendering, you might want to do a full functional (integration) test instead of mocking the Twig engine.\n\nThe Symfony documentation describes how [Application Tests](https://symfony.com/doc/current/testing.html#write-your-first-application-test) can be performed. This approach, however, is probably not suited for your shortcode controllers since these typically _are not_ reachable through routes and so you cannot perform direct HTTP requests against them.\n\nInstead, write an [integration test](https://symfony.com/doc/current/testing.html#integration-tests) where you retrieve the controller as a service from the Dependency Injection Container and invoke the appropriate method on it directly. Then, just like described in the section before, perform assertions on the Response returned by the controller.\n\nHere is an example of what a test might look like.\n\n```php\n\u003c?php\n\nuse Symfony\\Bundle\\FrameworkBundle\\Test\\KernelTestCase;\n\nclass MyShortcodeControllerTest extends KernelTestCase\n{\n    public function test_renderImageAction_returns_img(): void\n    {\n        // Assume the controller is used to turn `[img id=42]` into some HTML markup\n\n        // create fixture/setup image with ID 42 in the database or similar\n        // ...\n\n        // Exercise controller method\n        $container = static::getContainer();\n        $controller = $container-\u003eget(MyShortcodeController::class);\n        $response = $controller-\u003erenderImageAction(42);\n\n        // Verify outcome\n        self::assertStringContainsString('\u003cimg src=\"...\" /\u003e', (string) $response-\u003egetContent());\n    }\n}\n```\n\n### Testing Configuration\n\nAfter you have written some tests that verify your handlers work as expected for different input parameters or other circumstances (e. g. database content), you also want to make sure a given handler is registered correctly and connected with the right shortcode name. Since we are now concerned with how this bundle, your configuration and your handlers all play together, we're in the realm of integration testing. These tests will be slower, since we need to boot a Symfony Kernel, fetch services from the Dependency Injection Container and test how various parts play together.\n\nThis bundle contains the `\\Webfactory\\ShortcodeBundle\\Test\\ShortcodeDefinitionTestHelper` class and a public service of the same name. Depending on the degree of test specifity you prefer, you can use this service to verify that...\n\n* A given shortcode name is known, i. e. a handler has been set up for it \n* Retrieve the handler for a given shortcode name, so you can for example perform assertions on the class being used\n* When using controllers as shortcode handlers, test if the controller reference for a given shortcode can be resolved (the controller actually exists)\n* Retrieve an instance of the controller to perform assertions on it.\n\nFor all these tests, you probably need to use `KernelTestCase` as your test base class ([documentation](https://symfony.com/doc/current/testing.html#integration-tests)). Basically, you will need to boot the kernel, then get the `ShortcodeDefinitionTestHelper` from the container and use its methods to check your shortcode configuration.\n\nMaybe you want to have a look at [the tests for `ShortcodeDefinitionTestHelper` itself](tests/Functional/ShortcodeDefinitionTestHelperTest.php) to see a few examples of how this class can be used.\n\nRemember – this type of test should not test all the possible inputs and outputs for your handlers; you've already covered that with more specific, direct tests. In this test layer, we're only concerned with making sure all the single parts are connected correctly.\n\n### Full End-to-End Tests\n\nIf, for some reason, you would like to do a full end-to-end test for shortcode processing, from a given string containing shortcode markup to the processed result,  have a look at the `\\Webfactory\\ShortcodeBundle\\Test\\EndToEndTestHelper` class.\n\nThis helper class can be used in integration test cases and will do the full shortcode processing on a given input, including dispatching sub-requests to controllers used as shortcode handlers.\n\nA test might look like this:\n\n```php\n\u003c?php\n\nuse Symfony\\Bundle\\FrameworkBundle\\Test\\KernelTestCase;\nuse Webfactory\\ShortcodeBundle\\Test\\EndToEndTestHelper;\n\nclass MyFullScaleTest extends KernelTestCase\n{\n    /** @test */\n    public function replace_text_color(): void\n    {\n        self::bootKernel();\n        \n        $result = EndToEndTestHelper::createFromContainer(static::$container)-\u003eprocessShortcode('[text color=\"red\"]This is red text.[/text]');\n        \n        self::assertSame('\u003cspan style=\"color: red;\"\u003eThis is red text.\u003c/span\u003e', $result);\n    }\n}\n```\n\nAssuming that your application configuration registers a handler for the `text` shortcode, which might also be a controller, this test will perform a full-stack test.\n\n## Credits, Copyright and License\n\nThis bundle was started at webfactory GmbH, Bonn.\n\n- \u003chttps://www.webfactory.de\u003e\n- \u003chttps://twitter.com/webfactory\u003e\n\nCopyright 2018-2023 webfactory GmbH, Bonn. Code released under [the MIT license](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwebfactory%2Fwebfactoryshortcodebundle","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwebfactory%2Fwebfactoryshortcodebundle","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwebfactory%2Fwebfactoryshortcodebundle/lists"}