├── .distignore ├── .gitignore ├── .husky └── pre-commit ├── .prettierignore ├── .prettierrc.json ├── assets ├── admin │ ├── css │ │ └── prefix-admin.css │ └── js │ │ └── prefix-admin.js └── public │ ├── css │ └── prefix-public.css │ └── js │ └── prefix-public.js ├── bin └── dist.sh ├── composer.json ├── composer.lock ├── includes ├── Bootstrap │ ├── AdminEnqueues.php │ ├── FrontendEnqueues.php │ ├── I18n.php │ ├── Loader.php │ ├── Main.php │ └── SetupCron.php ├── Controllers │ └── .gitkeep ├── Helpers │ └── Functions.php ├── Models │ └── .gitkeep ├── Notices │ ├── Admin.php │ ├── Loader.php │ ├── Notice.php │ ├── ReviewNotices.php │ └── UpsellsNotices.php ├── RootActivator.php ├── RootDeactivator.php ├── Traits │ └── PluginInfo.php └── Views │ └── .gitkeep ├── index.php ├── package-lock.json ├── package.json ├── phpcs.xml ├── plugin-boilerplate.php ├── readme.md ├── readme.txt └── uninstall.php /.distignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | .parcel-cache 3 | .git 4 | .DS_Store 5 | .distignore 6 | .gitignore 7 | .husky 8 | .prettierignore 9 | .prettierrc.json 10 | .github 11 | .wordpress-org 12 | .idea 13 | composer.json 14 | composer.lock 15 | package.json 16 | package-lock.json 17 | node_modules 18 | artifact 19 | dist 20 | bin 21 | phpcs.xml 22 | logs 23 | assets/admin/js/*.js 24 | assets/public/js/*.js -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .parcel-cache 3 | .vscode 4 | .idea 5 | artifact 6 | dist 7 | logs 8 | node_modules 9 | vendor 10 | assets/admin/js/build/ 11 | assets/public/js/build/ -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npm run format 5 | composer run format -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | assets/admin/js/build/ 2 | assets/public/js/build/ 3 | assets/img/ 4 | *.php -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /assets/admin/css/prefix-admin.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UVLabs/wordpress-plugin-boilerplate/32251d5d207e4f2376834f1cbc27fe125f363b52/assets/admin/css/prefix-admin.css -------------------------------------------------------------------------------- /assets/admin/js/prefix-admin.js: -------------------------------------------------------------------------------- 1 | (function ($) { 2 | "use strict"; 3 | 4 | /** 5 | * All of the code for your public-facing JavaScript source 6 | * should reside in this file. 7 | * 8 | * Note: It has been assumed you will write jQuery code here, so the 9 | * $ function reference has been prepared for usage within the scope 10 | * of this function. 11 | * 12 | * This enables you to define handlers, for when the DOM is ready: 13 | * 14 | * $(function() { 15 | * 16 | * }); 17 | * 18 | * When the window is loaded: 19 | * 20 | * $( window ).load(function() { 21 | * 22 | * }); 23 | * 24 | * ...and/or other possibilities. 25 | * 26 | * Ideally, it is not considered best practise to attach more than a 27 | * single DOM-ready or window-load handler for a particular page. 28 | * Although scripts in the WordPress core, Plugins and Themes may be 29 | * practising this, we should strive to set a better example in our own work. 30 | */ 31 | 32 | $(document).ready(function () {}); 33 | })(jQuery); 34 | -------------------------------------------------------------------------------- /assets/public/css/prefix-public.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UVLabs/wordpress-plugin-boilerplate/32251d5d207e4f2376834f1cbc27fe125f363b52/assets/public/css/prefix-public.css -------------------------------------------------------------------------------- /assets/public/js/prefix-public.js: -------------------------------------------------------------------------------- 1 | (function ($) { 2 | "use strict"; 3 | 4 | /** 5 | * All of the code for your public-facing JavaScript source 6 | * should reside in this file. 7 | * 8 | * Note: It has been assumed you will write jQuery code here, so the 9 | * $ function reference has been prepared for usage within the scope 10 | * of this function. 11 | * 12 | * This enables you to define handlers, for when the DOM is ready: 13 | * 14 | * $(function() { 15 | * 16 | * }); 17 | * 18 | * When the window is loaded: 19 | * 20 | * $( window ).load(function() { 21 | * 22 | * }); 23 | * 24 | * ...and/or other possibilities. 25 | * 26 | * Ideally, it is not considered best practise to attach more than a 27 | * single DOM-ready or window-load handler for a particular page. 28 | * Although scripts in the WordPress core, Plugins and Themes may be 29 | * practising this, we should strive to set a better example in our own work. 30 | */ 31 | 32 | $(document).ready(function () {}); 33 | })(jQuery); 34 | -------------------------------------------------------------------------------- /bin/dist.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Prepare plugin for uploading to wp.org. 4 | 5 | # Start fresh 6 | rm -rf dist 7 | rm -rf artifact 8 | 9 | # Make our directories 10 | mkdir -p dist 11 | mkdir -p artifact 12 | 13 | # Remove vendor folder so we can redownload without dev dependencies. 14 | rm -rf vendor 15 | 16 | # Install without dev dependencies and optimize composer. 17 | composer install --no-dev -o 18 | composer dumpautoload -o 19 | 20 | # Run Prettier 21 | npm run format 22 | 23 | # Build our JS files with parcel 24 | npm run build 25 | 26 | # Sync dist folder 27 | rsync -acvP --delete --exclude-from=".distignore" ./ "./dist" 28 | 29 | #Change to our dist folder and zip to artifact folder 30 | (cd dist && zip -r ../artifact/prefix.zip .) 31 | 32 | # Delete dist folder 33 | rm -rf dist 34 | 35 | # Re-add dev dependencies 36 | composer install 37 | composer dumpautoload 38 | 39 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "lint" : "mkdir -p logs; vendor/bin/phpcs -s > ./logs/log.txt", 4 | "format": "vendor/bin/phpcbf -p", 5 | "dist": "sh bin/dist.sh" 6 | }, 7 | "require-dev": { 8 | "dealerdirect/phpcodesniffer-composer-installer": "0.7.1", 9 | "wp-coding-standards/wpcs": "2.3", 10 | "suin/phpcs-psr4-sniff": "^3.0" 11 | }, 12 | "autoload":{ 13 | "psr-4": { 14 | "Root\\" : "includes/" 15 | } 16 | }, 17 | "config": { 18 | "allow-plugins": { 19 | "dealerdirect/phpcodesniffer-composer-installer": true 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "8cbff63dc670f52b3505139ed181a4ab", 8 | "packages": [], 9 | "packages-dev": [ 10 | { 11 | "name": "dealerdirect/phpcodesniffer-composer-installer", 12 | "version": "v0.7.1", 13 | "source": { 14 | "type": "git", 15 | "url": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer.git", 16 | "reference": "fe390591e0241955f22eb9ba327d137e501c771c" 17 | }, 18 | "dist": { 19 | "type": "zip", 20 | "url": "https://api.github.com/repos/Dealerdirect/phpcodesniffer-composer-installer/zipball/fe390591e0241955f22eb9ba327d137e501c771c", 21 | "reference": "fe390591e0241955f22eb9ba327d137e501c771c", 22 | "shasum": "" 23 | }, 24 | "require": { 25 | "composer-plugin-api": "^1.0 || ^2.0", 26 | "php": ">=5.3", 27 | "squizlabs/php_codesniffer": "^2.0 || ^3.0 || ^4.0" 28 | }, 29 | "require-dev": { 30 | "composer/composer": "*", 31 | "phpcompatibility/php-compatibility": "^9.0", 32 | "sensiolabs/security-checker": "^4.1.0" 33 | }, 34 | "type": "composer-plugin", 35 | "extra": { 36 | "class": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" 37 | }, 38 | "autoload": { 39 | "psr-4": { 40 | "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" 41 | } 42 | }, 43 | "notification-url": "https://packagist.org/downloads/", 44 | "license": [ 45 | "MIT" 46 | ], 47 | "authors": [ 48 | { 49 | "name": "Franck Nijhof", 50 | "email": "franck.nijhof@dealerdirect.com", 51 | "homepage": "http://www.frenck.nl", 52 | "role": "Developer / IT Manager" 53 | } 54 | ], 55 | "description": "PHP_CodeSniffer Standards Composer Installer Plugin", 56 | "homepage": "http://www.dealerdirect.com", 57 | "keywords": [ 58 | "PHPCodeSniffer", 59 | "PHP_CodeSniffer", 60 | "code quality", 61 | "codesniffer", 62 | "composer", 63 | "installer", 64 | "phpcs", 65 | "plugin", 66 | "qa", 67 | "quality", 68 | "standard", 69 | "standards", 70 | "style guide", 71 | "stylecheck", 72 | "tests" 73 | ], 74 | "support": { 75 | "issues": "https://github.com/dealerdirect/phpcodesniffer-composer-installer/issues", 76 | "source": "https://github.com/dealerdirect/phpcodesniffer-composer-installer" 77 | }, 78 | "time": "2020-12-07T18:04:37+00:00" 79 | }, 80 | { 81 | "name": "phpstan/phpdoc-parser", 82 | "version": "1.4.5", 83 | "source": { 84 | "type": "git", 85 | "url": "https://github.com/phpstan/phpdoc-parser.git", 86 | "reference": "129a63b3bc7caeb593c224c41f420675e63cfefc" 87 | }, 88 | "dist": { 89 | "type": "zip", 90 | "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/129a63b3bc7caeb593c224c41f420675e63cfefc", 91 | "reference": "129a63b3bc7caeb593c224c41f420675e63cfefc", 92 | "shasum": "" 93 | }, 94 | "require": { 95 | "php": "^7.2 || ^8.0" 96 | }, 97 | "require-dev": { 98 | "php-parallel-lint/php-parallel-lint": "^1.2", 99 | "phpstan/extension-installer": "^1.0", 100 | "phpstan/phpstan": "^1.5", 101 | "phpstan/phpstan-strict-rules": "^1.0", 102 | "phpunit/phpunit": "^9.5", 103 | "symfony/process": "^5.2" 104 | }, 105 | "type": "library", 106 | "autoload": { 107 | "psr-4": { 108 | "PHPStan\\PhpDocParser\\": [ 109 | "src/" 110 | ] 111 | } 112 | }, 113 | "notification-url": "https://packagist.org/downloads/", 114 | "license": [ 115 | "MIT" 116 | ], 117 | "description": "PHPDoc parser with support for nullable, intersection and generic types", 118 | "support": { 119 | "issues": "https://github.com/phpstan/phpdoc-parser/issues", 120 | "source": "https://github.com/phpstan/phpdoc-parser/tree/1.4.5" 121 | }, 122 | "time": "2022-04-22T11:11:01+00:00" 123 | }, 124 | { 125 | "name": "slevomat/coding-standard", 126 | "version": "7.1", 127 | "source": { 128 | "type": "git", 129 | "url": "https://github.com/slevomat/coding-standard.git", 130 | "reference": "b521bd358b5f7a7d69e9637fd139e036d8adeb6f" 131 | }, 132 | "dist": { 133 | "type": "zip", 134 | "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/b521bd358b5f7a7d69e9637fd139e036d8adeb6f", 135 | "reference": "b521bd358b5f7a7d69e9637fd139e036d8adeb6f", 136 | "shasum": "" 137 | }, 138 | "require": { 139 | "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7", 140 | "php": "^7.2 || ^8.0", 141 | "phpstan/phpdoc-parser": "^1.4.1", 142 | "squizlabs/php_codesniffer": "^3.6.2" 143 | }, 144 | "require-dev": { 145 | "phing/phing": "2.17.2", 146 | "php-parallel-lint/php-parallel-lint": "1.3.2", 147 | "phpstan/phpstan": "1.4.10|1.5.2", 148 | "phpstan/phpstan-deprecation-rules": "1.0.0", 149 | "phpstan/phpstan-phpunit": "1.0.0|1.1.0", 150 | "phpstan/phpstan-strict-rules": "1.1.0", 151 | "phpunit/phpunit": "7.5.20|8.5.21|9.5.19" 152 | }, 153 | "type": "phpcodesniffer-standard", 154 | "extra": { 155 | "branch-alias": { 156 | "dev-master": "7.x-dev" 157 | } 158 | }, 159 | "autoload": { 160 | "psr-4": { 161 | "SlevomatCodingStandard\\": "SlevomatCodingStandard" 162 | } 163 | }, 164 | "notification-url": "https://packagist.org/downloads/", 165 | "license": [ 166 | "MIT" 167 | ], 168 | "description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.", 169 | "support": { 170 | "issues": "https://github.com/slevomat/coding-standard/issues", 171 | "source": "https://github.com/slevomat/coding-standard/tree/7.1" 172 | }, 173 | "funding": [ 174 | { 175 | "url": "https://github.com/kukulich", 176 | "type": "github" 177 | }, 178 | { 179 | "url": "https://tidelift.com/funding/github/packagist/slevomat/coding-standard", 180 | "type": "tidelift" 181 | } 182 | ], 183 | "time": "2022-03-29T12:44:16+00:00" 184 | }, 185 | { 186 | "name": "squizlabs/php_codesniffer", 187 | "version": "3.6.2", 188 | "source": { 189 | "type": "git", 190 | "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", 191 | "reference": "5e4e71592f69da17871dba6e80dd51bce74a351a" 192 | }, 193 | "dist": { 194 | "type": "zip", 195 | "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/5e4e71592f69da17871dba6e80dd51bce74a351a", 196 | "reference": "5e4e71592f69da17871dba6e80dd51bce74a351a", 197 | "shasum": "" 198 | }, 199 | "require": { 200 | "ext-simplexml": "*", 201 | "ext-tokenizer": "*", 202 | "ext-xmlwriter": "*", 203 | "php": ">=5.4.0" 204 | }, 205 | "require-dev": { 206 | "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" 207 | }, 208 | "bin": [ 209 | "bin/phpcs", 210 | "bin/phpcbf" 211 | ], 212 | "type": "library", 213 | "extra": { 214 | "branch-alias": { 215 | "dev-master": "3.x-dev" 216 | } 217 | }, 218 | "notification-url": "https://packagist.org/downloads/", 219 | "license": [ 220 | "BSD-3-Clause" 221 | ], 222 | "authors": [ 223 | { 224 | "name": "Greg Sherwood", 225 | "role": "lead" 226 | } 227 | ], 228 | "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", 229 | "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", 230 | "keywords": [ 231 | "phpcs", 232 | "standards" 233 | ], 234 | "support": { 235 | "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", 236 | "source": "https://github.com/squizlabs/PHP_CodeSniffer", 237 | "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" 238 | }, 239 | "time": "2021-12-12T21:44:58+00:00" 240 | }, 241 | { 242 | "name": "suin/phpcs-psr4-sniff", 243 | "version": "v3.0.0", 244 | "source": { 245 | "type": "git", 246 | "url": "https://github.com/suin/phpcs-psr4-sniff.git", 247 | "reference": "b000ca1e3d04c9876b39c2e56859760b93dfc84d" 248 | }, 249 | "dist": { 250 | "type": "zip", 251 | "url": "https://api.github.com/repos/suin/phpcs-psr4-sniff/zipball/b000ca1e3d04c9876b39c2e56859760b93dfc84d", 252 | "reference": "b000ca1e3d04c9876b39c2e56859760b93dfc84d", 253 | "shasum": "" 254 | }, 255 | "require": { 256 | "ext-json": "*", 257 | "php": ">=7.1", 258 | "slevomat/coding-standard": ">=4.7 <8.0.0", 259 | "squizlabs/php_codesniffer": ">=3.3 <4.0.0" 260 | }, 261 | "type": "phpcodesniffer-standard", 262 | "autoload": { 263 | "psr-0": { 264 | "Suin\\Sniffs\\Classes\\": "src" 265 | } 266 | }, 267 | "notification-url": "https://packagist.org/downloads/", 268 | "license": [ 269 | "MIT" 270 | ], 271 | "authors": [ 272 | { 273 | "name": "suin", 274 | "email": "suinyeze@gmail.com", 275 | "homepage": "https://github.com/suin", 276 | "role": "Developer" 277 | } 278 | ], 279 | "description": "PHP_CodeSniffer sniff that checks class name matches PSR-4 project structure.", 280 | "homepage": "https://github.com/suin/php", 281 | "keywords": [ 282 | "PSR-4", 283 | "coding-standards", 284 | "coding-style", 285 | "namespace", 286 | "php-codesniffer", 287 | "phpcs", 288 | "static-analysis" 289 | ], 290 | "support": { 291 | "issues": "https://github.com/suin/php/issues", 292 | "source": "https://github.com/suin/phpcs-psr4-sniff/tree/v3.0.0" 293 | }, 294 | "time": "2021-06-02T06:16:24+00:00" 295 | }, 296 | { 297 | "name": "wp-coding-standards/wpcs", 298 | "version": "2.3.0", 299 | "source": { 300 | "type": "git", 301 | "url": "https://github.com/WordPress/WordPress-Coding-Standards.git", 302 | "reference": "7da1894633f168fe244afc6de00d141f27517b62" 303 | }, 304 | "dist": { 305 | "type": "zip", 306 | "url": "https://api.github.com/repos/WordPress/WordPress-Coding-Standards/zipball/7da1894633f168fe244afc6de00d141f27517b62", 307 | "reference": "7da1894633f168fe244afc6de00d141f27517b62", 308 | "shasum": "" 309 | }, 310 | "require": { 311 | "php": ">=5.4", 312 | "squizlabs/php_codesniffer": "^3.3.1" 313 | }, 314 | "require-dev": { 315 | "dealerdirect/phpcodesniffer-composer-installer": "^0.5 || ^0.6", 316 | "phpcompatibility/php-compatibility": "^9.0", 317 | "phpcsstandards/phpcsdevtools": "^1.0", 318 | "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" 319 | }, 320 | "suggest": { 321 | "dealerdirect/phpcodesniffer-composer-installer": "^0.6 || This Composer plugin will sort out the PHPCS 'installed_paths' automatically." 322 | }, 323 | "type": "phpcodesniffer-standard", 324 | "notification-url": "https://packagist.org/downloads/", 325 | "license": [ 326 | "MIT" 327 | ], 328 | "authors": [ 329 | { 330 | "name": "Contributors", 331 | "homepage": "https://github.com/WordPress/WordPress-Coding-Standards/graphs/contributors" 332 | } 333 | ], 334 | "description": "PHP_CodeSniffer rules (sniffs) to enforce WordPress coding conventions", 335 | "keywords": [ 336 | "phpcs", 337 | "standards", 338 | "wordpress" 339 | ], 340 | "support": { 341 | "issues": "https://github.com/WordPress/WordPress-Coding-Standards/issues", 342 | "source": "https://github.com/WordPress/WordPress-Coding-Standards", 343 | "wiki": "https://github.com/WordPress/WordPress-Coding-Standards/wiki" 344 | }, 345 | "time": "2020-05-13T23:57:56+00:00" 346 | } 347 | ], 348 | "aliases": [], 349 | "minimum-stability": "stable", 350 | "stability-flags": [], 351 | "prefer-stable": false, 352 | "prefer-lowest": false, 353 | "platform": [], 354 | "platform-dev": [], 355 | "plugin-api-version": "2.1.0" 356 | } 357 | -------------------------------------------------------------------------------- /includes/Bootstrap/AdminEnqueues.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | 12 | namespace Root\Bootstrap; 13 | 14 | if ( ! defined( 'ABSPATH' ) ) { 15 | exit; 16 | } 17 | 18 | use Root\Helpers\Functions; 19 | 20 | /** 21 | * Class responsible for methods to do with admin enqueing of JS and CSS. 22 | * 23 | * @package Root\Bootstrap 24 | * @since 1.0.0 25 | */ 26 | class AdminEnqueues { 27 | 28 | /** 29 | * The ID of this plugin. 30 | * 31 | * @since 1.0.0 32 | * @access private 33 | * @var string $plugin_name The ID of this plugin. 34 | */ 35 | private $plugin_name; 36 | 37 | /** 38 | * The version of this plugin. 39 | * 40 | * @since 1.0.0 41 | * @access private 42 | * @var string $version The current version of this plugin. 43 | */ 44 | private $version; 45 | 46 | /** 47 | * Burst cache if on Local dev environment. 48 | * 49 | * @var int 50 | * @since 1.0.0 51 | */ 52 | private $maybe_burst_cache; 53 | 54 | /** 55 | * Initialize the class and set its properties. 56 | * 57 | * @since 1.0.0 58 | */ 59 | public function __construct() { 60 | $this->plugin_name = PREFIX_PLUGIN_NAME; 61 | $this->version = PREFIX_VERSION; 62 | $this->maybe_burst_cache = ( defined( 'PREFIX_DEBUG' ) && PREFIX_DEBUG ) ? time() : ''; 63 | } 64 | 65 | /** 66 | * Register the stylesheets for the admin area. 67 | * 68 | * @since 1.0.0 69 | */ 70 | public function enqueueStyles() { 71 | wp_enqueue_style( $this->plugin_name, PREFIX_PLUGIN_ASSETS_PATH_URL . 'admin/css/prefix-admin.css', array(), $this->version . $this->maybe_burst_cache, 'all' ); 72 | } 73 | 74 | /** 75 | * Register the JavaScript for the admin area. 76 | * 77 | * @since 1.0.0 78 | */ 79 | public function enqueueScripts() { 80 | $path = ! ( PREFIX_DEBUG ) ? 'build/' : ''; 81 | wp_enqueue_script( $this->plugin_name, PREFIX_PLUGIN_ASSETS_PATH_URL . 'admin/js/' . $path . 'prefix-admin.js', array( 'jquery' ), $this->version . $this->maybe_burst_cache, false ); 82 | } 83 | 84 | /** 85 | * Turn a script into a module so that we can make use of JS components. 86 | * 87 | * @param string $tag 88 | * @param string $handle 89 | * @param string $src 90 | * @return string 91 | * @since 1.0.0 92 | */ 93 | public function getScriptsAsModules( string $tag, string $handle, string $src ) { 94 | 95 | if ( PREFIX_DEBUG === false ) { // Live scripts are built in Parcel so no need to make them modules. 96 | return $tag; 97 | } 98 | 99 | $modules_handlers = array( 100 | $this->plugin_name, // Name of default js handler 101 | // $this->plugin_name . '-my-other-script', // You can add other script handlers. 102 | ); 103 | 104 | if ( ! in_array( $handle, $modules_handlers, true ) ) { 105 | return $tag; 106 | } 107 | 108 | return Functions::makeScriptsModules( $tag, $handle, $src ); 109 | } 110 | 111 | } 112 | -------------------------------------------------------------------------------- /includes/Bootstrap/FrontendEnqueues.php: -------------------------------------------------------------------------------- 1 | 19 | */ 20 | namespace Root\Bootstrap; 21 | 22 | if ( ! defined( 'ABSPATH' ) ) { 23 | exit; 24 | } 25 | 26 | use Root\Helpers\Functions; 27 | 28 | /** 29 | * Class responsible for methods to do with frontend enqueing of JS and CSS. 30 | * 31 | * @package Root\Bootstrap 32 | * @since 1.0.0 33 | */ 34 | class FrontendEnqueues { 35 | 36 | /** 37 | * The ID of this plugin. 38 | * 39 | * @since 1.0.0 40 | * @access private 41 | * @var string $plugin_name The ID of this plugin. 42 | */ 43 | private $plugin_name; 44 | 45 | /** 46 | * The version of this plugin. 47 | * 48 | * @since 1.0.0 49 | * @access private 50 | * @var string $version The current version of this plugin. 51 | */ 52 | private $version; 53 | 54 | /** 55 | * Burst cache if on Local dev environment. 56 | * 57 | * @var int 58 | * @since 1.0.0 59 | */ 60 | private $maybe_burst_cache; 61 | 62 | /** 63 | * Initialize the class and set its properties. 64 | * 65 | * @since 1.0.0 66 | */ 67 | public function __construct() { 68 | $this->plugin_name = PREFIX_PLUGIN_NAME; 69 | $this->version = PREFIX_VERSION; 70 | $this->maybe_burst_cache = ( defined( 'PREFIX_DEBUG' ) && PREFIX_DEBUG ) ? time() : ''; 71 | } 72 | 73 | /** 74 | * Register the stylesheets for the public-facing side of the site. 75 | * 76 | * @since 1.0.0 77 | */ 78 | public function enqueueStyles() { 79 | wp_enqueue_style( $this->plugin_name, PREFIX_PLUGIN_ASSETS_PATH_URL . 'public/css/prefix-public.css', array(), $this->version . $this->maybe_burst_cache, 'all' ); 80 | } 81 | 82 | /** 83 | * Register the JavaScript for the public-facing side of the site. 84 | * 85 | * @since 1.0.0 86 | */ 87 | public function enqueueScripts() { 88 | $path = ! ( PREFIX_DEBUG ) ? 'build/' : ''; 89 | wp_enqueue_script( $this->plugin_name, PREFIX_PLUGIN_ASSETS_PATH_URL . 'public/js/' . $path . 'prefix-public.js', array( 'jquery' ), $this->version . $this->maybe_burst_cache, false ); 90 | } 91 | 92 | /** 93 | * Turn a script into a module so that we can make use of JS components. 94 | * 95 | * @param string $tag 96 | * @param string $handle 97 | * @param string $src 98 | * @return string 99 | * @since 1.0.0 100 | */ 101 | public function getScriptsAsModules( string $tag, string $handle, string $src ) { 102 | 103 | if ( PREFIX_DEBUG === false ) { // Live scripts are built in Parcel so no need to make them modules. 104 | return $tag; 105 | } 106 | 107 | $modules_handlers = array( 108 | $this->plugin_name, 109 | // $this->plugin_name . '-my-other-script', // You can add other script handlers. 110 | ); 111 | 112 | if ( ! in_array( $handle, $modules_handlers, true ) ) { 113 | return $tag; 114 | } 115 | 116 | return Functions::makeScriptsModules( $tag, $handle, $src ); 117 | } 118 | 119 | } 120 | -------------------------------------------------------------------------------- /includes/Bootstrap/I18n.php: -------------------------------------------------------------------------------- 1 | 23 | */ 24 | namespace Root\Bootstrap; 25 | 26 | if ( ! defined( 'ABSPATH' ) ) { 27 | exit; 28 | } 29 | 30 | /** 31 | * Class responsible for setting up text domain. 32 | * 33 | * @package Root\Bootstrap 34 | */ 35 | class I18n { 36 | 37 | /** 38 | * Load the plugin text domain for translation. 39 | * 40 | * @since 1.0.0 41 | */ 42 | public function loadPluginTextdomain() { 43 | 44 | load_plugin_textdomain( 45 | 'text-domain', 46 | false, 47 | dirname( dirname( plugin_basename( __FILE__ ) ) ) . '/languages/' 48 | ); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /includes/Bootstrap/Loader.php: -------------------------------------------------------------------------------- 1 | 26 | */ 27 | class Loader { 28 | 29 | /** 30 | * The array of actions registered with WordPress. 31 | * 32 | * @since 1.0.0 33 | * @access protected 34 | * @var array $actions The actions registered with WordPress to fire when the plugin loads. 35 | */ 36 | protected $actions; 37 | 38 | /** 39 | * The array of filters registered with WordPress. 40 | * 41 | * @since 1.0.0 42 | * @access protected 43 | * @var array $filters The filters registered with WordPress to fire when the plugin loads. 44 | */ 45 | protected $filters; 46 | 47 | /** 48 | * Initialize the collections used to maintain the actions and filters. 49 | * 50 | * @since 1.0.0 51 | */ 52 | public function __construct() { 53 | $this->actions = array(); 54 | $this->filters = array(); 55 | } 56 | 57 | /** 58 | * Add a new action to the collection to be registered with WordPress. 59 | * 60 | * @since 1.0.0 61 | * @param string $hook The name of the WordPress action that is being registered. 62 | * @param object $component A reference to the instance of the object on which the action is defined. 63 | * @param string $callback The name of the function definition on the $component. 64 | * @param int $priority Optional. The priority at which the function should be fired. Default is 10. 65 | * @param int $accepted_args Optional. The number of arguments that should be passed to the $callback. Default is 1. 66 | */ 67 | public function add_action( $hook, $component, $callback, $priority = 10, $accepted_args = 1 ) { 68 | $this->actions = $this->add( $this->actions, $hook, $component, $callback, $priority, $accepted_args ); 69 | } 70 | 71 | /** 72 | * Add a new filter to the collection to be registered with WordPress. 73 | * 74 | * @since 1.0.0 75 | * @param string $hook The name of the WordPress filter that is being registered. 76 | * @param object $component A reference to the instance of the object on which the filter is defined. 77 | * @param string $callback The name of the function definition on the $component. 78 | * @param int $priority Optional. The priority at which the function should be fired. Default is 10. 79 | * @param int $accepted_args Optional. The number of arguments that should be passed to the $callback. Default is 1. 80 | */ 81 | public function add_filter( $hook, $component, $callback, $priority = 10, $accepted_args = 1 ) { 82 | $this->filters = $this->add( $this->filters, $hook, $component, $callback, $priority, $accepted_args ); 83 | } 84 | 85 | /** 86 | * A utility function that is used to register the actions and hooks into a single 87 | * collection. 88 | * 89 | * @since 1.0.0 90 | * @access private 91 | * @param array $hooks The collection of hooks that is being registered (that is, actions or filters). 92 | * @param string $hook The name of the WordPress filter that is being registered. 93 | * @param object $component A reference to the instance of the object on which the filter is defined. 94 | * @param string $callback The name of the function definition on the $component. 95 | * @param int $priority The priority at which the function should be fired. 96 | * @param int $accepted_args The number of arguments that should be passed to the $callback. 97 | * @return array The collection of actions and filters registered with WordPress. 98 | */ 99 | private function add( $hooks, $hook, $component, $callback, $priority, $accepted_args ) { 100 | 101 | $hooks[] = array( 102 | 'hook' => $hook, 103 | 'component' => $component, 104 | 'callback' => $callback, 105 | 'priority' => $priority, 106 | 'accepted_args' => $accepted_args, 107 | ); 108 | 109 | return $hooks; 110 | } 111 | 112 | /** 113 | * Register the filters and actions with WordPress. 114 | * 115 | * @since 1.0.0 116 | */ 117 | public function run() { 118 | 119 | foreach ( $this->filters as $hook ) { 120 | add_filter( $hook['hook'], array( $hook['component'], $hook['callback'] ), $hook['priority'], $hook['accepted_args'] ); 121 | } 122 | 123 | foreach ( $this->actions as $hook ) { 124 | add_action( $hook['hook'], array( $hook['component'], $hook['callback'] ), $hook['priority'], $hook['accepted_args'] ); 125 | } 126 | } 127 | 128 | } 129 | -------------------------------------------------------------------------------- /includes/Bootstrap/Main.php: -------------------------------------------------------------------------------- 1 | 26 | */ 27 | 28 | namespace Root\Bootstrap; 29 | 30 | if ( ! defined( 'ABSPATH' ) ) { 31 | exit; 32 | } 33 | 34 | /* 35 | use Root\Notices\Loader as NoticesLoader; 36 | use Root\Notices\Notice; 37 | */ 38 | 39 | /** 40 | * Class Main. 41 | * 42 | * Class responsible for firing public and admin hooks. 43 | */ 44 | class Main { 45 | 46 | /** 47 | * The loader that's responsible for maintaining and registering all hooks that power 48 | * the plugin. 49 | * 50 | * @since 1.0.0 51 | * @access protected 52 | * @var Loader $loader Maintains and registers all hooks for the plugin. 53 | */ 54 | protected $loader; 55 | 56 | /** 57 | * The unique identifier of this plugin. 58 | * 59 | * @since 1.0.0 60 | * @access protected 61 | * @var string $plugin_name The string used to uniquely identify this plugin. 62 | */ 63 | protected $plugin_name; 64 | 65 | /** 66 | * The current version of the plugin. 67 | * 68 | * @since 1.0.0 69 | * @access protected 70 | * @var string $version The current version of the plugin. 71 | */ 72 | protected $version; 73 | 74 | /** 75 | * Plugin instance 76 | * 77 | * @var mixed 78 | */ 79 | private static $instance; 80 | 81 | /** 82 | * Gets an instance of our plugin. 83 | * 84 | * @return Main() 85 | */ 86 | public static function getInstance() { 87 | if ( self::$instance === null ) { 88 | self::$instance = new self(); 89 | } 90 | 91 | return self::$instance; 92 | } 93 | 94 | /** 95 | * Define the core functionality of the plugin. 96 | * 97 | * Set the plugin name and the plugin version that can be used throughout the plugin. 98 | * Load the dependencies, define the locale, and set the hooks for the admin area and 99 | * the public-facing side of the site. 100 | * 101 | * @since 1.0.0 102 | */ 103 | private function __construct() { 104 | $this->version = PREFIX_VERSION; 105 | 106 | $this->plugin_name = PREFIX_PLUGIN_NAME; 107 | 108 | $this->loadDependencies(); 109 | $this->setLocale(); 110 | $this->defineAdminHooks(); 111 | $this->definePublicHooks(); 112 | } 113 | 114 | /** 115 | * Load the required dependencies for this plugin. 116 | * 117 | * Create an instance of the loader which will be used to register the hooks 118 | * with WordPress. 119 | * 120 | * @since 1.0.0 121 | * @access private 122 | */ 123 | private function loadDependencies() { 124 | $this->loader = new Loader(); 125 | } 126 | 127 | /** 128 | * Define the locale for this plugin for internationalization. 129 | * 130 | * Uses the i18n class in order to set the domain and to register the hook 131 | * with WordPress. 132 | * 133 | * @since 1.0.0 134 | * @access private 135 | */ 136 | private function setLocale() { 137 | $plugin_i18n = new I18n(); 138 | $this->loader->add_action( 'plugins_loaded', $plugin_i18n, 'loadPluginTextdomain' ); 139 | } 140 | 141 | /** 142 | * Register all of the hooks related to the admin area functionality 143 | * of the plugin. 144 | * 145 | * @since 1.0.0 146 | * @access private 147 | */ 148 | private function defineAdminHooks() { 149 | 150 | if ( ! is_admin() && ! wp_doing_cron() ) { 151 | return; // Bail if not admin request and not doing cron. 152 | } 153 | 154 | $plugin_admin = new AdminEnqueues(); 155 | $bootstrap_cron_setup = new SetupCron(); 156 | /* 157 | // (uncomment if making use of notice class). 158 | $notice = new Notice(); 159 | $notices_loader = new NoticesLoader(); 160 | */ 161 | 162 | $this->loader->add_action( 'admin_enqueue_scripts', $plugin_admin, 'enqueueStyles' ); 163 | $this->loader->add_action( 'admin_enqueue_scripts', $plugin_admin, 'enqueueScripts' ); 164 | 165 | $this->loader->add_filter( 'plugin_action_links', $this, 'addPluginActionLinks', PHP_INT_MAX, 2 ); 166 | 167 | // Cron tasks. 168 | $this->loader->add_action( 'admin_init', $bootstrap_cron_setup, 'setCronTasks' ); 169 | 170 | /** 171 | * Make scripts modules 172 | * See the getScriptsAsModules() method for how this works. 173 | */ 174 | $this->loader->add_filter( 'script_loader_tag', $plugin_admin, 'getScriptsAsModules', 10, 3 ); 175 | 176 | /* 177 | // Notices Loader (uncomment if making use of notice class). 178 | $this->loader->add_action( 'admin_notices', $notices_loader, 'loadNotices' ); 179 | 180 | // Notices Ajax dismiss method (uncomment if making use of notice class). 181 | $this->loader->add_action( 'wp_ajax_prefix_dismissNotice', $notice, 'dismissNotice' ); 182 | */ 183 | } 184 | 185 | /** 186 | * Register all of the hooks related to the public-facing functionality 187 | * of the plugin. 188 | * 189 | * @since 1.0.0 190 | * @access private 191 | */ 192 | private function definePublicHooks() { 193 | 194 | if ( is_admin() && ! wp_doing_ajax() ) { 195 | return; // Bail if is admin request and not doing ajax. 196 | } 197 | 198 | $plugin_public = new FrontendEnqueues(); 199 | 200 | $this->loader->add_action( 'wp_enqueue_scripts', $plugin_public, 'enqueueStyles' ); 201 | $this->loader->add_action( 'wp_enqueue_scripts', $plugin_public, 'enqueueScripts' ); 202 | 203 | /** 204 | * Make scripts modules 205 | */ 206 | $this->loader->add_filter( 'script_loader_tag', $plugin_public, 'getScriptsAsModules', 10, 3 ); 207 | } 208 | 209 | /** 210 | * Run the loader to execute all of the hooks with WordPress. 211 | * 212 | * @since 1.0.0 213 | */ 214 | public function run() { 215 | $this->loader->run(); 216 | } 217 | 218 | /** 219 | * The name of the plugin used to uniquely identify it within the context of 220 | * WordPress and to define internationalization functionality. 221 | * 222 | * @since 1.0.0 223 | * @return string The name of the plugin. 224 | */ 225 | public function getPluginName() { 226 | return $this->plugin_name; 227 | } 228 | 229 | /** 230 | * The reference to the class that orchestrates the hooks with the plugin. 231 | * 232 | * @since 1.0.0 233 | * @return Loader Orchestrates the hooks of the plugin. 234 | */ 235 | public function getLoader() { 236 | return $this->loader; 237 | } 238 | 239 | /** 240 | * Retrieve the version number of the plugin. 241 | * 242 | * @since 1.0.0 243 | * @return string The version number of the plugin. 244 | */ 245 | public function getVersion() { 246 | return $this->version; 247 | } 248 | 249 | /** 250 | * Add action Links for plugin 251 | * 252 | * @param array $plugin_actions Current plugin actions. 253 | * @param string $plugin_file Plugin file name. 254 | * @return array 255 | */ 256 | public function addPluginActionLinks( $plugin_actions, $plugin_file ) { 257 | return $plugin_actions; 258 | } 259 | } 260 | -------------------------------------------------------------------------------- /includes/Bootstrap/SetupCron.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | 12 | namespace Root\Helpers; 13 | 14 | if ( ! defined( 'ABSPATH' ) ) { 15 | exit; 16 | } 17 | 18 | /** 19 | * Class responsible for creating helper static methods. 20 | * 21 | * @package Root\Helpers 22 | * @since 1.0.0 23 | */ 24 | class Functions { 25 | 26 | /** 27 | * Turn a script into a module so that we can make use of JS components. 28 | * 29 | * @param string $tag 30 | * @param string $handle 31 | * @param string $src 32 | * @return string 33 | * @since 1.0.0 34 | */ 35 | public static function makeScriptsModules( string $tag, string $handle, string $src ) { 36 | 37 | $id = $handle . '-js'; 38 | $parts = explode( '', $tag ); // Break up our string 39 | 40 | foreach ( $parts as $key => $part ) { 41 | if ( strpos( $part, $src ) !== false ) { // Make sure we're only altering the tag for our module script. 42 | $parts[ $key ] = '', $parts ); // Bring everything back together 47 | 48 | return $tags; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /includes/Models/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UVLabs/wordpress-plugin-boilerplate/32251d5d207e4f2376834f1cbc27fe125f363b52/includes/Models/.gitkeep -------------------------------------------------------------------------------- /includes/Notices/Admin.php: -------------------------------------------------------------------------------- 1 | 42 | 43 |
HTML element */ 46 | echo sprintf( esc_html__( '%1$s%2$s my_plugin_name NOTICE:%3$s HTTPS not detected on this website. The plugin will not work. Please enable HTTPS on this website.%4$s', 'text-domain' ), '
', '', '', '
' ); 47 | ?> 48 | HTML element 2: Opening HTML element 3: Closing HTML element 4: Closing HTML element */
47 | echo sprintf( esc_html__( '%1$s%2$s my_plugin_name NOTICE:%3$s PHP version too low to use this plugin. Please change to at least PHP 7.4. You can contact your web host for assistance in updating your PHP version.%4$s', 'text-domain' ), ' ', '', '', ' HTML element 2: Opening HTML element 3: Closing HTML element 4: Closing HTML element */
65 | echo sprintf( esc_html__( '%1$s%2$s my_plugin_name NOTICE:%3$s PHP version too low to use this plugin. Please change to at least PHP 7.4. You can contact your web host for assistance in updating your PHP version.%4$s', 'text-domain' ), ' ', '', '', '
64 | assets/admin/js/build/
65 | assets/public/js/build/
66 |
67 |
68 | These are the build files for your JS and should be committed if you're deploying the plugin from github using a plugin like Git Updater.
--------------------------------------------------------------------------------
/readme.txt:
--------------------------------------------------------------------------------
1 | === my_plugin_name ===
2 | Contributors: user, user, user
3 | Tags: tag, tag, tag
4 | Donate link: http://example.com/
5 | Requires at least: 4.0
6 | Tested up to: 4.8
7 | Requires PHP: 7.4
8 | Stable tag: 1.0.0
9 | License: GPLv2 or later
10 | License URI: http://www.gnu.org/licenses/gpl-2.0.html
11 |
12 | Short description of this great plugin. No more than 150 characters, no markup.
13 |
14 | == Description ==
15 | Long description of this great plugin. No characters limit, and you can use markdown.
16 |
17 | For backwards compatibility, if this section is missing, the full length of the short description will be used, and
18 | markdown parsed.
19 |
20 | Ordered list:
21 |
22 | 1. Some feature
23 | 1. Another feature
24 | 1. Something else about the plugin
25 |
26 | Unordered list:
27 |
28 | * something
29 | * something else
30 | * third thing
31 |
32 | Link to [WordPress](http://wordpress.org/ "Your favorite software") and one to [Markdown's Syntax Documentation][markdown syntax].
33 |
34 | Titles are optional, naturally.
35 |
36 | Asterisks for *emphasis*.
37 |
38 | Double it up for **strong**.
39 |
40 | == Installation ==
41 | 1. Upload "test-plugin.php" to the "/wp-content/plugins/" directory.
42 | 1. Activate the plugin through the "Plugins" menu in WordPress.
43 | 1. Place "do_action( 'plugin_name_hook' );" in your templates.
44 |
45 | == Frequently Asked Questions ==
46 | = A question that someone might have =
47 | An answer to that question.
48 |
49 | = What about foo bar? =
50 | Answer to foo bar dilemma.
51 |
52 | == Screenshots ==
53 | 1. The screenshot description corresponds to screenshot-1.(png|jpg|jpeg|gif).
54 | 2. The screenshot description corresponds to screenshot-2.(png|jpg|jpeg|gif).
55 | 3. The screenshot description corresponds to screenshot-3.(png|jpg|jpeg|gif).
56 |
57 | == Changelog ==
58 | = 1.0.1 =
59 | * A change since the previous version.
60 | * Another change.
61 |
62 | = 1.0.0 =
63 | * Initial release.
64 |
65 | == Upgrade Notice ==
66 | = 1.0.1 =
67 | Upgrade notices describe the reason a user should upgrade
68 |
69 | = 1.0.0 =
70 | This version fixes a security related bug. Upgrade immediately.
--------------------------------------------------------------------------------
/uninstall.php:
--------------------------------------------------------------------------------
1 |