├── .gitattributes ├── .github └── CONTRIBUTING.md ├── .gitignore ├── .jshintrc ├── .travis.yml ├── .yo-rc.json ├── LICENSE.md ├── README.md ├── app ├── USAGE ├── index.js └── templates │ ├── .travis.yml │ ├── Dockunit.json │ ├── README.md │ ├── _bowerrc │ ├── _editorconfig │ ├── _gitignore │ ├── assets │ ├── README.md │ ├── css │ │ └── style.css │ ├── js │ │ └── index.js │ └── repo │ │ └── README.md │ ├── bin │ └── install-wp-tests.sh │ ├── bower.json │ ├── composer.json │ ├── config │ ├── settings.js │ └── webpack.config.js │ ├── includes │ └── README.md │ ├── package.json │ ├── phpcs.xml │ ├── phpunit.xml │ ├── plugin.php │ └── tests │ ├── bootstrap.php │ └── test-base.php ├── cli ├── README.md ├── index.js └── templates │ ├── cli.php │ └── tests.php ├── cpt ├── README.md ├── index.js └── templates │ ├── cpt.php │ └── tests.php ├── css ├── README.md ├── index.js └── templates │ └── styles.css ├── endpoint ├── README.md ├── index.js └── templates │ ├── endpoint.php │ └── tests.php ├── include ├── README.md ├── index.js └── templates │ ├── include.php │ └── tests.php ├── js ├── README.md ├── index.js └── templates │ ├── _eslintrc.json │ └── main.js ├── npm-shrinkwrap.json ├── options ├── README.md ├── index.js └── templates │ ├── options.php │ └── tests.php ├── package-lock.json ├── package.json ├── pagebuilder ├── README.md ├── index.js └── templates │ ├── class-pagebuilder.php │ └── tests.php ├── phpcs.xml ├── plugin-wp-base.js ├── taxonomy ├── README.md ├── index.js └── templates │ ├── taxonomy.php │ └── tests.php ├── test ├── test-app.js ├── test-assets │ └── subgenerator-test-plugin │ │ ├── .bowerrc │ │ ├── .editorconfig │ │ ├── .eslintrc.js │ │ ├── .gitignore │ │ ├── .sass-lint.yml │ │ ├── .travis.yml │ │ ├── .yo-rc.json │ │ ├── Dockunit.json │ │ ├── Gruntfile.js │ │ ├── Gulpfile.js │ │ ├── README.md │ │ ├── assets │ │ ├── README.md │ │ └── repo │ │ │ └── README.md │ │ ├── bin │ │ └── install-wp-tests.sh │ │ ├── bower.json │ │ ├── includes │ │ └── README.md │ │ ├── package.json │ │ ├── phpcs.xml │ │ ├── phpunit.xml │ │ ├── subgenerator-test-plugin.php │ │ └── tests │ │ ├── bootstrap.php │ │ └── test-base.php ├── test-cpt.js ├── test-css.js ├── test-endpoint.js ├── test-include.js ├── test-js.js ├── test-options.js ├── test-taxonomy.js └── test-widget.js └── widget ├── README.md ├── index.js └── templates ├── tests.php └── widget.php /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Testing Your Changes 2 | 3 | To test `yo plugin-wp` using any changes you've made, while in the repo 4 | folder, run `npm link` and NPM will know to use `yo plugin-wp` using the code 5 | and templates from the repo. 6 | 7 | To get back to the official NPM `plugin-wp` command, do: 8 | 9 | ``` 10 | npm unlink && npm install -g generator-plugin-wp 11 | ``` 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Node/npm 2 | node_modules/ 3 | npm-debug.log 4 | .grunt 5 | .sass-cache 6 | 7 | # OSX 8 | .DS_Store 9 | .AppleDouble 10 | .LSOverride 11 | .Spotlight-V100 12 | .Trashes 13 | .AppleDB 14 | .AppleDesktop 15 | Network Trash Folder 16 | Temporary Items 17 | .apdisk 18 | 19 | # Icon must end with two \r 20 | Icon 21 | 22 | 23 | # Thumbnails 24 | ._* 25 | 26 | 27 | # Vim 28 | [._]*.s[a-w][a-z] 29 | [._]s[a-w][a-z] 30 | *.un~ 31 | Session.vim 32 | .netrwhist 33 | *~ 34 | 35 | # Other, add your own ignored things here. 36 | .idea/ 37 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | "esnext": true, 4 | "bitwise": true, 5 | "camelcase": true, 6 | "curly": true, 7 | "eqeqeq": true, 8 | "immed": true, 9 | "indent": 2, 10 | "latedef": true, 11 | "newcap": true, 12 | "noarg": true, 13 | "quotmark": "single", 14 | "undef": true, 15 | "unused": true, 16 | "strict": true 17 | } 18 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 'stable' 4 | before_install: 5 | - currentfolder=${PWD##*/} 6 | - if [ "$currentfolder" != 'generator-plugin-wp' ]; then cd .. && eval "mv $currentfolder generator-plugin-wp" && cd generator-plugin-wp; fi 7 | notifications: 8 | slack: 9 | secure: HSOxec12MVmrsccR3tqFgW2e4FcsO39OrOwxhDuCJBfHUEAJs99unlk/fjxe7bRRc7X85q+jyzKu/13dO4WGT51HnPnpDL/r5SNCIDGjSlpmfRfx7XAe1FLdZbY9gYHeGbGoL9Z3jvvq4UEyv6HHhy19X+NQDBmg8yp4OxECLtLKT+kFIyGCngOuu3GcXiLurKToeDBb3L0lE0mxcnslZRGSldFSH9RfnX5v96Wst+LvXF+HXiRJb+FOdL1aeGz4UiT4kzUFWWI03WNpF7HuQojP7getM9Wzhl3os6NR7TlDN5LR8SNIvBsG0zbTG37Qt0hoFDCQ5D9igYNN9rhlOfc3t+LmujAepZXx7xiuDRQoRe1nQBAeD0pY3NhdeCFNWFUqyWpcXrdAv5/8oLfuS6w4N2tCHDG46wfmkgIFCV06TjYTce1duWiJoypPveyjA4ePlbQcxzGXwStQrHspChMp2QI8VTbLD3RQ9DwlIo5QAID/f2U4cCPs6HQeo28w60oBZrCb6bjOJikBs33M1E2oc9teFbqeMKo7xFZ9kttsIBHGpFms1oRymw+idxkgFmoNOzBhCZV16Yp/8T9Xi4OfI/jJpwwWDFLsenJarMgoXScifpO9DkFMTiXDcLP4fVTti18HiQEq6aCStzQpPfejtgnS3Okp2UWxFpb0gHM= 10 | -------------------------------------------------------------------------------- /.yo-rc.json: -------------------------------------------------------------------------------- 1 | { 2 | "generator-generator": {} 3 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # generator-plugin-wp [![buddy pipeline](https://app.buddy.works/webdevstudios/generator-plugin-wp/pipelines/pipeline/226897/badge.svg?token=2471ae60766a1e9a657f772e493188dde748aa18c236d0b1c325e80be13a2ac6 "buddy pipeline")](https://app.buddy.works/webdevstudios/generator-plugin-wp/pipelines/pipeline/226897) 2 | 3 | 4 | > [Yeoman](http://yeoman.io) generator for WordPress plugins. 5 | 6 | WebDevStudios. WordPress for big brands. 7 | 8 | ## Getting Started 9 | 10 | Pre-requisites: You'll need [node](https://nodejs.org/download/) which comes 11 | with [npm](https://github.com/npm/npm#super-easy-install). 12 | 13 | If you don't have [Yeoman](http://yeoman.io/) installed: 14 | 15 | ```bash 16 | npm install -g yo 17 | ``` 18 | 19 | To install generator-plugin-wp from npm, run: 20 | 21 | ```bash 22 | npm install -g generator-plugin-wp 23 | ``` 24 | 25 | To use generator-plugin-wp, `cd` to your WordPress plugins folder and: 26 | 27 | ```bash 28 | yo plugin-wp 29 | ``` 30 | You'll be prompted with steps for creating your plugin. 31 | 32 | ## Sub-generators 33 | 34 | Once your nifty new plugin has been generated, `cd` into your new plugin's 35 | directory. While in the plugin directory, you can run additional commands 36 | called sub-generators to automatically generate files to enhance your plugin. 37 | 38 | * `yo plugin-wp:include ` [Basic Include](include/README.md) 39 | * `yo plugin-wp:cpt ` [Custom Post Type](cpt/README.md) 40 | * `yo plugin-wp:cli ` [WP CLI Command](cli/README.md) 41 | * `yo plugin-wp:taxonomy ` [Taxonomy](taxonomy/README.md) 42 | * `yo plugin-wp:options ` [Option Page](options/README.md) 43 | * `yo plugin-wp:widget ` [Widget](widget/README.md) 44 | * `yo plugin-wp:endpoint ` [WP-API Endpoint](endpoint/README.md) 45 | * `yo plugin-wp:js` [Javascript](js/README.md) 46 | * `yo plugin-wp:css` [Styles](css/README.md) 47 | 48 | For the names of the include, cpt, options, and widget subgenerators remember 49 | that the plugin prefix will be added to the class name so no need to include the 50 | original plugin name there. Think of it as the file name for each instead. 51 | 52 | ## Tests 53 | 54 | By default the plugin generator adds some built in tests for you to add on to as 55 | you develop your plugin. To run these tests run the `install-wp-tests.sh` script 56 | in the bin folder with the proper database details for your local setup. 57 | 58 | Once you've run the `install-wp-tests.sh` script you can run just `phpunit` in 59 | the main folder of your plugin. 60 | 61 | If you don't want tests included in your plugin when it is generated run the 62 | main generator with the `--notests` option. 63 | 64 | ## PHP 5.2 65 | 66 | By default PHP 5.2 is not supported in the generated plugin. To generate a plugin 67 | with PHP 5.2 support, run the main generator with the `--php52` option. 68 | 69 | ## CMB2 70 | CMB2 is included by default with the options sub-generator. It can also be a useful tool with CPT and taxonomy sub-generators using the --cmb2 flag. 71 | 72 | ## Adding Packages with Composer 73 | 74 | If you chose composer as the autoloader option during the plugin's initiation, 75 | you can use composer to add additional dependencies. 76 | 77 | Let's `cd` into our new plugin's directory and add [CMB2](https://github.com/CMB2/CMB2): 78 | 79 | ```bash 80 | composer require cmb2/cmb2 81 | ``` 82 | 83 | CMB2 will now appear under `vendor` 84 | 85 | ```bash 86 | -plugins 87 | -wds-foo-plugin 88 | -vendor 89 | -cmb2 90 | -cmb2 91 | ``` 92 | 93 | ## Contributors 94 | The following humans contributed to this awesome generator: 95 | 96 | ![](https://avatars1.githubusercontent.com/u/804253?v=3&s=20) [CamdenSegal](https://github.com/CamdenSegal), ![](https://avatars0.githubusercontent.com/u/1098900?v=3&s=20) [jtsternberg](https://github.com/jtsternberg), ![](https://avatars2.githubusercontent.com/u/991511?v=3&s=20) [jazzsequence](https://github.com/jazzsequence), ![](https://avatars1.githubusercontent.com/u/16279215?v=3&s=20) [binarygary](https://github.com/binarygary), ![](https://avatars1.githubusercontent.com/u/66798?v=3&s=20) [bradp](https://github.com/bradp), ![](https://avatars3.githubusercontent.com/u/720377?v=3&s=20) [JeffreyNaval](https://github.com/JeffreyNaval), ![](https://avatars1.githubusercontent.com/u/200280?v=3&s=20) [gregrickaby](https://github.com/gregrickaby), ![](https://avatars0.githubusercontent.com/u/1777519?v=3&s=20) [DevNIX](https://github.com/DevNIX), ![](https://avatars2.githubusercontent.com/u/871924?v=3&s=20) [JPry](https://github.com/JPry), ![](https://avatars2.githubusercontent.com/u/2522431?v=3&s=20) [RC Lations](https://github.com/rclations), ![](https://avatars2.githubusercontent.com/u/796639?v=3&s=20) [tnorthcutt](https://github.com/tnorthcutt), ![](https://avatars2.githubusercontent.com/u/1753298?v=3&s=20) [aubreypwd](https://github.com/aubreypwd), ![](https://avatars2.githubusercontent.com/u/6805601?v=3&s=20) [JeffMatson](https://github.com/JeffMatson) 97 | -------------------------------------------------------------------------------- /app/USAGE: -------------------------------------------------------------------------------- 1 | Subgenerators: 2 | yo plugin-wp:include 3 | yo plugin-wp:cpt 4 | yo plugin-wp:cli 5 | yo plugin-wp:taxonomy 6 | yo plugin-wp:options 7 | yo plugin-wp:widget 8 | yo plugin-wp:endpoint 9 | yo plugin-wp:js 10 | yo plugin-wp:css 11 | -------------------------------------------------------------------------------- /app/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var base = require('../plugin-wp-base'); 3 | var chalk = require('chalk'); 4 | var yosay = require('yosay'); 5 | var fs = require('fs'); 6 | var request = require( 'request' ); 7 | var child_process = require('child_process'); 8 | 9 | module.exports = base.extend({ 10 | 11 | constructor: function () { 12 | 13 | base.apply(this, arguments); 14 | 15 | this.option('do-install', { 16 | type: Boolean, 17 | required: false, 18 | desc: 'Automatically install dependecies' 19 | }); 20 | 21 | this.option('php52', { 22 | type: Boolean, 23 | required: false, 24 | desc: 'Include PHP 5.2 support' 25 | }); 26 | }, 27 | 28 | initializing: function () { 29 | 30 | // Grab package.json. 31 | this.pkg = require('../package.json'); 32 | 33 | // Set the initial value. 34 | this.currentVersionWP = '5.0.7'; 35 | 36 | // Get the latest WP version. 37 | this.getLatestWPVersion(); 38 | 39 | // Set Composer to false. 40 | this.autoloaderList = ['Basic', 'None']; 41 | 42 | // Check and see if Composer is available. 43 | this.checkComposerStatus(); 44 | 45 | // Get the plugin gen version. 46 | var pjson = require( '../package.json' ); 47 | this.plugingenversion = pjson.version; 48 | 49 | }, 50 | 51 | prompting: function () { 52 | var done = this.async(); 53 | 54 | // Have Yeoman greet the user. 55 | this.log(yosay( 56 | 'Welcome to the neat ' + chalk.red('Plugin WP') + ' generator!' 57 | )); 58 | 59 | // Set up all our prompts. 60 | var prompts = [{ 61 | type : 'input', 62 | name : 'name', 63 | message: 'Name', 64 | default: 'WDS Client Plugin Name' 65 | }, { 66 | type : 'input', 67 | name : 'homepage', 68 | message: 'Homepage', 69 | default: 'https://webdevstudios.com', 70 | store: true 71 | }, { 72 | type : 'input', 73 | name : 'description', 74 | message: 'Description', 75 | default: 'A radical new plugin for WordPress!' 76 | }, { 77 | type : 'input', 78 | name : 'version', 79 | message: 'Version', 80 | default: '0.0.0' 81 | }, { 82 | type : 'input', 83 | name : 'author', 84 | message: 'Author', 85 | default: 'WebDevStudios', 86 | save : true, 87 | store: true 88 | }, { 89 | type : 'input', 90 | name : 'authoremail', 91 | message: 'Author Email', 92 | default: 'contact@webdevstudios.com', 93 | save : true, 94 | store: true 95 | }, { 96 | type : 'input', 97 | name : 'authorurl', 98 | message: 'Author URL', 99 | default: 'https://webdevstudios.com', 100 | save : true, 101 | store: true 102 | }, { 103 | type : 'input', 104 | name : 'license', 105 | message: 'License', 106 | default: 'GPLv2', 107 | save : true, 108 | store : true 109 | }, { 110 | type : 'input', 111 | name : 'licenseuri', 112 | message: 'License URI', 113 | default: 'http://www.gnu.org/licenses/gpl-2.0.html', 114 | save : true, 115 | store : true 116 | }, { 117 | type : 'input', 118 | name : 'slug', 119 | message: 'Plugin Slug', 120 | default: function( p ) { 121 | return this._.slugify( p.name ); 122 | }.bind(this) 123 | }, { 124 | type : 'input', 125 | name : 'classname', 126 | message: 'Plugin Class Name', 127 | default: function( p ) { 128 | return this._wpClassify( p.name ); 129 | }.bind(this) 130 | }, { 131 | type : 'input', 132 | name : 'prefix', 133 | message: 'Plugin Prefix', 134 | default: function( p ) { 135 | return this._.underscored( this._.slugify( p.slug ) ); 136 | }.bind(this) 137 | }, { 138 | type : 'list', 139 | name : 'autoloader', 140 | message: 'Use Autoloader', 141 | choices: this.autoloaderList, 142 | store: true 143 | }]; 144 | 145 | // Sanitize inputs. 146 | this.prompt(prompts, function (props) { 147 | this.name = this._.clean( props.name ); 148 | this.homepage = this._.clean( props.homepage ); 149 | this.description = this._.clean( props.description ); 150 | this.descriptionEscaped = this._escapeDoubleQuotes( this.description ); 151 | this.version = this._.clean( props.version ); 152 | this.author = this._.clean( props.author ); 153 | this.authoremail = this._.clean( props.authoremail ); 154 | this.authorurl = this._.clean( props.authorurl ); 155 | this.license = this._.clean( props.license ); 156 | this.licenseuri = this._.clean( props.licenseuri ); 157 | this.slug = this._.slugify( props.slug ); 158 | this.classname = this._wpClassify( props.classname ); 159 | this.mainclassname = this.classname; 160 | this.classprefix = this._wpClassPrefix( this.classname ); 161 | this.prefix = this._.underscored( props.prefix ); 162 | this.year = new Date().getFullYear(); 163 | this.autoloader = props.autoloader; 164 | this.php52 = this.options.php52; 165 | 166 | // All done. 167 | done(); 168 | }.bind(this)); 169 | }, 170 | 171 | writing: { 172 | 173 | folder: function() { 174 | var done = this.async(); 175 | 176 | // Grab our destination path folder. 177 | fs.lstat( this.destinationPath( this.slug ), function(err, stats) { 178 | 179 | // If its not an error, but it exists, flag that to the user. 180 | if (!err && stats.isDirectory()) { 181 | this.log( chalk.red( 'A plugin already exists with this folder name, exiting...' ) ); 182 | process.exit(); 183 | } 184 | 185 | // Set our destination to our slug. 186 | this.destinationRoot( this.slug ); 187 | 188 | // Done. 189 | done(); 190 | }.bind(this)); 191 | }, 192 | 193 | dotfiles: function() { 194 | this.fs.copy( 195 | this.templatePath('_bowerrc'), 196 | this.destinationPath('/.bowerrc') 197 | ); 198 | this.fs.copyTpl( 199 | this.templatePath('_gitignore'), 200 | this.destinationPath('/.gitignore'), 201 | this 202 | ); 203 | this.fs.copyTpl( 204 | this.templatePath('_editorconfig'), 205 | this.destinationPath('/.editorconfig'), 206 | this 207 | ); 208 | }, 209 | 210 | configs: function() { 211 | this.fs.copyTpl( 212 | this.templatePath('bower.json'), 213 | this.destinationPath('/bower.json'), 214 | this 215 | ); 216 | this.fs.copyTpl( 217 | this.templatePath('package.json'), 218 | this.destinationPath('/package.json'), 219 | this 220 | ); 221 | if ( this.autoloader === 'Composer' ) { 222 | this.fs.copyTpl( 223 | this.templatePath('composer.json'), 224 | this.destinationPath('/composer.json'), 225 | this 226 | ); 227 | } 228 | this.fs.copy( 229 | this.templatePath('phpcs.xml'), 230 | this.destinationPath('/phpcs.xml') 231 | ); 232 | this.fs.copyTpl( 233 | this.templatePath('config/settings.js'), 234 | this.destinationPath('/config/settings.js'), 235 | this 236 | ); 237 | this.fs.copy( 238 | this.templatePath('config/webpack.config.js'), 239 | this.destinationPath('/config/webpack.config.js') 240 | ); 241 | }, 242 | 243 | php: function() { 244 | this.fs.copyTpl( 245 | this.templatePath('plugin.php'), 246 | this.destinationPath('/' + this.slug + '.php'), 247 | this 248 | ); 249 | }, 250 | 251 | readme: function() { 252 | this.fs.copyTpl( 253 | this.templatePath('README.md'), 254 | this.destinationPath('/README.md'), 255 | this 256 | ); 257 | }, 258 | 259 | tests: function() { 260 | this.fs.copy( 261 | this.templatePath('phpunit.xml'), 262 | this.destinationPath('/phpunit.xml'), 263 | this 264 | ); 265 | 266 | this.fs.copy( 267 | this.templatePath('.travis.yml'), 268 | this.destinationPath('/.travis.yml'), 269 | this 270 | ); 271 | 272 | this.fs.copy( 273 | this.templatePath('Dockunit.json'), 274 | this.destinationPath('/Dockunit.json'), 275 | this 276 | ); 277 | 278 | this.fs.copy( 279 | this.templatePath('bin/install-wp-tests.sh'), 280 | this.destinationPath('bin/install-wp-tests.sh'), 281 | this 282 | ); 283 | 284 | 285 | this.fs.copyTpl( 286 | this.templatePath('tests/bootstrap.php'), 287 | this.destinationPath('tests/bootstrap.php'), 288 | this 289 | ); 290 | 291 | this.fs.copyTpl( 292 | this.templatePath('tests/test-base.php'), 293 | this.destinationPath('tests/test-base.php'), 294 | this 295 | ); 296 | }, 297 | 298 | folders: function() { 299 | this.fs.copyTpl( 300 | this.templatePath('assets/README.md'), 301 | this.destinationPath('assets/README.md'), 302 | this 303 | ); 304 | 305 | this.fs.copyTpl( 306 | this.templatePath('assets/repo/README.md'), 307 | this.destinationPath('assets/repo/README.md'), 308 | this 309 | ); 310 | 311 | this.fs.copy( 312 | this.templatePath('assets/js/index.js'), 313 | this.destinationPath('assets/js/index.js'), 314 | this 315 | ); 316 | 317 | this.fs.copy( 318 | this.templatePath('assets/css/style.css'), 319 | this.destinationPath('assets/css/style.css'), 320 | this 321 | ); 322 | 323 | this.fs.copyTpl( 324 | this.templatePath('includes/README.md'), 325 | this.destinationPath('includes/README.md'), 326 | this 327 | ); 328 | }, 329 | 330 | saveConfig: function() { 331 | this.config.set( 'name', this.name ); 332 | this.config.set( 'homepage', this.homepage ); 333 | this.config.set( 'description', this.description ); 334 | this.config.set( 'version', this.version ); 335 | this.config.set( 'author', this.author ); 336 | this.config.set( 'authoremail', this.authoremail ); 337 | this.config.set( 'authorurl', this.authorurl ); 338 | this.config.set( 'license', this.license ); 339 | this.config.set( 'licenseuri', this.licenseuri ); 340 | this.config.set( 'slug', this.slug ); 341 | this.config.set( 'classname', this.classname ); 342 | this.config.set( 'mainclassname', this.classname ); 343 | this.config.set( 'classprefix', this.classprefix ); 344 | this.config.set( 'prefix', this.prefix ); 345 | this.config.set( 'year', this.year ); 346 | 347 | this.config.set( 'currentVersionWP', this.currentVersionWP ); 348 | 349 | this.config.set( 'plugingenversion', this.plugingenversion ); 350 | 351 | this.config.save(); 352 | } 353 | }, 354 | 355 | checkComposerStatus: function() { 356 | var composerResult = child_process.spawnSync('composer',['--version', '--no-ansi']); 357 | 358 | if ( 0 === composerResult.status) { 359 | this.autoloaderList = ['Basic', 'Composer', 'None']; 360 | } 361 | 362 | }, 363 | 364 | getLatestWPVersion: function() { 365 | // Save the generator (this) to a variable so that we can access it within the nested function below. 366 | var generator = this; 367 | 368 | request.get({ 369 | url: 'https://api.wordpress.org/core/version-check/1.7/', 370 | json: true, 371 | headers: { 'User-Agent': 'request' } 372 | }, function (err, res, data) { 373 | // Check for status code. 374 | if ( ! err && ( 200 === res.statusCode ) ) { 375 | // Loop through results to find only the "upgrade" version 376 | for ( var i in data.offers ) { 377 | if ( 'upgrade' === data.offers[i].response ) { 378 | generator.currentVersionWP = data.offers[i].current; 379 | return; 380 | } 381 | } 382 | } 383 | }); 384 | }, 385 | 386 | install: function () { 387 | 388 | // If we flagged we want an install, install our dependecies. 389 | if ( this.options['do-install'] ) { 390 | this.installDependencies(); 391 | 392 | // If we're loading Composer, run a composer install. 393 | if ( this.autoloader === 'Composer' ) { 394 | this.spawnCommand('composer', ['install']); 395 | } 396 | } 397 | } 398 | }); 399 | -------------------------------------------------------------------------------- /app/templates/.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | notifications: 4 | email: 5 | on_success: never 6 | on_failure: change 7 | 8 | php: 9 | - 5.3 10 | - 5.5 11 | 12 | env: 13 | - WP_VERSION=latest WP_MULTISITE=0 14 | 15 | matrix: 16 | include: 17 | - php: 5.3 18 | env: WP_VERSION=latest WP_MULTISITE=1 19 | 20 | before_script: 21 | - bash bin/install-wp-tests.sh wordpress_test root '' localhost $WP_VERSION 22 | 23 | script: phpunit 24 | -------------------------------------------------------------------------------- /app/templates/Dockunit.json: -------------------------------------------------------------------------------- 1 | { 2 | "containers":[ 3 | { 4 | "prettyName":"PHP 7.0 FPM WordPress Latest", 5 | "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-7.0-rc-4-fpm", 6 | "beforeScripts":[ 7 | "service mysql start", 8 | "bash bin/install-wp-tests.sh wordpress_test root '' localhost" 9 | ], 10 | "testCommand":"phpunit" 11 | }, 12 | { 13 | "prettyName":"PHP 7.0 FPM WordPress 4.7", 14 | "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-7.0-rc-4-fpm", 15 | "beforeScripts":[ 16 | "service mysql start", 17 | "bash bin/install-wp-tests.sh wordpress_test root '' localhost 4.7" 18 | ], 19 | "testCommand":"phpunit" 20 | }, 21 | { 22 | "prettyName":"PHP 7.0 FPM WordPress 4.6", 23 | "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-7.0-rc-4-fpm", 24 | "beforeScripts":[ 25 | "service mysql start", 26 | "bash bin/install-wp-tests.sh wordpress_test root '' localhost 4.6" 27 | ], 28 | "testCommand":"phpunit" 29 | }, 30 | { 31 | "prettyName":"PHP 7.0 FPM WordPress 4.5", 32 | "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-7.0-rc-4-fpm", 33 | "beforeScripts":[ 34 | "service mysql start", 35 | "bash bin/install-wp-tests.sh wordpress_test root '' localhost 4.5" 36 | ], 37 | "testCommand":"phpunit" 38 | }, 39 | { 40 | "prettyName":"PHP 7.0 FPM WordPress 4.4", 41 | "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-7.0-rc-4-fpm", 42 | "beforeScripts":[ 43 | "service mysql start", 44 | "bash bin/install-wp-tests.sh wordpress_test root '' localhost 4.4" 45 | ], 46 | "testCommand":"phpunit" 47 | }, 48 | { 49 | "prettyName":"PHP 7.0 FPM WordPress 4.3", 50 | "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-7.0-rc-4-fpm", 51 | "beforeScripts":[ 52 | "service mysql start", 53 | "bash bin/install-wp-tests.sh wordpress_test root '' localhost 4.3" 54 | ], 55 | "testCommand":"phpunit" 56 | }, 57 | { 58 | "prettyName":"PHP 5.6 FPM WordPress Latest", 59 | "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-5.6-fpm", 60 | "beforeScripts":[ 61 | "service mysql start", 62 | "bash bin/install-wp-tests.sh wordpress_test2 root '' localhost" 63 | ], 64 | "testCommand":"phpunit" 65 | }, 66 | { 67 | "prettyName":"PHP 5.6 FPM WordPress 4.7", 68 | "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-5.6-fpm", 69 | "beforeScripts":[ 70 | "service mysql start", 71 | "bash bin/install-wp-tests.sh wordpress_test2 root '' localhost 4.7" 72 | ], 73 | "testCommand":"phpunit" 74 | }, 75 | { 76 | "prettyName":"PHP 5.6 FPM WordPress 4.6", 77 | "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-5.6-fpm", 78 | "beforeScripts":[ 79 | "service mysql start", 80 | "bash bin/install-wp-tests.sh wordpress_test2 root '' localhost 4.6" 81 | ], 82 | "testCommand":"phpunit" 83 | }, 84 | { 85 | "prettyName":"PHP 5.6 FPM WordPress 4.5", 86 | "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-5.6-fpm", 87 | "beforeScripts":[ 88 | "service mysql start", 89 | "bash bin/install-wp-tests.sh wordpress_test2 root '' localhost 4.5" 90 | ], 91 | "testCommand":"phpunit" 92 | }, 93 | { 94 | "prettyName":"PHP 5.6 FPM WordPress 4.4", 95 | "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-5.6-fpm", 96 | "beforeScripts":[ 97 | "service mysql start", 98 | "bash bin/install-wp-tests.sh wordpress_test2 root '' localhost 4.4" 99 | ], 100 | "testCommand":"phpunit" 101 | }, 102 | { 103 | "prettyName":"PHP 5.6 FPM WordPress 4.3", 104 | "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-5.6-fpm", 105 | "beforeScripts":[ 106 | "service mysql start", 107 | "bash bin/install-wp-tests.sh wordpress_test2 root '' localhost 4.3" 108 | ], 109 | "testCommand":"phpunit" 110 | }, 111 | { 112 | "prettyName":"PHP 5.2 FPM WordPress 4.7", 113 | "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-5.2-fpm", 114 | "beforeScripts":[ 115 | "service mysql start", 116 | "bash bin/install-wp-tests.sh wordpress_test3 root '' localhost 4.7" 117 | ], 118 | "testCommand":"phpunit" 119 | }, 120 | { 121 | "prettyName":"PHP 5.2 FPM WordPress 4.6", 122 | "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-5.2-fpm", 123 | "beforeScripts":[ 124 | "service mysql start", 125 | "bash bin/install-wp-tests.sh wordpress_test3 root '' localhost 4.6" 126 | ], 127 | "testCommand":"phpunit" 128 | }, 129 | { 130 | "prettyName":"PHP 5.2 FPM WordPress 4.5", 131 | "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-5.2-fpm", 132 | "beforeScripts":[ 133 | "service mysql start", 134 | "bash bin/install-wp-tests.sh wordpress_test3 root '' localhost 4.5" 135 | ], 136 | "testCommand":"phpunit" 137 | }, 138 | { 139 | "prettyName":"PHP 5.2 FPM WordPress 4.4", 140 | "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-5.2-fpm", 141 | "beforeScripts":[ 142 | "service mysql start", 143 | "bash bin/install-wp-tests.sh wordpress_test3 root '' localhost 4.4" 144 | ], 145 | "testCommand":"phpunit" 146 | }, 147 | { 148 | "prettyName":"PHP 5.2 FPM WordPress 4.3", 149 | "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-5.2-fpm", 150 | "beforeScripts":[ 151 | "service mysql start", 152 | "bash bin/install-wp-tests.sh wordpress_test3 root '' localhost 4.3" 153 | ], 154 | "testCommand":"phpunit" 155 | } 156 | ] 157 | } 158 | -------------------------------------------------------------------------------- /app/templates/README.md: -------------------------------------------------------------------------------- 1 | # <%= name %> # 2 | **Contributors:** <%= author %> 3 | **Donate link:** <%= homepage %> 4 | **Tags:** 5 | **Requires at least:** 5.0.7 6 | **Tested up to:** <%= currentVersionWP %> 7 | **Stable tag:** <%= version %> 8 | **License:** <%= license %> 9 | **License URI:** <%= licenseuri %> 10 | 11 | ## Description ## 12 | 13 | <%= description %> 14 | 15 | ## Installation ## 16 | 17 | ### Manual Installation ### 18 | 19 | 1. Upload the entire `/<%= slug %>` directory to the `/wp-content/plugins/` directory. 20 | 2. Activate <%= name %> through the 'Plugins' menu in WordPress. 21 | 22 | ## Frequently Asked Questions ## 23 | 24 | 25 | ## Screenshots ## 26 | 27 | 28 | ## Changelog ## 29 | 30 | ### <%= version %> ### 31 | * First release 32 | 33 | ## Upgrade Notice ## 34 | 35 | ### <%= version %> ### 36 | First Release 37 | -------------------------------------------------------------------------------- /app/templates/_bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "assets/bower" 3 | } -------------------------------------------------------------------------------- /app/templates/_editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | end_of_line = lf 9 | insert_final_newline = true 10 | 11 | # Matches multiple files with brace expansion notation 12 | # Set default charset 13 | [*.{html,js,php,css,scss}] 14 | charset = utf-8 15 | 16 | # 4 space indentation 17 | [*.{html,js,php,css,scss}] 18 | indent_style = tab 19 | indent_size = 4 20 | 21 | # Matches the exact files 22 | [{package.json,bower.json,.bowerrc,.eslintrc,.travis.yml,.sass-lint.yml,phpcs.xml}] 23 | indent_style = space 24 | indent_size = 2 25 | -------------------------------------------------------------------------------- /app/templates/_gitignore: -------------------------------------------------------------------------------- 1 | # Node/npm 2 | node_modules/ 3 | npm-debug.log 4 | .grunt 5 | .sass-cache 6 | 7 | # OSX 8 | .DS_Store 9 | .AppleDouble 10 | .LSOverride 11 | .Spotlight-V100 12 | .Trashes 13 | .AppleDB 14 | .AppleDesktop 15 | Network Trash Folder 16 | Temporary Items 17 | .apdisk 18 | 19 | # Icon must end with two \r 20 | Icon 21 | 22 | 23 | # Thumbnails 24 | ._* 25 | 26 | 27 | # Vim 28 | [._]*.s[a-w][a-z] 29 | [._]s[a-w][a-z] 30 | *.un~ 31 | Session.vim 32 | .netrwhist 33 | *~ 34 | 35 | ### Bower ### 36 | bower_components 37 | .bower-cache 38 | .bower-registry 39 | .bower-tmp 40 | 41 | # Logs 42 | logs 43 | *.log 44 | 45 | # Runtime data 46 | pids 47 | *.pid 48 | *.seed 49 | 50 | # Directory for instrumented libs generated by jscoverage/JSCover 51 | lib-cov 52 | 53 | # Coverage directory used by tools like istanbul 54 | coverage 55 | 56 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 57 | .grunt 58 | 59 | # node-waf configuration 60 | .lock-wscript 61 | 62 | # Compiled binary addons (http://nodejs.org/api/addons.html) 63 | build/Release 64 | 65 | # Dependency directory 66 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 67 | node_modules 68 | 69 | <% if ( autoloader == 'Composer' ) { %> 70 | ### Composer ### 71 | composer.phar 72 | vendor/ 73 | <% } %> 74 | 75 | # Commit your application's lock file http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file 76 | # You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file 77 | # composer.lock 78 | 79 | 80 | # Other, add your own ignored things here. 81 | .idea/ 82 | release 83 | dist 84 | -------------------------------------------------------------------------------- /app/templates/assets/README.md: -------------------------------------------------------------------------------- 1 | # <%= name %> Assets # 2 | <%= homepage %> 3 | Copyright (c) <%= year %> <%= author %> 4 | Licensed under the <%= license %> license. 5 | 6 | Assets such as styles, javascript, and images. -------------------------------------------------------------------------------- /app/templates/assets/css/style.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WebDevStudios/generator-plugin-wp/b268962277e30a4c557c11daf5abcc1f7150652d/app/templates/assets/css/style.css -------------------------------------------------------------------------------- /app/templates/assets/js/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WebDevStudios/generator-plugin-wp/b268962277e30a4c557c11daf5abcc1f7150652d/app/templates/assets/js/index.js -------------------------------------------------------------------------------- /app/templates/assets/repo/README.md: -------------------------------------------------------------------------------- 1 | # <%= name %> Repo Assets # 2 | <%= homepage %> 3 | Copyright (c) <%= year %> <%= author %> 4 | Licensed under the <%= license %> license. 5 | 6 | Assets such as screenshots and banner for WordPress.org plugin repository listing. -------------------------------------------------------------------------------- /app/templates/bin/install-wp-tests.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [ $# -lt 2 ]; then 4 | echo "usage: $0 [db-pass=''] [db-host='localhost'] [wp-version='latest']" 5 | exit 1 6 | fi 7 | 8 | DB_NAME=$1 9 | DB_USER=$2 10 | DB_PASS=${3-''} 11 | DB_HOST=${4-localhost} 12 | WP_VERSION=${5-latest} 13 | 14 | WP_TESTS_DIR=${WP_TESTS_DIR-/tmp/wordpress-tests-lib} 15 | WP_CORE_DIR=${WP_CORE_DIR-/tmp/wordpress/} 16 | 17 | download() { 18 | if [ "$(which curl)" ]; then 19 | curl -s "$1" > "$2"; 20 | elif [ "$(which wget)" ]; then 21 | wget -nv -O "$2" "$1" 22 | fi 23 | } 24 | 25 | echo 'Hey, this is going to create a databse or stomp out '"$DB_NAME"' if it exists, continue? [y/n]' 26 | read -r GO_ON 27 | 28 | if [[ 'y' != "$GO_ON" ]]; then 29 | echo 'See ya! http://bit.ly/2sxOB0u' 30 | exit; 31 | fi 32 | 33 | if [[ $WP_VERSION =~ [0-9]+\.[0-9]+(\.[0-9]+)? ]]; then 34 | WP_TESTS_TAG="tags/$WP_VERSION" 35 | else 36 | # http serves a single offer, whereas https serves multiple. we only want one 37 | download http://api.wordpress.org/core/version-check/1.7/ /tmp/wp-latest.json 38 | grep '[0-9]+\.[0-9]+(\.[0-9]+)?' /tmp/wp-latest.json 39 | LATEST_VERSION=$(grep -o '"version":"[^"]*' /tmp/wp-latest.json | sed 's/"version":"//') 40 | if [[ -z "$LATEST_VERSION" ]]; then 41 | echo "Latest WordPress version could not be found" 42 | exit 1 43 | fi 44 | WP_TESTS_TAG="tags/$LATEST_VERSION" 45 | fi 46 | 47 | set -ex 48 | 49 | install_wp() { 50 | 51 | if [ -d "$WP_CORE_DIR" ]; then 52 | return; 53 | fi 54 | 55 | mkdir -p "$WP_CORE_DIR" 56 | 57 | if [ "$WP_VERSION" == 'latest' ]; then 58 | local ARCHIVE_NAME='latest' 59 | else 60 | local ARCHIVE_NAME="wordpress-$WP_VERSION" 61 | fi 62 | 63 | download https://wordpress.org/"${ARCHIVE_NAME}".tar.gz /tmp/wordpress.tar.gz 64 | tar --strip-components=1 -zxmf /tmp/wordpress.tar.gz -C "$WP_CORE_DIR" 65 | 66 | download https://raw.github.com/markoheijnen/wp-mysqli/master/db.php "$WP_CORE_DIR"/wp-content/db.php 67 | } 68 | 69 | install_test_suite() { 70 | # portable in-place argument for both GNU sed and Mac OSX sed 71 | if [[ $(uname -s) == 'Darwin' ]]; then 72 | local ioption='-i .bak' 73 | else 74 | local ioption='-i' 75 | fi 76 | 77 | # set up testing suite if it doesn't yet exist 78 | if [ ! -d "$WP_TESTS_DIR" ]; then 79 | # set up testing suite 80 | mkdir -p "$WP_TESTS_DIR" 81 | svn co --quiet https://develop.svn.wordpress.org/"${WP_TESTS_TAG}"/tests/phpunit/ "$WP_TESTS_DIR" 82 | fi 83 | 84 | cd "$WP_TESTS_DIR" 85 | 86 | if [ ! -f wp-tests-config.php ]; then 87 | download https://develop.svn.wordpress.org/"${WP_TESTS_TAG}"/wp-tests-config-sample.php "$WP_TESTS_DIR"/wp-tests-config.php 88 | sed $ioption "s:dirname( __FILE__ ) . '/src/':'$WP_CORE_DIR':" "$WP_TESTS_DIR"/wp-tests-config.php 89 | sed $ioption "s:define( 'WP_DEBUG', true );:define( 'WP_DEBUG', true ); define( 'WP_DEBUG_LOG', true );:" "$WP_TESTS_DIR"/wp-tests-config.php 90 | sed $ioption "s/youremptytestdbnamehere/$DB_NAME/" "$WP_TESTS_DIR"/wp-tests-config.php 91 | sed $ioption "s/yourusernamehere/$DB_USER/" "$WP_TESTS_DIR"/wp-tests-config.php 92 | sed $ioption "s/yourpasswordhere/$DB_PASS/" "$WP_TESTS_DIR"/wp-tests-config.php 93 | sed $ioption "s|localhost|${DB_HOST}|" "$WP_TESTS_DIR"/wp-tests-config.php 94 | fi 95 | 96 | } 97 | 98 | install_db() { 99 | # parse DB_HOST for port or socket references 100 | local PARTS=("${DB_HOST//\:/ }") 101 | local DB_HOSTNAME=${PARTS[0]}; 102 | local DB_SOCK_OR_PORT=${PARTS[1]}; 103 | local EXTRA="" 104 | 105 | if ! [ -z "$DB_HOSTNAME" ] ; then 106 | if [ $(echo $DB_SOCK_OR_PORT | grep -e '^[0-9]\{1,\}$') ]; then 107 | EXTRA=" --host=$DB_HOSTNAME --port=$DB_SOCK_OR_PORT --protocol=tcp" 108 | elif ! [ -z "$DB_SOCK_OR_PORT" ] ; then 109 | EXTRA=" --socket=$DB_SOCK_OR_PORT" 110 | elif ! [ -z "$DB_HOSTNAME" ] ; then 111 | EXTRA=" --host=$DB_HOSTNAME --protocol=tcp" 112 | fi 113 | fi 114 | 115 | # create database, maybe. BOOM. 116 | DB_EXISTS=$(echo 'SHOW DATABASES' | mysql -u"$DB_USER" --password="$DB_PASS" $EXTRA | grep -E "$DB_NAME\$" | wc -l | tr -d '[:space:]') 117 | 118 | if [[ 0 == "$DB_EXISTS" ]]; then 119 | mysqladmin create "$DB_NAME" --user="$DB_USER" --password="$DB_PASS"$EXTRA 120 | else 121 | echo "$DB_NAME"' already exists, not gonna do that again.' 122 | fi 123 | } 124 | 125 | install_wp 126 | install_test_suite 127 | install_db 128 | -------------------------------------------------------------------------------- /app/templates/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "<%= slug %>", 3 | "description": "<%= descriptionEscaped %>", 4 | "license": "<%= license %>", 5 | "authors": [ 6 | "<%= author %>" 7 | ], 8 | "private": true, 9 | "ignore": [ 10 | "**/.*", 11 | "node_modules", 12 | "bower_components", 13 | "test", 14 | "tests" 15 | ], 16 | "dependencies": { 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/templates/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "<%= slug %>", 3 | "description": "<%= descriptionEscaped %>", 4 | "keywords": ["wordpress", "plugin", "generator-plugin-wp"], 5 | "homepage": "<%= homepage %>", 6 | "license": "<%= license %>", 7 | "authors": [ 8 | { 9 | "name": "<%= author %>", 10 | "homepage": "<%= authorurl %>" 11 | } 12 | ], 13 | "minimum-stability": "dev", 14 | "type": "wordpress-plugin", 15 | "autoload": { 16 | "classmap": ["<%= slug %>.php", "includes/"] 17 | }<%if (php52) { %>, 18 | "require": { 19 | "php": ">=5.2", 20 | "xrstf/composer-php52": "1.*" 21 | }, 22 | "scripts": { 23 | "post-install-cmd": [ 24 | "xrstf\\Composer52\\Generator::onPostInstallCmd" 25 | ], 26 | "post-update-cmd": [ 27 | "xrstf\\Composer52\\Generator::onPostInstallCmd" 28 | ], 29 | "post-autoload-dump": [ 30 | "xrstf\\Composer52\\Generator::onPostInstallCmd" 31 | ] 32 | } 33 | <% } %> 34 | } 35 | -------------------------------------------------------------------------------- /app/templates/config/settings.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Config settings. 3 | */ 4 | const path = require( 'path' ); 5 | 6 | /** 7 | * Resolve path. 8 | * 9 | * @since 1.0.0 10 | * 11 | * @param {string} src Path of the entry source. 12 | * @return {string} Resolved path. 13 | */ 14 | const resolvePath = ( src ) => { 15 | return path.resolve( process.cwd(), src ); 16 | }; 17 | 18 | module.exports = { 19 | entries: { 20 | index: resolvePath( './assets/js/index.js' ), 21 | 22 | // Stylesheets. 23 | style: resolvePath( './assets/css/style.css' ), 24 | }, 25 | filename: { 26 | js: 'js/[name].js', 27 | css: 'css/[name].css', 28 | }, 29 | paths: { 30 | src: { 31 | base: './assets/', 32 | css: './assets/css', 33 | js: './assets/js', 34 | }, 35 | dist: { 36 | base: resolvePath( './dist/' ), 37 | }, 38 | }, 39 | BrowserSyncConfig: { 40 | host: 'localhost', 41 | port: 3000, 42 | proxy: 'https://<%= slug %>.local', 43 | open: false, 44 | files: [ '**/*.php', 'dist/js/**/*.js', 'dist/css/**/*.css' ], 45 | }, 46 | }; 47 | -------------------------------------------------------------------------------- /app/templates/config/webpack.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Webpack config. 3 | */ 4 | const settings = require( './settings' ); 5 | const defaultConfig = require( '@wordpress/scripts/config/webpack.config' ); 6 | const MiniCssExtractPlugin = require( 'mini-css-extract-plugin' ); 7 | const FixStyleOnlyEntriesPlugin = require( 'webpack-fix-style-only-entries' ); 8 | const StyleLintPlugin = require( 'stylelint-webpack-plugin' ); 9 | const WebpackBar = require( 'webpackbar' ); 10 | const BrowserSyncPlugin = require( 'browser-sync-webpack-plugin' ); 11 | const { mode, resolve, stats, devtool } = defaultConfig; 12 | 13 | const isProduction = 'production' === mode; 14 | 15 | module.exports = { 16 | mode, 17 | entry: settings.entries, 18 | output: { 19 | path: settings.paths.dist.base, 20 | pathinfo: true, 21 | filename: settings.filename.js, 22 | }, 23 | resolve, 24 | module: { 25 | ...defaultConfig.module, 26 | rules: [ ...defaultConfig.module.rules ], 27 | }, 28 | plugins: [ 29 | new MiniCssExtractPlugin( { 30 | filename: settings.filename.css, 31 | chunkFilename: settings.filename.css, 32 | } ), 33 | 34 | new FixStyleOnlyEntriesPlugin( { 35 | silent: true, 36 | } ), 37 | 38 | // Lint CSS. 39 | new StyleLintPlugin( { 40 | context: settings.paths.src.css, 41 | files: '**/*.css', 42 | } ), 43 | 44 | // Webpack bar. 45 | new WebpackBar(), 46 | 47 | ! isProduction && 48 | new BrowserSyncPlugin( 49 | { 50 | host: settings.BrowserSyncConfig.host, 51 | port: settings.BrowserSyncConfig.port, 52 | proxy: settings.BrowserSyncConfig.proxy, 53 | open: settings.BrowserSyncConfig.open, 54 | files: settings.BrowserSyncConfig.files, 55 | }, 56 | { 57 | injectCss: true, 58 | reload: false, 59 | } 60 | ), 61 | ].filter( Boolean ), 62 | stats, 63 | devtool, 64 | }; 65 | -------------------------------------------------------------------------------- /app/templates/includes/README.md: -------------------------------------------------------------------------------- 1 | # <%= name %> Includes # 2 | <%= homepage %> 3 | Copyright (c) <%= year %> <%= author %> 4 | Licensed under the <%= license %> license. 5 | 6 | Additional PHP functionality goes here. -------------------------------------------------------------------------------- /app/templates/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "<%= slug %>", 3 | "title": "<%= name %>", 4 | "version": "<%= version %>", 5 | "description": "<%= descriptionEscaped %>", 6 | "author": { 7 | "name": "<%= author %>", 8 | "url": "<%= authorurl %>" 9 | }, 10 | "license": "<%= license %>", 11 | "devDependencies": { 12 | "@webdevstudios/css-coding-standards": "^1.0.0", 13 | "@webdevstudios/js-coding-standards": "^1.0.2", 14 | "@wordpress/scripts": "^12.0.0", 15 | "browser-sync": "^2.26.7", 16 | "browser-sync-webpack-plugin": "^2.2.2", 17 | "mini-css-extract-plugin": "^0.9.0", 18 | "stylelint-webpack-plugin": "^2.1.0", 19 | "webpack-fix-style-only-entries": "^0.5.1", 20 | "webpackbar": "^4.0.0" 21 | }, 22 | "scripts": { 23 | "dev": "wp-scripts start --config config/webpack.config.js", 24 | "build": "wp-scripts build --config config/webpack.config.js", 25 | "test": "dockunit", 26 | "preversion": "npm test" 27 | }, 28 | "sasslintConfig": "node_modules/@webdevstudios/css-coding-standards/.sass-lint.yml", 29 | "stylelint": { 30 | "extends": "stylelint-config-wordpress", 31 | "ignoreFiles": "**/*.scss" 32 | }, 33 | "eslintConfig": { 34 | "extends": "@webdevstudios/js-coding-standards" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/templates/phpcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | A modified set of rules, based on the WordPress Coding Standards. 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /app/templates/phpunit.xml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | ./tests/ 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /app/templates/plugin.php: -------------------------------------------------------------------------------- 1 | 4 | * Plugin URI: <%= homepage %> 5 | * Description: <%= description %> 6 | * Version: <%= version %> 7 | * Author: <%= author %> 8 | * Author URI: <%= authorurl %> 9 | * Donate link: <%= homepage %> 10 | * License: <%= license %> 11 | * License URI: <%= licenseuri %> 12 | * Text Domain: <%= slug %> 13 | * Domain Path: /languages 14 | * 15 | * @link <%= homepage %> 16 | * 17 | * @package <%= mainclassname %> 18 | * @version <%= version %> 19 | * 20 | * Built using generator-plugin-wp (https://github.com/WebDevStudios/generator-plugin-wp) 21 | */ 22 | <% if ( license == 'GPLv2' ) { %> // @codingStandardsIgnoreLine 23 | /** 24 | * Copyright (c) <%= year %> <%= author %> (email : <%= authoremail %>) 25 | * 26 | * This program is free software; you can redistribute it and/or modify 27 | * it under the terms of the GNU General Public License, version 2 or, at 28 | * your discretion, any later version, as published by the Free 29 | * Software Foundation. 30 | * 31 | * This program is distributed in the hope that it will be useful, 32 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 33 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 34 | * GNU General Public License for more details. 35 | * 36 | * You should have received a copy of the GNU General Public License 37 | * along with this program; if not, write to the Free Software 38 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 39 | */<% } else { %> // @codingStandardsIgnoreLine 40 | /** 41 | * Copyright (c) <%= year %> <%= author %> (email : <%= authoremail %>) 42 | */<% } %> // @codingStandardsIgnoreLine 43 | <% if ( autoloader == 'Basic' ) { %> // @codingStandardsIgnoreLine 44 | /** 45 | * Autoloads files with classes when needed. 46 | * 47 | * @since <%= version %> 48 | * @param string $class_name Name of the class being requested. 49 | * @return void 50 | */ 51 | function <%= prefix %>_autoload_classes( $class_name ) { // @codingStandardsIgnoreLine 52 | 53 | // If our class doesn't have our prefix, don't load it. 54 | if ( 0 !== strpos( $class_name, '<%= classprefix %>' ) ) { 55 | return; 56 | } 57 | 58 | // Set up our filename. 59 | $filename = strtolower( str_replace( '_', '-', substr( $class_name, strlen( '<%= classprefix %>' ) ) ) ); 60 | 61 | // Include our file. 62 | <%= classname %>::include_file( 'includes/class-' . $filename ); // @codingStandardsIgnoreLine 63 | } 64 | spl_autoload_register( '<%= prefix %>_autoload_classes' ); 65 | <% } else if ( autoloader == 'Composer' && php52 ) { %> // @codingStandardsIgnoreLine 66 | // Use composer autoload with PHP 5.2 compatibility. 67 | require 'vendor/autoload_52.php'; 68 | <% } else if ( autoloader == 'Composer' ) { %> // @codingStandardsIgnoreLine 69 | // Use composer autoload. 70 | require 'vendor/autoload.php'; 71 | <% } else { %> // @codingStandardsIgnoreLine 72 | // Include additional php files here. 73 | // require 'includes/something.php'; // @codingStandardsIgnoreLine 74 | <% } %> // @codingStandardsIgnoreLine 75 | /** 76 | * Main initiation class. 77 | * 78 | * @since <%= version %> 79 | */ 80 | final class <%= classname %> { // @codingStandardsIgnoreLine 81 | 82 | /** 83 | * Current version. 84 | * 85 | * @var string 86 | * @since <%= version %> 87 | */ 88 | const VERSION = '<%= version %>'; 89 | 90 | /** 91 | * URL of plugin directory. 92 | * 93 | * @var string 94 | * @since <%= version %> 95 | */ 96 | protected $url = ''; 97 | 98 | /** 99 | * Path of plugin directory. 100 | * 101 | * @var string 102 | * @since <%= version %> 103 | */ 104 | protected $path = ''; 105 | 106 | /** 107 | * Plugin basename. 108 | * 109 | * @var string 110 | * @since <%= version %> 111 | */ 112 | protected $basename = ''; 113 | 114 | /** 115 | * Detailed activation error messages. 116 | * 117 | * @var array 118 | * @since <%= version %> 119 | */ 120 | protected $activation_errors = array(); 121 | 122 | /** 123 | * Singleton instance of plugin. 124 | * 125 | * @var <%= classname %> 126 | * @since <%= version %> 127 | */ 128 | protected static $single_instance = null; 129 | 130 | /** 131 | * Creates or returns an instance of this class. 132 | * 133 | * @since <%= version %> 134 | * @return <%= classname %> A single instance of this class. 135 | */ 136 | public static function get_instance() { 137 | if ( null === self::$single_instance ) { 138 | self::$single_instance = new self(); 139 | } 140 | 141 | return self::$single_instance; 142 | } 143 | 144 | /** 145 | * Sets up our plugin. 146 | * 147 | * @since <%= version %> 148 | */ 149 | protected function __construct() { 150 | $this->basename = plugin_basename( __FILE__ ); 151 | $this->url = plugin_dir_url( __FILE__ ); 152 | $this->path = plugin_dir_path( __FILE__ ); 153 | } 154 | 155 | /** 156 | * Attach other plugin classes to the base plugin class. 157 | * 158 | * @since <%= version %> 159 | */ 160 | public function plugin_classes() { 161 | // $this->plugin_class = new <%= classprefix %>Plugin_Class( $this ); 162 | } // END OF PLUGIN CLASSES FUNCTION 163 | 164 | /** 165 | * Add hooks and filters. 166 | * Priority needs to be 167 | * < 10 for CPT_Core, 168 | * < 5 for Taxonomy_Core, 169 | * and 0 for Widgets because widgets_init runs at init priority 1. 170 | * 171 | * @since <%= version %> 172 | */ 173 | public function hooks() { 174 | add_action( 'init', array( $this, 'init' ), 0 ); 175 | } 176 | 177 | /** 178 | * Activate the plugin. 179 | * 180 | * @since <%= version %> 181 | * @return void 182 | */ 183 | public function activate() { 184 | // Bail early if requirements aren't met. 185 | if ( ! $this->check_requirements() ) { 186 | return; 187 | } 188 | 189 | // Make sure any rewrite functionality has been loaded. 190 | flush_rewrite_rules(); 191 | } 192 | 193 | /** 194 | * Deactivate the plugin. 195 | * Uninstall routines should be in uninstall.php. 196 | * 197 | * @since <%= version %> 198 | */ 199 | public function deactivate() { 200 | // Add deactivation cleanup functionality here. 201 | } 202 | 203 | /** 204 | * Init hooks 205 | * 206 | * @since <%= version %> 207 | * @return void 208 | */ 209 | public function init() { 210 | 211 | // Bail early if requirements aren't met. 212 | if ( ! $this->check_requirements() ) { 213 | return; 214 | } 215 | 216 | // Load translated strings for plugin. 217 | load_plugin_textdomain( '<%= slug %>', false, dirname( $this->basename ) . '/languages/' ); 218 | 219 | // Initialize plugin classes. 220 | $this->plugin_classes(); 221 | } 222 | 223 | /** 224 | * Check if the plugin meets requirements and 225 | * disable it if they are not present. 226 | * 227 | * @since <%= version %> 228 | * 229 | * @return boolean True if requirements met, false if not. 230 | */ 231 | public function check_requirements() { 232 | 233 | // Bail early if plugin meets requirements. 234 | if ( $this->meets_requirements() ) { 235 | return true; 236 | } 237 | 238 | // Add a dashboard notice. 239 | add_action( 'all_admin_notices', array( $this, 'requirements_not_met_notice' ) ); 240 | 241 | // Deactivate our plugin. 242 | add_action( 'admin_init', array( $this, 'deactivate_me' ) ); 243 | 244 | // Didn't meet the requirements. 245 | return false; 246 | } 247 | 248 | /** 249 | * Deactivates this plugin, hook this function on admin_init. 250 | * 251 | * @since <%= version %> 252 | */ 253 | public function deactivate_me() { 254 | 255 | // We do a check for deactivate_plugins before calling it, to protect 256 | // any developers from accidentally calling it too early and breaking things. 257 | if ( function_exists( 'deactivate_plugins' ) ) { 258 | deactivate_plugins( $this->basename ); 259 | } 260 | } 261 | 262 | /** 263 | * Check that all plugin requirements are met. 264 | * 265 | * @since <%= version %> 266 | * 267 | * @return boolean True if requirements are met. 268 | */ 269 | public function meets_requirements() { 270 | 271 | // Do checks for required classes / functions or similar. 272 | // Add detailed messages to $this->activation_errors array. 273 | return true; 274 | } 275 | 276 | /** 277 | * Adds a notice to the dashboard if the plugin requirements are not met. 278 | * 279 | * @since <%= version %> 280 | */ 281 | public function requirements_not_met_notice() { 282 | 283 | // Compile default message. 284 | $default_message = sprintf( 285 | // Translators: Admin plugins URL. 286 | __( '<%= name %> is missing requirements and has been deactivated. Please make sure all requirements are available.', '<%= slug %>' ), 287 | admin_url( 'plugins.php' ) 288 | ); 289 | 290 | // Default details to null. 291 | $details = null; 292 | 293 | // Add details if any exist. 294 | if ( $this->activation_errors && is_array( $this->activation_errors ) ) { 295 | $details = '' . implode( '
', $this->activation_errors ) . ''; 296 | } 297 | 298 | // Output errors. 299 | ?> 300 |
301 |

302 | 303 |
304 | 311 | * 312 | * @param string $field Field to get. 313 | * @throws Exception Throws an exception if the field is invalid. 314 | * @return mixed Value of the field. 315 | */ 316 | public function __get( $field ) { 317 | switch ( $field ) { 318 | case 'version': 319 | return self::VERSION; 320 | case 'basename': 321 | case 'url': 322 | case 'path': 323 | return $this->$field; 324 | default: 325 | throw new Exception( 'Invalid ' . __CLASS__ . ' property: ' . $field ); 326 | } 327 | }<% if ( autoloader == 'Basic' ) { %> // @codingStandardsIgnoreLine 328 | 329 | /** 330 | * Include a file from the includes directory. 331 | * 332 | * @since <%= version %> 333 | * 334 | * @param string $filename Name of the file to be included. 335 | * @return boolean Result of include call. 336 | */ 337 | public static function include_file( $filename ) { 338 | $file = self::dir( $filename . '.php' ); 339 | if ( file_exists( $file ) ) { 340 | return include_once $file; 341 | } 342 | return false; 343 | } 344 | 345 | /** 346 | * This plugin's directory. 347 | * 348 | * @since <%= version %> 349 | * 350 | * @param string $path (optional) appended path. 351 | * @return string Directory and path. 352 | */ 353 | public static function dir( $path = '' ) { 354 | static $dir; 355 | $dir = $dir ? $dir : trailingslashit( dirname( __FILE__ ) ); 356 | return $dir . $path; 357 | } 358 | 359 | /** 360 | * This plugin's url. 361 | * 362 | * @since <%= version %> 363 | * 364 | * @param string $path (optional) appended path. 365 | * @return string URL and path. 366 | */ 367 | public static function url( $path = '' ) { 368 | static $url; 369 | $url = $url ? $url : trailingslashit( plugin_dir_url( __FILE__ ) ); 370 | return $url . $path; 371 | }<% } %> // @codingStandardsIgnoreLine 372 | } 373 | 374 | /** 375 | * Grab the <%= classname %> object and return it. 376 | * Wrapper for <%= classname %>::get_instance(). 377 | * 378 | * @since <%= version %> 379 | * @return <%= classname %> Singleton instance of plugin class. 380 | */ 381 | function <%= prefix %>() { // @codingStandardsIgnoreLine 382 | return <%= classname %>::get_instance(); // @codingStandardsIgnoreLine 383 | } 384 | 385 | // Kick it off. 386 | add_action( 'plugins_loaded', array( <%= prefix %>(), 'hooks' ) ); // @codingStandardsIgnoreLine 387 | 388 | // Activation and deactivation. 389 | register_activation_hook( __FILE__, array( <%= prefix %>(), 'activate' ) ); // @codingStandardsIgnoreLine 390 | register_deactivation_hook( __FILE__, array( <%= prefix %>(), 'deactivate' ) ); // @codingStandardsIgnoreLine 391 | -------------------------------------------------------------------------------- /app/templates/tests/bootstrap.php: -------------------------------------------------------------------------------- 1 | Test Bootstrapper. 4 | * 5 | * @since <%= version %> 6 | * @package <%= mainclassname %> 7 | */ 8 | 9 | // Get our tests directory. 10 | $_tests_dir = ( getenv( 'WP_TESTS_DIR' ) ) ? getenv( 'WP_TESTS_DIR' ) : '/tmp/wordpress-tests-lib'; 11 | 12 | // Include our tests functions. 13 | require_once $_tests_dir . '/includes/functions.php'; 14 | 15 | /** 16 | * Manually require our plugin for testing. 17 | * 18 | * @since <%= version %> 19 | */ 20 | function _manually_load_<%= prefix %>_plugin() { // @codingStandardsIgnoreLine 21 | 22 | // Include the REST API main plugin file if we're using it so we can run endpoint tests. 23 | if ( class_exists( 'WP_REST_Controller' ) && file_exists( WP_PLUGIN_DIR . '/rest-api/plugin.php' ) ) { 24 | require WP_PLUGIN_DIR . '/rest-api/plugin.php'; 25 | } 26 | 27 | // Require our plugin. 28 | require dirname( dirname( __FILE__ ) ) . '/<%= slug %>.php'; 29 | } 30 | 31 | // Inject in our plugin. 32 | tests_add_filter( 'muplugins_loaded', '_manually_load_<%= prefix %>_plugin' ); 33 | 34 | // Include the main tests bootstrapper. 35 | require $_tests_dir . '/includes/bootstrap.php'; 36 | -------------------------------------------------------------------------------- /app/templates/tests/test-base.php: -------------------------------------------------------------------------------- 1 | . 4 | * 5 | * @since <%= version %> 6 | * @package <%= mainclassname %> 7 | */ 8 | 9 | /** 10 | * <%= mainclassname %>. 11 | * 12 | * @since <%= version %> 13 | */ 14 | class <%= mainclassname %>_Test extends WP_UnitTestCase { // @codingStandardsIgnoreLine 15 | 16 | /** 17 | * Test if our class exists. 18 | * 19 | * @since <%= version %> 20 | */ 21 | public function test_class_exists() { 22 | $this->assertTrue( class_exists( '<%= classname %>' ) ); 23 | } 24 | 25 | /** 26 | * Test that our main helper function is an instance of our class. 27 | * 28 | * @since <%= version %> 29 | */ 30 | public function test_get_instance() { 31 | $this->assertInstanceOf( '<%= classname %>', <%= prefix %>() ); // @codingStandardsIgnoreLine 32 | } 33 | 34 | /** 35 | * Replace this with some actual testing code. 36 | * 37 | * @since <%= version %> 38 | */ 39 | public function test_sample() { 40 | $this->assertTrue( true ); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /cli/README.md: -------------------------------------------------------------------------------- 1 | # generator-plugin-wp CLI Sub-generator 2 | 3 | ```bash 4 | yo plugin-wp:cli 5 | ``` 6 | 7 | Creates a skeleton cli file for your plugin and registers a command. 8 | Keep in mind this will not protect you from trying to use WP-CLI default commands. 9 | -------------------------------------------------------------------------------- /cli/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var base = require('../plugin-wp-base'); 3 | 4 | module.exports = base.extend({ 5 | constructor: function () { 6 | base.apply(this, arguments); 7 | 8 | this.argument('name', { 9 | required: false, 10 | type: String, 11 | desc: 'The cli name' 12 | }); 13 | }, 14 | 15 | initializing: { 16 | intro: function () { 17 | // Have Yeoman greet the user. 18 | this.log('Welcome to the neat Plugin WP CLI subgenerator!'); 19 | }, 20 | 21 | readingYORC: function () { 22 | this.rc = this.config.getAll() || {}; 23 | }, 24 | 25 | readingPackage: function () { 26 | this.pkg = this.fs.readJSON(this.destinationPath('package.json')) || {}; 27 | }, 28 | 29 | settingValues: function () { 30 | this.version = this.pkg.version; 31 | if (this.name) { 32 | this.name = this._.titleize(this.name.split('-').join(' ')); 33 | this.nameslug = this._.slugify(this.name); 34 | } 35 | this.pluginname = this.rc.name; 36 | this.cliname = this.pluginname + ' ' + this._.capitalize(this.name); 37 | this.clislug = this.slug + '-cli-' + this._.slugify(this.name); 38 | this.uslug = this._.underscored(this.cliname); 39 | this.classslug = this._.underscored( this._wpClassify( this.name ) ); 40 | this.classname = this.rc.classprefix + this._wpClassify(this.name); 41 | 42 | // get the main classname 43 | this.mainclassname = this._wpClassify(this.pluginname); 44 | } 45 | }, 46 | 47 | prompting: function () { 48 | var done = this.async(); 49 | 50 | var prompts = []; 51 | 52 | if (!this.version) { 53 | prompts.push({ 54 | type: 'input', 55 | name: 'version', 56 | message: 'Version', 57 | default: '0.1.0' 58 | }); 59 | } 60 | 61 | if (!this.name) { 62 | prompts.push({ 63 | type: 'input', 64 | name: 'name', 65 | message: 'CLI Name', 66 | default: 'frontend' 67 | }); 68 | } 69 | 70 | if (!this.pluginname) { 71 | prompts.push({ 72 | type: 'input', 73 | name: 'pluginname', 74 | message: 'Plugin Name', 75 | default: 'WDS Client Plugin' 76 | }); 77 | } 78 | 79 | if (prompts.length > 0) { 80 | this.log('Missing some info about the original plugin, help me out?'); 81 | this.prompt(prompts, function (props) { 82 | if (props.version) { 83 | this.version = props.version; 84 | } 85 | 86 | if (props.name) { 87 | this.name = this._.titleize(props.name.split('-').join(' ')); 88 | this.nameslug = this._.slugify(this.name); 89 | } 90 | 91 | if (props.pluginname) { 92 | this.pluginname = props.pluginname; 93 | } 94 | 95 | if (props.name || props.pluginname) { 96 | this.cliname = this.pluginname + ' ' + this._.capitalize(this.name); 97 | this.classname = this._wpClassPrefix(this.pluginname) + this._wpClassify(this.name); 98 | } 99 | 100 | done(); 101 | }.bind(this)); 102 | } else { 103 | done(); 104 | } 105 | }, 106 | 107 | writing: function () { 108 | this.fs.copyTpl( 109 | this.templatePath('cli.php'), 110 | this.destinationPath('includes/class-' + this._.slugify(this.name) + '.php'), 111 | this 112 | ); 113 | 114 | if (!this.rc.notests) { 115 | this.fs.copyTpl( 116 | this.templatePath('tests.php'), 117 | this.destinationPath('tests/test-' + this._.slugify(this.name) + '.php'), 118 | this 119 | ); 120 | } 121 | 122 | this._addIncludeClass(this._.slugify(this.name), this.classname); 123 | } 124 | }); 125 | -------------------------------------------------------------------------------- /cli/templates/cli.php: -------------------------------------------------------------------------------- 1 | . 4 | * 5 | * @since <%= version %> 6 | * @package <%= mainclassname %> 7 | */ 8 | 9 | /** 10 | * <%= cliname %>. 11 | * 12 | * @since <%= version %> 13 | */ 14 | class <%= classname %> { // @codingStandardsIgnoreLine 15 | /** 16 | * Parent plugin class 17 | * 18 | * @var <%= mainclassname %> 19 | * 20 | * @since <%= version %> 21 | */ 22 | protected $plugin = null; 23 | 24 | /** 25 | * Constructor. 26 | * 27 | * @since <%= version %> 28 | * 29 | * @param <%= mainclassname %> $plugin Main plugin object. 30 | */ 31 | public function __construct( $plugin ) { 32 | $this->plugin = $plugin; 33 | 34 | // If we have WP CLI, add our commands. 35 | if ( $this->verify_wp_cli() ) { 36 | $this->add_commands(); 37 | } 38 | } 39 | 40 | /** 41 | * Check for WP CLI running. 42 | * 43 | * @since <%= version %> 44 | * 45 | * @return boolean True if WP CLI currently running. 46 | */ 47 | public function verify_wp_cli() { 48 | return ( defined( 'WP_CLI' ) && WP_CLI ); 49 | } 50 | 51 | /** 52 | * Add our commands. 53 | * 54 | * @since <%= version %> 55 | */ 56 | public function add_commands() { 57 | WP_CLI::add_command( '<%= uslug %>', array( $this, '<%= uslug %>_command' ) ); 58 | } 59 | 60 | /** 61 | * Create a method stub for our first CLI command. 62 | * 63 | * @since <%= version %> 64 | */ 65 | public function <%= uslug %>_command() { // @codingStandardsIgnoreLine 66 | 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /cli/templates/tests.php: -------------------------------------------------------------------------------- 1 | Tests. 4 | * 5 | * @since <%= version %> 6 | * @package <%= mainclassname %> 7 | */ 8 | 9 | /** 10 | * <%= cliname %> Tests. 11 | * 12 | * @since <%= version %> 13 | */ 14 | class <%= classname %>_Test extends WP_UnitTestCase { // @codingStandardsIgnoreLine 15 | 16 | /** 17 | * Test if our class exists. 18 | * 19 | * @since <%= version %> 20 | */ 21 | public function test_class_exists() { 22 | $this->assertTrue( class_exists( '<%= classname %>' ) ); 23 | } 24 | 25 | /** 26 | * Test that we can access our class through our helper function. 27 | * 28 | * @since <%= version %> 29 | */ 30 | public function test_class_access() { 31 | $this->assertInstanceOf( '<%= classname %>', <%= rc.prefix %>()-><%= classslug %> ); // @codingStandardsIgnoreLine 32 | } 33 | 34 | /** 35 | * Replace this with some actual testing code. 36 | * 37 | * @since <%= version %> 38 | */ 39 | public function test_sample() { 40 | $this->assertTrue( true ); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /cpt/README.md: -------------------------------------------------------------------------------- 1 | # generator-plugin-wp CPT Sub-generator 2 | 3 | ```bash 4 | yo plugin-wp:cpt 5 | ``` 6 | 7 | Creates a skeleton custom post type using [CPT_Core](https://github.com/WebDevStudios/CPT_Core). 8 | 9 | You can optionally include [CMB2](https://github.com/CMB2/CMB2) by using the `--cmb2` option when running the subgenerator. 10 | 11 | Refer to [CPT_Core](https://github.com/WebDevStudios/CPT_Core) for more details on extending the CPT_Core class. 12 | -------------------------------------------------------------------------------- /cpt/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var base = require('../plugin-wp-base'); 3 | var ghdownload = require('github-download'); 4 | 5 | module.exports = base.extend({ 6 | constructor: function () { 7 | base.apply(this, arguments); 8 | 9 | this.option('cmb2'); 10 | 11 | this.argument('name', { 12 | required: false, 13 | type : String, 14 | desc : 'The CPT name' 15 | }); 16 | }, 17 | 18 | initializing: { 19 | intro: function () { 20 | // Have Yeoman greet the user. 21 | this.log('Welcome to the neat Plugin WP CPT subgenerator!'); 22 | }, 23 | 24 | readingYORC: function() { 25 | this.rc = this.config.getAll() || {}; 26 | }, 27 | 28 | readingPackage: function() { 29 | this.pkg = this.fs.readJSON( this.destinationPath('package.json')) || {}; 30 | }, 31 | 32 | settingValues: function() { 33 | this.version = this.rc.version; 34 | if ( this.name ) { 35 | this.name = this._.titleize( this.name.split('-').join(' ') ); 36 | this.nameslug = this._.slugify( this.name ); 37 | } 38 | this.pluginname = this.rc.name; 39 | this.cptname = this.pluginname + ' ' + this._.capitalize( this.name ); 40 | this.classname = this.rc.classprefix + this._wpClassify( this.name ); 41 | this.slug = this.rc.slug; 42 | this.classslug = this._.underscored( this._wpClassify( this.name ) ); 43 | this.cptslug = this._.slugify( this.classname ).substr( 0, 20 ); 44 | this.cptprefix = this._.underscored( this.cptslug ); 45 | 46 | // get the main classname 47 | this.mainclassname = this._wpClassify( this.pluginname ); 48 | 49 | this.composer = this.fs.exists('composer.json'); 50 | } 51 | }, 52 | 53 | prompting: function () { 54 | var done = this.async(); 55 | 56 | var prompts = []; 57 | 58 | if ( !this.version ) { 59 | prompts.push({ 60 | type : 'input', 61 | name : 'version', 62 | message: 'Version', 63 | default: '0.1.0' 64 | }); 65 | } 66 | 67 | if ( !this.name ) { 68 | prompts.push({ 69 | type : 'input', 70 | name : 'name', 71 | message: 'CPT Name', 72 | default: 'basic-cpt' 73 | }); 74 | } 75 | 76 | if ( !this.pluginname ) { 77 | prompts.push({ 78 | type : 'input', 79 | name : 'pluginname', 80 | message: 'Plugin Name', 81 | default: 'WDS Client Plugin' 82 | }); 83 | } 84 | 85 | if ( prompts.length > 0 ) { 86 | this.log( 'Missing some info about the original plugin, help me out?' ); 87 | this.prompt(prompts, function (props) { 88 | if ( props.version ) { 89 | this.version = props.version; 90 | } 91 | 92 | if ( props.name ) { 93 | this.name = this._.titleize( props.name.split('-').join(' ') ); 94 | this.nameslug = this._.slugify( this.name ); 95 | } 96 | 97 | if ( props.pluginname ) { 98 | this.pluginname = props.pluginname; 99 | this.slug = this._.slugify( props.pluginname ); 100 | } 101 | 102 | if ( props.name || props.pluginname ) { 103 | this.cptname = this.pluginname + ' ' + this._.capitalize( this.name ); 104 | this.classname = this._wpClassPrefix( this.pluginname ) + this._wpClassify( this.name ); 105 | this.cptslug = this.slug + '-' + this._.slugify( this.name ); 106 | this.cptslug = this.cptslug.substr(0,20); 107 | this.cptprefix = this._.underscored( this.slug + ' ' + this.name ); 108 | } 109 | 110 | done(); 111 | }.bind(this)); 112 | } else { 113 | done(); 114 | } 115 | }, 116 | 117 | writing: function () { 118 | 119 | this.fs.copyTpl( 120 | this.templatePath('cpt.php'), 121 | this.destinationPath('includes/class-' + this._.slugify( this.name ) + '.php'), 122 | this 123 | ); 124 | 125 | if ( !this.rc.notests ) { 126 | this.fs.copyTpl( 127 | this.templatePath('tests.php'), 128 | this.destinationPath('tests/test-' + this._.slugify( this.name ) + '.php'), 129 | this 130 | ); 131 | } 132 | 133 | this._addIncludeClass( this._.slugify( this.name ), this.classname, this.version ); 134 | }, 135 | 136 | install: function () { 137 | if ( this.options['skip-install'] ) { 138 | return; 139 | } 140 | 141 | if ( this.composer ) { 142 | this.spawnCommand('composer', ['require', 'webdevstudios/cpt-core']); 143 | 144 | if ( this.options.cmb2 ) { 145 | this.spawnCommand('composer', ['require', 'cmb2/cmb2']); 146 | } 147 | } else { 148 | this.mkdir('vendor'); 149 | if ( !this.fs.exists('vendor/cpt-core/CPT_Core.php') ) { 150 | ghdownload({ 151 | user: 'WebDevStudios', 152 | repo: 'CPT_Core', 153 | ref : 'master' 154 | }, this.destinationPath('vendor/cpt-core') ); 155 | } 156 | 157 | if ( !this.fs.exists('vendor/cmb2/init.php') && this.options.cmb2 ) { 158 | ghdownload({ 159 | user: 'CMB2', 160 | repo: 'CMB2', 161 | ref : 'master' 162 | }, this.destinationPath('vendor/cmb2') ); 163 | } 164 | } 165 | } 166 | }); 167 | -------------------------------------------------------------------------------- /cpt/templates/cpt.php: -------------------------------------------------------------------------------- 1 | . 4 | * 5 | * @since <%= version %> 6 | * @package <%= mainclassname %> 7 | */ // @codingStandardsIgnoreLine 8 | <% if ( ! composer ) { %> // @codingStandardsIgnoreLine 9 | /** 10 | * Include CPT Core 11 | * 12 | * @since <%= version %> 13 | */ 14 | require_once dirname( __FILE__ ) . '/../vendor/cpt-core/CPT_Core.php'; 15 | <% if ( options.cmb2 ) { %> // @codingStandardsIgnoreLine 16 | /** 17 | * Include CMB2 18 | * 19 | * @since <%= version %> 20 | */ 21 | require_once dirname( __FILE__ ) . '/../vendor/cmb2/init.php'; 22 | <% } // @codingStandardsIgnoreLine 23 | } %> // @codingStandardsIgnoreLine 24 | /** 25 | * <%= cptname %> post type class. 26 | * 27 | * @since <%= version %> 28 | * 29 | * @see https://github.com/WebDevStudios/CPT_Core 30 | */ 31 | class <%= classname %> extends CPT_Core { // @codingStandardsIgnoreLine 32 | /** 33 | * Parent plugin class. 34 | * 35 | * @var <%= mainclassname %> 36 | * @since <%= version %> 37 | */ 38 | protected $plugin = null; 39 | 40 | /** 41 | * Constructor. 42 | * 43 | * Register Custom Post Types. 44 | * 45 | * See documentation in CPT_Core, and in wp-includes/post.php. 46 | * 47 | * @since <%= version %> 48 | * 49 | * @param <%= mainclassname %> $plugin Main plugin object. 50 | */ 51 | public function __construct( $plugin ) { 52 | $this->plugin = $plugin; 53 | $this->hooks(); 54 | 55 | // Register this cpt. 56 | // First parameter should be an array with Singular, Plural, and Registered name. 57 | parent::__construct( 58 | array( 59 | esc_html__( '<%= cptname %>', '<%= slug %>' ), 60 | esc_html__( '<%= cptname %>s', '<%= slug %>' ), 61 | '<%= cptslug %>', 62 | ), 63 | array( 64 | 'supports' => array( 65 | 'title', 66 | 'editor', 67 | 'excerpt', 68 | 'thumbnail', 69 | ), 70 | 'menu_icon' => 'dashicons-admin-post', // https://developer.wordpress.org/resource/dashicons/ - Developer Resources: Dashicons. 71 | 'public' => true, 72 | ) 73 | ); 74 | } 75 | 76 | /** 77 | * Initiate our hooks. 78 | * 79 | * @since <%= version %> 80 | */ 81 | public function hooks() {<% if ( options.cmb2 ) { %> // @codingStandardsIgnoreLine 82 | add_action( 'cmb2_init', array( $this, 'fields' ) ); 83 | } 84 | 85 | /** 86 | * Add custom fields to the CPT. 87 | * 88 | * @since <%= version %> 89 | */ 90 | public function fields() { 91 | 92 | // Set our prefix. 93 | $prefix = '<%= cptprefix %>_'; 94 | 95 | // Define our metaboxes and fields. 96 | $cmb = new_cmb2_box( 97 | array( 98 | 'id' => $prefix . 'metabox', 99 | 'title' => esc_html__( '<%= cptname %> Meta Box', '<%= slug %>' ), 100 | 'object_types' => array( '<%= cptslug %>' ), 101 | ) 102 | );<% } %> // @codingStandardsIgnoreLine 103 | } 104 | 105 | /** 106 | * Registers admin columns to display. Hooked in via CPT_Core. 107 | * 108 | * @since <%= version %> 109 | * 110 | * @param array $columns Array of registered column names/labels. 111 | * @return array Modified array. 112 | */ 113 | public function columns( $columns ) { 114 | $new_column = array(); 115 | return array_merge( $new_column, $columns ); 116 | } 117 | 118 | /** 119 | * Handles admin column display. Hooked in via CPT_Core. 120 | * 121 | * @since <%= version %> 122 | * 123 | * @param array $column Column currently being rendered. 124 | * @param integer $post_id ID of post to display column for. 125 | */ 126 | public function columns_display( $column, $post_id ) { 127 | switch ( $column ) { // @codingStandardsIgnoreLine 128 | } 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /cpt/templates/tests.php: -------------------------------------------------------------------------------- 1 | Tests. 4 | * 5 | * @since <%= version %> 6 | * @package <%= mainclassname %> 7 | */ 8 | 9 | /** 10 | * <%= cptname %> Tests. 11 | * 12 | * @since <%= version %> 13 | */ 14 | class <%= classname %>_Test extends WP_UnitTestCase { // @codingStandardsIgnoreLine 15 | 16 | /** 17 | * Test if our class exists. 18 | * 19 | * @since <%= version %> 20 | */ 21 | public function test_class_exists() { 22 | $this->assertTrue( class_exists( '<%= classname %>' ) ); 23 | } 24 | 25 | /** 26 | * Test that we can access our class through our helper function. 27 | * 28 | * @since <%= version %> 29 | */ 30 | public function test_class_access() { 31 | $this->assertInstanceOf( '<%= classname %>', <%= rc.prefix %>()-><%= classslug %> ); // @codingStandardsIgnoreLine 32 | } 33 | 34 | /** 35 | * Test to make sure the CPT now exists. 36 | * 37 | * @since <%= version %> 38 | */ 39 | public function test_cpt_exists() { 40 | $this->assertTrue( post_type_exists( '<%= cptslug %>' ) ); 41 | } 42 | 43 | /** 44 | * Replace this with some actual testing code. 45 | * 46 | * @since <%= version %> 47 | */ 48 | public function test_sample() { 49 | $this->assertTrue( true ); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /css/README.md: -------------------------------------------------------------------------------- 1 | # generator-plugin-wp CSS Subgenerator 2 | 3 | ```bash 4 | yo plugin-wp:css 5 | ``` 6 | 7 | Initializes styles for your plugin, including configuring the Gruntfile.js with the proper tasks. 8 | 9 | The sub-generator prompts for type of style setup, either SASS with minification, or basic CSS with minification. 10 | 11 | You will need to manually enqueue the styles. 12 | -------------------------------------------------------------------------------- /css/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var base = require('../plugin-wp-base'); 3 | 4 | module.exports = base.extend({ 5 | initializing: function () { 6 | this.pkg = require('../package.json'); 7 | this.rc = this.config.getAll(); 8 | 9 | // Have Yeoman greet the user. 10 | this.log('Welcome to the neat Plugin WP Styles subgenerator!'); 11 | }, 12 | 13 | prompting: function () { 14 | var done = this.async(); 15 | 16 | var prompts = [{ 17 | type : 'list', 18 | name : 'type', 19 | message: 'Style setup', 20 | choices: ['SASS', 'Basic'] 21 | }]; 22 | 23 | // Sanitize inputs 24 | this.prompt(prompts, function (props) { 25 | this.type = props.type; 26 | 27 | done(); 28 | }.bind(this)); 29 | }, 30 | 31 | configuring: function() { 32 | if ( !this.fs.exists( 'Gruntfile.js') ){ 33 | this.log( 'No Gruntfile.js found, no Grunt tasks added.' ); 34 | return; 35 | } 36 | 37 | if ( this.type === 'SASS' ) { 38 | this.gruntfile.insertConfig('sass', "{dist: {options: {sourceMap: true}, files: {'assets/css/" + this.rc.slug + ".css': 'assets/css/sass/styles.scss'}}}"); 39 | this.gruntfile.registerTask('styles', 'sass'); 40 | } 41 | 42 | this.gruntfile.insertConfig('cssmin', "{dist: {files: {'assets/css/" + this.rc.slug + ".min.css': 'assets/css/" + this.rc.slug + ".css'}}}"); 43 | this.gruntfile.insertConfig('usebanner', "{ taskName: { options: { position: 'top', banner: bannerTemplate, linebreak: true }, files: { src: [ 'assets/css/" + this.rc.slug + ".min.css' ] } } }"); 44 | 45 | this.gruntfile.registerTask('styles', 'cssmin'); 46 | this.gruntfile.registerTask('styles', 'usebanner'); 47 | }, 48 | 49 | writing: function () { 50 | if ( this.type === 'SASS' ) { 51 | this.fs.copyTpl( 52 | this.templatePath('styles.css'), 53 | this.destinationPath('assets/css/sass/styles.scss'), 54 | this 55 | ); 56 | } else { 57 | this.fs.copyTpl( 58 | this.templatePath('styles.css'), 59 | this.destinationPath('assets/css/' + this.rc.slug + '.css'), 60 | this 61 | ); 62 | } 63 | }, 64 | 65 | install: function () { 66 | } 67 | }); 68 | -------------------------------------------------------------------------------- /css/templates/styles.css: -------------------------------------------------------------------------------- 1 | /** 2 | * <%= rc.name %> 3 | * <%= rc.homepage %> 4 | * 5 | * Copyright (c) <%= new Date().getFullYear() %> <%= rc.author %> 6 | * Licensed under the GPLv2+ license. 7 | */ -------------------------------------------------------------------------------- /endpoint/README.md: -------------------------------------------------------------------------------- 1 | # generator-plugin-wp Endpoint Sub-generator 2 | 3 | ```bash 4 | yo plugin-wp:endpoint 5 | ``` 6 | 7 | Creates a skeleton WP-API endpoint class for your plugin, [refer here](http://v2.wp-api.org/extending/adding/#the-controller-pattern) for more info on how to build out your endpoint. 8 | -------------------------------------------------------------------------------- /endpoint/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var base = require('../plugin-wp-base'); 3 | 4 | module.exports = base.extend({ 5 | constructor: function () { 6 | base.apply(this, arguments); 7 | 8 | this.argument('name', { 9 | required: false, 10 | type : String, 11 | desc : 'The include name' 12 | }); 13 | }, 14 | 15 | initializing: { 16 | intro: function () { 17 | // Have Yeoman greet the user. 18 | this.log('Welcome to the neat Plugin WP Include subgenerator!'); 19 | }, 20 | 21 | readingYORC: function() { 22 | this.rc = this.config.getAll() || {}; 23 | }, 24 | 25 | readingPackage: function() { 26 | this.pkg = this.fs.readJSON( this.destinationPath('package.json')) || {}; 27 | }, 28 | 29 | settingValues: function() { 30 | this.version = this.pkg.version; 31 | if ( this.name ) { 32 | this.name = this._.titleize( this.name.split('-').join(' ') ); 33 | this.nameslug = this._.slugify( this.name ); 34 | } 35 | this.pluginname = this.rc.name; 36 | this.pluginslug = this.rc.slug; 37 | this.includename = this.pluginname + ' ' + this._.capitalize( this.name ); 38 | this.classname = this.rc.classprefix + this._wpClassify( this.name ); 39 | this.classslug = this._.underscored( this._wpClassify( this.name ) ); 40 | 41 | // get the main classname 42 | this.mainclassname = this._wpClassify( this.pluginname ); 43 | } 44 | }, 45 | 46 | prompting: function () { 47 | var done = this.async(); 48 | 49 | var prompts = []; 50 | 51 | if ( !this.version ) { 52 | prompts.push({ 53 | type : 'input', 54 | name : 'version', 55 | message: 'Version', 56 | default: '0.1.0' 57 | }); 58 | } 59 | 60 | if ( !this.name ) { 61 | prompts.push({ 62 | type : 'input', 63 | name : 'name', 64 | message: 'Include Name', 65 | default: 'frontend' 66 | }); 67 | } 68 | 69 | if ( !this.pluginname ) { 70 | prompts.push({ 71 | type : 'input', 72 | name : 'pluginname', 73 | message: 'Plugin Name', 74 | default: 'WDS Client Plugin' 75 | }); 76 | } 77 | 78 | if ( prompts.length > 0 ) { 79 | this.log( 'Missing some info about the original plugin, help me out?' ); 80 | this.prompt(prompts, function (props) { 81 | if ( props.version ) { 82 | this.version = props.version; 83 | } 84 | 85 | if ( props.name ) { 86 | this.name = this._.titleize( props.name.split('-').join(' ') ); 87 | this.nameslug = this._.slugify( this.name ); 88 | } 89 | 90 | if ( props.pluginname ) { 91 | this.pluginname = props.pluginname; 92 | this.pluginslug = this._.slugify( this.pluginname ); 93 | } 94 | 95 | if ( props.name || props.pluginname ) { 96 | this.includename = this.pluginname + ' ' + this._.capitalize( this.name ); 97 | this.classname = this._wpClassPrefix( this.pluginname ) + this._wpClassify( this.name ); 98 | } 99 | 100 | done(); 101 | }.bind(this)); 102 | } else { 103 | done(); 104 | } 105 | }, 106 | 107 | writing: function () { 108 | this.fs.copyTpl( 109 | this.templatePath('endpoint.php'), 110 | this.destinationPath('includes/class-' + this._.slugify( this.name ) + '.php'), 111 | this 112 | ); 113 | 114 | if ( !this.rc.notests ) { 115 | this.fs.copyTpl( 116 | this.templatePath('tests.php'), 117 | this.destinationPath('tests/test-' + this._.slugify( this.name ) + '.php'), 118 | this 119 | ); 120 | } 121 | 122 | this._addIncludeClass( this._.slugify( this.name ), this.classname, this.version ); 123 | } 124 | }); 125 | -------------------------------------------------------------------------------- /endpoint/templates/endpoint.php: -------------------------------------------------------------------------------- 1 | . 4 | * 5 | * @since <%= version %> 6 | * @package <%= mainclassname %> 7 | */ 8 | 9 | if ( class_exists( 'WP_REST_Controller' ) ) { 10 | /** 11 | * Endpoint class. 12 | * 13 | * @since <%= version %> 14 | */ 15 | class <%= classname %> extends WP_REST_Controller { // @codingStandardsIgnoreLine 16 | /** 17 | * Parent plugin class. 18 | * 19 | * @var <%= mainclassname %> 20 | * @since <%= version %> 21 | */ 22 | protected $plugin = null; 23 | 24 | /** 25 | * Constructor. 26 | * 27 | * @since <%= version %> 28 | * 29 | * @param <%= mainclassname %> $plugin Main plugin object. 30 | */ 31 | public function __construct( $plugin ) { 32 | $this->plugin = $plugin; 33 | $this->hooks(); 34 | } 35 | 36 | /** 37 | * Add our hooks. 38 | * 39 | * @since <%= version %> 40 | */ 41 | public function hooks() { 42 | add_action( 'rest_api_init', array( $this, 'register_routes' ) ); 43 | } 44 | 45 | /** 46 | * Register the routes for the objects of the controller. 47 | * 48 | * @since <%= version %> 49 | */ 50 | public function register_routes() { 51 | 52 | // Set up defaults. 53 | $version = '1'; 54 | $namespace = '<%= pluginslug %>/v' . $version; 55 | $base = '<%= nameslug %>'; 56 | 57 | // Example register_rest_route calls. 58 | register_rest_route( 59 | $namespace, 60 | '/' . $base, 61 | array( 62 | array( 63 | 'methods' => WP_REST_Server::READABLE, 64 | 'callback' => array( $this, 'get_items' ), 65 | 'permission_callback' => array( $this, 'get_items_permission_check' ), 66 | 'args' => array(), 67 | ), 68 | ) 69 | ); 70 | 71 | register_rest_route( 72 | $namespace, 73 | '/' . $base . '/(?P[\d]+)', 74 | array( 75 | array( 76 | 'methods' => WP_REST_Server::READABLE, 77 | 'callback' => array( $this, 'get_item' ), 78 | 'permission_callback' => array( $this, 'get_item_permissions_check' ), 79 | 'args' => array( 80 | 'context' => array( 81 | 'default' => 'view', 82 | ), 83 | ), 84 | ), 85 | array( 86 | 'methods' => WP_REST_Server::EDITABLE, 87 | 'callback' => array( $this, 'update_item' ), 88 | 'permission_callback' => array( $this, 'update_item_permissions_check' ), 89 | 'args' => $this->get_endpoint_args_for_item_schema( false ), 90 | ), 91 | array( 92 | 'methods' => WP_REST_Server::DELETABLE, 93 | 'callback' => array( $this, 'delete_item' ), 94 | 'permission_callback' => array( $this, 'delete_item_permissions_check' ), 95 | 'args' => array( 96 | 'force' => array( 97 | 'default' => false, 98 | ), 99 | ), 100 | ), 101 | ) 102 | ); 103 | 104 | register_rest_route( 105 | $namespace, 106 | '/' . $base . '/schema', 107 | array( 108 | 'methods' => WP_REST_Server::READABLE, 109 | 'callback' => array( $this, 'get_public_item_schema' ), 110 | ) 111 | ); 112 | } 113 | 114 | /** 115 | * Get items. 116 | * 117 | * @since <%= version %> 118 | * 119 | * @param WP_REST_Request $request Full details about the request. 120 | */ 121 | public function get_items( $request ) {} 122 | 123 | /** 124 | * Permission check for getting items. 125 | * 126 | * @since <%= version %> 127 | * 128 | * @param WP_REST_Request $request Full details about the request. 129 | */ 130 | public function get_items_permission_check( $request ) {} 131 | 132 | /** 133 | * Get item. 134 | * 135 | * @since <%= version %> 136 | * 137 | * @param WP_REST_Request $request Full details about the request. 138 | */ 139 | public function get_item( $request ) {} 140 | 141 | /** 142 | * Permission check for getting item. 143 | * 144 | * @since <%= version %> 145 | * 146 | * @param WP_REST_Request $request Full details about the request. 147 | */ 148 | public function get_item_permissions_check( $request ) {} 149 | 150 | /** 151 | * Update item. 152 | * 153 | * @since <%= version %> 154 | * 155 | * @param WP_REST_Request $request Full details about the request. 156 | */ 157 | public function update_item( $request ) {} 158 | 159 | /** 160 | * Permission check for updating items. 161 | * 162 | * @since <%= version %> 163 | * 164 | * @param WP_REST_Request $request Full details about the request. 165 | */ 166 | public function update_item_permissions_check( $request ) {} 167 | 168 | /** 169 | * Delete item. 170 | * 171 | * @since <%= version %> 172 | * 173 | * @param WP_REST_Request $request Full details about the request. 174 | */ 175 | public function delete_item( $request ) {} 176 | 177 | /** 178 | * Permission check for deleting items. 179 | * 180 | * @since <%= version %> 181 | * 182 | * @param WP_REST_Request $request Full details about the request. 183 | */ 184 | public function delete_item_permissions_check( $request ) {} 185 | 186 | /** 187 | * Get item schema. 188 | * 189 | * @since <%= version %> 190 | */ 191 | public function get_public_item_schema() {} 192 | } 193 | } 194 | -------------------------------------------------------------------------------- /endpoint/templates/tests.php: -------------------------------------------------------------------------------- 1 | Tests. 4 | * 5 | * @since <%= version %> 6 | * @package <%= mainclassname %> 7 | */ 8 | 9 | /** 10 | * <%= includename %> Tests. 11 | * 12 | * @since <%= version %> 13 | */ 14 | class <%= classname %>_Test extends WP_UnitTestCase { // @codingStandardsIgnoreLine 15 | 16 | /** 17 | * Test if our class exists. 18 | * 19 | * @since <%= version %> 20 | */ 21 | public function test_class_exists() { 22 | $this->assertTrue( class_exists( '<%= classname %>' ) ); 23 | } 24 | 25 | /** 26 | * Test that we can access our class through our helper function. 27 | * 28 | * @since <%= version %> 29 | */ 30 | public function test_class_access() { 31 | $this->assertInstanceOf( '<%= classname %>', <%= rc.prefix %>()-><%= classslug %> ); // @codingStandardsIgnoreLine 32 | } 33 | 34 | /** 35 | * Replace this with some actual testing code. 36 | * 37 | * @since <%= version %> 38 | */ 39 | public function test_sample() { 40 | $this->assertTrue( true ); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /include/README.md: -------------------------------------------------------------------------------- 1 | # generator-plugin-wp Include Sub-generator 2 | 3 | ```bash 4 | yo plugin-wp:include 5 | ``` 6 | 7 | Creates a skeleton include file for your plugin. 8 | -------------------------------------------------------------------------------- /include/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var base = require('../plugin-wp-base'); 3 | 4 | module.exports = base.extend({ 5 | constructor: function () { 6 | base.apply(this, arguments); 7 | 8 | this.argument('name', { 9 | required: false, 10 | type : String, 11 | desc : 'The include name' 12 | }); 13 | }, 14 | 15 | initializing: { 16 | intro: function () { 17 | // Have Yeoman greet the user. 18 | this.log('Welcome to the neat Plugin WP Include subgenerator!'); 19 | }, 20 | 21 | readingYORC: function() { 22 | this.rc = this.config.getAll() || {}; 23 | }, 24 | 25 | readingPackage: function() { 26 | this.pkg = this.fs.readJSON( this.destinationPath('package.json')) || {}; 27 | }, 28 | 29 | settingValues: function() { 30 | this.version = this.pkg.version; 31 | if ( this.name ) { 32 | this.name = this._.titleize( this.name.split('-').join(' ') ); 33 | this.nameslug = this._.slugify( this.name ); 34 | this.property = this._.underscored( this.nameslug ); 35 | } 36 | this.pluginname = this.rc.name; 37 | this.includename = this.pluginname + ' ' + this._.capitalize( this.name ); 38 | this.classname = this.rc.classprefix + this._wpClassify( this.name ); 39 | 40 | // get the main classname 41 | this.mainclassname = this._wpClassify( this.pluginname ); 42 | } 43 | }, 44 | 45 | prompting: function () { 46 | var done = this.async(); 47 | 48 | var prompts = []; 49 | 50 | if ( !this.version ) { 51 | prompts.push({ 52 | type : 'input', 53 | name : 'version', 54 | message: 'Version', 55 | default: '0.1.0' 56 | }); 57 | } 58 | 59 | if ( !this.name ) { 60 | prompts.push({ 61 | type : 'input', 62 | name : 'name', 63 | message: 'Include Name', 64 | default: 'frontend' 65 | }); 66 | } 67 | 68 | if ( !this.pluginname ) { 69 | prompts.push({ 70 | type : 'input', 71 | name : 'pluginname', 72 | message: 'Plugin Name', 73 | default: 'WDS Client Plugin' 74 | }); 75 | } 76 | 77 | if ( prompts.length > 0 ) { 78 | this.log( 'Missing some info about the original plugin, help me out?' ); 79 | this.prompt(prompts, function (props) { 80 | if ( props.version ) { 81 | this.version = props.version; 82 | } 83 | 84 | if ( props.name ) { 85 | this.name = this._.titleize( props.name.split('-').join(' ') ); 86 | this.nameslug = this._.slugify( this.name ); 87 | } 88 | 89 | if ( props.pluginname ) { 90 | this.pluginname = props.pluginname; 91 | } 92 | 93 | if ( props.name || props.pluginname ) { 94 | this.includename = this.pluginname + ' ' + this._.capitalize( this.name ); 95 | this.classname = this._wpClassPrefix( this.pluginname ) + this._wpClassify( this.name ); 96 | } 97 | 98 | done(); 99 | }.bind(this)); 100 | } else { 101 | done(); 102 | } 103 | }, 104 | 105 | writing: function () { 106 | this.fs.copyTpl( 107 | this.templatePath('include.php'), 108 | this.destinationPath('includes/class-' + this._.slugify( this.name ) + '.php'), 109 | this 110 | ); 111 | 112 | if ( !this.rc.notests ) { 113 | this.fs.copyTpl( 114 | this.templatePath('tests.php'), 115 | this.destinationPath('tests/test-' + this._.slugify( this.name ) + '.php'), 116 | this 117 | ); 118 | } 119 | 120 | this._addIncludeClass( this._.slugify( this.name ), this.classname, this.version ); 121 | } 122 | }); 123 | -------------------------------------------------------------------------------- /include/templates/include.php: -------------------------------------------------------------------------------- 1 | . 4 | * 5 | * @since <%= version %> 6 | * @package <%= mainclassname %> 7 | */ 8 | 9 | /** 10 | * <%= includename %>. 11 | * 12 | * @since <%= version %> 13 | */ 14 | class <%= classname %> { // @codingStandardsIgnoreLine 15 | /** 16 | * Parent plugin class. 17 | * 18 | * @since <%= version %> 19 | * 20 | * @var <%= mainclassname %> 21 | */ 22 | protected $plugin = null; 23 | 24 | /** 25 | * Constructor. 26 | * 27 | * @since <%= version %> 28 | * 29 | * @param <%= mainclassname %> $plugin Main plugin object. 30 | */ 31 | public function __construct( $plugin ) { 32 | $this->plugin = $plugin; 33 | $this->hooks(); 34 | } 35 | 36 | /** 37 | * Initiate our hooks. 38 | * 39 | * @since <%= version %> 40 | */ 41 | public function hooks() { 42 | 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /include/templates/tests.php: -------------------------------------------------------------------------------- 1 | Tests. 4 | * 5 | * @since <%= version %> 6 | * @package <%= mainclassname %> 7 | */ 8 | 9 | /** 10 | * <%= includename %> Tests. 11 | * 12 | * @since <%= version %> 13 | */ 14 | class <%= classname %>_Test extends WP_UnitTestCase { // @codingStandardsIgnoreLine 15 | 16 | /** 17 | * Test if our class exists. 18 | * 19 | * @since <%= version %> 20 | */ 21 | public function test_class_exists() { 22 | $this->assertTrue( class_exists( '<%= classname %>' ) ); 23 | } 24 | 25 | /** 26 | * Test that we can access our class through our helper function. 27 | * 28 | * @since <%= version %> 29 | */ 30 | public function test_class_access() { 31 | $this->assertInstanceOf( '<%= classname %>', <%= rc.prefix %>()-><%= property %> ); // @codingStandardsIgnoreLine 32 | } 33 | 34 | /** 35 | * Replace this with some actual testing code. 36 | * 37 | * @since <%= version %> 38 | */ 39 | public function test_sample() { 40 | $this->assertTrue( true ); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /js/README.md: -------------------------------------------------------------------------------- 1 | # generator-plugin-wp JS Subgenerator 2 | 3 | ```bash 4 | yo plugin-wp:js 5 | ``` 6 | 7 | Initializes javascript for your plugin, including configuring the Gruntfile.js with the proper tasks. 8 | 9 | The sub-generator prompts for type of javscript setup; Browserify, Concatination, or just Uglification. 10 | 11 | You will need to manually enqueue the javascript. 12 | -------------------------------------------------------------------------------- /js/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var base = require('../plugin-wp-base'); 3 | 4 | module.exports = base.extend({ 5 | initializing: function () { 6 | this.pkg = require('../package.json'); 7 | this.rc = this.config.getAll(); 8 | 9 | // Have Yeoman greet the user. 10 | this.log('Welcome to the neat Plugin WP Javascript subgenerator!'); 11 | }, 12 | 13 | prompting: function () { 14 | var done = this.async(); 15 | 16 | var prompts = [{ 17 | type: 'list', 18 | name: 'type', 19 | message: 'Javascript setup', 20 | choices: ['Browserify', 'Concat', 'Basic'] 21 | }]; 22 | 23 | this.prompt(prompts, function (props) { 24 | // Sanitize inputs 25 | this.type = props.type; 26 | 27 | this.jsclassname = this.rc.classname.replace( /\_/gi, '' ); 28 | 29 | done(); 30 | }.bind(this)); 31 | }, 32 | 33 | configuring: function() { 34 | if ( !this.fs.exists( 'Gruntfile.js') ){ 35 | this.log( 'No Gruntfile.js found, no Grunt tasks added.' ); 36 | return; 37 | } 38 | 39 | if ( this.type === 'Basic' ) { 40 | this.gruntfile.insertConfig('eslint', "{src: ['assets/js/**/*.js','!**/*.min.js'] }"); 41 | } else { 42 | this.gruntfile.insertConfig('eslint', "{src: ['assets/js/components/**/*.js','!**/*.min.js'] }"); 43 | } 44 | this.gruntfile.loadNpmTasks('gruntify-eslint'); 45 | this.gruntfile.registerTask('scripts', 'eslint'); 46 | 47 | if ( this.type === 'Concat' ) { 48 | this.gruntfile.insertConfig('concat', "{options: { stripBanners: true, banner: bannerTemplate }, dist: {files: {'assets/js/" + this.rc.slug + ".js': 'assets/js/components/**/*.js'}}}"); 49 | 50 | this.gruntfile.registerTask('scripts', 'concat'); 51 | } 52 | 53 | if ( this.type === 'Browserify' ) { 54 | this.gruntfile.insertConfig('browserify', "{options: { stripBanners: true, banner: bannerTemplate, transform: [['babelify', { presets: ['es2015'] }], ['browserify-shim', { global: true }]] }, dist: { files: { 'assets/js/" + this.rc.slug + ".js': 'assets/js/components/main.js' } } }"); 55 | this.gruntfile.registerTask('scripts', 'browserify'); 56 | } 57 | 58 | this.gruntfile.insertConfig('uglify', "{dist: { files: { 'assets/js/" + this.rc.slug + ".min.js': 'assets/js/" + this.rc.slug + ".js' }, options: { banner: compactBannerTemplate } } }"); 59 | this.gruntfile.registerTask('scripts', 'uglify'); 60 | }, 61 | 62 | writing: function () { 63 | var mainfile = 'assets/js/'; 64 | 65 | if ( this.type !== 'Basic' ) { 66 | mainfile += 'components/main.js'; 67 | } else { 68 | mainfile += this.rc.slug + '.js'; 69 | } 70 | 71 | this.fs.copyTpl( 72 | this.templatePath('main.js'), 73 | this.destinationPath(mainfile), 74 | this 75 | ); 76 | 77 | this.fs.copy( 78 | this.templatePath('_eslintrc.json'), 79 | this.destinationPath('.eslintrc.json') 80 | ); 81 | }, 82 | 83 | install: function () { 84 | } 85 | }); 86 | -------------------------------------------------------------------------------- /js/templates/_eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "globals": { 3 | }, 4 | 5 | "env": { 6 | "browser": true, 7 | "commonjs": true, 8 | "jquery": true 9 | }, 10 | 11 | "parserOptions": { 12 | "ecmaVersion": 6, 13 | "sourceType": "module", 14 | "ecmaFeatures": { 15 | "jsx": true, 16 | "impliedStrict": true 17 | } 18 | }, 19 | 20 | "rules": { 21 | // Possible Errors 22 | "comma-dangle": 2, 23 | "no-cond-assign": 2, 24 | "no-console": 1, 25 | "no-constant-condition": 2, 26 | "no-control-regex": 2, 27 | "no-debugger": 1, 28 | "no-dupe-args": 2, 29 | "no-dupe-keys": 2, 30 | "no-duplicate-case": 2, 31 | "no-empty-character-class": 2, 32 | "no-empty": 2, 33 | "no-ex-assign": 2, 34 | "no-extra-boolean-cast": 2, 35 | "no-extra-parens": 2, 36 | "no-extra-semi": 2, 37 | "no-func-assign": 2, 38 | "no-inner-declarations": 2, 39 | "no-invalid-regexp": 2, 40 | "no-irregular-whitespace": 2, 41 | "no-negated-in-lhs": 2, 42 | "no-obj-calls": 2, 43 | "no-regex-spaces": 2, 44 | "no-sparse-arrays": 2, 45 | "no-unreachable": 2, 46 | "use-isnan": 2, 47 | "valid-jsdoc": 2, 48 | "valid-typeof": 2, 49 | "no-unexpected-multiline": 2, 50 | // Best Practices 51 | "accessor-pairs": 2, 52 | "block-scoped-var": 2, 53 | "complexity": 2, 54 | "consistent-return": 2, 55 | "curly": 2, 56 | "default-case": 2, 57 | "dot-notation": 2, 58 | "dot-location": [2, "property"], 59 | "eqeqeq": 2, 60 | "guard-for-in": 2, 61 | "no-alert": 2, 62 | "no-caller": 2, 63 | "no-div-regex": 2, 64 | "no-else-return": 2, 65 | "no-eq-null": 2, 66 | "no-eval": 2, 67 | "no-extend-native": 2, 68 | "no-extra-bind": 2, 69 | "no-fallthrough": 2, 70 | "no-floating-decimal": 2, 71 | "no-implied-eval": 2, 72 | "no-iterator": 2, 73 | "no-labels": 2, 74 | "no-lone-blocks": 2, 75 | "no-loop-func": 2, 76 | "no-multi-spaces": [2, { "exceptions": { "VariableDeclarator": true } }], 77 | "no-multi-str": 2, 78 | "no-native-reassign": 2, 79 | "no-new-func": 2, 80 | "no-new-wrappers": 2, 81 | "no-new": 2, 82 | "no-octal-escape": 2, 83 | "no-octal": 2, 84 | "no-process-env": 2, 85 | "no-proto": 2, 86 | "no-redeclare": 2, 87 | "no-return-assign": 2, 88 | "no-script-url": 2, 89 | "no-self-compare": 2, 90 | "no-sequences": 2, 91 | "no-throw-literal": 2, 92 | "no-unused-expressions": 2, 93 | "no-useless-call": 2, 94 | "no-useless-concat": 2, 95 | "no-void": 2, 96 | "no-warning-comments": 2, 97 | "no-with": 2, 98 | "radix": 2, 99 | "vars-on-top": 2, 100 | "wrap-iife": 2, 101 | "yoda": [1, "always"], 102 | // Strict Mode 103 | "strict": 2, 104 | // Variables 105 | "no-catch-shadow": 2, 106 | "no-delete-var": 2, 107 | "no-label-var": 2, 108 | "no-shadow-restricted-names": 2, 109 | "no-shadow": 2, 110 | "no-undef-init": 2, 111 | "no-undef": 2, 112 | "no-undefined": 2, 113 | "no-unused-vars": 2, 114 | "no-use-before-define": 2, 115 | // Stylistic Issues 116 | "array-bracket-spacing": [2, "always"], 117 | "block-spacing": 2, 118 | "brace-style": 2, 119 | "camelcase": 2, 120 | "comma-spacing": [2, {"before": false, "after": true}], 121 | "comma-style": [2, "last"], 122 | "consistent-this": 2, 123 | "eol-last": 2, 124 | "func-style": 2, 125 | "id-match": 2, 126 | "indent": [2, "tab", {"SwitchCase": 1} ], 127 | "key-spacing": [1, { "align": "value" }], 128 | "lines-around-comment": [2, { "beforeBlockComment": true, "allowBlockStart": true , "allowObjectStart": true }], 129 | "linebreak-style": 2, 130 | "max-nested-callbacks": 2, 131 | "new-cap": 2, 132 | "new-parens": 2, 133 | "newline-after-var": 2, 134 | "no-array-constructor": 2, 135 | "no-continue": 2, 136 | "no-inline-comments": 2, 137 | "no-lonely-if": 2, 138 | "no-mixed-spaces-and-tabs": 2, 139 | "no-multiple-empty-lines": 2, 140 | "no-nested-ternary": 2, 141 | "no-new-object": 2, 142 | "no-spaced-func": 2, 143 | "no-trailing-spaces": 2, 144 | "no-underscore-dangle": 2, 145 | "no-unneeded-ternary": 2, 146 | "object-curly-spacing": [2, "always"], 147 | "one-var": 2, 148 | "operator-assignment": 2, 149 | "operator-linebreak": 2, 150 | "padded-blocks": [2, "never"], 151 | "quote-props": [2, "as-needed"], 152 | "quotes": [2, "single"], 153 | "semi-spacing": 2, 154 | "semi": [2, "always"], 155 | "keyword-spacing": 1, 156 | "space-before-blocks": 2, 157 | "space-before-function-paren": [2, "never"], 158 | "space-in-parens": [2, "always"], 159 | "space-infix-ops": 2, 160 | "space-unary-ops": [1, { "words": true, "nonwords": true }], 161 | "spaced-comment": 2, 162 | "wrap-regex": 2, 163 | // Legacy 164 | "max-depth": 2, 165 | "max-len": [1, 100, 4], 166 | "max-params": [2, 4], 167 | "max-statements": 1, 168 | "no-bitwise": 2, 169 | "no-plusplus": 2 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /js/templates/main.js: -------------------------------------------------------------------------------- 1 | /** 2 | * <%= rc.name %> 3 | * <%= rc.homepage %> 4 | * 5 | * Licensed under the GPLv2+ license. 6 | */ 7 | 8 | window.<%= jsclassname %> = window.<%= jsclassname %> || {}; 9 | 10 | ( function( window, document, $, plugin ) { 11 | <% if ( type === 'Browserify' ) { 12 | %>let $c = {};<% 13 | } else { 14 | %>var $c = {};<% 15 | }%> 16 | 17 | plugin.init = function() { 18 | plugin.cache(); 19 | plugin.bindEvents(); 20 | }; 21 | 22 | plugin.cache = function() { 23 | $c.window = $( window ); 24 | $c.body = $( document.body ); 25 | }; 26 | 27 | plugin.bindEvents = function() { 28 | }; 29 | 30 | $( plugin.init ); 31 | }( window, document, <% if ( type === 'Browserify' ) {%>require( 'jquery' )<%} else {%>jQuery<%}%>, window.<%= jsclassname %> ) ); 32 | -------------------------------------------------------------------------------- /npm-shrinkwrap.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "graceful-fs": { 4 | "version": "4.2.2" 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /options/README.md: -------------------------------------------------------------------------------- 1 | # generator-plugin-wp Options Page Sub-generator 2 | 3 | ```bash 4 | yo plugin-wp:options 5 | ``` 6 | 7 | Creates a skeleton options page using [CMB2](https://github.com/CMB2/CMB2) for custom fields. 8 | 9 | You can optionally not include CMB2 by using the `--nocmb2` option when running the subgenerator, which gives you a basic empty options page for you to fill out however you'd like. 10 | 11 | Refer to [CMB2](https://github.com/CMB2/CMB2) and the [CMB2 options page example](https://github.com/CMB2/CMB2-Snippet-Library/tree/master/options-and-settings-pages) for more details on creating your options page. 12 | -------------------------------------------------------------------------------- /options/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var base = require('../plugin-wp-base'); 3 | var ghdownload = require('github-download'); 4 | 5 | module.exports = base.extend({ 6 | constructor: function () { 7 | base.apply(this, arguments); 8 | 9 | this.option('nocmb2'); 10 | 11 | this.argument('name', { 12 | required: false, 13 | type : String, 14 | desc : 'The options page name' 15 | }); 16 | }, 17 | 18 | initializing: { 19 | intro: function () { 20 | // Have Yeoman greet the user. 21 | this.log('Welcome to the neat Plugin WP Options Page subgenerator!'); 22 | }, 23 | 24 | readingYORC: function() { 25 | this.rc = this.config.getAll() || {}; 26 | }, 27 | 28 | readingPackage: function() { 29 | this.pkg = this.fs.readJSON( this.destinationPath('package.json')) || {}; 30 | }, 31 | 32 | settingValues: function() { 33 | this.version = this.pkg.version; 34 | if ( this.name ) { 35 | this.name = this._.titleize( this.name.split('-').join(' ') ); 36 | this.nameslug = this._.slugify( this.name ); 37 | } 38 | this.pluginname = this.rc.name; 39 | this.optionsname = this.pluginname + ' ' + this._.capitalize( this.name ); 40 | this.classname = this.rc.classprefix + this._wpClassify( this.name ); 41 | this.slug = this.rc.slug; 42 | this.optionsslug = this.slug + '-' + this._.slugify( this.name ); 43 | this.classslug = this._.underscored( this._wpClassify( this.name ) ); 44 | this.optionsprefix = this._.underscored( this.slug + ' ' + this.name ); 45 | 46 | // get the main classname 47 | this.mainclassname = this._wpClassify( this.pluginname ); 48 | 49 | this.composer = this.fs.exists('composer.json'); 50 | } 51 | }, 52 | 53 | prompting: function () { 54 | var done = this.async(); 55 | 56 | var prompts = []; 57 | 58 | if ( !this.version ) { 59 | prompts.push({ 60 | type : 'input', 61 | name : 'version', 62 | message: 'Version', 63 | default: '0.1.0' 64 | }); 65 | } 66 | 67 | if ( !this.name ) { 68 | prompts.push({ 69 | type : 'input', 70 | name : 'name', 71 | message: 'Options Page Name', 72 | default: 'basic-options' 73 | }); 74 | } 75 | 76 | if ( !this.pluginname ) { 77 | prompts.push({ 78 | type : 'input', 79 | name : 'pluginname', 80 | message: 'Plugin Name', 81 | default: 'WDS Client Plugin' 82 | }); 83 | } 84 | 85 | if ( prompts.length > 0 ) { 86 | this.log( 'Missing some info about the original plugin, help me out?' ); 87 | this.prompt(prompts, function (props) { 88 | if ( props.version ) { 89 | this.version = props.version; 90 | } 91 | 92 | if ( props.name ) { 93 | this.name = this._.titleize( props.name.split('-').join(' ') ); 94 | this.nameslug = this._.slugify( this.name ); 95 | } 96 | 97 | if ( props.pluginname ) { 98 | this.pluginname = props.pluginname; 99 | this.slug = this._.slugify( props.pluginname ); 100 | } 101 | 102 | if ( props.name || props.pluginname ) { 103 | this.optionsname = this.pluginname + ' ' + this._.capitalize( this.name ); 104 | this.classname = this._wpClassPrefix( this.pluginname ) + this._wpClassify( this.name ); 105 | this.optionsslug = this.slug + '-' + this._.slugify( this.name ); 106 | this.optionsprefix = this._.underscored( this.slug + ' ' + this.name ); 107 | } 108 | 109 | done(); 110 | }.bind(this)); 111 | } else { 112 | done(); 113 | } 114 | }, 115 | 116 | writing: function () { 117 | this.fs.copyTpl( 118 | this.templatePath('options.php'), 119 | this.destinationPath('includes/class-' + this._.slugify( this.name ) + '.php'), 120 | this 121 | ); 122 | 123 | if ( !this.rc.notests ) { 124 | this.fs.copyTpl( 125 | this.templatePath('tests.php'), 126 | this.destinationPath('tests/test-' + this._.slugify( this.name ) + '.php'), 127 | this 128 | ); 129 | } 130 | 131 | this._addIncludeClass( this._.slugify( this.name ), this.classname, this.version ); 132 | }, 133 | 134 | install: function () { 135 | if ( this.options['skip-install'] ) { 136 | return; 137 | } 138 | 139 | if ( this.composer ) { 140 | if ( !this.options.nocmb2 ) { 141 | this.spawnCommand('composer', ['require', 'cmb2/cmb2']); 142 | } 143 | } else { 144 | this.mkdir('vendor'); 145 | if ( !this.fs.exists('vendor/cmb2/init.php') && !this.options.nocmb2 ) { 146 | ghdownload({ 147 | user: 'CMB2', 148 | repo: 'CMB2', 149 | ref : 'master' 150 | }, this.destinationPath('vendor/cmb2') ); 151 | } 152 | } 153 | } 154 | }); 155 | -------------------------------------------------------------------------------- /options/templates/options.php: -------------------------------------------------------------------------------- 1 | . 4 | * 5 | * @since <%= version %> 6 | * @package <%= mainclassname %> 7 | */ // @codingStandardsIgnoreLine 8 | <% if ( ! composer && ! options.nocmb2 ) { %> // @codingStandardsIgnoreLine 9 | /** 10 | * Include CMB2 11 | * 12 | * @since <%= version %> 13 | */ 14 | require_once dirname( __FILE__ ) . '/../vendor/cmb2/init.php'; 15 | <% } %> // @codingStandardsIgnoreLine 16 | /** 17 | * <%= optionsname %> class. 18 | * 19 | * @since <%= version %> 20 | */ 21 | class <%= classname %> { // @codingStandardsIgnoreLine 22 | /** 23 | * Parent plugin class. 24 | * 25 | * @var <%= mainclassname %> 26 | * @since <%= version %> 27 | */ 28 | protected $plugin = null; 29 | 30 | /** 31 | * Option key, and option page slug. 32 | * 33 | * @var string 34 | * @since <%= version %> 35 | */ 36 | protected static $key = '<%= optionsprefix %>'; 37 | 38 | /** 39 | * Options page metabox ID. 40 | * 41 | * @var string 42 | * @since <%= version %> 43 | */ 44 | protected static $metabox_id = '<%= optionsprefix %>_metabox'; 45 | 46 | /** 47 | * Options Page title. 48 | * 49 | * @var string 50 | * @since <%= version %> 51 | */ 52 | protected $title = ''; 53 | 54 | /** 55 | * Options Page hook. 56 | * 57 | * @var string 58 | */ 59 | protected $options_page = ''; 60 | 61 | /** 62 | * Constructor. 63 | * 64 | * @since <%= version %> 65 | * 66 | * @param <%= mainclassname %> $plugin Main plugin object. 67 | */ 68 | public function __construct( $plugin ) { 69 | $this->plugin = $plugin; 70 | $this->hooks(); 71 | 72 | // Set our title. 73 | $this->title = esc_attr__( '<%= optionsname %>', '<%= slug %>' ); 74 | } 75 | 76 | /** 77 | * Initiate our hooks. 78 | * 79 | * @since <%= version %> 80 | */ 81 | public function hooks() { 82 | // Hook in our actions to the admin. 83 | <% if ( options.nocmb2 ) { // @codingStandardsIgnoreLine 84 | %> add_action( 'admin_init', array( $this, 'admin_init' ) ); // @codingStandardsIgnoreLine 85 | add_action( 'admin_menu', array( $this, 'add_options_page' ) );<% } else { // @codingStandardsIgnoreLine 86 | %> add_action( 'cmb2_admin_init', array( $this, 'add_options_page_metabox' ) );<% } %> // @codingStandardsIgnoreLine 87 | }<% if ( options.nocmb2 ) { %> // @codingStandardsIgnoreLine 88 | 89 | /** 90 | * Register our setting to WP. 91 | * 92 | * @since <%= version %> 93 | */ 94 | public function admin_init() { 95 | register_setting( self::$key, self::$key ); 96 | } 97 | 98 | /** 99 | * Add menu options page. 100 | * 101 | * @since <%= version %> 102 | */ 103 | public function add_options_page() { 104 | $this->options_page = add_menu_page( 105 | $this->title, 106 | $this->title, 107 | 'manage_options', 108 | self::$key, 109 | array( $this, 'admin_page_display' ) 110 | ); 111 | } 112 | 113 | /** 114 | * Admin page markup. Mostly handled by CMB2. 115 | * 116 | * @since <%= version %> 117 | */ 118 | public function admin_page_display() { 119 | ?> 120 |
121 |

122 | 123 |
124 | // @codingStandardsIgnoreLine 126 | 127 | /** 128 | * Add custom fields to the options page. 129 | * 130 | * @since <%= version %> 131 | */ 132 | public function add_options_page_metabox() { 133 | 134 | // Add our CMB2 metabox. 135 | $cmb = new_cmb2_box( 136 | array( 137 | 'id' => self::$metabox_id, 138 | 'title' => $this->title, 139 | 'object_types' => array( 'options-page' ), 140 | 141 | /* 142 | * The following parameters are specific to the options-page box 143 | * Several of these parameters are passed along to add_menu_page()/add_submenu_page(). 144 | */ 145 | 146 | 'option_key' => self::$key, // The option key and admin menu page slug. 147 | // 'icon_url' => 'dashicons-palmtree', // Menu icon. Only applicable if 'parent_slug' is left empty. 148 | // 'menu_title' => esc_html__( 'Options', 'cmb2' ), // Falls back to 'title' (above). 149 | // 'parent_slug' => 'themes.php', // Make options page a submenu item of the themes menu. 150 | // 'capability' => 'manage_options', // Cap required to view options-page. 151 | // 'position' => 1, // Menu position. Only applicable if 'parent_slug' is left empty. 152 | // 'admin_menu_hook' => 'network_admin_menu', // 'network_admin_menu' to add network-level options page. 153 | // 'display_cb' => false, // Override the options-page form output (CMB2_Hookup::options_page_output()). 154 | // 'save_button' => esc_html__( 'Save Theme Options', 'cmb2' ), // The text for the options-page save button. Defaults to 'Save'. 155 | ) 156 | ); 157 | 158 | // Add your fields here. 159 | $cmb->add_field( 160 | array( 161 | 'name' => __( 'Test Text', '<%= slug %>' ), 162 | 'desc' => __( 'field description (optional)', '<%= slug %>' ), 163 | 'id' => 'test_text', // No prefix needed. 164 | 'type' => 'text', 165 | 'default' => __( 'Default Text', '<%= slug %>' ), 166 | ) 167 | ); 168 | } 169 | 170 | /** 171 | * Wrapper function around cmb2_get_option. 172 | * 173 | * @since <%= version %> 174 | * 175 | * @param string $key Options array key. 176 | * @param mixed $default Optional default value. 177 | * @return mixed Option value. 178 | */ 179 | public static function get_value( $key = '', $default = false ) { 180 | if ( function_exists( 'cmb2_get_option' ) ) { 181 | 182 | // Use cmb2_get_option as it passes through some key filters. 183 | return cmb2_get_option( self::$key, $key, $default ); 184 | } 185 | 186 | // Fallback to get_option if CMB2 is not loaded yet. 187 | $opts = get_option( self::$key, $default ); 188 | 189 | $val = $default; 190 | 191 | if ( 'all' === $key ) { 192 | $val = $opts; 193 | } elseif ( is_array( $opts ) && array_key_exists( $key, $opts ) && false !== $opts[ $key ] ) { 194 | $val = $opts[ $key ]; 195 | } 196 | 197 | return $val; 198 | }<% } %> // @codingStandardsIgnoreLine 199 | } 200 | -------------------------------------------------------------------------------- /options/templates/tests.php: -------------------------------------------------------------------------------- 1 | Tests. 4 | * 5 | * @since <%= version %> 6 | * @package <%= mainclassname %> 7 | */ 8 | 9 | /** 10 | * <%= optionsname %> Tests. 11 | * 12 | * @since <%= version %> 13 | */ 14 | class <%= classname %>_Test extends WP_UnitTestCase { // @codingStandardsIgnoreLine 15 | 16 | /** 17 | * Test if our class exists. 18 | * 19 | * @since <%= version %> 20 | */ 21 | public function test_class_exists() { 22 | $this->assertTrue( class_exists( '<%= classname %>' ) ); 23 | } 24 | 25 | /** 26 | * Test that we can access our class through our helper function. 27 | * 28 | * @since <%= version %> 29 | */ 30 | public function test_class_access() { 31 | $this->assertInstanceOf( '<%= classname %>', <%= rc.prefix %>()-><%= classslug %> ); // @codingStandardsIgnoreLine 32 | } 33 | 34 | /** 35 | * Replace this with some actual testing code. 36 | * 37 | * @since <%= version %> 38 | */ 39 | public function test_sample() { 40 | $this->assertTrue( true ); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "generator-plugin-wp", 3 | "version": "0.20.2", 4 | "description": "Yeoman generator for WordPress plugins.", 5 | "license": "MIT", 6 | "main": "app/index.js", 7 | "repository": { 8 | "type": "git", 9 | "url": "git+https://github.com/WebDevStudios/generator-plugin-wp" 10 | }, 11 | "author": { 12 | "name": "WebDevStudios", 13 | "email": "contact@WebDevStudios.com", 14 | "url": "https://webdevstudios.com" 15 | }, 16 | "engines": { 17 | "node": ">=0.10.0" 18 | }, 19 | "scripts": { 20 | "test": "mocha" 21 | }, 22 | "files": [ 23 | "app", 24 | "include", 25 | "js", 26 | "css", 27 | "widget", 28 | "cpt", 29 | "options", 30 | "taxonomy", 31 | "pagebuilder", 32 | "endpoint", 33 | "cli", 34 | "plugin-wp-base.js" 35 | ], 36 | "keywords": [ 37 | "yeoman-generator" 38 | ], 39 | "dependencies": { 40 | "chalk": "^0.5.0", 41 | "github-download": "^0.3.0", 42 | "request": "^2.79.0", 43 | "update-notifier": "^0.4.0", 44 | "yeoman-generator": "^0.18.0", 45 | "yosay": "^0.3.0" 46 | }, 47 | "devDependencies": { 48 | "fs-extra": "^0.16.5", 49 | "mocha": "*" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /pagebuilder/README.md: -------------------------------------------------------------------------------- 1 | # generator-plugin-wp WDS Simple Page Builder Sub-generator 2 | 3 | ```bash 4 | yo plugin-wp:pagebuilder --partsdir 'part/directory' 5 | ``` 6 | 7 | Adds [WDS Simple Page Builder](https://github.com/WebDevStudios/WDS-Simple-Page-Builder) support to your plugin. 8 | 9 | Use the --partsdir argument to specify a custom part directory name, by default this directory is 'includes/parts'. 10 | 11 | Refer to the [WDS Simple Page Builder](https://github.com/WebDevStudios/WDS-Simple-Page-Builder/wiki) wiki for more information about Page Builder. 12 | -------------------------------------------------------------------------------- /pagebuilder/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var base = require('../plugin-wp-base'); 3 | 4 | module.exports = base.extend({ 5 | constructor: function () { 6 | base.apply(this, arguments); 7 | 8 | this.argument('name', { 9 | required: false, 10 | type : String, 11 | desc : 'The page builder include class name' 12 | }); 13 | 14 | this.option('partsdir', { 15 | desc : 'Directory to place parts in', 16 | type : String, 17 | defaults: 'includes/parts' 18 | }); 19 | }, 20 | 21 | initializing: { 22 | intro: function () { 23 | // Have Yeoman greet the user. 24 | this.log('Welcome to the neat Plugin WP WDS Simple Page Builder subgenerator!'); 25 | }, 26 | 27 | readingYORC: function() { 28 | this.rc = this.config.getAll() || {}; 29 | }, 30 | 31 | readingPackage: function() { 32 | this.pkg = this.fs.readJSON( this.destinationPath('package.json')) || {}; 33 | }, 34 | 35 | settingValues: function() { 36 | this.composer = this.fs.exists('composer.json'); 37 | this.version = this.pkg.version; 38 | 39 | if ( this.name ) { 40 | this.name = this._.titleize( this.name.split('-').join(' ') ); 41 | this.nameslug = this._.slugify( this.name ); 42 | } 43 | this.slug = this.rc.slug; 44 | 45 | this.pluginname = this.rc.name; 46 | this.classname = this.rc.classprefix + this._wpClassify( this.name ); 47 | this.prefix = this.rc.prefix; 48 | 49 | // get the main classname 50 | this.mainclassname = this._wpClassify( this.pluginname ); 51 | 52 | this.composer = this.fs.exists('composer.json'); 53 | 54 | this.partsdir = this.options.partsdir; 55 | } 56 | }, 57 | 58 | prompting: function () { 59 | var done = this.async(); 60 | 61 | var prompts = []; 62 | 63 | if ( !this.version ) { 64 | prompts.push({ 65 | type : 'input', 66 | name : 'version', 67 | message: 'Version', 68 | default: '0.1.0' 69 | }); 70 | } 71 | 72 | if ( !this.name ) { 73 | prompts.push({ 74 | type : 'input', 75 | name : 'name', 76 | message: 'Include Name', 77 | default: 'pagebuilder' 78 | }); 79 | } 80 | 81 | if ( !this.pluginname ) { 82 | prompts.push({ 83 | type : 'input', 84 | name : 'pluginname', 85 | message: 'Plugin Name', 86 | default: 'WDS Client Plugin' 87 | }); 88 | } 89 | 90 | if ( prompts.length > 0 ) { 91 | this.log( 'Missing some info about the original plugin, help me out?' ); 92 | this.prompt(prompts, function (props) { 93 | if ( props.version ) { 94 | this.version = props.version; 95 | } 96 | 97 | if ( props.name ) { 98 | this.name = this._.titleize( props.name ); 99 | this.nameslug = this._.slugify( this.name ); 100 | } 101 | 102 | if ( props.pluginname ) { 103 | this.pluginname = props.pluginname; 104 | this.slug = this._.slugify( props.pluginname ); 105 | } 106 | 107 | done(); 108 | }.bind(this)); 109 | } else { 110 | done(); 111 | } 112 | }, 113 | 114 | writing: function () { 115 | this.fs.copyTpl( 116 | this.templatePath('class-pagebuilder.php'), 117 | this.destinationPath('includes/class-' + this._.slugify( this.name ) + '.php'), 118 | this 119 | ); 120 | 121 | if ( !this.rc.notests ) { 122 | this.fs.copyTpl( 123 | this.templatePath('tests.php'), 124 | this.destinationPath('tests/test-' + this._.slugify( this.name ) + '.php'), 125 | this 126 | ); 127 | } 128 | 129 | this._addIncludeClass( this._.slugify( this.name ), this.classname ); 130 | }, 131 | 132 | install: function () { 133 | if ( this.options['skip-install'] ) { 134 | return; 135 | } 136 | } 137 | }); 138 | -------------------------------------------------------------------------------- /pagebuilder/templates/class-pagebuilder.php: -------------------------------------------------------------------------------- 1 | Page Builder. 4 | * 5 | * @since <%= version %> 6 | * @package <%= mainclassname %> 7 | */ 8 | 9 | /** 10 | * <%= pluginname %> Page Builder. 11 | */ 12 | class <%= classname %> { // @codingStandardsIgnoreLine 13 | /** 14 | * Parent plugin class. 15 | * 16 | * @var <%= mainclassname %> 17 | * @since <%= version %> 18 | */ 19 | protected $plugin = null; 20 | 21 | /** 22 | * Constructor. 23 | * 24 | * @since <%= version %> 25 | * 26 | * @param <%= mainclassname %> $plugin Main plugin object. 27 | */ 28 | public function __construct( $plugin ) { 29 | $this->plugin = $plugin; 30 | $this->hooks(); 31 | } 32 | 33 | /** 34 | * Initiate our hooks. 35 | * 36 | * @since <%= version %> 37 | */ 38 | public function hooks() { 39 | add_action( 'spb_init', array( $this, 'load_pagebuilder_parts' ) ); 40 | } 41 | 42 | /** 43 | * Registers our parts directory in the Page Builder template stack. 44 | * 45 | * @since <%= version %> 46 | */ 47 | public function load_pagebuilder_parts() { 48 | spb_register_template_stack( array( $this, 'get_template_part_dir' ), 10 ); 49 | } 50 | 51 | /** 52 | * Register our plugin's template parts directory. 53 | * This function needs to be in the global scope to work properly. 54 | * 55 | * @since <%= version %> 56 | * 57 | * @return string Absolute path to template parts directory. 58 | */ 59 | public function get_template_part_dir() { 60 | 61 | /** 62 | * Filters the absolute path of the template location. 63 | * 64 | * @param string The absolute path of the template package in use. 65 | */ 66 | return apply_filters( '<%= prefix %>_get_template_part_dir', $this->plugin->path . '<%= partsdir %>/' ); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /pagebuilder/templates/tests.php: -------------------------------------------------------------------------------- 1 | Page Builder Tests. 4 | * 5 | * @since <%= version %> 6 | * @package <%= mainclassname %> 7 | */ 8 | 9 | /** 10 | * <%= pluginname %> Page Builder Tests. 11 | * 12 | * @since <%= version %> 13 | * @package <%= mainclassname %> 14 | */ 15 | class <%= classname %>_Test extends WP_UnitTestCase { // @codingStandardsIgnoreLine 16 | 17 | /** 18 | * Test if our class exists. 19 | * 20 | * @since <%= version %> 21 | */ 22 | public function test_class_exists() { 23 | $this->assertTrue( class_exists( '<%= classname %>' ) ); 24 | } 25 | 26 | /** 27 | * Test that we can access our class through our helper function. 28 | * 29 | * @since <%= version %> 30 | */ 31 | public function test_class_access() { 32 | $this->assertInstanceOf( '<%= classname %>', <%= rc.prefix %>()-><%= nameslug %> ); // @codingStandardsIgnoreLine 33 | } 34 | 35 | /** 36 | * Replace this with some actual testing code. 37 | * 38 | * @since <%= version %> 39 | */ 40 | public function test_sample() { 41 | $this->assertTrue( true ); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /phpcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | A modified set of rules, based on the WordPress Coding Standards. 8 | 9 | 10 | /test/* 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /plugin-wp-base.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var yeoman = require('yeoman-generator'); 3 | var updateNotifier = require('update-notifier'); 4 | 5 | module.exports = yeoman.generators.Base.extend({ 6 | constructor: function () { 7 | // Calling the super constructor is important so our generator is correctly set up 8 | yeoman.generators.Base.apply(this, arguments); 9 | 10 | updateNotifier({ 11 | pkg: require('./package.json') 12 | }).notify({defer: false}); 13 | }, 14 | 15 | _wpClassify: function( s ) { 16 | var words = this._.words( s ); 17 | var result = ''; 18 | 19 | for ( var i = 0; i < words.length; i += 1 ) { 20 | if ( this._.classify( words[i] ) ) { 21 | result += this._.capitalize( words[i] ); 22 | if ( (i + 1) < words.length ) { 23 | result += '_'; 24 | } 25 | } 26 | } 27 | 28 | result = result.replace('-', '_'); 29 | return result; 30 | 31 | }, 32 | 33 | _wpClassPrefix: function( s ) { 34 | var words = s.replace( /_/g, ' ' ); 35 | var letters = words.replace(/[a-z]/g, ''); 36 | var hyphens = letters.replace(/\s/g, ''); 37 | var prefix = hyphens.replace(/-/g,''); 38 | return prefix + '_'; 39 | }, 40 | 41 | _escapeDoubleQuotes: function( s ) { 42 | return s.replace( /"/g, '\\"'); 43 | }, 44 | 45 | __addStringToPluginClasses: function( mainPluginFile, toAdd ) { 46 | var endComment = '\t} // END OF PLUGIN CLASSES FUNCTION'; 47 | var newInclude = '\t\t' + toAdd + '\n' + endComment; 48 | 49 | return mainPluginFile.replace( endComment, newInclude ); 50 | }, 51 | 52 | _addStringToPluginClasses: function( toAdd ) { 53 | if ( ! this.rc.slug ) { 54 | return; 55 | } 56 | 57 | var mainPluginFile = this.fs.read( this.destinationPath( this.rc.slug + '.php' ) ); 58 | mainPluginFile = this.__addStringToPluginClasses( mainPluginFile, toAdd ); 59 | 60 | this.fs.write( this.destinationPath( this.rc.slug + '.php' ), mainPluginFile ); 61 | }, 62 | 63 | _addPluginProperty: function( file, slug, className, version ) { 64 | 65 | var toAdd = '\t/**'; 66 | toAdd += '\n\t * Instance of ' + className; 67 | toAdd += '\n\t *'; 68 | toAdd += '\n\t * @since' + version; 69 | toAdd += '\n\t * @var ' + className; 70 | toAdd += '\n\t */'; 71 | toAdd += '\n\tprotected $' + slug + ';'; 72 | 73 | var endComment = '\t/**\n\t * Creates or returns an instance of this class.'; 74 | 75 | return file.replace( endComment, toAdd + '\n\n' + endComment ); 76 | }, 77 | 78 | _addPluginClass: function( file, slug, className ) { 79 | var toAdd = '$this->' + slug + ' = new ' + className + '( $this );'; 80 | var toRemove = '\n\t\t// $this->plugin_class = new ' + this.rc.classprefix + 'Plugin_Class( $this );'; 81 | return this.__addStringToPluginClasses( file.replace( toRemove, '' ), toAdd ); 82 | }, 83 | 84 | _addPropertyMagicGetter: function( file, slug ) { 85 | 86 | var toAdd = '\t\t\tcase \'' + slug + '\':'; 87 | var endComment = '\t\t\t\treturn $this->$field;'; 88 | var newInclude = toAdd + '\n' + endComment; 89 | 90 | return file.replace( endComment, newInclude ); 91 | }, 92 | 93 | _addIncludeClass: function( slug, className, version ) { 94 | 95 | if ( ! this.rc.slug ) { 96 | return; 97 | } 98 | 99 | slug = this._.underscored( slug ); 100 | var mainPluginFile = this.fs.read( this.destinationPath( this.rc.slug + '.php' ) ); 101 | 102 | mainPluginFile = this._addPluginProperty( mainPluginFile, slug, className, version ); 103 | mainPluginFile = this._addPluginClass( mainPluginFile, slug, className ); 104 | mainPluginFile = this._addPropertyMagicGetter( mainPluginFile, slug ); 105 | 106 | this.fs.write( this.destinationPath( this.rc.slug + '.php' ), mainPluginFile ); 107 | } 108 | 109 | }); 110 | -------------------------------------------------------------------------------- /taxonomy/README.md: -------------------------------------------------------------------------------- 1 | # generator-plugin-wp Taxonomy Sub-generator 2 | 3 | ```bash 4 | yo plugin-wp:taxonomy 5 | ``` 6 | 7 | Creates a skeleton taxonomy using [Taxonomy_Core](https://github.com/WebDevStudios/Taxonomy_Core). 8 | 9 | Refer to [Taxonomy_Core](https://github.com/WebDevStudios/Taxonomy_Core) for more details on extending the Taxonomy_Core class. 10 | -------------------------------------------------------------------------------- /taxonomy/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var base = require('../plugin-wp-base'); 3 | var ghdownload = require('github-download'); 4 | 5 | module.exports = base.extend({ 6 | constructor: function () { 7 | base.apply(this, arguments); 8 | 9 | this.option('cmb2'); 10 | 11 | this.argument('name', { 12 | required: false, 13 | type : String, 14 | desc : 'The Taxonomy name' 15 | }); 16 | }, 17 | 18 | initializing: { 19 | intro: function () { 20 | // Have Yeoman greet the user. 21 | this.log('Welcome to the neat Plugin WP Taxonomy subgenerator!'); 22 | }, 23 | 24 | readingYORC: function() { 25 | this.rc = this.config.getAll() || {}; 26 | }, 27 | 28 | readingPackage: function() { 29 | this.pkg = this.fs.readJSON( this.destinationPath('package.json')) || {}; 30 | }, 31 | 32 | settingValues: function() { 33 | this.version = this.pkg.version; 34 | if ( this.name ) { 35 | this.name = this._.titleize( this.name.split('-').join(' ') ); 36 | this.nameslug = this._.slugify( this.name ); 37 | this.functionname = this.nameslug.replace( /-/g, '_' ); 38 | } 39 | this.pluginname = this.rc.name; 40 | this.taxonomyname = this.pluginname + ' ' + this._.capitalize( this.name ); 41 | this.classname = this.rc.classprefix + this._wpClassify( this.name ); 42 | this.slug = this.rc.slug; 43 | this.classslug = this._.underscored( this._wpClassify( this.name ) ); 44 | this.taxonomyslug = this._.slugify( this.classname ).substr( 0, 20 ); 45 | this.taxonomyprefix = this._.underscored( this.taxonomyslug ); 46 | 47 | // get the main classname 48 | this.mainclassname = this._wpClassify( this.pluginname ); 49 | 50 | this.composer = this.fs.exists('composer.json'); 51 | } 52 | }, 53 | 54 | prompting: function () { 55 | var done = this.async(); 56 | 57 | var prompts = []; 58 | 59 | if ( !this.version ) { 60 | prompts.push({ 61 | type : 'input', 62 | name : 'version', 63 | message: 'Version', 64 | default: '0.1.0' 65 | }); 66 | } 67 | 68 | if ( !this.name ) { 69 | prompts.push({ 70 | type : 'input', 71 | name : 'name', 72 | message: 'Taxonomy Name', 73 | default: 'taxonomy' 74 | }); 75 | } 76 | 77 | if ( !this.pluginname ) { 78 | prompts.push({ 79 | type : 'input', 80 | name : 'pluginname', 81 | message: 'Plugin Name', 82 | default: 'WDS Client Plugin' 83 | }); 84 | } 85 | 86 | if ( prompts.length > 0 ) { 87 | this.log( 'Missing some info about the original plugin, help me out?' ); 88 | this.prompt(prompts, function (props) { 89 | if ( props.version ) { 90 | this.version = props.version; 91 | } 92 | 93 | if ( props.name ) { 94 | this.name = this._.titleize( props.name.split('-').join(' ') ); 95 | this.nameslug = this._.slugify( this.name ); 96 | } 97 | 98 | if ( props.pluginname ) { 99 | this.pluginname = props.pluginname; 100 | this.slug = this._.slugify( props.pluginname ); 101 | } 102 | 103 | if ( props.name || props.pluginname ) { 104 | this.taxonomyname = this.pluginname + ' ' + this._.capitalize( this.name ); 105 | this.classname = this._wpClassPrefix( this.pluginname ) + this._wpClassify( this.name ); 106 | this.taxonomyslug = this.slug + '-' + this._.slugify( this.name ); 107 | this.taxonomyprefix = this._.underscored( this.slug + ' ' + this.name ); 108 | } 109 | 110 | done(); 111 | }.bind(this)); 112 | } else { 113 | done(); 114 | } 115 | }, 116 | 117 | writing: function () { 118 | this.fs.copyTpl( 119 | this.templatePath('taxonomy.php'), 120 | this.destinationPath('includes/class-' + this._.slugify( this.name ) + '.php'), 121 | this 122 | ); 123 | 124 | if ( !this.rc.notests ) { 125 | this.fs.copyTpl( 126 | this.templatePath('tests.php'), 127 | this.destinationPath('tests/test-' + this._.slugify( this.name ) + '.php'), 128 | this 129 | ); 130 | } 131 | 132 | this._addIncludeClass( this._.slugify( this.name ), this.classname, this.version ); 133 | }, 134 | 135 | install: function () { 136 | if ( this.options['skip-install'] ) { 137 | return; 138 | } 139 | 140 | if ( this.composer ) { 141 | this.spawnCommand('composer', ['require', 'webdevstudios/taxonomy_core']); 142 | 143 | if ( this.options.cmb2 ) { 144 | this.spawnCommand('composer', ['require', 'cmb2/cmb2']); 145 | } 146 | } else { 147 | this.mkdir('vendor'); 148 | if ( !this.fs.exists('vendor/taxonomy-core/Taxonomy_Core.php') ) { 149 | ghdownload({ 150 | user: 'WebDevStudios', 151 | repo: 'Taxonomy_Core', 152 | ref : 'master' 153 | }, this.destinationPath('vendor/taxonomy-core') ); 154 | } 155 | 156 | if ( !this.fs.exists('vendor/cmb2/init.php') && this.options.cmb2 ) { 157 | ghdownload({ 158 | user: 'CMB2', 159 | repo: 'CMB2', 160 | ref : 'master' 161 | }, this.destinationPath('vendor/cmb2') ); 162 | } 163 | } 164 | } 165 | }); 166 | -------------------------------------------------------------------------------- /taxonomy/templates/taxonomy.php: -------------------------------------------------------------------------------- 1 | . 4 | * 5 | * @since <%= version %> 6 | * @package <%= mainclassname %> 7 | */ // @codingStandardsIgnoreLine 8 | <% if ( ! composer ) { %> // @codingStandardsIgnoreLine 9 | /** 10 | * Include Taxonomy Core 11 | * 12 | * @since <%= version %> 13 | */ 14 | require_once dirname( __FILE__ ) . '/../vendor/taxonomy-core/Taxonomy_Core.php'; 15 | <% if ( options.cmb2 ) { %> // @codingStandardsIgnoreLine 16 | /** 17 | * Include CMB2 18 | * 19 | * @since <%= version %> 20 | */ 21 | require_once dirname( __FILE__ ) . '/../vendor/cmb2/init.php'; 22 | <% } // @codingStandardsIgnoreLine 23 | } %> // @codingStandardsIgnoreLine 24 | /** 25 | * <%= taxonomyname %>. 26 | * 27 | * @since <%= version %> 28 | * 29 | * @see https://github.com/WebDevStudios/Taxonomy_Core 30 | */ 31 | class <%= classname %> extends Taxonomy_Core { // @codingStandardsIgnoreLine 32 | /** 33 | * Parent plugin class. 34 | * 35 | * @var <%= mainclassname %> 36 | * @since <%= version %> 37 | */ 38 | protected $plugin = null; 39 | 40 | /** 41 | * Constructor. 42 | * 43 | * Register Taxonomy. 44 | * 45 | * See documentation in Taxonomy_Core, and in wp-includes/taxonomy.php. 46 | * 47 | * @since <%= version %> 48 | * 49 | * @param <%= mainclassname %> $plugin Main plugin object. 50 | */ 51 | public function __construct( $plugin ) { 52 | $this->plugin = $plugin; 53 | $this->hooks(); 54 | 55 | parent::__construct( 56 | // Should be an array with Singular, Plural, and Registered name. 57 | array( 58 | __( '<%= taxonomyname %>', '<%= slug %>' ), 59 | __( '<%= taxonomyname %>s', '<%= slug %>' ), 60 | '<%= taxonomyslug %>', 61 | ), 62 | // Register taxonomy arguments. 63 | array( 64 | 'hierarchical' => false, 65 | ), 66 | // Post types to attach to. 67 | array( 68 | 'post', 69 | ) 70 | ); 71 | } 72 | 73 | /** 74 | * Initiate our hooks. 75 | * 76 | * @since <%= version %> 77 | */ 78 | public function hooks() { 79 | 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /taxonomy/templates/tests.php: -------------------------------------------------------------------------------- 1 | Tests. 4 | * 5 | * @since <%= version %> 6 | * @package <%= mainclassname %> 7 | */ 8 | 9 | /** 10 | * <%= taxonomyname %> Tests. 11 | * 12 | * @since <%= version %> 13 | */ 14 | class <%= classname %>_Test extends WP_UnitTestCase { // @codingStandardsIgnoreLine 15 | 16 | /** 17 | * Test if our class exists. 18 | * 19 | * @since <%= version %> 20 | */ 21 | public function test_class_exists() { 22 | $this->assertTrue( class_exists( '<%= classname %>' ) ); 23 | } 24 | 25 | /** 26 | * Test that we can access our class through our helper function. 27 | * 28 | * @since <%= version %> 29 | */ 30 | public function test_class_access() { 31 | $this->assertInstanceOf( '<%= classname %>', <%= rc.prefix %>()-><%= classslug %> ); // @codingStandardsIgnoreLine 32 | } 33 | 34 | /** 35 | * Test that our taxonomy now exists. 36 | * 37 | * @since <%= version %> 38 | */ 39 | public function test_taxonomy_exists() { 40 | $this->assertTrue( taxonomy_exists( '<%= taxonomyslug %>' ) ); 41 | } 42 | 43 | /** 44 | * Replace this with some actual testing code. 45 | * 46 | * @since <%= version %> 47 | */ 48 | public function test_sample() { 49 | $this->assertTrue( true ); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /test/test-app.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var path = require('path'); 4 | var assert = require('yeoman-generator').assert; 5 | var helpers = require('yeoman-generator').test; 6 | var os = require('os'); 7 | 8 | describe('plugin-wp:app', function () { 9 | before(function (done) { 10 | helpers.run(path.join(__dirname, '../app')) 11 | .inDir(path.join(os.tmpdir(), './temp-test')) 12 | .withOptions() 13 | .withPrompt({ 14 | name: 'Test Plugin NAME' 15 | }) 16 | .on('end', done); 17 | }); 18 | 19 | it('creates files', function () { 20 | assert.file([ 21 | 'bower.json', 22 | 'package.json', 23 | '.bowerrc', 24 | '.gitignore', 25 | 'README.md', 26 | 'test-plugin-name.php', 27 | 'assets/css/style.css', 28 | 'assets/js/index.js', 29 | 'assets/README.md', 30 | 'includes/README.md', 31 | 'config/settings.js', 32 | 'config/webpack.config.js' 33 | ]); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /test/test-assets/subgenerator-test-plugin/.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "assets/bower" 3 | } -------------------------------------------------------------------------------- /test/test-assets/subgenerator-test-plugin/.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | end_of_line = lf 9 | insert_final_newline = true 10 | 11 | # Matches multiple files with brace expansion notation 12 | # Set default charset 13 | [*.{html,js,php,css,scss}] 14 | charset = utf-8 15 | 16 | # 4 space indentation 17 | [*.{html,js,php,css,scss}] 18 | indent_style = tab 19 | indent_size = 4 20 | 21 | # Matches the exact files 22 | [{package.json,bower.json,.bowerrc,.eslintrc,.travis.yml,.sass-lint.yml,phpcs.xml}] 23 | indent_style = space 24 | indent_size = 2 25 | -------------------------------------------------------------------------------- /test/test-assets/subgenerator-test-plugin/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "env": { 3 | "browser": true, 4 | "jquery": true, 5 | "es6": true, 6 | }, 7 | "extends": "wordpress", 8 | "installedESLint": true, 9 | "plugins": [], 10 | "rules": { 11 | // Enforce spacing inside array brackets 12 | 'array-bracket-spacing': ['error', 'always'], 13 | // Enforce one true brace style 14 | 'brace-style': 'error', 15 | // Require camel case names 16 | 'camelcase': ['error', { 17 | properties: 'always' 18 | }], 19 | // Disallow or enforce trailing commas 20 | 'comma-dangle': ['error', 'never'], 21 | // Enforce spacing before and after comma 22 | 'comma-spacing': 'error', 23 | // Enforce one true comma style 24 | 'comma-style': ['error', 'last'], 25 | // Encourages use of dot notation whenever possible 26 | 'dot-notation': ['error', { 27 | allowKeywords: true, 28 | allowPattern: '^[a-z]+(_[a-z]+)+$' 29 | }], 30 | // Enforce newline at the end of file, with no multiple empty lines 31 | 'eol-last': 'error', 32 | // Require or disallow spacing between function identifiers and their invocations 33 | 'func-call-spacing': 'off', 34 | // Enforces spacing between keys and values in object literal properties 35 | 'key-spacing': ['error', { 36 | beforeColon: false, 37 | afterColon: true 38 | }], 39 | // Enforce spacing before and after keywords 40 | 'keyword-spacing': 'error', 41 | // Disallow mixed "LF" and "CRLF" as linebreaks 42 | 'linebreak-style': ['error', 'unix'], 43 | // Enforces empty lines around comments 44 | 'lines-around-comment': ['error', { 45 | beforeLineComment: true 46 | }], 47 | // Disallow mixed spaces and tabs for indentation 48 | 'no-mixed-spaces-and-tabs': 'error', 49 | // Disallow use of multiline strings 50 | 'no-multi-str': 'error', 51 | // Disallow multiple empty lines 52 | 'no-multiple-empty-lines': 'error', 53 | // Disallow use of the with statement 54 | 'no-with': 'error', 55 | // Require or disallow an newline around variable declarations 56 | 'one-var-declaration-per-line': ['error', 'initializations'], 57 | // Enforce operators to be placed before or after line breaks 58 | 'operator-linebreak': ['error', 'after'], 59 | // Require or disallow use of semicolons instead of ASI 60 | 'semi': ['error', 'always'], 61 | // Require or disallow space before blocks 62 | 'space-before-blocks': ['error', 'always'], 63 | // Require or disallow space before function opening parenthesis 64 | 'space-before-function-paren': ['error', 'never'], 65 | // Require or disallow space before blocks 66 | 'space-in-parens': ['error', 'always', {exceptions: ['{}', '[]']}], 67 | // Require spaces around operators 68 | 'space-infix-ops': 'error', 69 | // Require or disallow spaces before/after unary operators (words on by default, nonwords) 70 | 'space-unary-ops': ['error', { 71 | overrides: {'!': true} 72 | }], 73 | // Requires to declare all vars on top of their containing scope 74 | 'vars-on-top': 'error', 75 | // Require or disallow Yoda conditions 76 | 'yoda': ['error', 'always'] 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /test/test-assets/subgenerator-test-plugin/.gitignore: -------------------------------------------------------------------------------- 1 | # Node/npm 2 | node_modules/ 3 | npm-debug.log 4 | .grunt 5 | .sass-cache 6 | 7 | # OSX 8 | .DS_Store 9 | .AppleDouble 10 | .LSOverride 11 | .Spotlight-V100 12 | .Trashes 13 | .AppleDB 14 | .AppleDesktop 15 | Network Trash Folder 16 | Temporary Items 17 | .apdisk 18 | 19 | # Icon must end with two \r 20 | Icon 21 | 22 | 23 | # Thumbnails 24 | ._* 25 | 26 | 27 | # Vim 28 | [._]*.s[a-w][a-z] 29 | [._]s[a-w][a-z] 30 | *.un~ 31 | Session.vim 32 | .netrwhist 33 | *~ 34 | 35 | ### Bower ### 36 | bower_components 37 | .bower-cache 38 | .bower-registry 39 | .bower-tmp 40 | 41 | # Logs 42 | logs 43 | *.log 44 | 45 | # Runtime data 46 | pids 47 | *.pid 48 | *.seed 49 | 50 | # Directory for instrumented libs generated by jscoverage/JSCover 51 | lib-cov 52 | 53 | # Coverage directory used by tools like istanbul 54 | coverage 55 | 56 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 57 | .grunt 58 | 59 | # node-waf configuration 60 | .lock-wscript 61 | 62 | # Compiled binary addons (http://nodejs.org/api/addons.html) 63 | build/Release 64 | 65 | # Dependency directory 66 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 67 | node_modules 68 | 69 | 70 | 71 | # Commit your application's lock file http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file 72 | # You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file 73 | # composer.lock 74 | 75 | 76 | # Other, add your own ignored things here. 77 | .idea/ 78 | release 79 | -------------------------------------------------------------------------------- /test/test-assets/subgenerator-test-plugin/.sass-lint.yml: -------------------------------------------------------------------------------- 1 | # Sample Configs 2 | # - https://github.com/sasstools/sass-lint/blob/develop/docs/sass-lint.yml 3 | # - https://github.com/sasstools/gulp-sass-lint/blob/master/tests/.sass-lint.yml 4 | 5 | # Sass Lint Rules 6 | # - https://github.com/sasstools/sass-lint/tree/develop/docs/rules 7 | 8 | # Severity 9 | # - 0: turns rule off 10 | # - 1: set as a warning 11 | # - 2: set to error 12 | 13 | # File Options 14 | files: 15 | ignore: 16 | - 'sass/vendor/**/*.scss' 17 | - 'sass/tests/**/*.scss' 18 | - 'bourbon/app/**/*.scss' 19 | - 'bourbon-neat/app/**/*.scss' 20 | 21 | # Rule Configuration 22 | rules: 23 | # Extends 24 | placeholder-in-extend: 0 25 | 26 | # Mixins 27 | mixins-before-declarations: 28 | - 1 29 | - 30 | exclude: ['media'] # except @include media(); 31 | 32 | # Line Spacing 33 | empty-line-between-blocks: 34 | - 1 35 | - 36 | allow-single-line-rulesets: false 37 | 38 | # Disallows 39 | no-color-literals: 40 | - 1 41 | - 42 | allow-rgba: true 43 | no-debug: 0 44 | no-ids: 0 45 | no-mergeable-selectors: 0 46 | no-qualifying-elements: 47 | - 1 48 | - 49 | allow-element-with-attribute: true 50 | allow-element-with-class: false 51 | allow-element-with-id: false 52 | no-vendor-prefixes: 0 53 | no-warn: 0 54 | 55 | # Nesting 56 | force-attribute-nesting: 0 57 | force-element-nesting: 0 58 | force-pseudo-nesting: 0 59 | 60 | # Name Formats 61 | function-name-format: 62 | - 1 63 | - 64 | convention-explanation: Please use hyphenated lowercase for function names. Also, you may use a leading underscore if you prefer. 65 | mixin-name-format: 66 | - 1 67 | - 68 | convention-explanation: Please use hyphenated lowercase for mixin names. Also, you may use a leading underscore if you prefer. 69 | placeholder-name-format: 70 | - 1 71 | - 72 | convention-explanation: Please use hyphenated lowercase for placeholder names. Also, you may use a leading underscore if you prefer. 73 | variable-name-format: 74 | - 1 75 | - 76 | allow-leading-underscore: false 77 | convention-explanation: Please use hyphenated lowercase for variable names. No leading underscore is allowed. 78 | 79 | # Style Guide 80 | attribute-quotes: 1 81 | border-zero: 0 82 | brace-style: 83 | - 1 84 | - 85 | style: 1tbs 86 | allow-single-line: false 87 | class-name-format: 88 | - 1 89 | - 90 | allow-leading-underscore: false 91 | convention-explanation: Please use hypenated lowercase for class names, and without a leading underscore. If you find a WordPress core condition that conflicts with this convention feel free to modify and extend the ignore option. 92 | ignore: ['current_page_item', 'widget_search'] # ignore selectors declared by WordPress 93 | 94 | empty-args: 0 95 | hex-length: 1 96 | hex-notation: 1 97 | id-name-format: 98 | - 1 99 | - 100 | convention-explanation: Please try to use hyphenated lowercase ID name format. If overriding a plugin that does not use this format then please ignore or extend the list of ignore option. 101 | indentation: 102 | - 1 103 | - 104 | size: tab 105 | leading-zero: 106 | - 1 107 | - 108 | include: true 109 | 110 | nesting-depth: 111 | - 1 112 | - 113 | max-depth: 3 114 | 115 | property-units: 116 | - 1 117 | - 118 | per-property: { width: ['rem', 'vw'], height: ['rem', 'vh'], margin: ['rem'], padding: ['rem'] } 119 | 120 | quotes: 121 | - 1 122 | - 123 | style: double 124 | 125 | shorthand-values: 126 | - 1 127 | - 128 | allowed-shorthands: 129 | - 1 130 | - 2 131 | 132 | # Inner Spacing 133 | space-between-parens: 0 134 | 135 | # Final Items 136 | final-newline: 0 137 | 138 | no-misspelled-properties: 139 | - 1 140 | - 141 | 'extra-properties': 142 | - '-webkit-overflow-scrolling' 143 | -------------------------------------------------------------------------------- /test/test-assets/subgenerator-test-plugin/.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | notifications: 4 | email: 5 | on_success: never 6 | on_failure: change 7 | 8 | php: 9 | - 5.3 10 | - 5.5 11 | 12 | env: 13 | - WP_VERSION=latest WP_MULTISITE=0 14 | 15 | matrix: 16 | include: 17 | - php: 5.3 18 | env: WP_VERSION=latest WP_MULTISITE=1 19 | 20 | before_script: 21 | - bash bin/install-wp-tests.sh wordpress_test root '' localhost $WP_VERSION 22 | 23 | script: phpunit 24 | -------------------------------------------------------------------------------- /test/test-assets/subgenerator-test-plugin/.yo-rc.json: -------------------------------------------------------------------------------- 1 | { 2 | "generator-plugin-wp-local": { 3 | "name": "Subgenerator Test Plugin", 4 | "homepage": "https://webdevstudios.com", 5 | "description": "A radical new plugin for WordPress!", 6 | "version": "0.0.0", 7 | "author": "WebDevStudios", 8 | "authoremail": "contact@webdevstudios.com", 9 | "authorurl": "https://webdevstudios.com", 10 | "license": "GPLv2", 11 | "slug": "subgenerator-test-plugin", 12 | "classname": "Subgenerator_Test_Plugin", 13 | "mainclassname": "Subgenerator_Test_Plugin", 14 | "classprefix": "STP_", 15 | "prefix": "subgenerator_test_plugin", 16 | "year": 2017, 17 | "currentVersionWP": "4.7.2" 18 | } 19 | } -------------------------------------------------------------------------------- /test/test-assets/subgenerator-test-plugin/Dockunit.json: -------------------------------------------------------------------------------- 1 | { 2 | "containers":[ 3 | { 4 | "prettyName":"PHP 7.0 FPM WordPress Latest", 5 | "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-7.0-rc-4-fpm", 6 | "beforeScripts":[ 7 | "service mysql start", 8 | "bash bin/install-wp-tests.sh wordpress_test root '' localhost" 9 | ], 10 | "testCommand":"phpunit" 11 | }, 12 | { 13 | "prettyName":"PHP 7.0 FPM WordPress 4.7", 14 | "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-7.0-rc-4-fpm", 15 | "beforeScripts":[ 16 | "service mysql start", 17 | "bash bin/install-wp-tests.sh wordpress_test root '' localhost 4.7" 18 | ], 19 | "testCommand":"phpunit" 20 | }, 21 | { 22 | "prettyName":"PHP 7.0 FPM WordPress 4.6", 23 | "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-7.0-rc-4-fpm", 24 | "beforeScripts":[ 25 | "service mysql start", 26 | "bash bin/install-wp-tests.sh wordpress_test root '' localhost 4.6" 27 | ], 28 | "testCommand":"phpunit" 29 | }, 30 | { 31 | "prettyName":"PHP 7.0 FPM WordPress 4.5", 32 | "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-7.0-rc-4-fpm", 33 | "beforeScripts":[ 34 | "service mysql start", 35 | "bash bin/install-wp-tests.sh wordpress_test root '' localhost 4.5" 36 | ], 37 | "testCommand":"phpunit" 38 | }, 39 | { 40 | "prettyName":"PHP 7.0 FPM WordPress 4.4", 41 | "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-7.0-rc-4-fpm", 42 | "beforeScripts":[ 43 | "service mysql start", 44 | "bash bin/install-wp-tests.sh wordpress_test root '' localhost 4.4" 45 | ], 46 | "testCommand":"phpunit" 47 | }, 48 | { 49 | "prettyName":"PHP 7.0 FPM WordPress 4.3", 50 | "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-7.0-rc-4-fpm", 51 | "beforeScripts":[ 52 | "service mysql start", 53 | "bash bin/install-wp-tests.sh wordpress_test root '' localhost 4.3" 54 | ], 55 | "testCommand":"phpunit" 56 | }, 57 | { 58 | "prettyName":"PHP 5.6 FPM WordPress Latest", 59 | "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-5.6-fpm", 60 | "beforeScripts":[ 61 | "service mysql start", 62 | "bash bin/install-wp-tests.sh wordpress_test2 root '' localhost" 63 | ], 64 | "testCommand":"phpunit" 65 | }, 66 | { 67 | "prettyName":"PHP 5.6 FPM WordPress 4.7", 68 | "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-5.6-fpm", 69 | "beforeScripts":[ 70 | "service mysql start", 71 | "bash bin/install-wp-tests.sh wordpress_test2 root '' localhost 4.7" 72 | ], 73 | "testCommand":"phpunit" 74 | }, 75 | { 76 | "prettyName":"PHP 5.6 FPM WordPress 4.6", 77 | "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-5.6-fpm", 78 | "beforeScripts":[ 79 | "service mysql start", 80 | "bash bin/install-wp-tests.sh wordpress_test2 root '' localhost 4.6" 81 | ], 82 | "testCommand":"phpunit" 83 | }, 84 | { 85 | "prettyName":"PHP 5.6 FPM WordPress 4.5", 86 | "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-5.6-fpm", 87 | "beforeScripts":[ 88 | "service mysql start", 89 | "bash bin/install-wp-tests.sh wordpress_test2 root '' localhost 4.5" 90 | ], 91 | "testCommand":"phpunit" 92 | }, 93 | { 94 | "prettyName":"PHP 5.6 FPM WordPress 4.4", 95 | "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-5.6-fpm", 96 | "beforeScripts":[ 97 | "service mysql start", 98 | "bash bin/install-wp-tests.sh wordpress_test2 root '' localhost 4.4" 99 | ], 100 | "testCommand":"phpunit" 101 | }, 102 | { 103 | "prettyName":"PHP 5.6 FPM WordPress 4.3", 104 | "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-5.6-fpm", 105 | "beforeScripts":[ 106 | "service mysql start", 107 | "bash bin/install-wp-tests.sh wordpress_test2 root '' localhost 4.3" 108 | ], 109 | "testCommand":"phpunit" 110 | }, 111 | { 112 | "prettyName":"PHP 5.2 FPM WordPress 4.7", 113 | "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-5.2-fpm", 114 | "beforeScripts":[ 115 | "service mysql start", 116 | "bash bin/install-wp-tests.sh wordpress_test3 root '' localhost 4.7" 117 | ], 118 | "testCommand":"phpunit" 119 | }, 120 | { 121 | "prettyName":"PHP 5.2 FPM WordPress 4.6", 122 | "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-5.2-fpm", 123 | "beforeScripts":[ 124 | "service mysql start", 125 | "bash bin/install-wp-tests.sh wordpress_test3 root '' localhost 4.6" 126 | ], 127 | "testCommand":"phpunit" 128 | }, 129 | { 130 | "prettyName":"PHP 5.2 FPM WordPress 4.5", 131 | "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-5.2-fpm", 132 | "beforeScripts":[ 133 | "service mysql start", 134 | "bash bin/install-wp-tests.sh wordpress_test3 root '' localhost 4.5" 135 | ], 136 | "testCommand":"phpunit" 137 | }, 138 | { 139 | "prettyName":"PHP 5.2 FPM WordPress 4.4", 140 | "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-5.2-fpm", 141 | "beforeScripts":[ 142 | "service mysql start", 143 | "bash bin/install-wp-tests.sh wordpress_test3 root '' localhost 4.4" 144 | ], 145 | "testCommand":"phpunit" 146 | }, 147 | { 148 | "prettyName":"PHP 5.2 FPM WordPress 4.3", 149 | "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-5.2-fpm", 150 | "beforeScripts":[ 151 | "service mysql start", 152 | "bash bin/install-wp-tests.sh wordpress_test3 root '' localhost 4.3" 153 | ], 154 | "testCommand":"phpunit" 155 | } 156 | ] 157 | } 158 | -------------------------------------------------------------------------------- /test/test-assets/subgenerator-test-plugin/Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function( grunt ) { 2 | 3 | require('load-grunt-tasks')(grunt); 4 | 5 | var pkg = grunt.file.readJSON( 'package.json' ); 6 | 7 | var bannerTemplate = '/**\n' + 8 | ' * <%= pkg.title %> - v<%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %>\n' + 9 | ' * <%= pkg.author.url %>\n' + 10 | ' *\n' + 11 | ' * Copyright (c) <%= grunt.template.today("yyyy") %>;\n' + 12 | ' * Licensed GPLv2+\n' + 13 | ' */\n'; 14 | 15 | var compactBannerTemplate = '/** ' + 16 | '<%= pkg.title %> - v<%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %> | <%= pkg.author.url %> | Copyright (c) <%= grunt.template.today("yyyy") %>; | Licensed GPLv2+' + 17 | ' **/\n'; 18 | 19 | // Project configuration 20 | grunt.initConfig( { 21 | 22 | pkg: pkg, 23 | 24 | 25 | watch: { 26 | styles: { 27 | files: ['assets/**/*.css','assets/**/*.scss'], 28 | tasks: ['styles'], 29 | options: { 30 | spawn: false, 31 | livereload: true, 32 | debounceDelay: 500 33 | } 34 | }, 35 | scripts: { 36 | files: ['assets/**/*.js'], 37 | tasks: ['scripts'], 38 | options: { 39 | spawn: false, 40 | livereload: true, 41 | debounceDelay: 500 42 | } 43 | }, 44 | php: { 45 | files: ['**/*.php', '!vendor/**.*.php'], 46 | tasks: ['php'], 47 | options: { 48 | spawn: false, 49 | debounceDelay: 500 50 | } 51 | } 52 | }, 53 | 54 | makepot: { 55 | dist: { 56 | options: { 57 | domainPath: '/languages/', 58 | potFilename: pkg.name + '.pot', 59 | type: 'wp-plugin' 60 | } 61 | } 62 | }, 63 | 64 | addtextdomain: { 65 | dist: { 66 | options: { 67 | textdomain: pkg.name 68 | }, 69 | target: { 70 | files: { 71 | src: ['**/*.php'] 72 | } 73 | } 74 | } 75 | }, 76 | 77 | replace: { 78 | version_php: { 79 | src: [ 80 | '**/*.php', 81 | '!vendor/**', 82 | ], 83 | overwrite: true, 84 | replacements: [ { 85 | from: /Version:(\s*?)[a-zA-Z0-9\.\-\+]+$/m, 86 | to: 'Version:$1' + pkg.version 87 | }, { 88 | from: /@version(\s*?)[a-zA-Z0-9\.\-\+]+$/m, 89 | to: '@version$1' + pkg.version 90 | }, { 91 | from: /@since(.*?)NEXT/mg, 92 | to: '@since$1' + pkg.version 93 | }, { 94 | from: /VERSION(\s*?)=(\s*?['"])[a-zA-Z0-9\.\-\+]+/mg, 95 | to: 'VERSION$1=$2' + pkg.version 96 | } ] 97 | }, 98 | version_readme: { 99 | src: 'README.md', 100 | overwrite: true, 101 | replacements: [ { 102 | from: /^\*\*Stable tag:\*\*(\s*?)[a-zA-Z0-9.-]+(\s*?)$/mi, 103 | to: '**Stable tag:**$1<%= pkg.version %>$2' 104 | } ] 105 | }, 106 | readme_txt: { 107 | src: 'README.md', 108 | dest: 'release/' + pkg.version + '/readme.txt', 109 | replacements: [ { 110 | from: /^# (.*?)( #+)?$/mg, 111 | to: '=== $1 ===' 112 | }, { 113 | from: /^## (.*?)( #+)?$/mg, 114 | to: '== $1 ==' 115 | }, { 116 | from: /^### (.*?)( #+)?$/mg, 117 | to: '= $1 =' 118 | }, { 119 | from: /^\*\*(.*?):\*\*/mg, 120 | to: '$1:' 121 | } ] 122 | } 123 | }, 124 | 125 | copy: { 126 | release: { 127 | src: [ 128 | '**', 129 | '!assets/js/components/**', 130 | '!assets/css/sass/**', 131 | '!assets/repo/**', 132 | '!bin/**', 133 | '!release/**', 134 | '!tests/**', 135 | '!node_modules/**', 136 | '!**/*.md', 137 | '!.travis.yml', 138 | '!.bowerrc', 139 | '!.gitignore', 140 | '!bower.json', 141 | '!Dockunit.json', 142 | '!Gruntfile.js', 143 | '!package.json', 144 | '!phpunit.xml', 145 | ], 146 | dest: 'release/' + pkg.version + '/' 147 | }, 148 | svn: { 149 | cwd: 'release/<%= pkg.version %>/', 150 | expand: true, 151 | src: '**', 152 | dest: 'release/svn/' 153 | } 154 | }, 155 | 156 | compress: { 157 | dist: { 158 | options: { 159 | mode: 'zip', 160 | archive: './release/<%= pkg.name %>.<%= pkg.version %>.zip' 161 | }, 162 | expand: true, 163 | cwd: 'release/<%= pkg.version %>', 164 | src: ['**/*'], 165 | dest: '<%= pkg.name %>' 166 | } 167 | }, 168 | 169 | wp_deploy: { 170 | dist: { 171 | options: { 172 | plugin_slug: '<%= pkg.name %>', 173 | build_dir: 'release/svn/', 174 | assets_dir: 'assets/repo/' 175 | } 176 | } 177 | }, 178 | 179 | clean: { 180 | release: [ 181 | 'release/<%= pkg.version %>/', 182 | 'release/svn/' 183 | ] 184 | } 185 | 186 | } ); 187 | 188 | grunt.registerTask( 'scripts', [] ); 189 | grunt.registerTask( 'styles', [] ); 190 | grunt.registerTask( 'php', [ 'addtextdomain', 'makepot' ] ); 191 | grunt.registerTask( 'default', ['styles', 'scripts', 'php'] ); 192 | 193 | grunt.registerTask( 'version', [ 'default', 'replace:version_php', 'replace:version_readme' ] ); 194 | grunt.registerTask( 'release', [ 'clean:release', 'replace:readme_txt', 'copy', 'compress', 'wp_deploy' ] ); 195 | 196 | grunt.util.linefeed = '\n'; 197 | }; 198 | -------------------------------------------------------------------------------- /test/test-assets/subgenerator-test-plugin/Gulpfile.js: -------------------------------------------------------------------------------- 1 | // Require our dependencies 2 | const autoprefixer = require( 'autoprefixer' ); 3 | const babel = require( 'gulp-babel' ); 4 | const bourbon = require( 'bourbon' ).includePaths; 5 | const browserSync = require( 'browser-sync' ); 6 | const cheerio = require( 'gulp-cheerio' ); 7 | const concat = require( 'gulp-concat' ); 8 | const cssnano = require( 'gulp-cssnano' ); 9 | const del = require( 'del' ); 10 | const eslint = require( 'gulp-eslint' ); 11 | const gulp = require( 'gulp' ); 12 | const gutil = require( 'gulp-util' ); 13 | const imagemin = require( 'gulp-imagemin' ); 14 | const mqpacker = require( 'css-mqpacker' ); 15 | const neat = require( 'bourbon-neat' ).includePaths; 16 | const notify = require( 'gulp-notify' ); 17 | const plumber = require( 'gulp-plumber' ); 18 | const postcss = require( 'gulp-postcss' ); 19 | const reload = browserSync.reload; 20 | const rename = require( 'gulp-rename' ); 21 | const sass = require( 'gulp-sass' ); 22 | const sassLint = require( 'gulp-sass-lint' ); 23 | const sort = require( 'gulp-sort' ); 24 | const sourcemaps = require( 'gulp-sourcemaps' ); 25 | const spritesmith = require( 'gulp.spritesmith' ); 26 | const svgmin = require( 'gulp-svgmin' ); 27 | const svgstore = require( 'gulp-svgstore' ); 28 | const uglify = require( 'gulp-uglify' ); 29 | const wpPot = require( 'gulp-wp-pot' ); 30 | 31 | // Set assets paths. 32 | const paths = { 33 | 'css': [ './*.css', '!*.min.css' ], 34 | 'icons': 'assets/images/svg-icons/*.svg', 35 | 'images': [ 'assets/images/*', '!assets/images/*.svg' ], 36 | 'php': [ './*.php', './**/*.php' ], 37 | 'sass': 'assets/css/sass/*.scss', 38 | 'concat_scripts': 'assets/scripts/concat/*.js', 39 | 'scripts': [ 'assets/scripts/*.js', 'assets/js/*.js', '!assets/scripts/*.min.js' ], 40 | 'sprites': 'assets/images/sprites/*.png' 41 | }; 42 | 43 | /** 44 | * Handle errors and alert the user. 45 | */ 46 | function handleErrors () { 47 | const args = Array.prototype.slice.call( arguments ); 48 | 49 | notify.onError( { 50 | 'title': 'Task Failed [<%= error.message %>', 51 | 'message': 'See console.', 52 | 'sound': 'Sosumi' // See: https://github.com/mikaelbr/node-notifier#all-notification-options-with-their-defaults 53 | } ).apply( this, args ); 54 | 55 | gutil.beep(); // Beep 'sosumi' again. 56 | 57 | // Prevent the 'watch' task from stopping. 58 | this.emit( 'end' ); 59 | } 60 | 61 | /** 62 | * Delete style.css and style.min.css before we minify and optimize 63 | */ 64 | gulp.task( 'clean:styles', () => 65 | del( [ 'style.css', 'style.min.css' ] ) 66 | ); 67 | 68 | /** 69 | * Compile Sass and run stylesheet through PostCSS. 70 | * 71 | * https://www.npmjs.com/package/gulp-sass 72 | * https://www.npmjs.com/package/gulp-postcss 73 | * https://www.npmjs.com/package/gulp-autoprefixer 74 | * https://www.npmjs.com/package/css-mqpacker 75 | */ 76 | gulp.task( 'postcss', [ 'clean:styles' ], () => 77 | gulp.src( 'assets/sass/*.scss', paths.css ) 78 | 79 | // Deal with errors. 80 | .pipe( plumber( {'errorHandler': handleErrors} ) ) 81 | 82 | // Wrap tasks in a sourcemap. 83 | .pipe( sourcemaps.init() ) 84 | 85 | // Compile Sass using LibSass. 86 | .pipe( sass( { 87 | 'includePaths': [].concat( bourbon, neat ), 88 | 'errLogToConsole': true, 89 | 'outputStyle': 'expanded' // Options: nested, expanded, compact, compressed 90 | } ) ) 91 | 92 | // Parse with PostCSS plugins. 93 | .pipe( postcss( [ 94 | autoprefixer( { 95 | 'browsers': [ 'last 2 version' ] 96 | } ), 97 | mqpacker( { 98 | 'sort': true 99 | } ) 100 | ] ) ) 101 | 102 | // Create sourcemap. 103 | .pipe( sourcemaps.write() ) 104 | 105 | // Create style.css. 106 | .pipe( gulp.dest( './' ) ) 107 | .pipe( browserSync.stream() ) 108 | ); 109 | 110 | /** 111 | * Minify and optimize style.css. 112 | * 113 | * https://www.npmjs.com/package/gulp-cssnano 114 | */ 115 | gulp.task( 'cssnano', [ 'postcss' ], () => 116 | gulp.src( 'style.css' ) 117 | .pipe( plumber( {'errorHandler': handleErrors} ) ) 118 | .pipe( cssnano( { 119 | 'safe': true // Use safe optimizations. 120 | } ) ) 121 | .pipe( rename( 'style.min.css' ) ) 122 | .pipe( gulp.dest( './' ) ) 123 | .pipe( browserSync.stream() ) 124 | ); 125 | 126 | /** 127 | * Delete the svg-icons.svg before we minify, concat. 128 | */ 129 | gulp.task( 'clean:icons', () => 130 | del( [ 'assets/images/svg-icons.svg' ] ) 131 | ); 132 | 133 | /** 134 | * Minify, concatenate, and clean SVG icons. 135 | * 136 | * https://www.npmjs.com/package/gulp-svgmin 137 | * https://www.npmjs.com/package/gulp-svgstore 138 | * https://www.npmjs.com/package/gulp-cheerio 139 | */ 140 | gulp.task( 'svg', [ 'clean:icons' ], () => 141 | gulp.src( paths.icons ) 142 | 143 | // Deal with errors. 144 | .pipe( plumber( {'errorHandler': handleErrors} ) ) 145 | 146 | // Minify SVGs. 147 | .pipe( svgmin() ) 148 | 149 | // Add a prefix to SVG IDs. 150 | .pipe( rename( {'prefix': 'icon-'} ) ) 151 | 152 | // Combine all SVGs into a single 153 | .pipe( svgstore( {'inlineSvg': true} ) ) 154 | 155 | // Clean up the by removing the following cruft... 156 | .pipe( cheerio( { 157 | 'run': function ( $, file ) { 158 | $( 'svg' ).attr( 'style', 'display:none' ); 159 | $( '[fill]' ).removeAttr( 'fill' ); 160 | $( 'path' ).removeAttr( 'class' ); 161 | }, 162 | 'parserOptions': {'xmlMode': true} 163 | } ) ) 164 | 165 | // Save svg-icons.svg. 166 | .pipe( gulp.dest( 'assets/images/' ) ) 167 | .pipe( browserSync.stream() ) 168 | ); 169 | 170 | /** 171 | * Optimize images. 172 | * 173 | * https://www.npmjs.com/package/gulp-imagemin 174 | */ 175 | gulp.task( 'imagemin', () => 176 | gulp.src( paths.images ) 177 | .pipe( plumber( {'errorHandler': handleErrors} ) ) 178 | .pipe( imagemin( { 179 | 'optimizationLevel': 5, 180 | 'progressive': true, 181 | 'interlaced': true 182 | } ) ) 183 | .pipe( gulp.dest( 'assets/images' ) ) 184 | ); 185 | 186 | /** 187 | * Delete the sprites.png before rebuilding sprite. 188 | */ 189 | gulp.task( 'clean:sprites', () => { 190 | del( [ 'assets/images/sprites.png' ] ) 191 | } ); 192 | 193 | /** 194 | * Concatenate images into a single PNG sprite. 195 | * 196 | * https://www.npmjs.com/package/gulp.spritesmith 197 | */ 198 | gulp.task( 'spritesmith', [ 'clean:sprites' ], () => 199 | gulp.src( paths.sprites ) 200 | .pipe( plumber( {'errorHandler': handleErrors} ) ) 201 | .pipe( spritesmith( { 202 | 'imgName': 'sprites.png', 203 | 'cssName': '../../assets/sass/base/_sprites.scss', 204 | 'imgPath': 'assets/images/sprites.png', 205 | 'algorithm': 'binary-tree' 206 | } ) ) 207 | .pipe( gulp.dest( 'assets/images/' ) ) 208 | .pipe( browserSync.stream() ) 209 | ); 210 | 211 | /** 212 | * Concatenate and transform JavaScript. 213 | * 214 | * https://www.npmjs.com/package/gulp-concat 215 | * https://github.com/babel/gulp-babel 216 | * https://www.npmjs.com/package/gulp-sourcemaps 217 | */ 218 | gulp.task( 'concat', () => 219 | gulp.src( paths.concat_scripts ) 220 | 221 | // Deal with errors. 222 | .pipe( plumber( 223 | {'errorHandler': handleErrors} 224 | ) ) 225 | 226 | // Start a sourcemap. 227 | .pipe( sourcemaps.init() ) 228 | 229 | // Convert ES6+ to ES2015. 230 | .pipe( babel( { 231 | presets: [ 'es2015' ] 232 | } ) ) 233 | 234 | // Concatenate partials into a single script. 235 | .pipe( concat( 'project.js' ) ) 236 | 237 | // Append the sourcemap to project.js. 238 | .pipe( sourcemaps.write() ) 239 | 240 | // Save project.js 241 | .pipe( gulp.dest( 'assets/scripts' ) ) 242 | .pipe( browserSync.stream() ) 243 | ); 244 | 245 | /** 246 | * Minify compiled JavaScript. 247 | * 248 | * https://www.npmjs.com/package/gulp-uglify 249 | */ 250 | gulp.task( 'uglify', [ 'concat' ], () => 251 | gulp.src( paths.scripts ) 252 | .pipe( rename( {'suffix': '.min'} ) ) 253 | .pipe( plumber( {'errorHandler': handleErrors} ) ) 254 | .pipe( uglify( { 255 | 'mangle': false 256 | } ) ) 257 | .pipe( gulp.dest( 'assets/scripts' ) ) 258 | ); 259 | 260 | /** 261 | * Delete the theme's .pot before we create a new one. 262 | */ 263 | gulp.task( 'clean:pot', () => 264 | del( [ 'languages/_s.pot' ] ) 265 | ); 266 | 267 | /** 268 | * Scan the theme and create a POT file. 269 | * 270 | * https://www.npmjs.com/package/gulp-wp-pot 271 | */ 272 | gulp.task( 'wp-pot', [ 'clean:pot' ], () => 273 | gulp.src( paths.php ) 274 | .pipe( plumber( {'errorHandler': handleErrors} ) ) 275 | .pipe( sort() ) 276 | .pipe( wpPot( { 277 | 'domain': '_s', 278 | 'destFile': '_s.pot', 279 | 'package': '_s', 280 | 'bugReport': 'http://_s.com', 281 | 'lastTranslator': 'John Doe ', 282 | 'team': 'Team ' 283 | } ) ) 284 | .pipe( gulp.dest( 'languages/' ) ) 285 | ); 286 | 287 | /** 288 | * Sass linting. 289 | * 290 | * https://www.npmjs.com/package/sass-lint 291 | */ 292 | gulp.task( 'sass:lint', () => 293 | gulp.src( [ 294 | 'assets/sass/**/*.scss', 295 | '!assets/sass/base/_normalize.scss', 296 | '!assets/sass/base/_sprites.scss', 297 | '!node_modules/**' 298 | ] ) 299 | .pipe( sassLint() ) 300 | .pipe( sassLint.format() ) 301 | .pipe( sassLint.failOnError() ) 302 | ); 303 | 304 | /** 305 | * JavaScript linting. 306 | * 307 | * https://www.npmjs.com/package/gulp-eslint 308 | */ 309 | gulp.task( 'js:lint', () => 310 | gulp.src( [ 311 | 'assets/scripts/concat/*.js', 312 | 'assets/scripts/*.js', 313 | '!assets/scripts/project.js', 314 | '!assets/scripts/*.min.js', 315 | '!Gruntfile.js', 316 | '!Gulpfile.js', 317 | '!node_modules/**' 318 | ] ) 319 | .pipe( eslint() ) 320 | .pipe( eslint.format() ) 321 | .pipe( eslint.failAfterError() ) 322 | ); 323 | 324 | /** 325 | * Process tasks and reload browsers on file changes. 326 | * 327 | * https://www.npmjs.com/package/browser-sync 328 | */ 329 | gulp.task( 'watch', function () { 330 | 331 | // Kick off BrowserSync. 332 | browserSync( { 333 | 'open': false, // Open project in a new tab? 334 | 'injectChanges': true, // Auto inject changes instead of full reload. 335 | 'proxy': 'testing.dev', // Use http://_s.com:3000 to use BrowserSync. 336 | 'watchOptions': { 337 | 'debounceDelay': 1000 // Wait 1 second before injecting. 338 | } 339 | } ); 340 | 341 | // Run tasks when files change. 342 | gulp.watch( paths.icons, [ 'icons' ] ); 343 | gulp.watch( paths.sass, [ 'styles' ] ); 344 | gulp.watch( paths.scripts, [ 'scripts' ] ); 345 | gulp.watch( paths.concat_scripts, [ 'scripts' ] ); 346 | gulp.watch( paths.sprites, [ 'sprites' ] ); 347 | gulp.watch( paths.php, [ 'markup' ] ); 348 | } ); 349 | 350 | /** 351 | * Create individual tasks. 352 | */ 353 | gulp.task( 'markup', browserSync.reload ); 354 | gulp.task( 'i18n', [ 'wp-pot' ] ); 355 | gulp.task( 'icons', [ 'svg' ] ); 356 | gulp.task( 'scripts', [ 'uglify' ] ); 357 | gulp.task( 'styles', [ 'cssnano' ] ); 358 | gulp.task( 'sprites', [ 'spritesmith' ] ); 359 | gulp.task( 'lint', [ 'sass:lint', 'js:lint' ] ); 360 | gulp.task( 'default', [ 'sprites', 'i18n', 'icons', 'styles', 'scripts', 'imagemin'] ); -------------------------------------------------------------------------------- /test/test-assets/subgenerator-test-plugin/README.md: -------------------------------------------------------------------------------- 1 | # Subgenerator Test Plugin # 2 | **Contributors:** WebDevStudios 3 | **Donate link:** https://webdevstudios.com 4 | **Tags:** 5 | **Requires at least:** 4.4 6 | **Tested up to:** 4.7.2 7 | **Stable tag:** 0.1.0 8 | **License:** GPLv2 9 | **License URI:** http://www.gnu.org/licenses/gpl-2.0.html 10 | 11 | ## Description ## 12 | 13 | A radical new plugin for WordPress! 14 | 15 | ## Installation ## 16 | 17 | ### Manual Installation ### 18 | 19 | 1. Upload the entire `/subgenerator-test-plugin` directory to the `/wp-content/plugins/` directory. 20 | 2. Activate Subgenerator Test Plugin through the 'Plugins' menu in WordPress. 21 | 22 | ## Frequently Asked Questions ## 23 | 24 | 25 | ## Screenshots ## 26 | 27 | 28 | ## Changelog ## 29 | 30 | ### 0.1.0 ### 31 | * First release 32 | 33 | ## Upgrade Notice ## 34 | 35 | ### 0.1.0 ### 36 | First Release 37 | -------------------------------------------------------------------------------- /test/test-assets/subgenerator-test-plugin/assets/README.md: -------------------------------------------------------------------------------- 1 | # Subgenerator Test Plugin Assets # 2 | https://webdevstudios.com 3 | Copyright (c) 2017 WebDevStudios 4 | Licensed under the GPLv2 license. 5 | 6 | Assets such as styles, javascript, and images. -------------------------------------------------------------------------------- /test/test-assets/subgenerator-test-plugin/assets/repo/README.md: -------------------------------------------------------------------------------- 1 | # Subgenerator Test Plugin Repo Assets # 2 | https://webdevstudios.com 3 | Copyright (c) 2017 WebDevStudios 4 | Licensed under the GPLv2 license. 5 | 6 | Assets such as screenshots and banner for WordPress.org plugin repository listing. -------------------------------------------------------------------------------- /test/test-assets/subgenerator-test-plugin/bin/install-wp-tests.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [ $# -lt 3 ]; then 4 | echo "usage: $0 [db-host] [wp-version]" 5 | exit 1 6 | fi 7 | 8 | DB_NAME=$1 9 | DB_USER=$2 10 | DB_PASS=$3 11 | DB_HOST=${4-localhost} 12 | WP_VERSION=${5-latest} 13 | 14 | WP_TESTS_DIR=${WP_TESTS_DIR-/tmp/wordpress-tests-lib} 15 | WP_CORE_DIR=${WP_CORE_DIR-/tmp/wordpress/} 16 | 17 | download() { 18 | if [ `which curl` ]; then 19 | curl -s "$1" > "$2"; 20 | elif [ `which wget` ]; then 21 | wget -nv -O "$2" "$1" 22 | fi 23 | } 24 | 25 | if [[ $WP_VERSION =~ [0-9]+\.[0-9]+(\.[0-9]+)? ]]; then 26 | WP_TESTS_TAG="tags/$WP_VERSION" 27 | else 28 | # http serves a single offer, whereas https serves multiple. we only want one 29 | download http://api.wordpress.org/core/version-check/1.7/ /tmp/wp-latest.json 30 | grep '[0-9]+\.[0-9]+(\.[0-9]+)?' /tmp/wp-latest.json 31 | LATEST_VERSION=$(grep -o '"version":"[^"]*' /tmp/wp-latest.json | sed 's/"version":"//') 32 | if [[ -z "$LATEST_VERSION" ]]; then 33 | echo "Latest WordPress version could not be found" 34 | exit 1 35 | fi 36 | WP_TESTS_TAG="tags/$LATEST_VERSION" 37 | fi 38 | 39 | set -ex 40 | 41 | install_wp() { 42 | 43 | if [ -d $WP_CORE_DIR ]; then 44 | return; 45 | fi 46 | 47 | mkdir -p $WP_CORE_DIR 48 | 49 | if [ $WP_VERSION == 'latest' ]; then 50 | local ARCHIVE_NAME='latest' 51 | else 52 | local ARCHIVE_NAME="wordpress-$WP_VERSION" 53 | fi 54 | 55 | download https://wordpress.org/${ARCHIVE_NAME}.tar.gz /tmp/wordpress.tar.gz 56 | tar --strip-components=1 -zxmf /tmp/wordpress.tar.gz -C $WP_CORE_DIR 57 | 58 | download https://raw.github.com/markoheijnen/wp-mysqli/master/db.php $WP_CORE_DIR/wp-content/db.php 59 | } 60 | 61 | install_test_suite() { 62 | # portable in-place argument for both GNU sed and Mac OSX sed 63 | if [[ $(uname -s) == 'Darwin' ]]; then 64 | local ioption='-i .bak' 65 | else 66 | local ioption='-i' 67 | fi 68 | 69 | # set up testing suite if it doesn't yet exist 70 | if [ ! -d $WP_TESTS_DIR ]; then 71 | # set up testing suite 72 | mkdir -p $WP_TESTS_DIR 73 | svn co --quiet https://develop.svn.wordpress.org/${WP_TESTS_TAG}/tests/phpunit/includes/ $WP_TESTS_DIR/includes 74 | fi 75 | 76 | cd $WP_TESTS_DIR 77 | 78 | if [ ! -f wp-tests-config.php ]; then 79 | download https://develop.svn.wordpress.org/${WP_TESTS_TAG}/wp-tests-config-sample.php "$WP_TESTS_DIR"/wp-tests-config.php 80 | sed $ioption "s:dirname( __FILE__ ) . '/src/':'$WP_CORE_DIR':" "$WP_TESTS_DIR"/wp-tests-config.php 81 | sed $ioption "s:define( 'WP_DEBUG', true );:define( 'WP_DEBUG', true ); define( 'WP_DEBUG_LOG', true );:" "$WP_TESTS_DIR"/wp-tests-config.php 82 | sed $ioption "s/youremptytestdbnamehere/$DB_NAME/" "$WP_TESTS_DIR"/wp-tests-config.php 83 | sed $ioption "s/yourusernamehere/$DB_USER/" "$WP_TESTS_DIR"/wp-tests-config.php 84 | sed $ioption "s/yourpasswordhere/$DB_PASS/" "$WP_TESTS_DIR"/wp-tests-config.php 85 | sed $ioption "s|localhost|${DB_HOST}|" "$WP_TESTS_DIR"/wp-tests-config.php 86 | fi 87 | 88 | } 89 | 90 | install_db() { 91 | # parse DB_HOST for port or socket references 92 | local PARTS=(${DB_HOST//\:/ }) 93 | local DB_HOSTNAME=${PARTS[0]}; 94 | local DB_SOCK_OR_PORT=${PARTS[1]}; 95 | local EXTRA="" 96 | 97 | if ! [ -z $DB_HOSTNAME ] ; then 98 | if [ $(echo $DB_SOCK_OR_PORT | grep -e '^[0-9]\{1,\}$') ]; then 99 | EXTRA=" --host=$DB_HOSTNAME --port=$DB_SOCK_OR_PORT --protocol=tcp" 100 | elif ! [ -z $DB_SOCK_OR_PORT ] ; then 101 | EXTRA=" --socket=$DB_SOCK_OR_PORT" 102 | elif ! [ -z $DB_HOSTNAME ] ; then 103 | EXTRA=" --host=$DB_HOSTNAME --protocol=tcp" 104 | fi 105 | fi 106 | 107 | # create database 108 | mysqladmin create $DB_NAME --user="$DB_USER" --password="$DB_PASS"$EXTRA 109 | } 110 | 111 | install_wp 112 | install_test_suite 113 | install_db 114 | -------------------------------------------------------------------------------- /test/test-assets/subgenerator-test-plugin/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "subgenerator-test-plugin", 3 | "description": "A radical new plugin for WordPress!", 4 | "license": "GPLv2", 5 | "authors": [ 6 | "WebDevStudios" 7 | ], 8 | "private": true, 9 | "ignore": [ 10 | "**/.*", 11 | "node_modules", 12 | "bower_components", 13 | "test", 14 | "tests" 15 | ], 16 | "dependencies": { 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /test/test-assets/subgenerator-test-plugin/includes/README.md: -------------------------------------------------------------------------------- 1 | # Subgenerator Test Plugin Includes # 2 | https://webdevstudios.com 3 | Copyright (c) 2017 WebDevStudios 4 | Licensed under the GPLv2 license. 5 | 6 | Additional PHP functionality goes here. -------------------------------------------------------------------------------- /test/test-assets/subgenerator-test-plugin/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "subgenerator-test-plugin", 3 | "title": "Subgenerator Test Plugin", 4 | "version": "0.1.0", 5 | "description": "A radical new plugin for WordPress!", 6 | "author": { 7 | "name": "WebDevStudios", 8 | "url": "https://webdevstudios.com" 9 | }, 10 | "license": "GPLv2", 11 | "devDependencies": { 12 | "grunt": "latest", 13 | "grunt-contrib-watch": "latest", 14 | "grunt-wp-i18n": "latest", 15 | "grunt-contrib-copy": "latest", 16 | "grunt-text-replace": "latest", 17 | "grunt-contrib-clean": "latest", 18 | "grunt-contrib-compress": "latest", 19 | "grunt-wp-deploy": "latest", 20 | "load-grunt-tasks": "latest", 21 | "autoprefixer": "latest", 22 | "babel-preset-es2015": "latest", 23 | "bourbon": "latest", 24 | "bourbon-neat": "latest", 25 | "browser-sync": "latest", 26 | "css-mqpacker": "latest", 27 | "del": "latest", 28 | "eslint-config-wordpress": "latest", 29 | "glob": "latest", 30 | "gulp": "latest", 31 | "gulp-babel": "latest", 32 | "gulp-cheerio": "latest", 33 | "gulp-concat": "latest", 34 | "gulp-cssnano": "latest", 35 | "gulp-eslint": "latest", 36 | "gulp-imagemin": "latest", 37 | "gulp-notify": "latest", 38 | "gulp-plumber": "latest", 39 | "gulp-postcss": "latest", 40 | "gulp-rename": "latest", 41 | "gulp-sass": "latest", 42 | "gulp-sass-lint": "latest", 43 | "gulp-sort": "latest", 44 | "gulp-sourcemaps": "latest", 45 | "gulp-svgmin": "latest", 46 | "gulp-svgstore": "latest", 47 | "gulp-uglify": "latest", 48 | "gulp-util": "latest", 49 | "gulp-wp-pot": "latest", 50 | "gulp.spritesmith": "latest" 51 | }, 52 | "scripts": { 53 | "test": "dockunit", 54 | "preversion": "npm test", 55 | "version": "grunt version && git add ." 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /test/test-assets/subgenerator-test-plugin/phpcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | A modified set of rules, based on the WordPress Coding Standards. 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /test/test-assets/subgenerator-test-plugin/phpunit.xml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | ./tests/ 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /test/test-assets/subgenerator-test-plugin/subgenerator-test-plugin.php: -------------------------------------------------------------------------------- 1 | basename = plugin_basename( __FILE__ ); 138 | $this->url = plugin_dir_url( __FILE__ ); 139 | $this->path = plugin_dir_path( __FILE__ ); 140 | } 141 | 142 | /** 143 | * Attach other plugin classes to the base plugin class. 144 | * 145 | * @since 0.1.0 146 | */ 147 | public function plugin_classes() { 148 | // $this->plugin_class = new STP_Plugin_Class( $this ); 149 | 150 | } // END OF PLUGIN CLASSES FUNCTION 151 | 152 | /** 153 | * Add hooks and filters. 154 | * Priority needs to be 155 | * < 10 for CPT_Core, 156 | * < 5 for Taxonomy_Core, 157 | * and 0 for Widgets because widgets_init runs at init priority 1. 158 | * 159 | * @since 0.1.0 160 | */ 161 | public function hooks() { 162 | add_action( 'init', array( $this, 'init' ), 0 ); 163 | } 164 | 165 | /** 166 | * Activate the plugin. 167 | * 168 | * @since 0.1.0 169 | */ 170 | public function _activate() { 171 | // Bail early if requirements aren't met. 172 | if ( ! $this->check_requirements() ) { 173 | return; 174 | } 175 | 176 | // Make sure any rewrite functionality has been loaded. 177 | flush_rewrite_rules(); 178 | } 179 | 180 | /** 181 | * Deactivate the plugin. 182 | * Uninstall routines should be in uninstall.php. 183 | * 184 | * @since 0.1.0 185 | */ 186 | public function _deactivate() { 187 | // Add deactivation cleanup functionality here. 188 | } 189 | 190 | /** 191 | * Init hooks 192 | * 193 | * @since 0.1.0 194 | */ 195 | public function init() { 196 | 197 | // Bail early if requirements aren't met. 198 | if ( ! $this->check_requirements() ) { 199 | return; 200 | } 201 | 202 | // Load translated strings for plugin. 203 | load_plugin_textdomain( 'subgenerator-test-plugin', false, dirname( $this->basename ) . '/languages/' ); 204 | 205 | // Initialize plugin classes. 206 | $this->plugin_classes(); 207 | } 208 | 209 | /** 210 | * Check if the plugin meets requirements and 211 | * disable it if they are not present. 212 | * 213 | * @since 0.1.0 214 | * 215 | * @return boolean True if requirements met, false if not. 216 | */ 217 | public function check_requirements() { 218 | 219 | // Bail early if plugin meets requirements. 220 | if ( $this->meets_requirements() ) { 221 | return true; 222 | } 223 | 224 | // Add a dashboard notice. 225 | add_action( 'all_admin_notices', array( $this, 'requirements_not_met_notice' ) ); 226 | 227 | // Deactivate our plugin. 228 | add_action( 'admin_init', array( $this, 'deactivate_me' ) ); 229 | 230 | // Didn't meet the requirements. 231 | return false; 232 | } 233 | 234 | /** 235 | * Deactivates this plugin, hook this function on admin_init. 236 | * 237 | * @since 0.1.0 238 | */ 239 | public function deactivate_me() { 240 | 241 | // We do a check for deactivate_plugins before calling it, to protect 242 | // any developers from accidentally calling it too early and breaking things. 243 | if ( function_exists( 'deactivate_plugins' ) ) { 244 | deactivate_plugins( $this->basename ); 245 | } 246 | } 247 | 248 | /** 249 | * Check that all plugin requirements are met. 250 | * 251 | * @since 0.1.0 252 | * 253 | * @return boolean True if requirements are met. 254 | */ 255 | public function meets_requirements() { 256 | 257 | // Do checks for required classes / functions or similar. 258 | // Add detailed messages to $this->activation_errors array. 259 | return true; 260 | } 261 | 262 | /** 263 | * Adds a notice to the dashboard if the plugin requirements are not met. 264 | * 265 | * @since 0.1.0 266 | */ 267 | public function requirements_not_met_notice() { 268 | 269 | // Compile default message. 270 | $default_message = sprintf( __( 'Subgenerator Test Plugin is missing requirements and has been deactivated. Please make sure all requirements are available.', 'subgenerator-test-plugin' ), admin_url( 'plugins.php' ) ); 271 | 272 | // Default details to null. 273 | $details = null; 274 | 275 | // Add details if any exist. 276 | if ( $this->activation_errors && is_array( $this->activation_errors ) ) { 277 | $details = '' . implode( '
', $this->activation_errors ) . ''; 278 | } 279 | 280 | // Output errors. 281 | ?> 282 |
283 |

284 | 285 |
286 | $field; 306 | default: 307 | throw new Exception( 'Invalid ' . __CLASS__ . ' property: ' . $field ); 308 | } 309 | } 310 | 311 | /** 312 | * Include a file from the includes directory. 313 | * 314 | * @since 0.1.0 315 | * 316 | * @param string $filename Name of the file to be included. 317 | * @return boolean Result of include call. 318 | */ 319 | public static function include_file( $filename ) { 320 | $file = self::dir( $filename . '.php' ); 321 | if ( file_exists( $file ) ) { 322 | return include_once( $file ); 323 | } 324 | return false; 325 | } 326 | 327 | /** 328 | * This plugin's directory. 329 | * 330 | * @since 0.1.0 331 | * 332 | * @param string $path (optional) appended path. 333 | * @return string Directory and path. 334 | */ 335 | public static function dir( $path = '' ) { 336 | static $dir; 337 | $dir = $dir ? $dir : trailingslashit( dirname( __FILE__ ) ); 338 | return $dir . $path; 339 | } 340 | 341 | /** 342 | * This plugin's url. 343 | * 344 | * @since 0.1.0 345 | * 346 | * @param string $path (optional) appended path. 347 | * @return string URL and path. 348 | */ 349 | public static function url( $path = '' ) { 350 | static $url; 351 | $url = $url ? $url : trailingslashit( plugin_dir_url( __FILE__ ) ); 352 | return $url . $path; 353 | } 354 | } 355 | 356 | /** 357 | * Grab the Subgenerator_Test_Plugin object and return it. 358 | * Wrapper for Subgenerator_Test_Plugin::get_instance(). 359 | * 360 | * @since 0.1.0 361 | * @return Subgenerator_Test_Plugin Singleton instance of plugin class. 362 | */ 363 | function subgenerator_test_plugin() { 364 | return Subgenerator_Test_Plugin::get_instance(); 365 | } 366 | 367 | // Kick it off. 368 | add_action( 'plugins_loaded', array( subgenerator_test_plugin(), 'hooks' ) ); 369 | 370 | // Activation and deactivation. 371 | register_activation_hook( __FILE__, array( subgenerator_test_plugin(), '_activate' ) ); 372 | register_deactivation_hook( __FILE__, array( subgenerator_test_plugin(), '_deactivate' ) ); 373 | -------------------------------------------------------------------------------- /test/test-assets/subgenerator-test-plugin/tests/bootstrap.php: -------------------------------------------------------------------------------- 1 | assertTrue( class_exists( 'Subgenerator_Test_Plugin') ); 17 | } 18 | 19 | /** 20 | * Test that our main helper function is an instance of our class. 21 | * 22 | * @since 0.1.0 23 | */ 24 | function test_get_instance() { 25 | $this->assertInstanceOf( subgenerator_test_plugin(), 'Subgenerator_Test_Plugin' ); 26 | } 27 | 28 | /** 29 | * Replace this with some actual testing code. 30 | * 31 | * @since 0.1.0 32 | */ 33 | function test_sample() { 34 | $this->assertTrue( true ); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /test/test-cpt.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var path = require('path'); 4 | var assert = require('yeoman-generator').assert; 5 | var helpers = require('yeoman-generator').test; 6 | var fs = require('fs-extra'); 7 | 8 | describe('plugin-wp:cpt', function () { 9 | before(function (done) { 10 | helpers.run(path.join( __dirname, '../cpt')) 11 | .inTmpDir( function (dir) { 12 | fs.copySync(path.join(__dirname, './test-assets/subgenerator-test-plugin'), dir); 13 | }) 14 | .withOptions({ force: true }) 15 | .withArguments('new-cpt') 16 | .withLocalConfig({ 17 | "name": "Subgenerator Test Plugin", 18 | "homepage": "https://webdevstudios.com", 19 | "description": "A radical new plugin for WordPress!", 20 | "version": "0.1.0", 21 | "author": "WebDevStudios", 22 | "authoremail": "contact@webdevstudios.com", 23 | "authorurl": "https://webdevstudios.com", 24 | "license": "GPLv2", 25 | "slug": "subgenerator-test-plugin", 26 | "classname": "Subgenerator_Test_Plugin", 27 | "prefix": "subgenerator_test_plugin", 28 | "year": 2017 29 | }) 30 | .on('end', done); 31 | }); 32 | 33 | it('creates files', function () { 34 | assert.file([ 35 | 'includes/class-new-cpt.php', 36 | 'tests/test-new-cpt.php' 37 | ]); 38 | }); 39 | }); 40 | -------------------------------------------------------------------------------- /test/test-css.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var path = require('path'); 4 | var assert = require('yeoman-generator').assert; 5 | var helpers = require('yeoman-generator').test; 6 | var fs = require('fs-extra'); 7 | 8 | describe('plugin-wp:css', function () { 9 | before(function (done) { 10 | helpers.run(path.join( __dirname, '../css')) 11 | .inTmpDir() 12 | .withOptions({ force: true }) 13 | .withPrompts({ type: 'SASS' }) 14 | .withLocalConfig({ 15 | "name": "Subgenerator Test Plugin", 16 | "homepage": "https://webdevstudios.com", 17 | "description": "A radical new plugin for WordPress!", 18 | "version": "0.1.0", 19 | "author": "WebDevStudios", 20 | "authoremail": "contact@webdevstudios.com", 21 | "authorurl": "https://webdevstudios.com", 22 | "license": "GPLv2", 23 | "slug": "subgenerator-test-plugin", 24 | "classname": "Subgenerator_Test_Plugin", 25 | "prefix": "subgenerator_test_plugin", 26 | "year": 2017 27 | }) 28 | .on('end', done); 29 | }); 30 | 31 | it('creates files', function () { 32 | assert.file([ 33 | 'assets/css/sass/styles.scss' 34 | ]); 35 | }); 36 | }); 37 | -------------------------------------------------------------------------------- /test/test-endpoint.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var path = require('path'); 4 | var assert = require('yeoman-generator').assert; 5 | var helpers = require('yeoman-generator').test; 6 | var fs = require('fs-extra'); 7 | 8 | describe('plugin-wp:endpoint', function () { 9 | before(function (done) { 10 | helpers.run(path.join( __dirname, '../endpoint')) 11 | .inTmpDir( function (dir) { 12 | fs.copySync(path.join(__dirname, './test-assets/subgenerator-test-plugin'), dir); 13 | }) 14 | .withOptions({ force: true }) 15 | .withArguments('new-endpoint') 16 | .withLocalConfig({ 17 | "name": "Subgenerator Test Plugin", 18 | "homepage": "https://webdevstudios.com", 19 | "description": "A radical new plugin for WordPress!", 20 | "version": "0.1.0", 21 | "author": "WebDevStudios", 22 | "authoremail": "contact@webdevstudios.com", 23 | "authorurl": "https://webdevstudios.com", 24 | "license": "GPLv2", 25 | "slug": "subgenerator-test-plugin", 26 | "classname": "Subgenerator_Test_Plugin", 27 | "prefix": "subgenerator_test_plugin", 28 | "year": 2017 29 | }) 30 | .on('end', done); 31 | }); 32 | 33 | it('creates files', function () { 34 | assert.file([ 35 | 'includes/class-new-endpoint.php', 36 | 'tests/test-new-endpoint.php' 37 | ]); 38 | }); 39 | }); 40 | -------------------------------------------------------------------------------- /test/test-include.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var path = require('path'); 4 | var assert = require('yeoman-generator').assert; 5 | var helpers = require('yeoman-generator').test; 6 | var fs = require('fs-extra'); 7 | 8 | describe('plugin-wp:include', function () { 9 | before(function (done) { 10 | helpers.run(path.join( __dirname, '../include')) 11 | .inTmpDir( function (dir) { 12 | fs.copySync(path.join(__dirname, './test-assets/subgenerator-test-plugin'), dir); 13 | }) 14 | .withOptions({ force: true }) 15 | .withArguments('new-include') 16 | .withLocalConfig({ 17 | "name": "Subgenerator Test Plugin", 18 | "homepage": "https://webdevstudios.com", 19 | "description": "A radical new plugin for WordPress!", 20 | "version": "0.1.0", 21 | "author": "WebDevStudios", 22 | "authoremail": "contact@webdevstudios.com", 23 | "authorurl": "https://webdevstudios.com", 24 | "license": "GPLv2", 25 | "slug": "subgenerator-test-plugin", 26 | "classname": "Subgenerator_Test_Plugin", 27 | "prefix": "subgenerator_test_plugin", 28 | "year": 2017 29 | }) 30 | .on('end', done); 31 | }); 32 | 33 | it('creates files', function () { 34 | assert.file([ 35 | 'includes/class-new-include.php', 36 | 'tests/test-new-include.php' 37 | ]); 38 | }); 39 | }); 40 | -------------------------------------------------------------------------------- /test/test-js.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var path = require('path'); 4 | var assert = require('yeoman-generator').assert; 5 | var helpers = require('yeoman-generator').test; 6 | 7 | describe('plugin-wp:js', function () { 8 | before(function (done) { 9 | helpers.run(path.join( __dirname, '../js')) 10 | .inTmpDir() 11 | .withOptions({ force: true }) 12 | .withPrompts({ type: 'Browserify' }) 13 | .withLocalConfig({ 14 | "name": "Subgenerator Test Plugin", 15 | "homepage": "https://webdevstudios.com", 16 | "description": "A radical new plugin for WordPress!", 17 | "version": "0.1.0", 18 | "author": "WebDevStudios", 19 | "authoremail": "contact@webdevstudios.com", 20 | "authorurl": "https://webdevstudios.com", 21 | "license": "GPLv2", 22 | "slug": "subgenerator-test-plugin", 23 | "classname": "Subgenerator_Test_Plugin", 24 | "prefix": "subgenerator_test_plugin", 25 | "year": 2017 26 | }) 27 | .on('end', done); 28 | }); 29 | 30 | it('creates files', function () { 31 | assert.file([ 32 | 'assets/js/components/main.js' 33 | ]); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /test/test-options.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var path = require('path'); 4 | var assert = require('yeoman-generator').assert; 5 | var helpers = require('yeoman-generator').test; 6 | var fs = require('fs-extra'); 7 | 8 | describe('plugin-wp:options', function () { 9 | before(function (done) { 10 | helpers.run(path.join( __dirname, '../options')) 11 | .inTmpDir( function (dir) { 12 | fs.copySync(path.join(__dirname, './test-assets/subgenerator-test-plugin'), dir); 13 | }) 14 | .withOptions({ force: true }) 15 | .withArguments('new-options') 16 | .withLocalConfig({ 17 | "name": "Subgenerator Test Plugin", 18 | "homepage": "https://webdevstudios.com", 19 | "description": "A radical new plugin for WordPress!", 20 | "version": "0.1.0", 21 | "author": "WebDevStudios", 22 | "authoremail": "contact@webdevstudios.com", 23 | "authorurl": "https://webdevstudios.com", 24 | "license": "GPLv2", 25 | "slug": "subgenerator-test-plugin", 26 | "classname": "Subgenerator_Test_Plugin", 27 | "prefix": "subgenerator_test_plugin", 28 | "year": 2017 29 | }) 30 | .on('end', done); 31 | }); 32 | 33 | it('creates files', function () { 34 | assert.file([ 35 | 'includes/class-new-options.php', 36 | 'tests/test-new-options.php' 37 | ]); 38 | }); 39 | }); 40 | -------------------------------------------------------------------------------- /test/test-taxonomy.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var path = require('path'); 4 | var assert = require('yeoman-generator').assert; 5 | var helpers = require('yeoman-generator').test; 6 | var fs = require('fs-extra'); 7 | 8 | describe('plugin-wp:taxonomy', function () { 9 | before(function (done) { 10 | helpers.run(path.join( __dirname, '../taxonomy')) 11 | .inTmpDir( function (dir) { 12 | fs.copySync(path.join(__dirname, './test-assets/subgenerator-test-plugin'), dir); 13 | }) 14 | .withOptions({ force: true }) 15 | .withArguments('new-tax' ) 16 | .withLocalConfig({ 17 | "name": "Subgenerator Test Plugin", 18 | "homepage": "https://webdevstudios.com", 19 | "description": "A radical new plugin for WordPress!", 20 | "version": "0.1.0", 21 | "author": "WebDevStudios", 22 | "authoremail": "contact@webdevstudios.com", 23 | "authorurl": "https://webdevstudios.com", 24 | "license": "GPLv2", 25 | "slug": "subgenerator-test-plugin", 26 | "classname": "Subgenerator_Test_Plugin", 27 | "prefix": "subgenerator_test_plugin", 28 | "year": 2017 29 | }) 30 | .on('end', done); 31 | }); 32 | 33 | it('creates files', function () { 34 | assert.file([ 35 | 'includes/class-new-tax.php', 36 | 'tests/test-new-tax.php' 37 | ]); 38 | }); 39 | }); 40 | -------------------------------------------------------------------------------- /test/test-widget.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var path = require('path'); 4 | var assert = require('yeoman-generator').assert; 5 | var helpers = require('yeoman-generator').test; 6 | var fs = require('fs-extra'); 7 | 8 | describe('plugin-wp:widget', function () { 9 | before(function (done) { 10 | helpers.run(path.join( __dirname, '../widget')) 11 | .inTmpDir( function (dir) { 12 | fs.copySync(path.join(__dirname, './test-assets/subgenerator-test-plugin'), dir); 13 | }) 14 | .withOptions({ force: true }) 15 | .withArguments('new-widget') 16 | .withLocalConfig({ 17 | "name": "Subgenerator Test Plugin", 18 | "homepage": "https://webdevstudios.com", 19 | "description": "A radical new plugin for WordPress!", 20 | "version": "0.1.0", 21 | "author": "WebDevStudios", 22 | "authoremail": "contact@webdevstudios.com", 23 | "authorurl": "https://webdevstudios.com", 24 | "license": "GPLv2", 25 | "slug": "subgenerator-test-plugin", 26 | "classname": "Subgenerator_Test_Plugin", 27 | "prefix": "subgenerator_test_plugin", 28 | "year": 2017 29 | }) 30 | .on('end', done); 31 | }); 32 | 33 | it('creates files', function () { 34 | assert.file([ 35 | 'includes/class-new-widget.php', 36 | 'tests/test-new-widget.php' 37 | ]); 38 | }); 39 | }); 40 | -------------------------------------------------------------------------------- /widget/README.md: -------------------------------------------------------------------------------- 1 | # generator-plugin-wp Widget Sub-generator 2 | 3 | ```bash 4 | yo plugin-wp Widget 5 | ``` 6 | 7 | Creates a skeleton widget and shortcode for your plugin. 8 | -------------------------------------------------------------------------------- /widget/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var base = require('../plugin-wp-base'); 3 | 4 | module.exports = base.extend({ 5 | constructor: function () { 6 | base.apply(this, arguments); 7 | 8 | this.argument('name', { 9 | required: false, 10 | type : String, 11 | desc : 'The widget name' 12 | }); 13 | }, 14 | 15 | initializing: { 16 | intro: function () { 17 | // Have Yeoman greet the user. 18 | this.log('Welcome to the neat Plugin WP Widget subgenerator!'); 19 | }, 20 | 21 | readingYORC: function() { 22 | this.rc = this.config.getAll() || {}; 23 | }, 24 | 25 | readingPackage: function() { 26 | this.pkg = this.fs.readJSON( this.destinationPath('package.json')) || {}; 27 | }, 28 | 29 | settingValues: function() { 30 | this.version = this.pkg.version; 31 | if ( this.name ) { 32 | this.name = this._.titleize( this.name.split('-').join(' ') ); 33 | this.nameslug = this._.slugify( this.name ); 34 | } 35 | this.pluginname = this.rc.name; 36 | this.widgetname = this.pluginname + ' ' + this._.capitalize( this.name ); 37 | this.classname = this.rc.classprefix + this._wpClassify( this.name ); 38 | this.mainclassname = this._wpClassify( this.pluginname ); 39 | this.slug = this.rc.slug; 40 | this.classslug = this._.underscored( this._wpClassify( this.name ) ); 41 | this.widgetslug = this.slug + '-' + this._.slugify( this.name ); 42 | this.widgetregister = this._.underscored( this.slug + ' register ' + this.name ); 43 | } 44 | }, 45 | 46 | prompting: function () { 47 | var done = this.async(); 48 | 49 | var prompts = []; 50 | 51 | if ( !this.version ) { 52 | prompts.push({ 53 | type : 'input', 54 | name : 'version', 55 | message: 'Version', 56 | default: '0.1.0' 57 | }); 58 | } 59 | 60 | if ( !this.name ) { 61 | prompts.push({ 62 | type : 'input', 63 | name : 'name', 64 | message: 'Widget Name', 65 | default: 'basic-widget' 66 | }); 67 | } 68 | 69 | if ( !this.pluginname ) { 70 | prompts.push({ 71 | type : 'input', 72 | name : 'pluginname', 73 | message: 'Plugin Name', 74 | default: 'WDS Client Plugin' 75 | }); 76 | } 77 | 78 | if ( prompts.length > 0 ) { 79 | this.log( 'Missing some info about the original plugin, help me out?' ); 80 | this.prompt(prompts, function (props) { 81 | if ( props.version ) { 82 | this.version = props.version; 83 | } 84 | 85 | if ( props.name ) { 86 | this.name = this._.titleize( props.name.split('-').join(' ') ); 87 | this.nameslug = this._.slugify( this.name ); 88 | } 89 | 90 | if ( props.pluginname ) { 91 | this.pluginname = props.pluginname; 92 | this.slug = this._.slugify( props.pluginname ); 93 | } 94 | 95 | if ( props.name || props.pluginname ) { 96 | this.widgetname = this.pluginname + ' ' + this._.capitalize( this.name ); 97 | this.classname = this._wpClassPrefix( this.pluginname ) + this._wpClassify( this.name ); 98 | this.widgetslug = this.slug + '-' + this._.slugify( this.name ); 99 | this.widgetprefix = this._.underscored( this.slug + ' ' + this.name ); 100 | } 101 | 102 | done(); 103 | }.bind(this)); 104 | } else { 105 | done(); 106 | } 107 | }, 108 | 109 | writing: function () { 110 | this.fs.copyTpl( 111 | this.templatePath('widget.php'), 112 | this.destinationPath('includes/class-' + this._.slugify( this.name ) + '.php'), 113 | this 114 | ); 115 | 116 | if ( !this.rc.notests ) { 117 | this.fs.copyTpl( 118 | this.templatePath('tests.php'), 119 | this.destinationPath('tests/test-' + this._.slugify( this.name ) + '.php'), 120 | this 121 | ); 122 | } 123 | 124 | this._addIncludeClass( this._.slugify( this.name ), this.classname, this.version ); 125 | } 126 | }); 127 | -------------------------------------------------------------------------------- /widget/templates/tests.php: -------------------------------------------------------------------------------- 1 | Tests. 4 | * 5 | * @since <%= version %> 6 | * @package <%= mainclassname %> 7 | */ 8 | 9 | /** 10 | * <%= widgetname %> Tests. 11 | * 12 | * @since <%= version %> 13 | */ 14 | class <%= classname %>_Test extends WP_UnitTestCase { // @codingStandardsIgnoreLine 15 | 16 | /** 17 | * Test if our class exists. 18 | * 19 | * @since <%= version %> 20 | */ 21 | public function test_class_exists() { 22 | $this->assertTrue( class_exists( '<%= classname %>' ) ); 23 | } 24 | 25 | /** 26 | * Test that we can access our class through our helper function. 27 | * 28 | * @since <%= version %> 29 | */ 30 | public function test_class_access() { 31 | $this->assertInstanceOf( '<%= classname %>', <%= rc.prefix %>()-><%= classslug %> ); // @codingStandardsIgnoreLine 32 | } 33 | 34 | /** 35 | * Replace this with some actual testing code. 36 | * 37 | * @since <%= version %> 38 | */ 39 | public function test_sample() { 40 | $this->assertTrue( true ); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /widget/templates/widget.php: -------------------------------------------------------------------------------- 1 | . 4 | * 5 | * @since <%= version %> 6 | * @package <%= mainclassname %> 7 | */ 8 | 9 | /** 10 | * <%= widgetname %> class. 11 | * 12 | * @since <%= version %> 13 | */ 14 | class <%= classname %> extends WP_Widget { // @codingStandardsIgnoreLine 15 | 16 | /** 17 | * Unique identifier for this widget. 18 | * 19 | * Will also serve as the widget class. 20 | * 21 | * @var string 22 | * @since <%= version %> 23 | */ 24 | protected $widget_slug = '<%= widgetslug %>'; 25 | 26 | 27 | /** 28 | * Widget name displayed in Widgets dashboard. 29 | * Set in __construct since __() shouldn't take a variable. 30 | * 31 | * @var string 32 | * @since <%= version %> 33 | */ 34 | protected $widget_name = ''; 35 | 36 | 37 | /** 38 | * Default widget title displayed in Widgets dashboard. 39 | * Set in __construct since __() shouldn't take a variable. 40 | * 41 | * @var string 42 | * @since <%= version %> 43 | */ 44 | protected $default_widget_title = ''; 45 | 46 | /** 47 | * Construct widget class. 48 | * 49 | * @since <%= version %> 50 | */ 51 | public function __construct() { 52 | 53 | $this->widget_name = esc_html__( '<%= widgetname %>', '<%= slug %>' ); 54 | $this->default_widget_title = esc_html__( '<%= widgetname %>', '<%= slug %>' ); 55 | 56 | parent::__construct( 57 | $this->widget_slug, 58 | $this->widget_name, 59 | array( 60 | 'classname' => $this->widget_slug, 61 | 'description' => esc_html__( 'A widget boilerplate description.', '<%= slug %>' ), 62 | ) 63 | ); 64 | 65 | // Clear cache on save. 66 | add_action( 'save_post', array( $this, 'flush_widget_cache' ) ); 67 | add_action( 'deleted_post', array( $this, 'flush_widget_cache' ) ); 68 | add_action( 'switch_theme', array( $this, 'flush_widget_cache' ) ); 69 | } 70 | 71 | /** 72 | * Delete this widget's cache. 73 | * 74 | * Note: Could also delete any transients 75 | * delete_transient( 'some-transient-generated-by-this-widget' ); 76 | * 77 | * @since <%= version %> 78 | */ 79 | public function flush_widget_cache() { 80 | wp_cache_delete( $this->widget_slug, 'widget' ); 81 | } 82 | 83 | /** 84 | * Front-end display of widget. 85 | * 86 | * @since <%= version %> 87 | * 88 | * @param array $args The widget arguments set up when a sidebar is registered. 89 | * @param array $instance The widget settings as set by user. 90 | */ 91 | public function widget( $args, $instance ) { 92 | 93 | // Set widget attributes. 94 | $atts = array( 95 | 'before_widget' => $args['before_widget'], 96 | 'after_widget' => $args['after_widget'], 97 | 'before_title' => $args['before_title'], 98 | 'after_title' => $args['after_title'], 99 | 'title' => $instance['title'], 100 | 'text' => $instance['text'], 101 | ); 102 | 103 | // Display the widget. 104 | echo $this->get_widget( $atts ); // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped 105 | } 106 | 107 | /** 108 | * Return the widget output 109 | * 110 | * @since <%= version %> 111 | * 112 | * @param array $atts Array of widget args. 113 | * @return string Widget output 114 | */ 115 | public function get_widget( $atts ) { 116 | 117 | $defaults = array( 118 | 'before_widget' => '', 119 | 'after_widget' => '', 120 | 'before_title' => '', 121 | 'after_title' => '', 122 | 'title' => '', 123 | 'text' => '', 124 | ); 125 | 126 | // Start an output buffer. 127 | ob_start(); 128 | 129 | // Start widget markup. 130 | echo $atts['before_widget']; // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped 131 | 132 | // Maybe display widget title. 133 | echo ( $atts['title'] ) ? $atts['before_title'] . esc_html( $atts['title'] ) . $atts['after_title'] : ''; // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped 134 | 135 | // Display widget text. 136 | echo wpautop( wp_kses_post( $atts['text'] ) ); // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped 137 | 138 | // End the widget markup. 139 | echo $atts['after_widget']; // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped 140 | 141 | // Return the output buffer. 142 | return ob_get_clean(); 143 | } 144 | 145 | /** 146 | * Update form values as they are saved. 147 | * 148 | * @since <%= version %> 149 | * 150 | * @param array $new_instance New settings for this instance as input by the user. 151 | * @param array $old_instance Old settings for this instance. 152 | * @return array Settings to save or bool false to cancel saving. 153 | */ 154 | public function update( $new_instance, $old_instance ) { 155 | 156 | // Previously saved values. 157 | $instance = $old_instance; 158 | 159 | // Sanity check new data existing. 160 | $title = isset( $new_instance['title'] ) ? $new_instance['title'] : ''; 161 | $text = isset( $new_instance['text'] ) ? $new_instance['text'] : ''; 162 | 163 | // Sanitize title before saving to database. 164 | $instance['title'] = sanitize_text_field( $title ); 165 | 166 | // Sanitize text before saving to database. 167 | if ( current_user_can( 'unfiltered_html' ) ) { 168 | $instance['text'] = force_balance_tags( $text ); 169 | } else { 170 | $instance['text'] = stripslashes( wp_filter_post_kses( addslashes( $text ) ) ); 171 | } 172 | 173 | // Flush cache. 174 | $this->flush_widget_cache(); 175 | 176 | return $instance; 177 | } 178 | 179 | /** 180 | * Back-end widget form with defaults. 181 | * 182 | * @since <%= version %> 183 | * 184 | * @param array $instance Current settings. 185 | */ 186 | public function form( $instance ) { 187 | 188 | // Set defaults. 189 | $defaults = array( 190 | 'title' => $this->default_widget_title, 191 | 'text' => '', 192 | ); 193 | 194 | // Parse args. 195 | $instance = wp_parse_args( (array) $instance, $defaults ); 196 | ?> 197 |

198 | 201 | 202 |

203 |

204 | 207 | 208 |

209 |

210 | ' ); ?> 211 |

212 | () { // @codingStandardsIgnoreLine 220 | register_widget( '<%= classname %>' ); 221 | } 222 | add_action( 'widgets_init', '<%= widgetregister %>' ); 223 | --------------------------------------------------------------------------------