1 | 'use strict';
|
2 |
|
3 | var util = require('util');
|
4 | var path = require('path');
|
5 | var yeoman = require('yeoman-generator');
|
6 | var latest = require('github-latest');
|
7 | var async = require('async');
|
8 | var chalk = require('chalk');
|
9 | var crypto = require('crypto');
|
10 | var request = require('request');
|
11 | var keygen = require('ssh-keygen');
|
12 | var fs = require('fs-extra');
|
13 |
|
14 |
|
15 | var 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 |
|
35 | util.inherits(WordpressGenerator, yeoman.generators.Base);
|
36 |
|
37 | WordpressGenerator.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 |
|
47 | WordpressGenerator.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 |
|
67 | WordpressGenerator.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 |
|
86 | WordpressGenerator.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 |
|
95 | WordpressGenerator.prototype.promptForWeb = function() {
|
96 | this.prompts.push({
|
97 | type: 'text',
|
98 | name: 'web',
|
99 | message: 'WordPress directory',
|
100 | default: 'web'
|
101 | });
|
102 | };
|
103 |
|
104 | WordpressGenerator.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 |
|
126 | WordpressGenerator.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 |
|
171 | WordpressGenerator.prototype.promptForIp = function() {
|
172 |
|
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 |
|
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 |
|
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 |
|
218 | WordpressGenerator.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 |
|
228 | WordpressGenerator.prototype.ready = function() {
|
229 | this.log.write('\n');
|
230 | this.log.info(chalk.green('Here we go!'));
|
231 | };
|
232 |
|
233 | WordpressGenerator.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 |
|
250 | WordpressGenerator.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 |
|
268 | WordpressGenerator.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 |
|
282 | WordpressGenerator.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 |
|
295 | WordpressGenerator.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 |
|
302 | WordpressGenerator.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 |
|
319 | WordpressGenerator.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 |
|
334 | WordpressGenerator.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 |
|
339 | WordpressGenerator.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 |
|
352 | module.exports = WordpressGenerator;
|