{"id":15046081,"url":"https://github.com/brianhenryie/strauss","last_synced_at":"2025-10-01T06:31:37.247Z","repository":{"id":43876935,"uuid":"232526737","full_name":"BrianHenryIE/strauss","owner":"BrianHenryIE","description":"Prefix PHP namespaces and classnames to allow multiple versions of libraries to exist without conflict.","archived":false,"fork":true,"pushed_at":"2025-01-18T21:02:12.000Z","size":3436,"stargazers_count":147,"open_issues_count":25,"forks_count":25,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-01-18T22:17:44.835Z","etag":null,"topics":["composer","namespaces"],"latest_commit_sha":null,"homepage":"https://brianhenryie.github.io/strauss/","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"coenjacobs/mozart","license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/BrianHenryIE.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}},"created_at":"2020-01-08T09:27:14.000Z","updated_at":"2025-01-17T23:17:18.000Z","dependencies_parsed_at":"2023-02-08T15:31:17.102Z","dependency_job_id":null,"html_url":"https://github.com/BrianHenryIE/strauss","commit_stats":{"total_commits":481,"total_committers":14,"mean_commits":"34.357142857142854","dds":0.4282744282744283,"last_synced_commit":"cff6d25373281e61941cf0aa02fc575a573c9505"},"previous_names":[],"tags_count":28,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BrianHenryIE%2Fstrauss","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BrianHenryIE%2Fstrauss/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BrianHenryIE%2Fstrauss/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BrianHenryIE%2Fstrauss/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/BrianHenryIE","download_url":"https://codeload.github.com/BrianHenryIE/strauss/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":234837012,"owners_count":18894515,"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":["composer","namespaces"],"created_at":"2024-09-24T20:52:40.929Z","updated_at":"2025-10-01T06:31:37.242Z","avatar_url":"https://github.com/BrianHenryIE.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![PHPUnit ](.github/coverage.svg)](https://brianhenryie.github.io/strauss/) [![PHPStan ](https://img.shields.io/badge/PHPStan-Level%207-2a5ea7.svg)](https://phpstan.org/)\n\n# Strauss – PHP Namespace Renamer\n\nA tool to prefix namespaces, classnames, and constants in PHP files to avoid autoloading collisions.\n\nA fork of [Mozart](https://github.com/coenjacobs/mozart/) for [Composer](https://getcomposer.org/) for PHP.\n\nHave you ever activated a WordPress plugin that has a conflict with another because the plugins use two different versions of the same PHP library? **Strauss is the solution to that problem** - it ensures that _your_ plugin's PHP dependencies are isolated and loaded from your plugin rather than loading from whichever plugin's autoloader registers \u0026 runs first.\n\n\u003e ⚠️ **Sponsorship**: It would be neat if you were to offer me a license to your plugin, or at least [post about where this is used](https://github.com/BrianHenryIE/strauss/discussions).\n\n## Table of Contents\n\n* [Installation](#installation)\n    * [As a `.phar` file](#as-a-phar-file-recommended) (recommended)\n    * [As a dev dependency via composer](#as-a-dev-dependency-via-composer-not-recommended)  (not recommended)\n    * [Edit `composer.json` scripts](#edit-composerjson-scripts)\n* [Usage](#usage)\n* [Configuration](#configuration)\n* [Autoloading](#autoloading)\n* [Motivation \u0026 Comparison to Mozart](#motivation--comparison-to-mozart)\n* [Alternatives](#alternatives)\n* [Breaking Changes](#breaking-changes)\n* [Acknowledgements](#acknowledgements)\n\n## Installation\n\n### As a `.phar` file (recommended)\n\nThere are a couple of small steps to make this possible.\n\n#### Create a `bin/.gitkeep` file\n\nThis ensures that there is a `bin/` directory in the root of your project. This is where the `.phar` file will go.\n\n```bash\nmkdir bin\ntouch bin/.gitkeep\n```\n\n#### `.gitignore` the `.phar` file\n\nAdd the following to your `.gitignore`:\n\n```bash\nbin/strauss.phar\n```\n\n#### Edit `composer.json` `scripts\n\nIn your `composer.json`, add `strauss` to the `scripts` section:\n\n```json\n\"scripts\": {\n    \"prefix-namespaces\": [\n        \"sh -c 'test -f ./bin/strauss.phar || curl -o bin/strauss.phar -L -C - https://github.com/BrianHenryIE/strauss/releases/latest/download/strauss.phar'\",\n        \"@php bin/strauss.phar\",\n        \"@composer dump-autoload\"\n    ],\n    \"post-install-cmd\": [\n        \"@prefix-namespaces\"\n    ],\n    \"post-update-cmd\": [\n        \"@prefix-namespaces\"\n    ],\n    \"post-autoload-dump\": [\n        \"@php bin/strauss.phar include-autoloader\"\n    ]\n}\n```\n\nThis provides `composer strauss`, which does the following:\n\n1. The `sh -c` command tests if `bin/strauss.phar` exists, and if not, downloads it from [releases](https://github.com/BrianHenryIE/strauss/releases).\n2. Then `@php bin/strauss.phar` is run to prefix the namespaces.\n3. Ensure that composer's autoload map is updated.\n\n### As a dev dependency via composer (not recommended)\n\nIf you prefer to include Strauss as a dev dependency, you can still do so. You mileage may vary when you include it this way.\n\n```\ncomposer require --dev brianhenryie/strauss\n```\n\n#### Edit `composer.json` `scripts\n\n```json\n\"scripts\": {\n    \"prefix-namespaces\": [\n        \"strauss\",\n        \"@php composer dump-autoload\"\n    ],\n    \"post-install-cmd\": [\n        \"@prefix-namespaces\"\n    ],\n    \"post-update-cmd\": [\n        \"@prefix-namespaces\"\n    ],\n    \"post-autoload-dump\": [\n        \"strauss include-autoloader\"\n    ]\n}\n```\n\n## Usage\n\nIf you add Strauss to your `composer.json` as indicated in [Installation](#installation), it will run when you `composer install` or `composer update`. To run Strauss directly, simply use:\n\n```bash\ncomposer prefix-namespaces\n```\n\nTo update the files that call the prefixed classes, you can use `--updateCallSites=true` which uses your autoload key, or `--updateCallSites=includes,templates` to explicitly specify the files and directories.\n\n```bash\ncomposer -- prefix-namespaces --updateCallSites=true\n```\n\nor\n\n```bash\ncomposer -- prefix-namespaces --updateCallSites=includes,templates\n```\n\nTo try it out without making changes, you can use the `--dry-run` flag:\n\n\u003cdetails\u003e\n\n\u003csummary\u003estrauss --dry-run\u003c/summary\u003e\n\n![](.github/strauss.mp4)\n\n\u003c/details\u003e\n\nVerbosity can be controlled with `--notice` (default), `--info`, `--debug` and `--silent`.\n\n## Configuration\n\nStrauss potentially requires zero configuration, but likely you'll want to customize a little, by adding in your `composer.json` an `extra/strauss` object. The following is the default config, where the `namespace_prefix` and `classmap_prefix` are determined from your `composer.json`'s `autoload` or `name` key and `packages` is determined from the `require` key:\n\n```json\n\"extra\": {\n    \"strauss\": {\n        \"target_directory\": \"vendor-prefixed\",\n        \"namespace_prefix\": \"BrianHenryIE\\\\My_Project\\\\\",\n        \"classmap_prefix\": \"BrianHenryIE_My_Project_\",\n        \"constant_prefix\": \"BHMP_\",\n        \"packages\": [\n        ],\n        \"update_call_sites\": false,\n        \"override_autoload\": {\n        },\n        \"exclude_from_copy\": {\n            \"packages\": [\n            ],\n            \"namespaces\": [\n            ],\n            \"file_patterns\": [\n            ]\n        },\n        \"exclude_from_prefix\": {\n            \"packages\": [\n            ],\n            \"namespaces\": [\n            ],\n            \"file_patterns\": [\n            ]\n        },\n        \"namespace_replacement_patterns\" : {\n        },\n        \"delete_vendor_packages\": false,\n        \"delete_vendor_files\": false\n    }\n},\n```\n\nThe following configuration is inferred:\n\n- `target_directory` defines the directory the files will be copied to, default `vendor-prefixed`\n- `namespace_prefix` defines the default string to prefix each namespace with\n- `classmap_prefix` defines the default string to prefix class names in the global namespace\n- `packages` is the list of packages to process. If absent, all packages in the `require` key of your `composer.json` are included\n- `classmap_output` is a `bool` to decide if Strauss will create `autoload-classmap.php` and `autoload.php`. If it is not set, it is `false` if `target_directory` is in your project's `autoload` key, `true` otherwise.\n\nThe following configuration is default:\n\n- `delete_vendor_packages`: `false` a boolean flag to indicate if the packages' vendor directories should be deleted after being processed. It defaults to false, so any destructive change is opt-in.\n- `delete_vendor_files`: `false` a boolean flag to indicate if files copied from the packages' vendor directories should be deleted after being processed. It defaults to false, so any destructive change is opt-in. This is maybe deprecated! Is there any use to this that is more appropriate than `delete_vendor_packages`?\n- `include_modified_date` is a `bool` to decide if Strauss should include a date in the (phpdoc) header written to modified files. Defaults to `true`.\n- `include_author` is a `bool` to decide if Strauss should include the author name in the (phpdoc) header written to modified files. Defaults to `true`.\n- `update_call_sites`: `false`. This can be `true`, `false` or an `array` of directories/filepaths. When set to `true` it defaults to the directories and files in the project's `autoload` key. The PHP files and directories' PHP files will be updated where they call the prefixed classes.\n\nThe remainder is empty:\n\n- `constant_prefix` is for `define( \"A_CONSTANT\", value );` -\u003e `define( \"MY_PREFIX_A_CONSTANT\", value );`. If it is empty, constants are not prefixed (this may change to an inferred value).\n- `override_autoload` a dictionary, keyed with the package names, of autoload settings to replace those in the original packages' `composer.json` `autoload` property.\n- `exclude_from_prefix` / [`file_patterns`](https://github.com/BrianHenryIE/strauss/blob/83484b79cfaa399bba55af0bf4569c24d6eb169d/src/ChangeEnumerator.php#L92-L96)\n- `exclude_from_copy`\n  - [`packages`](https://github.com/BrianHenryIE/strauss/blob/83484b79cfaa399bba55af0bf4569c24d6eb169d/src/FileEnumerator.php#L77-L79) array of package names to be skipped\n  - [`namespaces`](https://github.com/BrianHenryIE/strauss/blob/83484b79cfaa399bba55af0bf4569c24d6eb169d/src/FileEnumerator.php#L95-L97) array of namespaces to skip (exact match from the package autoload keys)\n  - [`file_patterns`](https://github.com/BrianHenryIE/strauss/blob/83484b79cfaa399bba55af0bf4569c24d6eb169d/src/FileEnumerator.php#L133-L137) array of regex patterns to check filenames against (including vendor relative path) where Strauss will skip that file if there is a match\n- `exclude_from_prefix`\n  - [`packages`](https://github.com/BrianHenryIE/strauss/blob/83484b79cfaa399bba55af0bf4569c24d6eb169d/src/ChangeEnumerator.php#L86-L90) array of package names to exclude from prefixing.\n  - [`namespaces`](https://github.com/BrianHenryIE/strauss/blob/83484b79cfaa399bba55af0bf4569c24d6eb169d/src/ChangeEnumerator.php#L177-L181) array of exact match namespaces to exclude (i.e. not substring/parent namespaces)\n- [`namespace_replacement_patterns`](https://github.com/BrianHenryIE/strauss/blob/83484b79cfaa399bba55af0bf4569c24d6eb169d/src/ChangeEnumerator.php#L183-L190) a dictionary to use in `preg_replace` instead of prefixing with `namespace_prefix`.\n\n## Autoloading\n\nStrauss uses Composer's own tools to generate a set of autoload files in the `target_directory` and creates an `autoload.php` alongside it, so in many projects autoloading is just a matter of:\n\n```php\nrequire_once __DIR__ . '/vendor-prefixed/autoload.php';\n```\n\nIf you plan to continue using Composer's autoloader you probably want to turn on `delete_vendor_packages` or set `target_directory` to `vendor`.\n\nYou can use `strauss include-autoloader` to add a line to `vendor/autoload.php` which includes the autoloader for the new files. \n\nWhen `delete_vendor_packages` is enabled, `vendor/composer/autoload_aliases.php` is created to allow modified classes to be loaded with their old name during development. This file should not be included in your production code.\n\n## Motivation \u0026 Comparison to Mozart\n\nI was happy to make PRs to Mozart to fix bugs, but they weren't being reviewed and merged. At the time of writing, somewhere approaching 50% of Mozart's code [was written by me](https://github.com/coenjacobs/mozart/graphs/contributors) with an additional [nine open PRs](https://github.com/coenjacobs/mozart/pulls?q=is%3Apr+author%3ABrianHenryIE+) and the majority of issues' solutions [provided by me](https://github.com/coenjacobs/mozart/issues?q=is%3Aissue+). This fork is a means to merge all outstanding bugfixes I've written and make some more drastic changes I see as a better approach to the problem.\n\nBenefits over Mozart:\n\n* A single output directory whose structure matches source vendor directory structure (conceptually easier than Mozart's independent `classmap_directory` and `dep_directory`)\n* A generated `autoload.php` to `include` in your project (analogous to Composer's `vendor/autoload.php`)\n* Handles `files` autoloaders – and any autoloaders that Composer itself recognises, since Strauss uses Composer's own tooling to parse the packages\n* Zero configuration – Strauss infers sensible defaults from your `composer.json`\n* No destructive defaults – `delete_vendor_files` defaults to `false`, so any destruction is explicitly opt-in\n* Licence files are included and PHP file headers are edited to adhere to licence requirements around modifications. My understanding is that re-distributing code that Mozart has handled is non-compliant with most open source licences – illegal!\n* Extensively tested – PhpUnit tests have been written to validate that many of Mozart's bugs are not present in Strauss\n* More configuration options – allowing exclusions in copying and editing files, and allowing specific/multiple namespace renaming\n* Respects `composer.json` `vendor-dir` configuration\n* Prefixes constants (`define`)\n* Handles meta-packages and virtual-packages\n\nStrauss will read the Mozart configuration from your `composer.json` to enable a seamless migration.\n\n## Alternatives\n\nI don't have a strong opinion on these. I began using Mozart because it was easy, then I adapted it to what I felt was most natural. I've never used these.\n\n* [humbug/php-scoper](https://github.com/humbug/php-scoper)\n* [TypistTech/imposter-plugin](https://github.com/TypistTech/imposter-plugin)\n* [Automattic/jetpack-autoloader](https://github.com/Automattic/jetpack-autoloader)\n* [tschallacka/wordpress-composer-plugin-builder](https://github.com/tschallacka/wordpress-composer-plugin-builder)\n* [Interfacelab/namespacer](https://github.com/Interfacelab/namespacer)\n* [PHP-Prefixer](https://github.com/PHP-Prefixer) SaaS!\n\n### Interesting\n\n* [composer-unused/composer-unused](https://github.com/composer-unused/composer-unused)\n* [sdrobov/autopsr4](https://github.com/sdrobov/autopsr4)\n* [jaem3l/unfuck](https://github.com/jaem3l/unfuck)\n* [bamarni/composer-bin-plugin](https://github.com/bamarni/composer-bin-plugin)\n* [phar-io/composer-distributor](https://github.com/phar-io/composer-distributor)\n\n## Breaking Changes\n\n* v0.21.0 – will prefix global functions\n* v0.16.0 – will no longer prefix PHP built-in classes seen in polyfill packages\n* v0.14.0 – `psr/*` packages no longer excluded by default\n* v0.12.0 – default output `target_directory` changes from `strauss` to `vendor-prefixed`\n\nPlease open issues to suggest possible breaking changes. I think we can probably move to 1.0.0 soon.\n\n### Backward Compatibility Promise\n\nThis project will not increase its minimum required PHP version ahead of WordPress.\n\nhttps://core.trac.wordpress.org/ticket/62622\n\n## Changes before v1.0\n\n* Comprehensive attribution of code forked from Mozart – changes have been drastic and `git blame` is now useless, so I intend to add more attributions\n* More consistent naming. Are we prefixing or are we renaming?\n* Further unit tests, particularly file-system related\n* Regex patterns in config need to be validated\n* Change the name? \"Renamespacer\"?\n\n## Changes before v2.0\n\nThe correct approach to this problem is probably via [PHP-Parser](https://github.com/nikic/PHP-Parser/). At least all the tests will be useful.\n\n## Acknowledgements\n\n[Coen Jacobs](https://github.com/coenjacobs/) and all the [contributors to Mozart](https://github.com/coenjacobs/mozart/graphs/contributors), particularly those who wrote nice issues.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrianhenryie%2Fstrauss","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbrianhenryie%2Fstrauss","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrianhenryie%2Fstrauss/lists"}