Skip to content
This repository has been archived by the owner on Sep 6, 2024. It is now read-only.

Commit

Permalink
Major refactor to provide actions and filters instead of having every…
Browse files Browse the repository at this point in the history
…thing done inside the launch_wordpress() function (#99)

* Introduce actions and filters

* Factor out handling of features like plugins multisite and ssl into own
files

* Make settings hookable

* Add some docs

* Add create_endpoint_feature_defaults filter

* add jurassic_ninja_rest_create_request_features filter

* Add jurassic_ninja_created_site_url filter

* move plugin features to individual files

* introduce collectFeaturesFromQueryString

* remove js check that is now made server side for jetpack branches

* Remove unnecessary filter jurassic_ninja_features

Defaults are implemented by each portion of code implementing hooks

* Fix default for empty search query

* Update license to GPL-2

* Bump version to 3.0

* Dockument all actions

* Document all filters

* fix path in features readme

* Move features directory to root and make their loading be filterable

* README improvements

* Improve development.md

* Remove word filtering as we now control the set of words
  • Loading branch information
oskosk authored Apr 3, 2018
1 parent d031933 commit 75166ef
Show file tree
Hide file tree
Showing 23 changed files with 1,326 additions and 507 deletions.
378 changes: 357 additions & 21 deletions LICENSE

Large diffs are not rendered by default.

62 changes: 30 additions & 32 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,80 +1,78 @@
# jurassic.ninja

A frontend to launching ephemeral WordPress instances that auto-destroy after some time
A frontend to launching ephemeral WordPress instances that auto-destroy after some time.

## Usage

### Requirements

* An ubuntu box managed by ServerPilot
* A ServerPilot plan. One of the paid plans. Coach plan is OK. This is to take advantage of multiple sysusers management
* `sshpass` installed on the box.
* `wp cli` and `composer` (which is already installed by ServerPilot).
* An [ubuntu box managed by ServerPilot](https://serverpilot.io/community/articles/connect-a-digitalocean-server.html).
* A [ServerPilot plan](https://serverpilot.io/community/articles/how-to-upgrade-your-account.html). One of the paid plans. Coach plan is OK. This is to take advantage of multiple sysusers management.
* [sshpass](https://linux.die.net/man/1/sshpass) installed on the box. (Just `apt-get install sshpass` after you have the Ubuntu box set up).
* **Have a domain name you fully control**.
* Add wildcard A record for every subdomain under that domain, pointing to the box's IP addresss.
* Add a wildcard A record for every subdomain under that domain, pointing to the box's IP addresss.

### Installation

**Warning**: On plugin activation, this plugin will create two tables on the same DB your WordPress is running.
This software is implemented as a WordPress plugin that can be added on top of WordPress and configured via wp-admin.

On plugin activation, this plugin will create two tables on the same database your WordPress is running. Named `sites` and `purged`.

Basically the steps are

1. Install the plugin and activate it.
1. Create the needed pages (home and `/create`).
1. Configure ServerPilot credentials.

#### Install the Plugin
#### 1. Install the Plugin

Install it
* Get the bundle from GitHub.

```sh
wp plugin install https://github.com/oskosk/jurassic.ninja/archive/master.zip
```
```sh
wp plugin install https://github.com/oskosk/jurassic.ninja/archive/master.zip
```

Install composer dependencies
* Install composer dependencies

```sh
cd wp-content/plugins/jurassic.ninja
composer install
```
```sh
cd wp-content/plugins/jurassic.ninja
composer install
```

#### Activate the plugin
* **Activate the plugin**

```sh
wp plugin activate jurassic.ninja
```
```sh
wp plugin activate jurassic.ninja
```

#### Create needed pages
#### 2. Create pages for launching the sites.

All of the frontend magic is done by a little piece of Javascript that detects if current page is
on the `/create` route and if it's the case it just launches a request in the background
to the plugin's REST API in order to launch a new site.
All of the frontend site launching is done by a little piece of Javascript that detects if current page is on the `/create` path and if it's the case it just launches a request in the background to this plugin's REST API in order to launch a new site.

#### Create a /create page_title
**Create a page with the slug `create` **

Create a page titled **Create**. Make sure its slug is `/create`.

And add this using the Text version of the editor:
And add this content using the Text version of the editor:

```html
<img id="img1" src="https://media.giphy.com/media/uIRyMKFfmoHyo/giphy.gif" style="display:none" />
<img id="img2" src="https://i1.wp.com/media.giphy.com/media/KF3r4Q6YCtfOM/giphy.gif?ssl=1" style="display:none" />
<p class="lead" id="progress">Launching a fresh WP with a Jetpack ...</p>
```

#### Create a home page with a link to `/create`
**Create a home page with a link to `/create`**

1. Create a new page and configure it a static front page with a link to `/create`.

#### Configure Jurassic Ninja Settings page in wp-admin
#### 3. Configure Jurassic Ninja Settings page in wp-admin

1. Visit the Jurassic Ninja Settings page in wp-admin.
2. Configure your Server pilot client id, client key and server id.
3. Configure the top-domain on which this is going to create sites.

#### Using docker image for testing
### Using a docker container for testing

It is convenient to test the application using a docker image. Make sure that docker is installed and running before proceed.
It may be convenient to use this plugin using a docker image for local development. Make sure that [docker is installed and running](https://docs.docker.com/install/) before proceeding.

1. In project directory create `jndb` folder where WordPress DB will be stored:

Expand Down
47 changes: 47 additions & 0 deletions docs/development.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@


The regular life cycle of a Jurassic Ninja site

```
* User gets to the Create page
* The JS on the create page fires a request to REST API endpoint: `/wp-json/jurassicninja/create`.
* The PHP function `launch_wordpress()` gets called and the new site is launched with all the features.
* The REST request finishes with an URL for the created site.
* That URL is shown to the user.
* The user visits the site, gets auto-logged in, acquiring a WordPress cookie.
* The site is purged 7 days after that first auto login or 7 days after the user entered credentials the last time. This can happen if the user signed out and signed in again.
```

The `launch_wordpress()` function can be explained as:

```
2. Collects requested features and merges with defaults.
3. Decide if we need to do something regarding the requested Features (`jurassic_ninja_do_feature_conditions` action).
4. Generates a random subdomain.
5. Creates a user. Hookable via the `jurassic_ninja_create_sysuser` action.
6. Launches a new environment for a PHP/MysQL app and installs WordPress. Hookable via the `jurassic_ninja_create_app` action.
7. Add features that need to be added before enabling the autologin mechanism (`jurassic_ninja_add_features_before_auto_login` action).
8. Enable autologin.
9. Add features that need to be added after enabling the autologin mechanism (`jurassic_ninja_add_features_before_auto_login` action).
```


### Adding Features

Basically you can go an peek the `features` directory which contains a few files that make use of the available actions and filters.

But the main hooks to look are:

* jurassic_ninja_init (Action).
* jurassic_ninja_admin_init (Action).
* jurassic_ninja_settings_options_page (Filter).
* jurassic_ninja_settings_options_page_default_plugins (Filter).
* jurassic_ninja_rest_feature_defaults (Filter).
* jurassic_ninja_rest_create_request_features (Filter ).
* jurassic_ninja_do_feature_conditions (Action).
* jurassic_ninja_add_features_before_auto_login (Action).
* jurassic_ninja_add_features_after_auto_login (Action).
* jurassic_ninja_feature_command (Filter).
* jurassic_ninja_created_site_url (Filter).


18 changes: 18 additions & 0 deletions features/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#### features

Features are whatever we put on to of a regular site.

A regular site would be defined as:

`Latest WordPress stable, single site installation running over http`.

The main file (stuff.php) defines a few hooks that allow us to build features on top of the site launching flow.

Some features are:

- Enabling of SSL. (`ssl.php`).
- Addition of plugins. (`plugins.php`).
- Setting of wp-config constants like WP_DEBU and WP_DEBUG_LOG. (`wp-debug-log.php`).
- Launching multisite installations instead of single site( '')

Refer to the [API](docs/development.md#API) section of the development doc to find out about existing hooks.
28 changes: 28 additions & 0 deletions features/config-constants.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace jn;

add_action( 'jurassic_ninja_init', function() {
$defaults = [
'config-constants' => false,
];

add_action( 'jurassic_ninja_add_features_before_auto_login', function( &$app, $features, $domain ) use ( $defaults ) {
$features = array_merge( $defaults, $features );
if ( $features['config-constants'] ) {
debug( '%s: Adding Config Constants Plugin', $domain );
add_config_constants_plugin();
}
}, 10, 3 );

} );

/**
* Installs and activates the Config Constants plugin on the site.
*/
function add_config_constants_plugin() {
$cmd = 'wp plugin install config-constants --activate';
add_filter( 'jurassic_ninja_feature_command', function ( $s ) use ( $cmd ) {
return "$s && $cmd";
} );
}
28 changes: 28 additions & 0 deletions features/gutenberg.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace jn;

add_action( 'jurassic_ninja_init', function() {
$defaults = [
'gutenberg' => false,
];

add_action( 'jurassic_ninja_add_features_before_auto_login', function( &$app, $features, $domain ) use ( $defaults ) {
$features = array_merge( $defaults, $features );
if ( $features['gutenberg'] ) {
debug( '%s: Adding Gutenberg', $domain );
add_gutenberg_plugin();
}
}, 10, 3 );

} );

/**
* Installs and activates Gutenberg Plugin on the site.
*/
function add_gutenberg_plugin() {
$cmd = 'wp plugin install gutenberg --activate';
add_filter( 'jurassic_ninja_feature_command', function ( $s ) use ( $cmd ) {
return "$s && $cmd";
} );
}
100 changes: 100 additions & 0 deletions features/jetpack-beta.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
<?php

namespace jn;

add_action( 'jurassic_ninja_init', function() {
$defaults = [
'jetpack-beta' => false,
'branch' => false,
];

add_action( 'jurassic_ninja_add_features_before_auto_login', function( &$app, $features, $domain ) use ( $defaults ) {
$features = array_merge( $defaults, $features );
if ( $features['jetpack-beta'] ) {
debug( '%s: Adding Jetpack Beta Tester Plugin', $domain );
add_jetpack_beta_plugin();
}

if ( $features['branch'] ) {
debug( '%s: Activating Jetpack %s branch in Beta plugin', $domain, $features['branch'] );
activate_jetpack_branch( $features['branch'] );
}
}, 10, 3 );

add_filter( 'jurassic_ninja_rest_feature_defaults', function( $defaults ) {
return array_merge( $defaults, [
'jetpack-beta' => (bool) settings( 'add_jetpack_beta_by_default', false ),
] );
} );

add_filter( 'jurassic_ninja_rest_create_request_features', function( $features, $json_params ) {
$branch = isset( $json_params['branch'] ) ? $json_params['branch'] : 'master';
if ( isset( $json_params['jetpack-beta'] ) && $json_params['jetpack-beta'] ) {
$url = get_jetpack_beta_url( $branch );

if ( null === $url ) {
return new \WP_Error(
'failed_to_launch_site_with_branch',
esc_html__( 'Invalid branch name or not ready yet: ' . $branch ),
[
'status' => 400,
]
);
}
$features['jetpack-beta'] = $json_params['jetpack-beta'];
$features['branch'] = $branch;
}

return $features;
}, 10, 2 );
} );

add_action( 'jurassic_ninja_admin_init', function() {
add_filter( 'jurassic_ninja_settings_options_page_default_plugins', function( $fields ) {
$field = [
'add_jetpack_beta_by_default' => [
'id' => 'add_jetpack_beta_by_default',
'title' => __( 'Add Jetpack Beta Tester plugin to every launched WordPress', 'jurassic-ninja' ),
'text' => __( 'Install and activate Jetpack Beta Tester on launch', 'jurassic-ninja' ),
'type' => 'checkbox',
'checked' => false,
],
];
return array_merge( $fields, $field );
}, 10 );
} );

/**
* Installs and activates Jetpack Beta Tester plugin on the site.
*/
function add_jetpack_beta_plugin() {
$jetpack_beta_plugin_url = JETPACK_BETA_PLUGIN_URL;
$cmd = "wp plugin install $jetpack_beta_plugin_url --activate" ;
add_filter( 'jurassic_ninja_feature_command', function ( $s ) use ( $cmd ) {
return "$s && $cmd";
} );
}

/**
* Activates jetpack branch in Beta plugin
*/
function activate_jetpack_branch( $branch_name ) {
$cmd = "wp jetpack-beta branch activate $branch_name";
add_filter( 'jurassic_ninja_feature_command', function ( $s ) use ( $cmd ) {
return "$s && $cmd";
} );
}

function get_jetpack_beta_url( $branch_name ) {
$branch_name = str_replace( '/', '_', $branch_name );
$manifest_url = 'https://betadownload.jetpack.me/jetpack-branches.json';
$manifest = json_decode( wp_remote_retrieve_body( wp_remote_get( $manifest_url ) ) );

if ( ( 'rc' === $branch_name || 'master' === $branch_name ) && isset( $manifest->{$branch_name}->download_url ) ) {
return $manifest->{$branch_name}->download_url;
}

if ( isset( $manifest->pr->{$branch_name}->download_url ) ) {
return $manifest->pr->{$branch_name}->download_url;
}
}
Loading

0 comments on commit 75166ef

Please sign in to comment.