README.md 7.13 KB
Newer Older
totten's avatar
totten committed
1
# civicrm/civicrm-asset-plugin
totten's avatar
totten committed
2

totten's avatar
totten committed
3
The `civicrm/civicrm-asset-plugin` is a [composer](https://getcomposer.org/)
totten's avatar
totten committed
4
5
6
7
plugin to support projects in which PHP files (`*.php`) and web-assets
(`*.js`, `*.css`, etc) must be split apart.  Its job is to identify
web-assets related to CiviCRM, copy them to another folder, and configure
CiviCRM to use that folder.
totten's avatar
totten committed
8

totten's avatar
totten committed
9
It reads assets from these composer packages:
totten's avatar
totten committed
10

totten's avatar
totten committed
11
12
13
14
15
16
17
18
* `civicrm/civicrm-core`
* `civicrm/civicrm-packages`
* Any `composer` package with a CiviCRM extension (`info.xml`) in the root

Assets are synchronized to a public folder.  If your web-site matches a
well-known project template (e.g.  `drupal/recommended-project` or
`drupal/legacy-project` in D8.8+), then the plugin will detect the output folder
automatically. Otherwise, it can be configured.
totten's avatar
totten committed
19
20
21

## Quick start

totten's avatar
totten committed
22
23
Simply add the package `civicrm/civicrm-asset-plugin` to your project:

totten's avatar
totten committed
24
25
26
27
```bash
composer require civicrm/civicrm-asset-plugin:~1.0
```

totten's avatar
totten committed
28
For a well-known project template, nothing more is required.
totten's avatar
totten committed
29

totten's avatar
totten committed
30
31
32
For a novel or unrecognized project structure, you should explicitly
configure the sync mechanism.  Edit `composer.json` and describe where
assets should go, e.g.:
totten's avatar
totten committed
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

```js
"extra": {
  "civicrm-asset": {
    "path": "web/libraries/civicrm",
    "url": "/libraries/civicrm"
  }
}
```

After editing the options, republish with:

```bash
composer civicrm:publish
```

The remainder of this document presents a fuller explanation of the
mechanics and options.
totten's avatar
totten committed
51

totten's avatar
totten committed
52
53
54
55
56
## Example

Suppose you have the following source tree:

```
totten's avatar
totten committed
57
58
web/
  index.php
totten's avatar
totten committed
59
60
vendor/
  civicrm/
totten's avatar
totten committed
61
62
    civicrm-core/
    civicrm-packages/
totten's avatar
totten committed
63
  civipkg/
totten's avatar
totten committed
64
65
66
67
    org.civicrm.api4/
    org.civicrm.flexmailer/
    org.civicrm.shoreditch/
    uk.co.vedaconsulting.mosaico/
totten's avatar
totten committed
68
69
```

totten's avatar
totten committed
70
The plugin will copy Civi-related assets from `vendor/` to `web/`.
totten's avatar
totten committed
71
72
73
74
75

```
web/
  libraries/
    civicrm/
totten's avatar
totten committed
76
77
78
79
80
81
      core/
      packages/
      org.civicrm.api4/
      org.civicrm.flexmailer/
      org.civicrm.shoreditch/
      uk.co.vedaconsulting.mosaico/
totten's avatar
totten committed
82
83
84
85
86
87
88
```

## Options

In the root `composer.json`,  the site administrator may customize some
options:

totten's avatar
totten committed
89
```js
totten's avatar
totten committed
90
91
"extra": {
  "civicrm-asset": {
totten's avatar
totten committed
92
    // Local file path of the public/web-readable folder
totten's avatar
totten committed
93
    "path": "web/libraries/civicrm",
totten's avatar
totten committed
94

totten's avatar
totten committed
95
    // Public URL of the public/web-readable folder
totten's avatar
totten committed
96
    "url": "/libraries/civicrm",
totten's avatar
totten committed
97

totten's avatar
totten committed
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
    // How to put the file in the public/web-readable folder?
    //
    // TIP: For a safe+portable default, use "copy". On a local-dev machine, set environment variable
    // `CIVICRM_COMPOSER_ASSET=symdir` so that all local builds use "symdir".
    //
    // Options:
    //  - "copy": Each asset/file is individually copied.
    //  - "symlink": Each asset/file is individually symlinked.
    //  - "symdir": The main directories are symlinked, bringing all files underneath.
    //
    //                                                   "copy"        "symlink"       "symdir"
    //                                                   ------        ---------       --------
    // Compatiblity: Windows                             Good          Poor            Poor
    // Compatiblity: Linux/OSX                           Good          Good            Good
    // Compatiblity: HTTPD                               Good          Depends         Depends
    // Precision: Does it *only* publish assets?         Good          Good            Poor
    // Updating: Do code-edits require manual sync?      Manual        Automatic       Automatic
    // Updating: Do new-files require manual sync?       Manual        Manual          Automatic
    //
totten's avatar
totten committed
117
118
    "file-mode": "copy",

totten's avatar
totten committed
119
    // Customize default list of assets
totten's avatar
totten committed
120
121
122
123
124
    "assets:*": {
      "include": ["**.js", "**.css"],
      "exclude-dir": [".git"]
    },

totten's avatar
totten committed
125
126
    // Customize the specific list of assets for "web/libraries/civicrm/core"
    // by replacing the inclusion-list and exclusion-list.
totten's avatar
totten committed
127
128
129
130
131
    "assets:core": {
      "include": ["js/**", "css/**", "ang/**", "templates/**.png", "templates/**.jpg"],
      "exclude-dir": [".git", "/CRM"]
    },

totten's avatar
totten committed
132
133
    // Customize the specific list of assets for "web/libraries/civicrm/packages"
    // by adding to the inclusion-list and exclusion-list.
totten's avatar
totten committed
134
    "assets:packages": {
totten's avatar
totten committed
135
      "+include": ["**.jpeg"],
totten's avatar
totten committed
136
137
138
139
140
141
      "+exclude-dir": ["_ORIGINAL_"]
    }
  }
}
```

totten's avatar
totten committed
142
143
144
If you do not set these explicitly, then some defaults come into play.

The defaults are tuned for a few different use-cases.
totten's avatar
totten committed
145
146

```js
totten's avatar
totten committed
147
// Use-Case: `drupal-composer/drupal-project`
totten's avatar
totten committed
148
149
// Use-Case: `drupal/recommended-project`
// Rule: If the `installer-paths` has a `drupal-library` or `drupal-core` mapping which uses `web/`, then default to:
totten's avatar
totten committed
150
151
152
153
154
{
  "path": "web/libraries/civicrm",
  "url": "/libraries/civicrm"
}

totten's avatar
totten committed
155
// Use-Case: Drupal 8 Tarball / Drush Dl
totten's avatar
totten committed
156
157
// Use-Case: `drupal/legacy-project`
// Rule: If the `installer-paths` has a `drupal-library` or `drupal-core` mapping which does NOT use `web/`, then default to:
totten's avatar
totten committed
158
159
160
161
162
{
  "path": "libraries/civicrm",
  "url": "/libraries/civicrm"
}

totten's avatar
totten committed
163
// Use-Case: Other/Unknown
totten's avatar
totten committed
164
// Rule: If no other defaults apply, then the defaults are:
totten's avatar
totten committed
165
166
167
168
169
170
{
  "path": "civicrm-assets"
  "url": "/civicrm-assets"
}
```

totten's avatar
totten committed
171
172
173
The full heuristics are enumerated in `src/PublisherDefaults.php`.

## Generated asset map and global variables
174

totten's avatar
totten committed
175
At runtime, CiviCRM needs some information about how to load assets/files provided by
totten's avatar
totten committed
176
`composer` packages (`civicrm/civicrm-core`, `civicrm/civicrm-packages`, and any extensions).
totten's avatar
totten committed
177
This plugin generates a map and puts it into a few global variables:
178
179
180

* `$civicrm_setting`: Defines certain path/URL-related settings such as `userFrameworkResourceURL`.
* `$civicrm_paths`: Defines the paths and URLs for `[civicrm.core]` and `[civicrm.packages]`.
totten's avatar
totten committed
181
* `$civicrm_asset_map`: For each composer package with sync'd assets, this identifies:
182
183
184
185
    * `src`: Local path where assets are read from
    * `dest`: Local path where assets are sync'd to
    * `url`: Configured URL for the `dest`

totten's avatar
totten committed
186
187
At runtime, the global variables will be loaded automatically (via `vendor/composer/autoload.php`).

totten's avatar
totten committed
188
## Automated Tests
totten's avatar
totten committed
189

totten's avatar
totten committed
190
191
192
193
The `tests/` folder includes integration tests written with PHPUnit.  Each
integration-test generates a new folder/project with a plausible,
representative `composer.json` file and executes `composer install`. It
checks the output has the expected files.
totten's avatar
totten committed
194

totten's avatar
totten committed
195
To run the tests, you will need `composer` and `phpunit` in the `PATH`.
totten's avatar
totten committed
196

totten's avatar
totten committed
197
198
199
200
201
202
203
204
205
206
207
```
[~/src/civicrm-asset-plugin] which composer
/Users/totten/bknix/civicrm-buildkit/bin/composer

[~/src/civicrm-asset-plugin] which phpunit
/Users/totten/bknix/civicrm-buildkit/bin/phpunit

[~/src/civicrm-asset-plugin] phpunit
PHPUnit 5.7.27 by Sebastian Bergmann and contributors.

.....                                                               5 / 5 (100%)
totten's avatar
totten committed
208

totten's avatar
totten committed
209
Time: 40.35 seconds, Memory: 10.00MB
totten's avatar
totten committed
210

totten's avatar
totten committed
211
212
213
214
215
216
217
218
OK (5 tests, 7 assertions)
```

The integration tests can be a bit large/slow. To monitor the tests more
closesly, set the `DEBUG` variable, as in:

```
[~/src/civicrm-asset-plugin] env DEBUG=2 phpunit
totten's avatar
totten committed
219
```
220
221
222
223
224
225
226
227
228
229
230

## Local Dev Harness

What if you want to produce an environment which uses the current plugin
code - one where you can quickly re-run `composer` commands while
iterating on code?

You may use any of the integration-tests to initialize a baseline
environment:

```
totten's avatar
totten committed
231
env USE_TEST_PROJECT=$HOME/src/myprj DEBUG=2 phpunit tests/Integration/DrupalProjectPathsTest.php
232
```