Updating README and CONTRIBUTING
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
# Contributing
|
# Contributing
|
||||||
|
|
||||||
## Code.
|
## PHP Code
|
||||||
- Two spaces indentation.
|
- Two spaces indentation.
|
||||||
- CamelCase for classes.
|
- CamelCase for classes.
|
||||||
- camelCase for methods.
|
- camelCase for methods.
|
||||||
@@ -10,27 +10,23 @@
|
|||||||
- Require other classes with 'use' at the beginning of the class file.
|
- Require other classes with 'use' at the beginning of the class file.
|
||||||
- Do not specify 'public' if method is public, it's implicit.
|
- Do not specify 'public' if method is public, it's implicit.
|
||||||
- Always use guard clauses.
|
- Always use guard clauses.
|
||||||
- Ensure compatibility with PHP 5.3 and newer versions.
|
- Ensure compatibility with PHP 5.5 and newer versions.
|
||||||
- Cover your code in tests.
|
- Cover your code in tests.
|
||||||
|
|
||||||
Recommendations:
|
## JS Code
|
||||||
- Max line length at 80 chars.
|
- Javascript code should follow the [Airbnb style guide](https://github.com/airbnb/javascript).
|
||||||
- Keep classes under 100 LOC.
|
|
||||||
- Keep methods under 10 LOC.
|
|
||||||
- Pass no more than 4 parameters/hash keys into a method.
|
|
||||||
- Keep Pull Requests small, under 100 LOC changed.
|
|
||||||
|
|
||||||
## Git flow.
|
## Git flow
|
||||||
- Do not commit to master.
|
- Do not commit to master.
|
||||||
- Open a short-living feature branch.
|
- Open a short-living feature branch.
|
||||||
- Open a pull request.
|
- Open a pull request.
|
||||||
- Add Jira issue reference in the title of the Pull Request.
|
- Add Jira issue reference in the title of the Pull Request.
|
||||||
- Work on the pull request.
|
- Work on the pull request.
|
||||||
- Wait for review and confirmation from another developer before merging to master.
|
- Use the `./do qa` command to check your code style before pushing.
|
||||||
- Commit title no more than 80 chars, empty line after.
|
- Use good commit messages as explained here https://chris.beams.io/posts/git-commit
|
||||||
- Commit description as long as you want, 80 chars wrap.
|
- Wait for review from another developer.
|
||||||
|
|
||||||
## Issues creation.
|
## Issues creation
|
||||||
- Issues are managed on Jira.
|
- Issues are managed on Jira.
|
||||||
- Discuss issues on public Slack chats, discuss code in pull requests.
|
- Discuss issues on public Slack chats, discuss code in pull requests.
|
||||||
- Open a small Jira issue only when it has been discussed.
|
- Open a small Jira issue only when it has been discussed.
|
||||||
|
289
README.md
289
README.md
@@ -1,187 +1,130 @@
|
|||||||
# MailPoet.
|
# MailPoet
|
||||||
|
|
||||||
MailPoet done the right way.
|
MailPoet done the right way.
|
||||||
|
|
||||||
# Install.
|
# Contents
|
||||||
|
|
||||||
- Install system dependencies:
|
- [Setup](#setup)
|
||||||
```
|
- [Frameworks and libraries](#frameworks-and-libraries)
|
||||||
php
|
- [Files structure](#files-structure)
|
||||||
nodejs
|
- [Workflow Commands](#workflow-commands)
|
||||||
wordpress
|
|
||||||
```
|
|
||||||
|
|
||||||
- Clone the repo in `wp-content/plugins`.
|
# Setup
|
||||||
|
|
||||||
- Install composer.
|
## Requirements
|
||||||
```sh
|
- PHP 5.6+
|
||||||
$ curl -sS https://getcomposer.org/installer | php
|
- NodeJS
|
||||||
$ ./composer.phar install
|
- WordPress
|
||||||
```
|
- Docker & Docker Compose
|
||||||
|
|
||||||
- Install dependencies.
|
## Installation
|
||||||
```sh
|
```bash
|
||||||
$ ./do install
|
# go to WP plugins directory
|
||||||
```
|
$ cd path_to_wp_directory/wp-content/plugins
|
||||||
|
# clone this repository
|
||||||
- Update dependencies when needed.
|
$ git clone https://github.com/mailpoet/mailpoet.git
|
||||||
```sh
|
$ cd mailpoet
|
||||||
$ ./do update
|
# create the .env file
|
||||||
```
|
|
||||||
|
|
||||||
- Copy .env.sample to .env.
|
|
||||||
```sh
|
|
||||||
$ cp .env.sample .env
|
$ cp .env.sample .env
|
||||||
```
|
# change the values on .env file
|
||||||
|
# download composer
|
||||||
- Compile assets.
|
$ curl -sS https://getcomposer.org/installer | php
|
||||||
```sh
|
$ chmod +x ./composer.phar
|
||||||
|
# install PHP dependencies
|
||||||
|
$ ./composer.phar install
|
||||||
|
# install all dependencies (PHP and JS)
|
||||||
|
$ ./do install
|
||||||
|
# compile JS and CSS files
|
||||||
$ ./do compile:all
|
$ ./do compile:all
|
||||||
```
|
```
|
||||||
|
|
||||||
# Tests.
|
# Frameworks and libraries
|
||||||
|
|
||||||
- Unit tests (using [verify](https://github.com/Codeception/Verify)):
|
- [Paris ORM](https://github.com/j4mie/paris).
|
||||||
```sh
|
- [Robo](https://robo.li/) is used to write and run workflow commands.
|
||||||
$ ./do test:unit
|
- [Codeception](https://codeception.com/) is used to write unit and acceptance tests.
|
||||||
|
- [Docker](https://www.docker.com/), [Docker Compose](https://docs.docker.com/compose/) and [Selenium](https://www.seleniumhq.org/) to run acceptance tests.
|
||||||
|
- [React](https://reactjs.org/) is used to create most of UIs.
|
||||||
|
- [Marionette](https://marionettejs.com/) is used to build the newsletters editor.
|
||||||
|
- [Stylus](http://stylus-lang.com/) is used to write styles.
|
||||||
|
- [Mocha](https://mochajs.org/), [Chai](https://www.chaijs.com/) and [Sinon](https://sinonjs.org/) are used to write Javascript tests.
|
||||||
|
- [ESLint](https://eslint.org/) is used to lint JS files.
|
||||||
|
- [Webpack](https://webpack.js.org/) is used to bundle assets.
|
||||||
|
|
||||||
|
# Files structure
|
||||||
|
```bash
|
||||||
|
assets/
|
||||||
|
css/src/ # CSS source files using Stylus
|
||||||
|
fonts/
|
||||||
|
img/
|
||||||
|
js/src/ # JS source files
|
||||||
|
codeception.acceptance.yml
|
||||||
|
codeception.unit.yml
|
||||||
|
composer.json
|
||||||
|
composer.lock
|
||||||
|
CONTRIBUTING.md
|
||||||
|
do -> vendor/bin/robo
|
||||||
|
docker-compose.yml
|
||||||
|
docker-entrypoint.sh
|
||||||
|
Dockerfile
|
||||||
|
index.php
|
||||||
|
lib/ # PHP source files
|
||||||
|
license.txt
|
||||||
|
mailpoet-cron.php
|
||||||
|
mailpoet_initializer.php
|
||||||
|
mailpoet.php
|
||||||
|
package.json
|
||||||
|
package-lock.json
|
||||||
|
README.md
|
||||||
|
readme.txt
|
||||||
|
RoboFile.php # workflow commands are defined here
|
||||||
|
tests/
|
||||||
|
acceptance/ # acceptance tests using Codeception
|
||||||
|
javascript/ # Javascript tests using mocha, chai and sinon
|
||||||
|
unit/ # PHP unit tests using Codeception
|
||||||
|
uninstall.php
|
||||||
|
views/ # templates using Twig and Handlebars
|
||||||
|
webpack.config.js
|
||||||
```
|
```
|
||||||
|
|
||||||
- JS tests (using Mocha):
|
# Workflow Commands
|
||||||
```sh
|
|
||||||
$ ./do test:javascript
|
```bash
|
||||||
|
$ ./do install # install PHP and JS dependencies
|
||||||
|
$ ./do update # update PHP and JS dependencies
|
||||||
|
|
||||||
|
$ ./do compile:css # compiles Stylus files into CSS.
|
||||||
|
$ ./do compile:js # bundles JS files for the browser.
|
||||||
|
$ ./do compile:all # compiles CSS and JS files.
|
||||||
|
|
||||||
|
$ ./do watch:css # watch CSS files for changes and compile them.
|
||||||
|
$ ./do watch:js # watch JS files for changes and compile them.
|
||||||
|
$ ./do watch # watch CSS and JS files for changes and compile them.
|
||||||
|
|
||||||
|
$ ./do test:unit [--file=...] [--multisite] [--debug]
|
||||||
|
# runs the PHP unit tests.
|
||||||
|
# if --file specified then only tests on that file are executed.
|
||||||
|
# if --multisite then unit tests are executed in a multisite wordpress setup.
|
||||||
|
# if --debug then tests are executed in debugging mode.
|
||||||
|
$ ./do test:multisite:unit # alias for ./do test:unit --multisite
|
||||||
|
$ ./do test:debug # alias for ./do test:unit --debug
|
||||||
|
$ ./do test:failed # run the last failing unit test.
|
||||||
|
$ ./do test:coverage # run unit tests and output coverage information.
|
||||||
|
$ ./do test:javascript # run the JS tests.
|
||||||
|
$ ./do test:acceptance [--file=...] [--skip-deps]
|
||||||
|
# run acceptances tests into a docker environment.
|
||||||
|
# if --file given then only tests on that file are executed.
|
||||||
|
# if --skip-deps then it skips installation of composer dependencies.
|
||||||
|
$ ./do test:acceptance:multisite [--file=...] [--skip-deps]
|
||||||
|
# same as test:acceptance but runs into a multisite wordpress setup.
|
||||||
|
$ ./do delete:docker # stop and remove all running docker containers.
|
||||||
|
|
||||||
|
$ ./do qa:lint # PHP code linter.
|
||||||
|
$ ./do qa:lint:javascript # JS code linter.
|
||||||
|
$ ./do qa # PHP and JS linters.
|
||||||
```
|
```
|
||||||
|
|
||||||
- Debug tests:
|
## Acceptance testing
|
||||||
```sh
|
|
||||||
$ ./do test:debug
|
|
||||||
```
|
|
||||||
|
|
||||||
- Code linters and quality checkers:
|
|
||||||
```sh
|
|
||||||
$ ./do qa
|
|
||||||
```
|
|
||||||
|
|
||||||
- Javascript linter:
|
|
||||||
```sh
|
|
||||||
$ ./do lint:javascript
|
|
||||||
```
|
|
||||||
|
|
||||||
# CSS
|
|
||||||
- [Stylus](https://learnboost.github.io/stylus/)
|
|
||||||
- [Nib extension](http://tj.github.io/nib/)
|
|
||||||
|
|
||||||
```sh
|
|
||||||
assets/css/src -> place your *.styl files here
|
|
||||||
```
|
|
||||||
|
|
||||||
### Watch for changes and recompile
|
|
||||||
```sh
|
|
||||||
$ ./do watch
|
|
||||||
```
|
|
||||||
|
|
||||||
## Module loading and organization
|
|
||||||
|
|
||||||
Our JS modules are stored in `assets/js/` folder. Modules should follow AMD module definition style:
|
|
||||||
|
|
||||||
```js
|
|
||||||
define('moduleName', ['dependency1', 'dependency2'], function(dependency1, dependency2){
|
|
||||||
// Module code here
|
|
||||||
|
|
||||||
return {
|
|
||||||
// Module exports here
|
|
||||||
};
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
Module loader will look for `dependency1` in `node_modules/` dependencies, as well as in `assets/js`. So you can use dependencies, defined in `package.json`, without the need of providing an absolute path to it.
|
|
||||||
Once found, dependencies will be injected into your module via function arguments.
|
|
||||||
|
|
||||||
When it comes to loading modules on a real page, WebPack uses "entry points" to create different bundles. In order for the module to be included in a specific bundle, it must be reachable from that bundle's entry point. [A good example on WebPack's website](http://webpack.github.io/docs/code-splitting.html#split-app-and-vendor-code).
|
|
||||||
|
|
||||||
Once javascript is compiled with `./do compile:javascript`, your module will be placed into a bundle. Including that bundle in a webpage will give provide you access to your module.
|
|
||||||
|
|
||||||
## Handlebars (`views/*.hbs`)
|
|
||||||
|
|
||||||
```html
|
|
||||||
<!-- use the `templates` block -->
|
|
||||||
<% block templates %>
|
|
||||||
<!-- include a .hbs template -->
|
|
||||||
<%= partial('my_template_1', 'form/templates/toolbar/fields.hbs') %>
|
|
||||||
|
|
||||||
<!-- include a .hbs template and register it as a partial -->
|
|
||||||
<%= partial('my_template_2', 'form/templates/blocks.hbs', '_my_partial') %>
|
|
||||||
|
|
||||||
<!-- custom partial using partial defined above -->
|
|
||||||
<script id="my_template_3" type="text/x-handlebars-template">
|
|
||||||
{{> _my_partial }}
|
|
||||||
</script>
|
|
||||||
<% endblock %>
|
|
||||||
```
|
|
||||||
|
|
||||||
# i18n
|
|
||||||
- Use the regular WordPress functions in PHP and Twig:
|
|
||||||
|
|
||||||
```php
|
|
||||||
__()
|
|
||||||
_n()
|
|
||||||
_x()
|
|
||||||
```
|
|
||||||
|
|
||||||
```html
|
|
||||||
<p>
|
|
||||||
<%= __('Click %shere%s!') | format('<a href="#">', '</a>') | raw %>
|
|
||||||
</p>
|
|
||||||
```
|
|
||||||
|
|
||||||
```html
|
|
||||||
<p>
|
|
||||||
<%= _n('deleted %d message', 'deleted %d messages', count) | format(count) %>
|
|
||||||
<!-- count === 1 -> "deleted 1 message" -->
|
|
||||||
<!-- count > 1 -> "deleted $count messages" -->
|
|
||||||
</p>
|
|
||||||
```
|
|
||||||
|
|
||||||
- Handlebars.
|
|
||||||
|
|
||||||
You can use Twig i18n functions in Handlebars, just load your template from a Twig view.
|
|
||||||
|
|
||||||
# Build
|
|
||||||
|
|
||||||
To build a plugin , run `./build.sh`.
|
|
||||||
|
|
||||||
Some build process steps are described below (their dependencies etc.).
|
|
||||||
|
|
||||||
## packtranslations step
|
|
||||||
|
|
||||||
This step imports translations from Transifex and generates MO files. It requires:
|
|
||||||
* `tx` client: https://docs.transifex.com/client/installing-the-client
|
|
||||||
* `msgfmt` command (from Gettext package)
|
|
||||||
Finally , a `WP_TRANSIFEX_API_TOKEN` environment variable should be initialized with a valid key.
|
|
||||||
|
|
||||||
# Publish
|
|
||||||
|
|
||||||
The `publish` command currently does the following:
|
|
||||||
* Pushes translations POT file to Transifex;
|
|
||||||
* Publishes the release in SVN.
|
|
||||||
|
|
||||||
Before you run it, you need to:
|
|
||||||
1. Ensure there is an up-to-date local copy of MailPoet SVN repository in `.mp_svn` directory by running `./do svn:checkout`.
|
|
||||||
2. Have all your features merged in Git `master`, your `mailpoet.php` and `readme.txt` tagged with a new version.
|
|
||||||
3. Run `./build.sh` to produce a `mailpoet.zip` distributable archive.
|
|
||||||
|
|
||||||
Everything's ready? Then run `./do publish`.
|
|
||||||
If the job goes fine, you'll get a message like this:
|
|
||||||
```
|
|
||||||
Go to '.mp_svn' and run 'svn ci -m "Release 3.0.0-beta.9"' to publish the
|
|
||||||
release
|
|
||||||
|
|
||||||
Run 'svn copy ...' to tag the release
|
|
||||||
```
|
|
||||||
It's quite literal: you can review the changes to be pushed and if you're satisfied, run the suggested command to finish the release publishing process.
|
|
||||||
|
|
||||||
If you're confident, execute `./do publish --force` and your release will be published to the remote SVN repository without manual intervention (automatically). For easier authentication you might want to set `WP_SVN_USERNAME` and `WP_SVN_PASSWORD` environment variables.
|
|
||||||
|
|
||||||
# Acceptance testing
|
|
||||||
|
|
||||||
We are using Gravity Flow plugin's setup as an example for our acceptance test suite: https://www.stevenhenty.com/learn-acceptance-testing-deeply/
|
We are using Gravity Flow plugin's setup as an example for our acceptance test suite: https://www.stevenhenty.com/learn-acceptance-testing-deeply/
|
||||||
|
|
||||||
@@ -193,13 +136,3 @@ The browser runs in a docker container. You can use a VNC client to watch the te
|
|||||||
repo: https://github.com/SeleniumHQ/docker-selenium
|
repo: https://github.com/SeleniumHQ/docker-selenium
|
||||||
If you’re on a Mac, you can open vnc://localhost:5900 in Safari to watch the tests running in Chrome. If you’re on Windows, you’ll need a VNC client. Password: secret.
|
If you’re on a Mac, you can open vnc://localhost:5900 in Safari to watch the tests running in Chrome. If you’re on Windows, you’ll need a VNC client. Password: secret.
|
||||||
|
|
||||||
|
|
||||||
To run tests:
|
|
||||||
```sh
|
|
||||||
$ ./do test:acceptance
|
|
||||||
```
|
|
||||||
|
|
||||||
You can skip installation of composer dependencies using --skip-deps parameter.
|
|
||||||
```sh
|
|
||||||
$ ./do test:acceptance --skip-deps
|
|
||||||
```
|
|
||||||
|
12
RoboFile.php
12
RoboFile.php
@@ -219,16 +219,8 @@ class RoboFile extends \Robo\Tasks {
|
|||||||
return $this->_exec('vendor/bin/security-checker security:check --format=simple');
|
return $this->_exec('vendor/bin/security-checker security:check --format=simple');
|
||||||
}
|
}
|
||||||
|
|
||||||
function testDebug($opts=['file' => null, 'xml' => false]) {
|
function testDebug($opts=['file' => null, 'xml' => false, 'debug' => true]) {
|
||||||
$this->loadEnv();
|
return $this->testUnit($opts);
|
||||||
$this->_exec('vendor/bin/codecept build -c codeception.unit.yml');
|
|
||||||
|
|
||||||
$command = 'vendor/bin/codecept run unit -c codeception.unit.yml --debug -f '.(($opts['file']) ? $opts['file'] : '');
|
|
||||||
|
|
||||||
if($opts['xml']) {
|
|
||||||
$command .= ' --xml';
|
|
||||||
}
|
|
||||||
return $this->_exec($command);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function testAcceptance($opts=['file' => null, 'skip-deps' => false]) {
|
function testAcceptance($opts=['file' => null, 'skip-deps' => false]) {
|
||||||
|
Reference in New Issue
Block a user