An Apache based Vagrant configuration for helping you get the most out of WordPress Development.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.
 
 
 
 
 

437 lines
12 KiB

  1. #!/usr/bin/env php
  2. <?php
  3. /**
  4. * Generate site configurations easily from the command line.
  5. *
  6. * @version 0.0.1
  7. * @author Chris Wiegman <info@chriswiegman.com>
  8. */
  9. $operations = array(
  10. // command operations.
  11. 'site-list::', // List existing sites.
  12. 'create-site::', // Use to create a site.
  13. 'delete-site::', // Use to delete a site.
  14. 'create-plugin::', // Create a plugin project
  15. 'create-theme::', // Create a theme project
  16. 'delete-plugin::', // Delete a plugin project
  17. 'delete-theme::', // Delete a theme project.
  18. );
  19. $args = array(
  20. // Project to work on.
  21. 'name::', // Primary project name for sites.
  22. // Options for all projects.
  23. 'root::', // The root directory to map.
  24. 'deletefiles::', // Set to perform deletion of all files when removing a project.
  25. // Virtualhost options.
  26. 'domain::', // The primary domain name for the site.
  27. 'database::', // Override database name.
  28. 'alias::', // Server alias(es).
  29. 'apacheroot::', // The apache docroot.
  30. 'nodatabase::', // Set to prevent creation of a database.
  31. // Vagrant options.
  32. 'noprovision::', // Set the flag to prevent a reload/provision.
  33. );
  34. $options = getopt( '', array_merge( $args, $operations ) );
  35. // Make sure the user provided a valid operation.
  36. $valid_operation = false;
  37. foreach ( $operations as $operation ) {
  38. if ( array_key_exists( str_replace( '::', '', $operation ), $options ) ) {
  39. $valid_operation = true;
  40. }
  41. }
  42. if ( false === $valid_operation ) {
  43. fwrite( STDERR, 'You must specify a valid operation. View README.md for more information on using the project generator.' . PHP_EOL );
  44. exit( 1 );
  45. }
  46. // Execute list functions.
  47. if ( isset( $options['list'] ) ) {
  48. echo 'Site list is still in progress. Please check back soon.' . PHP_EOL;
  49. exit();
  50. }
  51. // Make sure we have a project name.
  52. while ( ! isset( $options['name'] ) || empty( trim( $options['name'] ) ) ) {
  53. echo 'Enter a project name for the site:';
  54. $handle = fopen( 'php://stdin', 'r' );
  55. $options['name'] = sanitize_file_name( trim( fgets( $handle ) ) );
  56. fclose( $handle );
  57. }
  58. $options['name'] = sanitize_file_name( $options['name'] ); // Make sure the name is sanitized even if we didn't override.
  59. // Setup the site folder information.
  60. $options['site_folder'] = dirname( __FILE__ ) . '/user-data/sites/' . $options['name'];
  61. // A flag to prevent wasting time provisioning if it isn't needed.
  62. $needs_provision = false;
  63. // Setup variables common to both site creation and site deletion.
  64. if ( isset( $options['create-site'] ) || isset( $options['delete-site'] ) ) {
  65. // Make sure we have a domain name.
  66. if ( ! isset( $options['domain'] ) ) {
  67. $options['domain'] = $options['name'];
  68. }
  69. // Get the vhost file and make sure it hasn't already been created.
  70. $vhost_file = dirname( __FILE__ ) . '/user-data/vhosts/' . $options['name'] . '.pp';
  71. }
  72. // Execute create-site functions.
  73. if ( isset( $options['create-site'] ) ) {
  74. // Create the directory and verify the vhost file doesn't already exists or die if it already exists.
  75. if ( ! is_dir( $options['site_folder'] ) && ! file_exists( $vhost_file ) ) {
  76. mkdir( $options['site_folder'] );
  77. } elseif ( file_exists( $vhost_file ) || file_exists( $options['site_folder'] . '/pv-hosts' ) || file_exists( $options['site_folder'] . '/pv-mappings' ) ) {
  78. // Throw an error if any of the Primary Vagrant site files already exist.
  79. fwrite( STDERR, 'A site with this domain already seems to exist. Please use a different site name or delete the existing site first.' . PHP_EOL );
  80. exit( 1 );
  81. }
  82. echo 'Site folder created.' . PHP_EOL;
  83. // Make sure we have a valid site root.
  84. if ( ! isset( $options['root'] ) ) {
  85. $options['root'] = $options['site_folder'];
  86. } elseif ( ! is_dir( $options['root'] ) ) { // Throw an error if the root directory isn't already a valid directory.
  87. fwrite( STDERR, 'The project root directory specified is not valid. Please specify a valid directory as "root"' . PHP_EOL );
  88. exit( 1 );
  89. }
  90. // Make sure we have a valid apache doc root.
  91. if ( ! isset( $options['apacheroot'] ) ) {
  92. $options['apacheroot'] = '';
  93. }
  94. $options['apacheroot'] = sanitize_file_name( $options['apacheroot'] );
  95. $apache_path = $options['site_folder'] . '/' . $options['apacheroot'];
  96. // Create the apache root directory if it is different than the site root.
  97. if ( ! is_dir( $apache_path ) ) {
  98. mkdir( $apache_path );
  99. echo 'Apache docroot folder created.' . PHP_EOL;
  100. }
  101. // Create a list of the domain and any aliases.
  102. $domains = $options['domain'] . PHP_EOL;
  103. $aliases = ''; // A space delimited string of aliases only for use in the VHost configuration.
  104. if ( isset( $options['alias'] ) ) {
  105. if ( is_array( $options['alias'] ) ) {
  106. foreach ( $options['alias'] as $alias ) {
  107. $domains .= sanitize_file_name( $alias ) . PHP_EOL;
  108. $aliases .= sanitize_file_name( $alias ) . ' ';
  109. }
  110. $aliases = substr( $aliases, 0, strlen( $aliases ) - 1 ); // Remove the last space.
  111. } else {
  112. $domains .= sanitize_file_name( $options['alias'] ) . PHP_EOL;
  113. $aliases = sanitize_file_name( $options['alias'] );
  114. }
  115. }
  116. $domains = substr( $domains, 0, strlen( $domains ) - 1 ); // Remove the last newline.
  117. // Create and write the pv-hosts file.
  118. $handle = fopen( $options['site_folder'] . '/pv-hosts', 'x+' );
  119. fwrite( $handle, $domains );
  120. fclose( $handle );
  121. echo 'Hosts file created.' . PHP_EOL;
  122. // Write the mapping file.
  123. $mapping = 'config.vm.synced_folder "' . $options['root'] . '", "/var/www/' . $options['name'] . '", :owner => "www-data", :mount_options => [ "dmode=775", "fmode=774"]';
  124. $handle = fopen( $options['site_folder'] . '/pv-mappings', 'x+' );
  125. fwrite( $handle, $mapping );
  126. fclose( $handle );
  127. echo 'Mappings file created.' . PHP_EOL;
  128. // Create the vhost config.
  129. $vhost_config = '# Site Created with Primary Vagrant Site Generator.' . PHP_EOL . PHP_EOL; // Header for easier usage later.
  130. $vhost_config .= "apache::vhost { '" . $options['domain'] . "':" . PHP_EOL;
  131. if ( ! empty( $aliases ) ) {
  132. $vhost_config .= " serveraliases => '" . $aliases . "'," . PHP_EOL;
  133. }
  134. // @todo set more of these items as options.
  135. $vhost_config .= " docroot => '/var/www/" . $options['name'] . "/" . $options['apacheroot'] . "'," . PHP_EOL;
  136. $vhost_config .= " directory => '/var/www/" . $options['name'] . "/" . $options['apacheroot'] . "'," . PHP_EOL;
  137. $vhost_config .= " directory_allow_override => 'All'," . PHP_EOL;
  138. $vhost_config .= " ssl => true," . PHP_EOL;
  139. $vhost_config .= "}" . PHP_EOL;
  140. // Only add database information if we need to.
  141. if ( ! isset( $options['nodatabase'] ) ) {
  142. $database_name = $options['name'];
  143. // Respect and override set for the database name.
  144. if ( isset( $options['database'] ) ) {
  145. $database_name = sanitize_file_name( $options['database'] );
  146. }
  147. // @todo set more of these items as options.
  148. $vhost_config .= PHP_EOL;
  149. $vhost_config .= "mysql_database { '" . $database_name . "':" . PHP_EOL;
  150. $vhost_config .= " ensure => 'present'," . PHP_EOL;
  151. $vhost_config .= " charset => 'utf8mb4'," . PHP_EOL;
  152. $vhost_config .= " collate => 'utf8mb4_general_ci'," . PHP_EOL;
  153. $vhost_config .= " require => Class['mysql::server']," . PHP_EOL;
  154. $vhost_config .= "}" . PHP_EOL;
  155. }
  156. // Write the virtualhost file.
  157. $handle = fopen( $vhost_file, 'x+' );
  158. fwrite( $handle, $vhost_config );
  159. fclose( $handle );
  160. echo 'Virtualhost configuration created.' . PHP_EOL;
  161. $needs_provision = true;
  162. }
  163. // Execute delete-site functions.
  164. if ( isset( $options['delete-site'] ) ) {
  165. // Delete the site configuration.
  166. if ( file_exists( $vhost_file ) ) {
  167. unlink( $vhost_file );
  168. $needs_provision = true;
  169. echo 'Deleted ' . $vhost_file . PHP_EOL;
  170. } else {
  171. echo 'The virtualhost configuration has already been deleted. No action taken.' . PHP_EOL;
  172. }
  173. if ( isset( $options['deletefiles'] ) ) { // Remove entire site folder.
  174. if ( is_dir( $options['site_folder'] ) ) {
  175. delete_directory( $options['site_folder'] );
  176. $needs_provision = true;
  177. echo 'Deleted site folder.' . PHP_EOL;
  178. } else {
  179. echo 'The site folder has already been deleted. No action taken.' . PHP_EOL;
  180. }
  181. } else { // Only remove Primary Vagrant files.
  182. // Delete pv-hosts if it exists.
  183. if ( file_exists( $options['site_folder'] . '/pv-hosts' ) ) {
  184. unlink( $options['site_folder'] . '/pv-hosts' );
  185. $needs_provision = true;
  186. echo 'Deleted ' . $options['site_folder'] . '/pv-hosts' . PHP_EOL;
  187. } else {
  188. echo 'The pv-hosts file has already been deleted. No action taken.' . PHP_EOL;
  189. }
  190. // Delete pv-mappings if it exists.
  191. if ( file_exists( $options['site_folder'] . '/pv-mappings' ) ) {
  192. unlink( $options['site_folder'] . '/pv-mappings' );
  193. $needs_provision = true;
  194. echo 'Deleted ' . $options['site_folder'] . '/pv-mappings' . PHP_EOL;
  195. } else {
  196. echo 'The pv-mappings file has already been deleted. No action taken.' . PHP_EOL;
  197. }
  198. }
  199. }
  200. // Create a plugin or theme project
  201. if ( isset( $options['create-plugin'] ) || isset( $options['create-theme'] ) ) {
  202. $needs_provision = true;
  203. // Create the directory or die if it already exists.
  204. if ( ! is_dir( $options['site_folder'] ) ) {
  205. mkdir( $options['site_folder'] );
  206. } elseif ( file_exists( $options['site_folder'] . '/pv-mappings' ) ) {
  207. // Throw an error if any of the Primary Vagrant site files already exist.
  208. fwrite( STDERR, 'A project with this name already seems to exist. Please use a different project name or delete the existing project first.' . PHP_EOL );
  209. exit( 1 );
  210. }
  211. echo 'Project folder created.' . PHP_EOL;
  212. // Make sure we have a valid plugin root.
  213. if ( ! isset( $options['root'] ) ) {
  214. $options['root'] = $options['site_folder'];
  215. } elseif ( ! is_dir( $options['root'] ) ) { // Throw an error if the root directory isn't already a valid directory.
  216. fwrite( STDERR, 'The project root directory specified is not valid. Please specify a valid directory as "root"' . PHP_EOL );
  217. exit( 1 );
  218. }
  219. // Set the appropriate destination directory for a plugin or theme.
  220. $type_dir = 'plugins';
  221. if ( isset( $options['create-theme'] ) ) {
  222. $type_dir = 'themes';
  223. }
  224. // Write the mapping file.
  225. $mapping = 'config.vm.synced_folder "' . $options['root'] . '", "/var/www/default-sites/wordpress/content/' . $type_dir . '/' . $options['name'] . '", :owner => "www-data", :mount_options => [ "dmode=775", "fmode=774"]';
  226. $handle = fopen( $options['site_folder'] . '/pv-mappings', 'x+' );
  227. fwrite( $handle, $mapping );
  228. fclose( $handle );
  229. echo 'Mappings file created.' . PHP_EOL;
  230. }
  231. // Delete a plugin or theme project
  232. if ( isset( $options['delete-plugin'] ) || isset( $options['delete-theme'] ) ) {
  233. if ( isset( $options['deletefiles'] ) ) { // Remove entire site folder.
  234. if ( is_dir( $options['site_folder'] ) ) {
  235. delete_directory( $options['site_folder'] );
  236. $needs_provision = true;
  237. echo 'Deleted project folder.' . PHP_EOL;
  238. } else {
  239. echo 'The project folder has already been deleted. No action taken.' . PHP_EOL;
  240. }
  241. } else { // Only remove Primary Vagrant files.
  242. // Delete pv-mappings if it exists.
  243. if ( file_exists( $options['site_folder'] . '/pv-mappings' ) ) {
  244. unlink( $options['site_folder'] . '/pv-mappings' );
  245. $needs_provision = true;
  246. echo 'Deleted ' . $options['site_folder'] . '/pv-mappings' . PHP_EOL;
  247. } else {
  248. echo 'The pv-mappings file has already been deleted. No action taken.' . PHP_EOL;
  249. }
  250. }
  251. }
  252. // Reload and provision vagrant if needed.
  253. if ( ! isset( $options['noprovision'] ) && true === $needs_provision ) {
  254. echo 'Reloading Vagrant for changes to take effect.' . PHP_EOL;
  255. passthru( 'vagrant reload --provision' );
  256. } elseif ( ! isset( $options['noprovision'] ) ) {
  257. echo 'Provisioning of Vagrant is not required.' . PHP_EOL;
  258. }
  259. exit();
  260. /**
  261. * Removes a directory recursively.
  262. *
  263. * @since 0.0.1
  264. *
  265. * @param string $directory The name of the directory to remove.
  266. *
  267. * @return bool True on success or false.
  268. */
  269. function delete_directory( $directory ) {
  270. $files = array_diff( scandir( $directory ), array( '.', '..' ) );
  271. foreach ( $files as $file ) {
  272. ( is_dir( $directory . '/' . $file ) ) ? delete_directory( $directory . '/' . $file ) : unlink( $directory . '/' . $file );
  273. }
  274. return rmdir( $directory );
  275. }
  276. /**
  277. * Sanitize the file and folder names submitted.
  278. *
  279. * @since 0.0.1
  280. *
  281. * @param string $file_name The file/folder name to sanitize.
  282. *
  283. * @return string A sanitized file/folder name.
  284. */
  285. function sanitize_file_name( $file_name ) {
  286. // Replace all weird characters with dashes
  287. $file_name = preg_replace( '/[^\w\-\.]+/u', '-', $file_name );
  288. // Only allow one dash separator at a time (and make string lowercase)
  289. return mb_strtolower( preg_replace( '/--+/u', '-', $file_name ), 'UTF-8' );
  290. }