UNPKG

10.2 kBJavaScriptView Raw
1'use strict';
2
3var util = require('util');
4var path = require('path');
5var yeoman = require('yeoman-generator');
6var latest = require('github-latest');
7var async = require('async');
8var chalk = require('chalk');
9var crypto = require('crypto');
10var request = require('request');
11var keygen = require('ssh-keygen');
12var fs = require('fs-extra');
13
14
15var WordpressGenerator = function(args, options, config) {
16 yeoman.generators.Base.apply(this, arguments);
17
18 this.pkg = JSON.parse(this.readFileAsString(path.join(__dirname, '../package.json')));
19 this.prompts = [];
20
21 this.on('end', function() {
22 this.installDependencies({
23 bower: true,
24 npm: false,
25 skipInstall: options['skip-install'],
26 skipMessage: true,
27 callback: function() {
28 this.log.write();
29 this.log.ok('All done! Run ' + chalk.yellow('vagrant up') + ' to get started!');
30 }.bind(this)
31 });
32 });
33};
34
35util.inherits(WordpressGenerator, yeoman.generators.Base);
36
37WordpressGenerator.prototype.welcome = function() {
38 var message = this.readFileAsString(path.join(__dirname, 'welcome.txt'));
39
40 message = message.replace(/./g, function(match) {
41 return /\w/.test(match) ? chalk.yellow(match) : chalk.cyan(match);
42 });
43
44 this.log.writeln(message);
45};
46
47WordpressGenerator.prototype.promptForName = function() {
48 var existing = function() {
49 try {
50 var bower = JSON.parse(this.readFileAsString(path.join(this.env.cwd, 'bower.json')));
51
52 return bower.name;
53 } catch(e) {};
54 }.bind(this);
55
56 this.prompts.push({
57 required: true,
58 type: 'text',
59 name: 'name',
60 message: 'Repository name (e.g. MySite)',
61 default: function() {
62 return existing() || path.basename(this.env.cwd);
63 }.bind(this)
64 });
65};
66
67WordpressGenerator.prototype.promptForDomain = function() {
68 this.prompts.push({
69 required: true,
70 type: 'text',
71 name: 'domain',
72 message: 'Domain name (e.g. mysite.com)',
73 default: path.basename(this.env.cwd).toLowerCase(),
74 validate: function(input) {
75 if (/^[\w-]+\.\w+$/.test(input)) {
76 return true;
77 } else if (!input) {
78 return "Domain is required";
79 }
80
81 return chalk.yellow(input) + ' does not match the example';
82 }
83 });
84};
85
86WordpressGenerator.prototype.promptForGenesis = function() {
87 this.prompts.push({
88 type: 'text',
89 name: 'genesis',
90 message: 'Genesis library version',
91 default: '~0.2.*'
92 });
93};
94
95WordpressGenerator.prototype.promptForWeb = function() {
96 this.prompts.push({
97 type: 'text',
98 name: 'web',
99 message: 'WordPress directory',
100 default: 'web'
101 });
102};
103
104WordpressGenerator.prototype.promptForWordPress = function() {
105 var existing = function(web) {
106 try {
107 var file = this.readFileAsString(path.join(web, 'wp-includes', 'version.php'));
108 var version = file.match(/\$wp_version\s=\s['"]([^'"]+)/);
109
110 if (version.length) {
111 return version[1];
112 }
113 } catch(e) {}
114 }.bind(this);
115
116 this.prompts.push({
117 type: 'text',
118 name: 'wordpress',
119 message: 'WordPress version',
120 default: function(answers) {
121 return existing(answers.web) || '3.6.1';
122 }
123 });
124};
125
126WordpressGenerator.prototype.promptForDatabase = function() {
127 var done = this.async();
128 var existing = function(web, constant) {
129 try {
130 var config = this.readFileAsString(path.join(web, 'wp-config.php'));
131 var regex = new RegExp(constant + '[\'"],\\s*[\'"]([^\'"]+)');
132 var matches = regex.exec(config);
133
134 return matches && matches[1];
135 } catch(e) {}
136 }.bind(this);
137
138 crypto.randomBytes(12, function(err, buffer) {
139 this.prompts.push({
140 type: 'text',
141 name: 'DB_NAME',
142 message: 'Database name',
143 default: function(answers) { return existing(answers.web, 'DB_NAME') || 'wordpress'; }
144 });
145
146 this.prompts.push({
147 type: 'text',
148 name: 'DB_USER',
149 message: 'Database user',
150 default: function(answers) { return existing(answers.web, 'DB_USER') || 'wordpress'; }
151 });
152
153 this.prompts.push({
154 type: 'text',
155 name: 'DB_PASSWORD',
156 message: 'Database password',
157 default: function(answers) { return existing(answers.web, 'DB_PASSWORD') || buffer.toString('base64'); }
158 });
159
160 this.prompts.push({
161 type: 'text',
162 name: 'DB_HOST',
163 message: 'Database host',
164 default: function(answers) { return existing(answers.web, 'DB_HOST') || 'localhost'; }
165 });
166
167 done();
168 }.bind(this));
169};
170
171WordpressGenerator.prototype.promptForIp = function() {
172 // Private IP blocks
173 var blocks = [
174 ['192.168.0.0', '192.168.255.255'],
175 ['172.16.0.0', '172.31.255.255'],
176 ['10.0.0.0', '10.255.255.255']
177 ];
178
179 // Long IP ranges
180 var ranges = blocks.map(function(block) {
181 return block.map(function(ip) {
182 var parts = ip.split('.');
183
184 return parts[0] << 24 | parts[1] << 16 | parts[2] << 8 | parts[3] >>> 0;
185 });
186 });
187
188 // Randomize IP addresses
189 var ips = ranges.map(function(range) {
190 return Math.random() * (range[1] - range[0]) + range[0];
191 }).map(function(ip) {
192 return [
193 (ip & (0xff << 24)) >>> 24,
194 (ip & (0xff << 16)) >>> 16,
195 (ip & (0xff << 8)) >>> 8,
196 (ip & (0xff << 0)) >>> 0
197 ].join('.');
198 });
199
200 try {
201 var vagrant = this.readFileAsString('Vagrantfile').match(/ip:\s['"]([\d\.]+)['"]/);
202
203 if (vagrant.length) {
204 ips.unshift(vagrant[1]);
205 }
206 } catch(e) {}
207
208 this.prompts.push({
209 required: true,
210 type: 'list',
211 name: 'ip',
212 message: 'Vagrant IP',
213 pattern: /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/,
214 choices: ips
215 });
216};
217
218WordpressGenerator.prototype.ask = function() {
219 var done = this.async();
220
221 this.prompt(this.prompts, function(props) {
222 this.props = props;
223
224 done();
225 }.bind(this));
226};
227
228WordpressGenerator.prototype.ready = function() {
229 this.log.write('\n');
230 this.log.info(chalk.green('Here we go!'));
231};
232
233WordpressGenerator.prototype.writeProjectFiles = function() {
234 this.log.info('Writing project files...');
235
236 try {
237 this.readmeFile = this.readFileAsString(path.join(this.env.cwd, 'README.md'));
238 } catch(e) {
239 this.readmeFile = '';
240 }
241
242 this.template('gitignore', '.gitignore');
243 this.template('bower.json', 'bower.json');
244 this.template('Capfile', 'Capfile');
245 this.template('editorconfig', '.editorconfig');
246 this.template('README.md', 'README.md');
247 this.template('Vagrantfile', 'Vagrantfile');
248};
249
250WordpressGenerator.prototype.writeWordPress = function() {
251 var done = this.async();
252
253 this.log.info('Downloading WordPress...');
254
255 this.remote('wordpress', 'wordpress', this.props.wordpress, function(err, remote) {
256 this.log.info('Writing WordPress to ' + chalk.yellow(this.props.web));
257
258 fs.copy(remote.cachePath, this.props.web, function(err) {
259 if (err) {
260 return console.error(err);
261 }
262
263 done();
264 });
265 }.bind(this), true);
266};
267
268WordpressGenerator.prototype.writeWeb = function() {
269 this.log.info('Writing ' + chalk.yellow(this.props.web) + ' files...');
270
271 try {
272 this.htaccessFile = this.readFileAsString(path.join(this.env.cwd, this.props.web, '.htaccess'));
273 } catch(e) {
274 this.htaccessFile = '';
275 }
276
277 this.template('web/htaccess', path.join(this.props.web, '.htaccess'));
278 this.template('web/no_robots.txt', path.join(this.props.web, 'no_robots.txt'));
279 this.template('web/robots.txt', path.join(this.props.web, 'robots.txt'));
280};
281
282WordpressGenerator.prototype.fetchSalts = function() {
283 var done = this.async();
284
285 request('https://api.wordpress.org/secret-key/1.1/salt/', function(err, response, salts) {
286 if (err) {
287 throw err;
288 }
289
290 this.props.salts = salts;
291 done();
292 }.bind(this));
293};
294
295WordpressGenerator.prototype.setupWordPressConfig = function() {
296 this.log.info('Configuring ' + chalk.yellow('wp-config.php'));
297
298 this.wpConfigFile = this.readFileAsString(path.join(this.env.cwd, this.props.web, 'wp-config-sample.php'));
299 this.template('web/wp-config.php', path.join(this.props.web, 'wp-config.php'));
300};
301
302WordpressGenerator.prototype.setupProvisioning = function() {
303 this.log.info('Creating provisioning scripts...');
304
305 this.mkdir(path.join(this.env.cwd, 'bin'));
306 this.template('bin/provision', 'bin/provision');
307
308 this.mkdir(path.join(this.env.cwd, 'provisioning'));
309 this.template('provisioning/localhost', 'provisioning/localhost');
310 this.template('provisioning/local', 'provisioning/local');
311 this.template('provisioning/staging', 'provisioning/staging');
312 this.template('provisioning/production', 'provisioning/production');
313 this.template('provisioning/provision.yml', 'provisioning/provision.yml');
314
315 this.mkdir(path.join(this.env.cwd, 'provisioning', 'group_vars'));
316 this.template('provisioning/group_vars/webservers', 'provisioning/group_vars/webservers');
317};
318
319WordpressGenerator.prototype.createSshKeys = function() {
320 var done = this.async();
321 var location = path.join(this.env.cwd, 'provisioning', 'files', 'ssh', 'id_rsa');
322
323 this.log.info('Creating SSH keys...');
324
325 this.mkdir(path.dirname(location));
326
327 keygen({
328 location: location,
329 comment: 'deploy@' + this.props.domain,
330 read: false
331 }, done);
332};
333
334WordpressGenerator.prototype.fixPermissions = function() {
335 fs.chmodSync(path.join(this.env.cwd, 'bin', 'provision'), '744');
336 fs.chmodSync(path.join(this.env.cwd, 'provisioning', 'files', 'ssh', 'id_rsa'), '600');
337};
338
339WordpressGenerator.prototype.setupDeployment = function() {
340 this.log.info('Creating deployment scripts...');
341
342 this.mkdir(path.join(this.env.cwd, 'deployment'));
343 this.mkdir(path.join(this.env.cwd, 'deployment', 'deploy'));
344
345 this.template('deployment/deploy.rb', 'deployment/deploy.rb');
346 this.template('deployment/stages/old.rb', 'deployment/stages/old.rb');
347 this.template('deployment/stages/local.rb', 'deployment/stages/local.rb');
348 this.template('deployment/stages/staging.rb', 'deployment/stages/staging.rb');
349 this.template('deployment/stages/production.rb', 'deployment/stages/production.rb');
350};
351
352module.exports = WordpressGenerator;