Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docs: Adding an index and clarifying suggested usage #116

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 90 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,46 +2,61 @@

# Strauss – PHP Namespace Renamer

A tool to prefix namespaces and classnames in PHP files to avoid autoloading collisions.
A tool to prefix namespaces, classnames, and constants in PHP files to avoid autoloading collisions.

A fork of [Mozart](https://github.com/coenjacobs/mozart/). For [Composer](https://getcomposer.org/) for PHP.
A fork of [Mozart](https://github.com/coenjacobs/mozart/) for [Composer](https://getcomposer.org/) for PHP.

The primary use case is WordPress plugins, where different plugins active in a single WordPress install could each include different versions of the same library. The version of the class loaded would be whichever plugin registered the autoloader first, and all subsequent instantiations of the class will use that version, with potentially unpredictable behaviour and missing functionality.
Have 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 & runs first.

> ⚠️ **Sponsorship**: I don't want your money. [Please write a unit test to help the project](https://brianhenryie.github.io/strauss/).

## Breaking Changes

* v0.16.0 – will no longer prefix PHP built-in classes seen in polyfill packages
* v0.14.0 – `psr/*` packages no longer excluded by default
* v0.12.0 – default output `target_directory` changes from `strauss` to `vendor-prefixed`
## Table of Contents

Please open issues to suggest possible breaking changes. I think we can probably move to 1.0.0 soon.
* [Installation](#installation)
* [As a `.phar` file](#as-a-phar-file-within-composerjson-recommended) (recommended)
* [As a dev dependency via composer](#as-a-dev-dependency-via-composer-not-recommended) (not recommended)
* [Adding `composer dump-autoload`](#adding-composer-dump-autoload)
* [Usage](#usage)
* [Configuration](#configuration)
* [Autoloading](#autoloading)
* [Motivation & Comparison to Mozart](#motivation--comparison-to-mozart)
* [Alternatives](#alternatives)
* [Breaking Changes](#breaking-changes)
* [Acknowledgements](#acknowledgements)

## Use
## Installation

Require as normal with Composer:
### As a `.phar` file (recommended)

`composer require --dev brianhenryie/strauss`
There are a couple of small steps to make this possible.

and use `vendor/bin/strauss` to execute.
#### Create a `bin/.gitkeep` file

Or, download `strauss.phar` from [releases](https://github.com/BrianHenryIE/strauss/releases),
This ensures that there is a `bin/` directory in the root of your project. This is where the `.phar` file will go.

```shell
curl -o strauss.phar -L -C - https://github.com/BrianHenryIE/strauss/releases/latest/download/strauss.phar
```bash
mkdir bin
touch bin/.gitkeep
```

Then run it from the root of your project folder using `php strauss.phar`.
#### `.gitignore` the `.phar` file

To 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.
Add the following to your `.gitignore`:

Its use should be automated in Composer scripts.
```bash
bin/strauss.phar
```

#### Edit `composer.json` `scripts

In your `composer.json`, add `strauss` to the `scripts` section:

```json
"scripts": {
"prefix-namespaces": [
"strauss"
"sh -c 'test -f ./bin/strauss.phar || curl -o bin/strauss.phar -L -C - https://github.com/BrianHenryIE/strauss/releases/latest/download/strauss.phar'",
"@php bin/strauss.phar",
"@php composer dump-autoload"
],
"post-install-cmd": [
"@prefix-namespaces"
Expand All @@ -52,17 +67,56 @@ Its use should be automated in Composer scripts.
}
```

or
This provides `composer strauss`, which does the following:

1. The `sh -c` command tests if `bin/strauss.phar` exists, and if not, downloads it from [releases](https://github.com/BrianHenryIE/strauss/releases).
2. Then `@php bin/strauss.phar` is run to prefix the namespaces.
3. Ensure that composer's autoload map is updated.

### As a dev dependency via composer (not recommended)

If you prefer to include Strauss as a dev dependency, you can still do so. You mileage may vary when you include it this way.

```
composer require --dev brianhenryie/strauss
```

#### Edit `composer.json` `scripts

```json
"scripts": {
"prefix-namespaces": [
"@php strauss.phar"
"strauss",
"@php composer dump-autoload"
],
"post-install-cmd": [
"@prefix-namespaces"
],
"post-update-cmd": [
"@prefix-namespaces"
]
}
```

‼️ Add `composer dump-autoload` to your `scripts`/`strauss` if you set `target_directory` to `vendor` or `delete_vendor_packages`/`delete_vendor_files` to `true`, i.e. if you are using `require __DIR__ . '/vendor/autoload.php'` and Strauss modifies the files inside `vendor`, you must tell Composer to rebuild its autoload index.
## Usage

If 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:

```bash
composer prefix-namespaces
```

To 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.

```bash
composer -- prefix-namespaces --updateCallSites=true
```

or

```bash
composer -- prefix-namespaces --updateCallSites=includes,templates
```

## Configuration

Expand Down Expand Up @@ -115,7 +169,7 @@ The following configuration is inferred:
The following configuration is default:

- `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.
- `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`?
- `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`?
- `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`.
- `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`.

Expand All @@ -127,7 +181,7 @@ The remainder is empty:
- `constant_prefix` is for `define( "A_CONSTANT", value );` -> `define( "MY_PREFIX_A_CONSTANT", value );`. If it is empty, constants are not prefixed (this may change to an inferred value).
- `override_autoload` a dictionary, keyed with the package names, of autoload settings to replace those in the original packages' `composer.json` `autoload` property.
- `exclude_from_prefix` / [`file_patterns`](https://github.com/BrianHenryIE/strauss/blob/83484b79cfaa399bba55af0bf4569c24d6eb169d/src/ChangeEnumerator.php#L92-L96)
- `exclude_from_copy`
- `exclude_from_copy`
- [`packages`](https://github.com/BrianHenryIE/strauss/blob/83484b79cfaa399bba55af0bf4569c24d6eb169d/src/FileEnumerator.php#L77-L79) array of package names to be skipped
- [`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)
- [`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
Expand All @@ -138,7 +192,7 @@ The remainder is empty:

## Autoloading

Strauss uses Composer's own tools to generate a classmap file in the `target_directory` and creates an `autoload.php` alongside it, so in many projects autoloading is just a matter of:
Strauss uses Composer's own tools to generate a classmap file in the `target_directory` and creates an `autoload.php` alongside it, so in many projects autoloading is just a matter of:

```php
require_once __DIR__ . '/strauss/autoload.php';
Expand All @@ -161,7 +215,7 @@ I was happy to make PRs to Mozart to fix bugs, but they weren't being reviewed a
Benefits over Mozart:

* A single output directory whose structure matches source vendor directory structure (conceptually easier than Mozart's independent `classmap_directory` and `dep_directory`)
* A generated `autoload.php` to `include` in your project (analogous to Composer's `vendor/autoload.php`)
* A generated `autoload.php` to `include` in your project (analogous to Composer's `vendor/autoload.php`)
* Handles `files` autoloaders – and any autoloaders that Composer itself recognises, since Strauss uses Composer's own tooling to parse the packages
* Zero configuration – Strauss infers sensible defaults from your `composer.json`
* No destructive defaults – `delete_vendor_files` defaults to `false`, so any destruction is explicitly opt-in
Expand Down Expand Up @@ -191,6 +245,14 @@ I don't have a strong opinion on these. I began using Mozart because it was easy
* [sdrobov/autopsr4](https://github.com/sdrobov/autopsr4)
* [jaem3l/unfuck](https://github.com/jaem3l/unfuck)

## Breaking Changes

* v0.16.0 – will no longer prefix PHP built-in classes seen in polyfill packages
* v0.14.0 – `psr/*` packages no longer excluded by default
* v0.12.0 – default output `target_directory` changes from `strauss` to `vendor-prefixed`

Please open issues to suggest possible breaking changes. I think we can probably move to 1.0.0 soon.

## Changes before v1.0

* Comprehensive attribution of code forked from Mozart – changes have been drastic and `git blame` is now useless, so I intend to add more attributions
Expand All @@ -201,7 +263,7 @@ I don't have a strong opinion on these. I began using Mozart because it was easy

## Changes before v2.0

The correct approach to this problem is probably via [PHP-Parser](https://github.com/nikic/PHP-Parser/). At least all the tests will be useful.
The correct approach to this problem is probably via [PHP-Parser](https://github.com/nikic/PHP-Parser/). At least all the tests will be useful.

## Acknowledgements

Expand Down