silverstripe-framework/docs/en/04_Changelogs/4.1.0.md
Damian Mooyman 8d077203d4 API Implement support for public/ webroot folder (#7741)
* API Implement support for public/ webroot folder

* Bugfixes and refactor based on feedback
2018-01-12 16:25:02 +13:00

209 lines
7.3 KiB
Markdown

# 4.1.0
## Overview {#overview}
* Support for public webroot folder `public/`
* Better support for cross-platform filesystem path manipulation
## Upgrading
### Upgrade `public/` folder
This release allows the maintenance of a public webroot folder which separates all
web-accessible files from protected project files (like the vendor folder
and all of your PHP files). This makes your web hosting more secure, and
less likely to leak information through accidentally deployed files like
a project README. New projects will default to this behaviour. Existing
projects (updating from 3.x or 4.0) will continue working as-is, but we
strongly recommend switching to the public webroot structure in order to
get the security benefits.
This folder name is not configurable, but is turned on by creating this folder, and off by ensuring
this folder doesn't exist.
When separating the public webroot from the BASE_PATH it is necessary to move a few files during migration:
- Move `.htaccess` from base to `public/`
- Move `index.php` from base to `public/`
- Move `assets` folder (including the nested `assets/.protected` folder) into `public/`.
This is the only folder which needs write permissions.
- Ensure that the `public/resources` folder exists; If this folder already exists in root, you should
delete this, and re-generate it by running `composer vendor-expose` in your root path.
- Any public assets committed directly to your project intended to be served directly to the
webserver. E.g. move `mysite/javascript/script.js` to `public/javascript/script.js`.
You can then use `Requirements::css('javascript/script.js');` /
`<% require css('javascript/script.js') %>` to include this file.
- Ensure that the web-root configured for your server of choice points to the public/ folder instead of the base path.
E.g. an apache virtualhost configuration would look like:
```
<VirtualHost *:80>
ServerName mywebsite.com
ServerAlias *.mywebsite.com
VirtualDocumentRoot "/var/www/Sites/mywebsite/public/"
</VirtualHost>
```
You may also need to add various changes to your code if you reference the BASE_PATH directly:
- You should use `Director::publicFolder()` instead of `Director::baseFolder()` if referring to the
public folder.
- You can check if a public folder exists with `Director::publicDir()`
### Example `public/` folder structure
For example, this is an existing folder structure:
```
/var/www/mysite
├── assets/
│ └── .protected/
├── mysite/
│ ├── code/
│ │ ├── Page.php
│ │ └── PageController.php
│ └── css/
│ └── projectstyle.css
├── resources/ _(auto-generated by vendor-plugin `composer vendor-expose` command)_
│ └── silverstripe/
│ └── blog/
│ └── css/ _(symlink)_
│ └── blog.css
├── themes/
│ └── mytheme/
│ ├── css/
│ │ └── theme.css
│ └── templates/
│ └── BlogPage.ss
├── vendor/
│ └── silverstripe/
│ └── blog/
│ ├── css/ _(exposed in blog composer.json)_
│ │ └── blog.css
│ └── composer.json
├── .htaccess
├── composer.json
├── favicon.ico
├── index.php
└── install.php
```
After migration the folder structure would look like:
```
/var/www/mysite
├── mysite/
│ └── code/
│ ├── Page.php
│ └── PageController.php
├── public/
│ ├── assets/
│ │ └── .protected/
│ ├── css/
│ │ └── somestyle.css
│ ├── resources/ _(auto-generated by vendor-plugin `composer vendor-expose` command)_
│ │ ├── themes/
│ │ │ └── mytheme/
│ │ │ └── css/ _(symlink)_
│ │ │ └── theme.css
│ │ └── vendor/
│ │ └── silverstripe/
│ │ └── blog/
│ │ └── css/ _(symlink)_
│ │ └── blog.css
│ ├── .htaccess
│ ├── favicon.ico
│ ├── index.php
│ └── install.php
├── themes/
│ └── mytheme/
│ ├── css/ _(exposed in root composer.json)_
│ │ └── theme.css
│ └── templates/
│ └── BlogPage.ss
├── vendor/
│ └── silverstripe/
│ └── blog/
│ ├── css/ _(exposed in blog composer.json)_
│ │ └── blog.css
│ └── composer.json
└── composer.php
```
### Use new `$public` theme set
In addition there is a new helper pseudo-theme that you can configure to expose files in the `public/`
folder to the themed css / javascript file lookup. For instance, this is how you can prioritise those
files:
```yaml
---
Name: mytheme
---
SilverStripe\View\SSViewer:
themes:
- '$public'
- 'simple'
- '$default'
```
This would allow `<% require themedCSS('style.css') %>` to find a file comitted to `public/css/style.css`.
Note that `Requirements` calls will look in both the `public` folder (first) and then the base path when
resolving css or javascript files. Any files that aren't in the public folder must be exposed using
the composer.json "expose" mechanism described below.
### Expose root project files
If you have files comitted to source control outside of the `public` folder, but you need them to be available
to the web server, you can also use the composer.json `expose` directive to symlink / copy these to `public/resources/`.
**composer.json** (in project root)
```json
{
"extra": {
"expose": [
"mysite/client"
]
}
}
```
Then run the composer helper `composer vendor-expose` in your project root. This will symlink (or copy)
the `mysite/client` directory to `public/resources/mysite/client`.
If you are using third party modules which may not have explicit `expose` directives,
you can also expose those assets manually by declaring the full path to the directory to expose.
This works the same for `silverstripe-module` and `silverstripe-vendormodule` types.
```json
{
"extra": {
"expose": [
"vendor/somevendor/somemodule/css",
"anothermodule/css"
]
}
}
```
For more information on how vendor modules work please see the documentation on the
[vendor plugin page](https://github.com/silverstripe/vendor-plugin) or the
[publishing a module](/developer_guides/extending/how_tos/publish_a_module) documentation.
### Path manipulation helpers
The following filesystem helpers have been added in order to better support working with cross-platform
path manipulation:
* `SilverStripe\Core\Convert::slashes()` to convert directory separators to either `/` or `\`
* `SilverStripe\Core\Path::join()` which will join one or more relative or absolute paths.
* `SilverStripe\Core\Path::normalise()` which will normalise and trim directory separators in a relative or absolute path
For example: normalising `Convert::normalise('/some\\dir/')` will convert to `/some/dir`.
Setting the second arg to true will also trim leading slashes.
E.g. `Convert::normalise('/sub\\dir/', true)` will convert to `sub/dir`.
It is preferrable to use these helpers in your code instead of assuming `DIRECTORY_SEPARATOR` === `/`