├── .env.testing ├── .gitignore ├── .travis.yml ├── README.md ├── assets └── public │ ├── css │ ├── backend.css │ └── frontend.css │ └── js │ ├── backend.js │ ├── customizer.js │ └── frontend.js ├── codeception.dist.yml ├── composer.json ├── languages └── the-plugin-name-text-domain.pot ├── phpcs.xml.dist ├── src ├── App │ ├── Backend │ │ ├── Enqueue.php │ │ ├── Notices.php │ │ └── Settings.php │ ├── Cli │ │ └── Example.php │ ├── Cron │ │ └── Example.php │ ├── Frontend │ │ ├── Enqueue.php │ │ └── Templates.php │ ├── General │ │ ├── PostTypes.php │ │ ├── Queries.php │ │ ├── Shortcodes.php │ │ └── Widgets.php │ └── Rest │ │ └── Example.php ├── Bootstrap.php ├── Common │ ├── Abstracts │ │ └── Base.php │ ├── Functions.php │ ├── Traits │ │ ├── Requester.php │ │ └── Singleton.php │ └── Utils │ │ └── Errors.php ├── Compatibility │ └── Siteground │ │ └── Example.php ├── Config │ ├── Classes.php │ ├── I18n.php │ ├── Plugin.php │ ├── Requirements.php │ └── Setup.php └── Integrations │ ├── Example │ └── Api.php │ └── Widget │ └── HTML_Widget.php ├── templates └── test-template.php ├── tests ├── PluginTestsBootstrap.php ├── _data │ └── .gitkeep ├── _output │ └── .gitkeep ├── _support │ ├── AcceptanceTester.php │ ├── FunctionalTester.php │ ├── Helper │ │ ├── Acceptance.php │ │ ├── Functional.php │ │ ├── Unit.php │ │ └── Wpunit.php │ ├── UnitTester.php │ ├── WpunitTester.php │ └── _generated │ │ ├── AcceptanceTesterActions.php │ │ ├── FunctionalTesterActions.php │ │ ├── UnitTesterActions.php │ │ └── WpunitTesterActions.php ├── acceptance.suite.yml ├── functional.suite.yml ├── unit.suite.yml ├── unit │ └── RandomNameTest.php ├── wpunit.suite.yml └── wpunit │ └── RandomPostTest.php └── the-plugin-name.php /.env.testing: -------------------------------------------------------------------------------- 1 | WP_ROOT_FOLDER=/app/wordpress/ 2 | 3 | # For acceptance and functional tests 4 | TEST_SITE_DB_DSN=mysql:host=wordpress;dbname=wordpress 5 | TEST_SITE_DB_HOST=database 6 | TEST_SITE_DB_NAME=wordpress 7 | TEST_SITE_DB_USER=wordpress 8 | TEST_SITE_DB_PASSWORD=wordpress 9 | TEST_SITE_TABLE_PREFIX=wp_ 10 | TEST_SITE_ADMIN_USERNAME=admin 11 | TEST_SITE_ADMIN_PASSWORD=password 12 | TEST_SITE_WP_ADMIN_PATH=/wp-admin 13 | TEST_SITE_WP_URL=https://wp-strap.lndo.site/wordpress 14 | TEST_SITE_WP_DOMAIN=wp-strap.lndo.site/wordpress 15 | TEST_SITE_ADMIN_EMAIL=admin@email.test 16 | 17 | # For integration tests 18 | TEST_DB_NAME=wordpress 19 | TEST_DB_HOST=database 20 | TEST_DB_USER=wordpress 21 | TEST_DB_PASSWORD=wordpress 22 | TEST_TABLE_PREFIX=wp_ 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # IDE 2 | .idea 3 | 4 | # Node 5 | node_modules 6 | npm-debug.log 7 | package-lock.json 8 | yarn.lock 9 | 10 | # Composer 11 | vendor 12 | composer.lock 13 | 14 | # PHP 15 | phpunit.xml 16 | phpcs.xml 17 | .phpcs.xml 18 | 19 | # Others 20 | *.diff 21 | *.err 22 | *.orig 23 | *.log 24 | *.rej 25 | *.swo 26 | *.swp 27 | *.vi 28 | *~ 29 | *.sass-cache 30 | *.lock 31 | cache -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - 7.1 5 | - 7.2 6 | - 7.3 7 | 8 | notifications: 9 | email: 10 | on_success: never 11 | on_failure: change 12 | 13 | branches: 14 | only: 15 | - master 16 | 17 | cache: 18 | apt: true 19 | directories: 20 | - node_modules 21 | - $HOME/.composer/cache 22 | 23 | matrix: 24 | fast_finish: true 25 | include: 26 | - php: 7.3 27 | env: WP_VERSION=latest WP_MULTISITE=0 28 | - php: 7.2 29 | env: WP_VERSION=latest WP_MULTISITE=0 30 | - php: 7.1 31 | env: WP_VERSION=latest WP_MULTISITE=0 32 | 33 | install: 34 | - phpenv config-rm xdebug.ini || echo 'No xdebug config.' 35 | - composer install --no-interaction --no-suggest 36 | - phpenv rehash 37 | 38 | script: 39 | # Search for PHP syntax errors. 40 | - find -L . -path ./vendor -prune -o -name '*.php' -print0 | xargs -0 -n 1 -P 4 php -l 41 | # Run PHPCS. 42 | - composer phpcs 43 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WordPress Plugin Boilerplate 2 | 3 | [![Build Status](https://api.travis-ci.org/wp-strap/wordpress-plugin-boilerplate.svg?branch=master&status=passed)](https://travis-ci.org/github/wp-strap/wordpress-plugin-boilerplate) 4 | ![PHP 7.1+](https://img.shields.io/badge/PHP-7.1%2B-brightgreen) 5 | 6 | 7 | 11 | 12 |
8 | Plugin boilerplate with modern tools to kickstart your WordPress project
9 | This includes common and modern tools to facilitate plugin development and testing with an organized, object-oriented structure and kick-start a build-workflow for your WordPress plugins. 10 |
13 | 14 | * The Boilerplate is based on the [Plugin API](https://codex.wordpress.org/Plugin_API) 15 | , [Coding Standards](https://codex.wordpress.org/WordPress_Coding_Standards), 16 | and [Documentation Standards](https://make.wordpress.org/core/handbook/best-practices/inline-documentation-standards/php/). 17 | * Includes Composer, Requirements micropackage to test environment requirements for your plugin, Codeception to do 18 | unit/acceptance testing, PHPCodeSniffer with WordPress Coding Standards to validate your code, TravisCI configuration 19 | for automatic testing & continuous integration, object-oriented code structure for better overview, an automatic class 20 | loader that automatically instantiate classes based on type of request. 21 | * This can be combined with the [Webpack 5 workflow](https://github.com/wp-strap/wordpress-webpack-workflow) for 22 | front-end development using the npx quickstart script that includes the Webpack v5 bundler, BabelJS v7, BrowserSync 23 | v2, PostCSS v8, PurgeCSS v3, Autoprefixer, Eslint, Stylelint, SCSS processor, WPPot, and more. 24 | 25 | ## Quickstart 26 | 27 | ![Image](https://media.giphy.com/media/2Fb95iB53xkOAlYeTv/source.gif) 28 | 29 | Should be run inside your plugins folder (wp-content/plugins). 30 | ```bash 31 | npx wp-strap plugin 32 | ``` 33 | 34 | You can also use the npx script with predefined answers to get a quicker start 35 | ```bash 36 | npx wp-strap plugin "projectName:Your plugin name" "description:Test the plugin" "pluginVersion:1.0.0" license:MIT "author:The Dev Company" authorEmail:hello@the-dev-company.com url:the-dev-company.com webpack:Y codesniffer:Y codeception:Y travisCi:Y css:Sass+PostCSS 37 | ``` 38 | 39 | It will take a couple of minutes to install after your terminal input; it will clone the git repo's, search and replace 40 | all the plugin data, do a `composer install`, and when it's combined with the Webpack workflow then it wil also do 41 | a `npm install ` 42 | 43 | Read more about the configuration & build scripts 44 | ## Features & benefits 45 | 46 | ### Backend 47 | 48 | **Composer** (Namespaces + PSR4 autoloader + Dependency manager) 49 | >- [**Namespace**](https://www.php.net/manual/en/language.namespaces.rationale.php) support to group all of your code under a custom name. That way, your classes, functions, and so on don’t clash with other people’s code running on the site at the same time 50 | >- [**PSR-4 Autoloader**](https://www.php-fig.org/psr/psr-4/) to autoload files and directories in connection with namespaces 51 | >- Includes a [**dependency manager**](https://getcomposer.org/doc/00-intro.md#dependency-management) to easily load in 3rd party libraries from [**packagist**](https://packagist.org/), locked onto specific versions 52 | 53 | **Object-oriented & classes autoloader** 54 | >- Includes a [**OOP-style**](https://developer.wordpress.org/plugins/plugin-basics/best-practices/#object-oriented-programming-method) structure for building a high-quality PHP development 55 | >- Classes are being [auto-instantiated](https://github.com/wp-strap/wordpress-plugin-boilerplate/blob/master/src/Bootstrap.php#L79) by extending the PSR-4 Autoloader from Composer and [based on type of request and folder structure](https://github.com/wp-strap/wordpress-plugin-boilerplate/blob/master/src/Config/Classes.php#L28) for which you can add the [types of request here](https://github.com/wp-strap/wordpress-plugin-boilerplate/blob/master/src/Common/Traits/Requester.php#L30). So you can add your own new class files by naming them correctly and putting the files in the most appropriate location and work in it straight away without having to include them or instantiate them manually. Composer's Autoloader and the Bootstrap class will auto include your file and instantiate the class. 56 | >- The structure follows the the [Plugin API](https://codex.wordpress.org/Plugin_API) 57 | , [Coding Standards](https://codex.wordpress.org/WordPress_Coding_Standards), 58 | and [Documentation Standards](https://make.wordpress.org/core/handbook/best-practices/inline-documentation-standards/php/) 59 | 60 | **PHPCodeSniffer + WordPress Coding Standards + Automattic's phpcs-neutron-ruleset** 61 | >- [**PHP CodeSniffer**](https://github.com/squizlabs/PHP_CodeSniffer) is built in with predefined configuration for proper linting. PHP_CodeSniffer is an essential development tool that ensures your code remains clean and consistent. 62 | >- PHPCS is extended with the [**WordPress Coding Standards**](https://github.com/WordPress/WordPress-Coding-Standards) & [**PHPCompatibilityWP**](https://github.com/PHPCompatibility/PHPCompatibilityWP) for PHP_CodeSniffer which is a collection of PHP_CodeSniffer rules (sniffs) to validate code developed for WordPress. It ensures code quality and adherence to coding conventions, especially the official WordPress Coding Standards. 63 | >- PHPCS is also extented with [**Automattic's phpcs-neutron-ruleset**](https://github.com/Automattic/phpcs-neutron-ruleset) which is a set of modern (PHP >7) linting guidelines for WordPress development. 64 | 65 | **Codeception (unit/acceptance testing)** 66 | >- [**Codeception**](https://codeception.com/for/wordpress) is built in which combines all testing levels (acceptance, functional, integration, unit) with WordPress defined functions, constants, classes and methods in any test. 67 | >- With a flexible set of included modules, tests are easy to write, easy to use, and easy to maintain. 68 | 69 | 70 | **Plugin requirements** 71 | >- [**Requirements micropackage**](https://github.com/micropackage/requirements) is built in that allows you to test environment requirements to run your plugin. It can test: PHP version, PHP Extensions, WordPress version, Active plugins, Current theme, DocHooks support 72 | >- Easily to configure using a [**simple array**](https://github.com/wp-strap/wordpress-plugin-boilerplate/blob/master/src/Config/Requirements.php#L35) 73 | >- If the plugin doesn't pass the test then it will disable the plugin automatically for the user in WordPress and show a notification in the back-end 74 | 75 | 76 | **TravisCI** 77 | >- Ready to use [**TravisCI**](https://travis-ci.org/) configuration for automatic testing & continuous integration which currently only validates the plugin code with PHPCodeSniffer during automated testing when being deployed, but can also be extended to test unit/acceptance cases from Codeception 78 | 79 | **Prettified errors & Classes debug array** 80 | >- Includes a function called `Errors::wpDie` to show a [prettified WP_DEBUG error](https://i.imgur.com/PFoIwxD.png) with the plugin information and file source 81 | >- Includes a function called `Errors::pluginDie` to kill the plugin and show a [prettified admin notification](https://i.imgur.com/WGE9sBv.png) with the plugin information and file source 82 | >- Includes a [function if set true](https://github.com/wp-strap/wordpress-plugin-boilerplate/blob/master/src/Bootstrap.php#L43) to [debug the bootstrap's class loader and see](https://i.imgur.com/Rg2bSEq.png) which classes are loaded, if they load on the requested page, in which order and to check the execution time of the code run in each class 83 | 84 | 85 | ### Frontend (Webpack) 86 | For front-end tooling the webpack workflow is being cloned. Read more about this workflow here: https://github.com/wp-strap/wordpress-webpack-workflow 87 | 88 | **Styling (CSS)** 89 | 90 | >- **Minification** in production mode handled by Webpack 91 | >- [**PostCSS**](http://postcss.org/) for handy tools during post CSS transformation using Webpack's [**PostCSS-loader**](https://webpack.js.org/loaders/postcss-loader/) 92 | >- **Auto-prefixing** using PostCSS's [**autoprefixer**](https://github.com/postcss/autoprefixer) to parse CSS and add vendor prefixes to CSS rules using values from [Can I Use](https://caniuse.com/). It is [recommended](https://developers.google.com/web/tools/setup/setup-buildtools#dont_trip_up_with_vendor_prefixes) by Google and used in Twitter and Alibaba. 93 | >- [**PurgeCSS**](https://github.com/FullHuman/purgecss) which scans your php (template) files to remove unused selectors from your css when in production mode, resulting in smaller css files. 94 | >- **Sourcemaps** generation for debugging purposes with [various styles of source mapping](https://webpack.js.org/configuration/devtool/) handled by WebPack 95 | >- [**Stylelint**](https://stylelint.io/) that helps you avoid errors and enforce conventions in your styles. It includes a [linting tool for Sass](https://github.com/kristerkari/stylelint-scss). 96 | 97 | **Styling when using PostCSS-only** 98 | >- Includes [**postcss-import**](https://github.com/postcss/postcss-import) to consume local files, node modules or web_modules with the @import statement 99 | >- Includes [**postcss-import-ext-glob**](https://github.com/dimitrinicolas/postcss-import-ext-glob) that extends postcss-import path resolver to allow glob usage as a path 100 | >- Includes [**postcss-nested**](https://github.com/postcss/postcss-nested) to unwrap nested rules like how Sass does it. 101 | >- Includes [**postcss-nested-ancestors**](https://github.com/toomuchdesign/postcss-nested-ancestors) that introduces ^& selector which let you reference any parent ancestor selector with an easy and customizable interface 102 | >- Includes [**postcss-advanced-variables**](https://github.com/jonathantneal/postcss-advanced-variables) that lets you use Sass-like variables, conditionals, and iterators in CSS. 103 | 104 | 105 | **Styling when using Sass+PostCSS** 106 | > - **Sass to CSS conversion** using Webpack's [**sass-loader**](https://webpack.js.org/loaders/sass-loader/) 107 | >- Includes [**Sass magic importer**](https://github.com/maoberlehner/node-sass-magic-importer) to do lot of fancy things with Sass @import statements 108 | 109 | 110 | **JavaScript** 111 | > - [**BabelJS**](https://babeljs.io/) Webpack loader to use next generation Javascript with a **BabelJS Configuration file** 112 | >- **Minification** in production mode 113 | >- [**Code Splitting**](https://webpack.js.org/guides/code-splitting/), being able to structure JavaScript code into modules & bundles 114 | >- **Sourcemaps** generation for debugging purposes with [various styles of source mapping](https://webpack.js.org/configuration/devtool/) handled by WebPack 115 | >- [**ESLint**](https://eslint.org/) find and fix problems in your JavaScript code with a **linting configuration** including configurations and custom rules for WordPress development. 116 | >- [**Prettier**](https://prettier.io/) for automatic JavaScript / TypeScript code **formatting** 117 | 118 | **Images** 119 | 120 | > - [**ImageMinimizerWebpackPlugin**](https://webpack.js.org/plugins/image-minimizer-webpack-plugin/) + [**CopyWebpackPlugin**](https://webpack.js.org/plugins/copy-webpack-plugin/) 121 | to optimize (compress) all images using 122 | >- _File types: `.png`, `.jpg`, `.jpeg`, `.gif`, `.svg`_ 123 | 124 | **Translation** 125 | 126 | > - [**WP-Pot**](https://github.com/wp-pot/wp-pot-cli) scans all the files and generates `.pot` file automatically for i18n and l10n 127 | 128 | **BrowserSync, Watcher & WebpackBar** 129 | 130 | > - [**Watch Mode**](https://webpack.js.org/guides/development/#using-watch-mode), watches for changes in files to recompile 131 | >- _File types: `.css`, `.html`, `.php`, `.js`_ 132 | >- [**BrowserSync**](https://browsersync.io/), synchronising browsers, URLs, interactions and code changes across devices and automatically refreshes all the browsers on all devices on changes 133 | >- [**WebPackBar**](https://github.com/nuxt/webpackbar) so you can get a real progress bar while development which also includes a **profiler** 134 | 135 | **Configuration** 136 | 137 | > - All configuration files `.prettierrc.js`, `.eslintrc.js`, `.stylelintrc.js`, `babel.config.js`, `postcss.config.js` are organised in a single folder 138 | >- The Webpack configuration is divided into 2 environmental config files for the development and production build/environment 139 | 140 | ## Requirements 141 | - [Composer](https://getcomposer.org/doc/00-intro.md) 142 | - [Node.js](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) 143 | - [NPM](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) 144 | - [Yarn](https://classic.yarnpkg.com/en/docs/install/#mac-stable) 145 | 146 | ## File structure 147 | You can add your own new class files by naming them correctly and putting the files in the most appropriate location, 148 | see other files for examples. Composer's Autoloader and the Bootstrap class will auto include your file and instantiate 149 | the class. The idea of this organisation is to be more conscious of structuring your code. 150 | 151 | ```bash 152 | │ ## First level files 153 | ├──the-plugin-name.php # Main entry file for the plugin 154 | ├──composer.json # Composer dependencies & scripts 155 | ├──phpcs.xml.dist # PHPCodeSniffer configuration 156 | ├──codeception.dist.yml # Codeception testing configuration 157 | ├──.env.testing # Codeception testing environment configuration 158 | ├──.travis.yml # TravisCI configuration for automatic testing & continuous integration 159 | ├──package.json # (incl. when using webpack) Node.js dependencies & scripts (NPM functions) 160 | ├──webpack.config.js # (incl. when using webpack) Holds all the base Webpack configurations 161 | │ 162 | │ ## Folders 163 | ├──src # Holds all the plugin php classes 164 | │ ├── Bootstrap.php # Bootstraps the plugin and auto-instantiate classes 165 | │ ├── App # Holds the plugin application-specific functionality 166 | │ │ ├── Frontend # All public-facing hooks/functionality 167 | │ │ ├── Backend # All admin-specific hooks/functionality 168 | │ │ ├── General # Hooks/functionality shared between the back-end and frontend 169 | │ │ ├── Cli # Code for cli commands 170 | │ │ ├── Cron # Code for cron events 171 | │ │ ├── Rest # Code for rest api functionalities 172 | │ ├── Config # Plugin configuration code 173 | │ │ ├── Classes.php # Defines the folders and order of classes to init 174 | │ │ ├── I18n.php # Internationalization and localization definitions 175 | │ │ ├── Plugin.php # Plugin data which are used through the plugin 176 | │ │ ├── Requirements.php # Defines the requirements that are needed to run this plugin. 177 | │ │ ├── Setup.php # Plugin setup hooks (activation, deactivation, uninstall) 178 | │ ├── Common # Utilities & helpers shared in the whole plugin 179 | │ │ ├── Abstracts # Here you can add abstract classes to extend your php classes 180 | │ │ │ ├── Base.php # A base class which all classes extends to load in default methods, currently the plugin data is only being injected 181 | │ │ ├── Traits # Here you can add handy traits to extend your php classes 182 | │ │ │ ├── Requester.php # The requester trait to determine what we request; used to determine which classes we instantiate in the Bootstrap class 183 | │ │ │ ├── Singleton.php # The singleton skeleton trait to instantiate the class only once 184 | │ │ ├── Utils # Here you can add helper/utiliy functions, eg: array functions 185 | │ │ │ ├── Errors.php # Utility class for the prettified errors and to write debug logs as string or array 186 | │ │ ├── Functions.php # Main function class for external/global functions, eg: "plugin_name()->your_function" 187 | │ ├── Integrations # Includes the integration with libraries, api's or other plugins 188 | │ ├── Compatibility # 3rd party compatibility code 189 | ├──tests # Codeception test files 190 | ├──templates # Folder to include all the template files 191 | │ ├── test-template.php # Example template file 192 | ├──languages # WordPress default language map in Plugins & Themes 193 | │ ├── the-plugin-name.pot # Boilerplate POT File that gets overwritten by WP-Pot 194 | ├──webpack # (incl. when using webpack) Holds all the sub-config files for webpack 195 | │ ├── .prettierrc.js # Configuration for Prettier 196 | │ ├── .eslintrc.js # Configuration for Eslint 197 | │ ├── .stylelintrc.js # Configuration for Stylelint 198 | │ ├── babel.config.js # Configuration for BabelJS 199 | │ ├── postcss.config.js # Configuration for PostCSS 200 | │ ├── config.base.js # Base config for Webpack's development & production mode 201 | │ ├── config.development.js # Configuration for Webpack in development mode 202 | │ └── config.production.js # Configuration for Webpack in production mode 203 | └──assets 204 | ├── src # (incl. when using webpack) Holds all the source files 205 | │ ├── images # Uncompressed images 206 | │ ├── scss/pcss # Holds the Sass/PostCSS files 207 | │ │ ├─ frontend.scss/pcss # For front-end styling 208 | │ │ └─ backend.scss/pcss # For back-end / wp-admin styling 209 | │ └── js # Holds the JS files 210 | │ ├─ frontend.js # For front-end scripting 211 | │ └─ backend.js # For back-end / wp-admin scripting 212 | │ 213 | └── public 214 | ├── images # Optimized (compressed) images 215 | ├── css # Compiled CSS files with be generated here 216 | └── js # Compiled JS files with be generated here 217 | ``` 218 | 219 | ## What to configure 220 | 221 | 1. When using codeception; configure the environments settings in `.env.testing`, other configurations can be found in `codeception.dist.yml` 222 | 2. When using Webpack; edit the BrowserSync settings in `webpack.config.js` which applies to your local/server environment 223 | - You can also disable BrowserSync, Eslint & Stylelint in `webpack.config.js` 224 | - You may want to configure the files in `/webpack/` and `webpack.config.js` to better suite your needs 225 | 3. You can activate the plugin in WordPress and work on it straight away. 226 | 227 | ### Acceptance & Unit Testing 228 | 229 | - Testing with Codeception works out of the box 230 | - Create test files with `composer generate:wpunit` or `composer generate:acceptance` 231 | - Write your test methods and run `composer run:wpunit` or `composer run:acceptance` 232 | - Extensive documentation can be found here https://codeception.com/for/wordpress 233 | 234 | ### PHPCodeSniffer 235 | 236 | - Run PHPCodeSniffer with `composer phpcs` to validate your plugin code 237 | - Configure PHPCodeSniffer in `phpcs.xm.dist` 238 | - Documentation can be found here: 239 | - https://github.com/WordPress/WordPress-Coding-Standards 240 | - https://github.com/Dealerdirect/phpcodesniffer-composer-installer 241 | - https://github.com/Automattic/phpcs-neutron-ruleset 242 | - https://github.com/PHPCompatibility/PHPCompatibilityWP 243 | 244 | ### Plugin requirements 245 | - Set your plugin requirements in `src/Config/Requirements.php` using a simple array 246 | - It can test: PHP version, PHP Extensions, WordPress version, Active plugins, Current theme, DocHooks support 247 | - If the plugin doesn't pass the test then it will be disabled automatically in WordPress and show a notification in the back-end 248 | - Documentation can be found here: https://github.com/micropackage/requirements 249 | 250 | ### TravisCI 251 | - Configure TravisCI in `.travis.yml` 252 | - Currently it only validates the plugin code with PHPCodeSniffer during automated testing when being deployed 253 | - A great article can be found here: https://stevegrunwell.com/blog/travis-ci-wordpress-plugins/ 254 | 255 | ## Frontend/Webpack tooling 256 | When using webpack then you can use the following for the front-end build process. [Read here more](https://github.com/wp-strap/wordpress-webpack-workflow) for more information about this workflow. 257 | 258 | ### Developing Locally 259 | 260 | To work on the project locally (with Eslint, Stylelint & Prettier active), run: 261 | 262 | ```bash 263 | yarn dev 264 | ``` 265 | 266 | Or run with watcher & browserSync 267 | 268 | ```bash 269 | yarn dev:watch 270 | ``` 271 | 272 | This will open a browser, watch all files (php, scss, js, etc) and reload the browser when you press save. 273 | 274 | ### Building for Production 275 | 276 | To create an optimized production build (purged with PurgeCSS & fully minified CSS & JS files), run: 277 | 278 | ```bash 279 | yarn prod 280 | ``` 281 | 282 | Or run with watcher & browserSync 283 | 284 | ```bash 285 | yarn prod:watch 286 | ``` 287 | 288 | ### More Scripts/Tasks 289 | 290 | ```bash 291 | # To scan for text-domain functions and generate WP POT translation file 292 | yarn translate 293 | 294 | # To find problems in your JavaScript code 295 | yarn eslint 296 | 297 | # To find fix problems in your JavaScript code 298 | yarn eslint:fix 299 | 300 | # To find problems in your sass/css code 301 | yarn stylelint 302 | 303 | # To find fix problems in your sass/css code 304 | yarn stylelint:fix 305 | 306 | # To make sure files in assets/src/js are formatted 307 | yarn prettier 308 | 309 | # To fix and format the js files in assets/src/js 310 | yarn prettier:fix 311 | ``` 312 | 313 | ## Composer.json dependencies 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 |
DepedencyDescriptionVersion
Plugin Requirements
micropackage/requirementsAllows you to test environment requirements to run your plugin.1.0
PHPCodeSniffer
dealerdirect/phpcodesniffer-composer-installerAllows for easy installation of PHP_CodeSniffer coding standards (rulesets)0.7.1
wp-coding-standards/wpcsCollection of PHP_CodeSniffer rules (sniffs) to validate code developed for WordPress*
automattic/phpcs-neutron-rulesetSet of modern (PHP >7) linting guidelines for WordPress development3.3
phpcompatibility/phpcompatibility-wpAnalyse the codebase of a WordPress-based project for PHP cross-version compatibility2.1
Codeception
lucatume/function-mockerA Patchwork powered function mocker to mock function for testing1.0
lucatume/wp-browserProvides easy acceptance, functional, integration and unit testing for WordPress plugins, themes and whole sites using Codeception3.0
Codeception/lib-innerbrowserParent library for all Codeception framework modules and PhpBrowser.1.0
codeception/module-assertsA Codeception module containing various assertions1.0
codeception/module-phpbrowserUse to perform web acceptance tests with non-javascript browser1.0
codeception/module-webdriverRun tests in real browsers using the W3C WebDriver protocol.1.0
codeception/module-dbA database module for Codeception.1.0
codeception/module-filesystemA Codeception module for testing local filesystem.1.0
codeception/module-cliA Codeception module for testing basic shell commands and shell output.1.0
codeception/module-restA REST module for Codeception1.2
codeception/util-universalframeworkMock framework module used in internal Codeception tests1.0
codeception/codeception-progress-reporterReporter for codeception with a progress bar4.0.2
436 | 437 | ## Package.json dependencies 438 | https://github.com/wp-strap/wordpress-webpack-workflow#packagejson-dependencies 439 | 440 | ## Boilerplate's Changelog 441 | 442 | Documenting this project's progress... 443 | #### January 15, 2021 444 | * refactor: (webpack/frontend) Migrated from NPM to Yarn for speed, `install` went from 183.281s to 65.76s-90.02s. 445 | #### January 14, 2021 446 | * feat: Added `POT` File with all the translation strings 447 | * refactor: Moved classes array to own config file 448 | * feat: Added `npx` CLI build script + docs 449 | #### January 9, 2021 450 | * refactor: Rename plugin (meta) data to replace-able names 451 | #### January 8, 2021 452 | * feat: Added `PHP_CodeSniffer` with `WordPress-Coding-Standards` including configuration file 453 | * feat(`.travis.yml`): added TravisCI configuration file 454 | * feat: Added bootstrap classes debugger method 455 | * feat: `README.md` file 456 | -------------------------------------------------------------------------------- /assets/public/css/backend.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brandonkramer/wordpress-plugin-boilerplate/3f02a0e85eea155ad7fbece85a6abe52ec3a9629/assets/public/css/backend.css -------------------------------------------------------------------------------- /assets/public/css/frontend.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brandonkramer/wordpress-plugin-boilerplate/3f02a0e85eea155ad7fbece85a6abe52ec3a9629/assets/public/css/frontend.css -------------------------------------------------------------------------------- /assets/public/js/backend.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brandonkramer/wordpress-plugin-boilerplate/3f02a0e85eea155ad7fbece85a6abe52ec3a9629/assets/public/js/backend.js -------------------------------------------------------------------------------- /assets/public/js/customizer.js: -------------------------------------------------------------------------------- 1 | /** 2 | * File customizer.js. 3 | * 4 | * Plugin Customizer enhancements for a better user experience. 5 | */ 6 | 7 | ( function( $ ) { 8 | 9 | // Site title and description. 10 | wp.customize( 'blogname', function( value ) { 11 | value.bind( function( to ) { 12 | $( '.site-title a' ).text( to ); 13 | } ); 14 | } ); 15 | wp.customize( 'blogdescription', function( value ) { 16 | value.bind( function( to ) { 17 | $( '.site-description' ).text( to ); 18 | } ); 19 | } ); 20 | 21 | // Update footer address live 22 | wp.customize( 'footer_address', function( value ) { 23 | value.bind( function( to ) { 24 | $( '#js-footer-address' ).text( to ); 25 | }) 26 | } ); 27 | 28 | // Update header colour live 29 | // Adjust the selector and styles according to your theme markup. 30 | wp.customize( 'header_color', function( value ) { 31 | value.bind( function( to ) { 32 | $( '.site-header' ).css( 'background', to ); 33 | }); 34 | } ); 35 | 36 | } )( jQuery ); -------------------------------------------------------------------------------- /assets/public/js/frontend.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brandonkramer/wordpress-plugin-boilerplate/3f02a0e85eea155ad7fbece85a6abe52ec3a9629/assets/public/js/frontend.js -------------------------------------------------------------------------------- /codeception.dist.yml: -------------------------------------------------------------------------------- 1 | actor: Tester 2 | actor_suffix: Tester 3 | paths: 4 | tests: tests 5 | output: tests/_output 6 | data: tests/_data 7 | support: tests/_support 8 | envs: tests/_envs 9 | bootstrap: PluginTestsBootstrap.php 10 | settings: 11 | colors: true 12 | memory_limit: 1024M 13 | params: 14 | - .env.testing 15 | coverage: 16 | enabled: true 17 | exclude: 18 | - vendor/* 19 | include: 20 | - src/* 21 | low_limit: 30 22 | high_limit: 75 23 | extensions: 24 | enabled: 25 | - Codeception\ProgressReporter\ProgressReporter 26 | - Codeception\Extension\RunFailed 27 | commands: 28 | - Codeception\Command\GenerateWPUnit 29 | - Codeception\Command\GenerateWPRestApi 30 | - Codeception\Command\GenerateWPRestController 31 | - Codeception\Command\GenerateWPRestPostTypeController 32 | - Codeception\Command\GenerateWPAjax 33 | - Codeception\Command\GenerateWPCanonical 34 | - Codeception\Command\GenerateWPXMLRPC -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wpstrap/wordpress-plugin-boilerplate", 3 | "description": "Wordpress Plugin Boilerplate", 4 | "version": "0.3.1", 5 | "minimum-stability": "stable", 6 | "prefer-stable": true, 7 | "type": "wordpress-plugin", 8 | "license": "MIT", 9 | "homepage": "https://wp-strap.com", 10 | "autoload": { 11 | "psr-4": { 12 | "ThePluginName\\": "src/" 13 | } 14 | }, 15 | "scripts": { 16 | "codecept": "vendor/bin/codecept", 17 | "run:wpunit": "vendor/bin/codecept run wpunit", 18 | "run:functional": "vendor/bin/codecept run functional", 19 | "run:acceptance": "vendor/bin/codecept run acceptance", 20 | "generate:wpunit": "vendor/bin/codecept generate:wpunit wpunit", 21 | "generate:functional": "vendor/bin/codecept generate:cept functional", 22 | "generate:acceptance": "vendor/bin/codecept generate:test acceptance", 23 | "phpcs": "./vendor/bin/phpcs" 24 | }, 25 | "require": { 26 | "php": ">=7.1", 27 | "micropackage/requirements": "^1.0" 28 | }, 29 | "require-dev": { 30 | "dealerdirect/phpcodesniffer-composer-installer": "^0.7.1", 31 | "wp-coding-standards/wpcs": "*", 32 | "automattic/phpcs-neutron-ruleset": "^3.3", 33 | "phpcompatibility/phpcompatibility-wp": "^2.1", 34 | "lucatume/function-mocker": "~1.0", 35 | "lucatume/wp-browser": "^3.0", 36 | "codeception/lib-innerbrowser": "^1.0", 37 | "codeception/module-asserts": "^1.0", 38 | "codeception/module-phpbrowser": "^1.0", 39 | "codeception/module-webdriver": "^1.0", 40 | "codeception/module-db": "^1.0", 41 | "codeception/module-filesystem": "^1.0", 42 | "codeception/module-cli": "^1.0", 43 | "codeception/module-rest": "^1.2", 44 | "codeception/util-universalframework": "^1.0", 45 | "codeception/codeception-progress-reporter": "^4.0.2" 46 | }, 47 | "keywords": [ 48 | "wordpress", 49 | "plugin", 50 | "boilerplate", 51 | "framework" 52 | ], 53 | "authors": [ 54 | { 55 | "name": "WP-Strap", 56 | "email": "hello@wp-strap.com", 57 | "homepage": "https://wp-strap.com" 58 | } 59 | ] 60 | } 61 | -------------------------------------------------------------------------------- /languages/the-plugin-name-text-domain.pot: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2021 {{the-project-name}} 2 | # This file is distributed under the same license as the {{the-project-name}} package. 3 | msgid "" 4 | msgstr "" 5 | "Project-Id-Version: {{the-project-name}}\n" 6 | "MIME-Version: 1.0\n" 7 | "Content-Type: text/plain; charset=UTF-8\n" 8 | "Content-Transfer-Encoding: 8bit\n" 9 | "Language-Team: {{author_name}} <{{author_email}}>\n" 10 | "Last-Translator: {{author_name}} <{{author_email}}>\n" 11 | "Report-Msgid-Bugs-To: {{author_url}}\n" 12 | "X-Poedit-Basepath: ..\n" 13 | "X-Poedit-KeywordsList: __;_e;_ex:1,2c;_n:1,2;_n_noop:1,2;_nx:1,2,4c;_nx_noop:1,2,3c;_x:1,2c;esc_attr__;esc_attr_e;esc_attr_x:1,2c;esc_html__;esc_html_e;esc_html_x:1,2c\n" 14 | "X-Poedit-SearchPath-0: .\n" 15 | "X-Poedit-SearchPathExcluded-0: *.js\n" 16 | "X-Poedit-SourceCharset: UTF-8\n" 17 | "Plural-Forms: nplurals=2; plural=(n != 1);\n" 18 | 19 | #. translators: %s: php class namespace 20 | #: ../src/Bootstrap.php:182 21 | msgid "Could not load class \"%s\". The \"init\" method is probably missing or try a `composer dumpautoload -o` to refresh the autoloader." 22 | msgstr "" 23 | 24 | #: ../src/Bootstrap.php:186 25 | msgid "Plugin initialize failed" 26 | msgstr "" 27 | 28 | #: ../src/App/Backend/Customizer.php:71, ../src/App/Backend/Customizer.php:113 29 | msgid "Related posts" 30 | msgstr "" 31 | 32 | #: ../src/App/Backend/Customizer.php:88 33 | msgid "Number of posts to show" 34 | msgstr "" 35 | 36 | #: ../src/App/Backend/Notices.php:52 37 | msgid "This is an example of a notice that appears on the settings page." 38 | msgstr "" 39 | 40 | #. translators: %s: post type singular title 41 | #. translators: %s: post type singular title 42 | #: ../src/App/General/PostTypes.php:66, ../src/App/General/PostTypes.php:68 43 | msgid "New %s" 44 | msgstr "" 45 | 46 | #. translators: %s: post type singular title 47 | #: ../src/App/General/PostTypes.php:67 48 | msgid "Add New %s" 49 | msgstr "" 50 | 51 | #. translators: %s: post type singular title 52 | #: ../src/App/General/PostTypes.php:69 53 | msgid "Edit %s" 54 | msgstr "" 55 | 56 | #. translators: %s: post type singular title 57 | #: ../src/App/General/PostTypes.php:70 58 | msgid "View %s" 59 | msgstr "" 60 | 61 | #. translators: %s: post type title 62 | #: ../src/App/General/PostTypes.php:71 63 | msgid "All %s" 64 | msgstr "" 65 | 66 | #. translators: %s: post type title 67 | #: ../src/App/General/PostTypes.php:72 68 | msgid "Search %s" 69 | msgstr "" 70 | 71 | #: ../src/App/Rest/Example.php:65 72 | msgid "Text field demo of Post type" 73 | msgstr "" 74 | 75 | #: ../src/App/Rest/Example.php:128 76 | msgid "Failed to update post views." 77 | msgstr "" 78 | 79 | #. translators: %s: request function 80 | #: ../src/Common/Traits/Requester.php:53 81 | msgid "Unknown request type: %s" 82 | msgstr "" 83 | 84 | #: ../src/Common/Traits/Requester.php:56 85 | msgid "Classes are not being correctly requested" 86 | msgstr "" 87 | 88 | #: ../src/Common/Utils/Errors.php:50 89 | msgid "› Fatal Error" 90 | msgstr "" 91 | 92 | #. translators: %s: file path 93 | #. translators: %s: file path 94 | #: ../src/Common/Utils/Errors.php:61, ../src/Common/Utils/Errors.php:97 95 | msgid "Error source: %s" 96 | msgstr "" 97 | 98 | #: ../src/Common/Utils/Errors.php:86 99 | msgid "› Plugin Disabled" 100 | msgstr "" 101 | 102 | #: ../src/Integrations/Widget/HTML_Widget.php:68 103 | msgid "Displays HTML code with syntax highlighting." 104 | msgstr "" 105 | 106 | #: ../src/Integrations/Widget/HTML_Widget.php:72 107 | msgid "HTML Test Widget" 108 | msgstr "" 109 | 110 | #: ../src/Integrations/Widget/HTML_Widget.php:129 111 | msgid "Content:" 112 | msgstr "" 113 | 114 | #: ../templates/test-template.php:18 115 | msgid "This is being loaded inside \"wp_footer\" from the templates class" 116 | msgstr "" 117 | 118 | #: ../the-plugin-name.php:56 119 | msgid "{{The Plugin Name}} is unable to find the Bootstrap class." 120 | msgstr "" 121 | 122 | #: ../the-plugin-name.php:67 123 | msgid "{{The Plugin Name}} is unable to run the Bootstrap class." 124 | msgstr "" 125 | -------------------------------------------------------------------------------- /phpcs.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 3 | Ruleset for the The Plugin Name. 4 | 5 | the-plugin-name.php 6 | ./src/ 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | *\.php$ 18 | 19 | 20 | 21 | 22 | 0 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 0 92 | 93 | 94 | 0 95 | 96 | -------------------------------------------------------------------------------- /src/App/Backend/Enqueue.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright {{author_copyright}} 8 | * @license {{author_license}} 9 | * @link {{author_url}} 10 | */ 11 | 12 | declare( strict_types = 1 ); 13 | 14 | namespace ThePluginName\App\Backend; 15 | 16 | use ThePluginName\Common\Abstracts\Base; 17 | 18 | /** 19 | * Class Enqueue 20 | * 21 | * @package ThePluginName\App\Backend 22 | * @since 1.0.0 23 | */ 24 | class Enqueue extends Base { 25 | 26 | /** 27 | * Initialize the class. 28 | * 29 | * @since 1.0.0 30 | */ 31 | public function init() { 32 | /** 33 | * This backend class is only being instantiated in the backend as requested in the Bootstrap class 34 | * 35 | * @see Requester::isAdminBackend() 36 | * @see Bootstrap::__construct 37 | * 38 | * Add plugin code here 39 | */ 40 | add_action( 'admin_enqueue_scripts', [ $this, 'enqueueScripts' ] ); 41 | } 42 | 43 | /** 44 | * Enqueue scripts 45 | * 46 | * @since 1.0.0 47 | */ 48 | public function enqueueScripts() { 49 | // Enqueue CSS 50 | foreach ( 51 | [ 52 | [ 53 | 'deps' => [], 54 | 'handle' => 'plugin-name-backend-css', 55 | 'media' => 'all', 56 | 'source' => plugins_url( '/assets/public/css/backend.css', _THE_PLUGIN_NAME_PLUGIN_FILE ), // phpcs:disable ImportDetection.Imports.RequireImports.Symbol -- this constant is global 57 | 'version' => $this->plugin->version(), 58 | ], 59 | ] as $css ) { 60 | wp_enqueue_style( $css['handle'], $css['source'], $css['deps'], $css['version'], $css['media'] ); 61 | } 62 | // Enqueue JS 63 | foreach ( 64 | [ 65 | [ 66 | 'deps' => [], 67 | 'handle' => 'plugin-test-backend-js', 68 | 'in_footer' => true, 69 | 'source' => plugins_url( '/assets/public/js/backend.js', _THE_PLUGIN_NAME_PLUGIN_FILE ), // phpcs:disable ImportDetection.Imports.RequireImports.Symbol -- this constant is global 70 | 'version' => $this->plugin->version(), 71 | ], 72 | ] as $js ) { 73 | wp_enqueue_script( $js['handle'], $js['source'], $js['deps'], $js['version'], $js['in_footer'] ); 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/App/Backend/Notices.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright {{author_copyright}} 8 | * @license {{author_license}} 9 | * @link {{author_url}} 10 | */ 11 | 12 | declare( strict_types = 1 ); 13 | 14 | namespace ThePluginName\App\Backend; 15 | 16 | use ThePluginName\Common\Abstracts\Base; 17 | 18 | /** 19 | * Class Notices 20 | * 21 | * @package ThePluginName\App\Backend 22 | * @since 1.0.0 23 | */ 24 | class Notices extends Base { 25 | 26 | /** 27 | * Initialize the class. 28 | * 29 | * @since 1.0.0 30 | */ 31 | public function init() { 32 | /** 33 | * This backend class is only being instantiated in the backend as requested in the Bootstrap class 34 | * 35 | * @see Requester::isAdminBackend() 36 | * @see Bootstrap::__construct 37 | * 38 | * Add plugin code here for admin notices specific functions 39 | */ 40 | add_action( 'admin_notices', [ $this, 'exampleAdminNotice' ] ); 41 | } 42 | 43 | /** 44 | * Example admin notice 45 | * 46 | * @since 1.0.0 47 | */ 48 | public function exampleAdminNotice() { 49 | global $pagenow; 50 | if ( $pagenow === 'options-general.php' ) { 51 | echo '
52 |

' . __( 'This is an example of a notice that appears on the settings page.', 'the-plugin-name-text-domain' ) . '

53 |
'; 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/App/Backend/Settings.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright {{author_copyright}} 8 | * @license {{author_license}} 9 | * @link {{author_url}} 10 | */ 11 | 12 | declare( strict_types = 1 ); 13 | 14 | namespace ThePluginName\App\Backend; 15 | 16 | use ThePluginName\Common\Abstracts\Base; 17 | 18 | /** 19 | * Class Settings 20 | * 21 | * @package ThePluginName\App\Backend 22 | * @since 1.0.0 23 | */ 24 | class Settings extends Base { 25 | 26 | /** 27 | * Initialize the class. 28 | * 29 | * @since 1.0.0 30 | */ 31 | public function init() { 32 | /** 33 | * This backend class is only being instantiated in the backend as requested in the Bootstrap class 34 | * 35 | * @see Requester::isAdminBackend() 36 | * @see Bootstrap::__construct 37 | * 38 | * Add plugin code here for admin settings specific functions 39 | */ 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/App/Cli/Example.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright {{author_copyright}} 8 | * @license {{author_license}} 9 | * @link {{author_url}} 10 | */ 11 | 12 | declare( strict_types = 1 ); 13 | 14 | namespace ThePluginName\App\Cli; 15 | 16 | use ThePluginName\Common\Abstracts\Base; 17 | 18 | /** 19 | * Class Example 20 | * 21 | * @package ThePluginName\App\Cli 22 | * @since 1.0.0 23 | */ 24 | class Example extends Base { 25 | 26 | /** 27 | * Initialize the class. 28 | * 29 | * @since 1.0.0 30 | */ 31 | public function init() { 32 | /** 33 | * This class is only being instantiated if WP_Cli is defined in the requester as requested in the Bootstrap class 34 | * 35 | * @see Requester::isCli() 36 | * @see Bootstrap::__construct 37 | */ 38 | if ( class_exists( \WP_CLI ) ) { 39 | \WP_CLI::add_command( 'plugin_commandname', [ $this, 'commandExample' ] ); 40 | } 41 | } 42 | 43 | /** 44 | * Example command 45 | * API reference: https://wp-cli.org/docs/internal-api/ 46 | * 47 | * @param array $args The attributes. 48 | * @return void 49 | * @since 1.0.0 50 | */ 51 | public function commandExample( array $args ) { 52 | // Message prefixed with "Success: ". 53 | \WP_CLI::success( $args[0] ); 54 | // Message prefixed with "Warning: ". 55 | \WP_CLI::warning( $args[0] ); 56 | // Message prefixed with "Debug: ". when '--debug' is used 57 | \WP_CLI::debug( $args[0] ); 58 | // Message prefixed with "Error: ". 59 | \WP_CLI::error( $args[0] ); 60 | // Message with no prefix 61 | \WP_CLI::log( $args[0] ); 62 | // Colorize a string for output 63 | \WP_CLI::colorize( $args[0] ); 64 | // Halt script execution with a specific return code 65 | \WP_CLI::halt( $args[0] ); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/App/Cron/Example.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright {{author_copyright}} 8 | * @license {{author_license}} 9 | * @link {{author_url}} 10 | */ 11 | 12 | declare( strict_types = 1 ); 13 | 14 | namespace ThePluginName\App\Cron; 15 | 16 | use ThePluginName\Common\Abstracts\Base; 17 | 18 | /** 19 | * Class Example 20 | * 21 | * @package ThePluginName\App\Cron 22 | * @since 1.0.0 23 | */ 24 | class Example extends Base { 25 | 26 | /** 27 | * Initialize the class. 28 | * 29 | * @since 1.0.0 30 | */ 31 | public function init() { 32 | /** 33 | * This class is only being instantiated if DOING_CRON is defined in the requester as requested in the Bootstrap class 34 | * 35 | * @see Requester::isCron() 36 | * @see Bootstrap::__construct 37 | */ 38 | 39 | add_action( 'wp', [ $this, 'activationDeactivationExample' ] ); 40 | add_action( 'plugin_cronjobs', [ $this, 'cronjobRepeatingFunctionExample' ] ); 41 | } 42 | 43 | /** 44 | * Activates a scheduled event (if it does not exist already) 45 | * 46 | * @since 1.0.0 47 | */ 48 | public function activationDeactivationExample() { 49 | if ( ! wp_next_scheduled( 'plugin_cronjobs' ) ) { 50 | wp_schedule_event( time(), 'daily', 'plugin_cronjobs' ); 51 | } else { 52 | $timestamp = wp_next_scheduled( 'mycronjob' ); 53 | wp_unschedule_event( $timestamp, 'mycronjob' ); 54 | } 55 | } 56 | 57 | /** 58 | * The function that gets called with the scheduled event 59 | * 60 | * @since 1.0.0 61 | */ 62 | public function cronjobRepeatingFunctionExample() { 63 | // do here what needs to be done automatically as per schedule 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/App/Frontend/Enqueue.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright {{author_copyright}} 8 | * @license {{author_license}} 9 | * @link {{author_url}} 10 | */ 11 | 12 | declare( strict_types = 1 ); 13 | 14 | namespace ThePluginName\App\Frontend; 15 | 16 | use ThePluginName\Common\Abstracts\Base; 17 | 18 | /** 19 | * Class Enqueue 20 | * 21 | * @package ThePluginName\App\Frontend 22 | * @since 1.0.0 23 | */ 24 | class Enqueue extends Base { 25 | 26 | /** 27 | * Initialize the class. 28 | * 29 | * @since 1.0.0 30 | */ 31 | public function init() { 32 | /** 33 | * This frontend class is only being instantiated in the frontend as requested in the Bootstrap class 34 | * 35 | * @see Requester::isFrontend() 36 | * @see Bootstrap::__construct 37 | * 38 | * Add plugin code here 39 | */ 40 | add_action( 'wp_enqueue_scripts', [ $this, 'enqueueScripts' ] ); 41 | } 42 | 43 | /** 44 | * Enqueue scripts function 45 | * 46 | * @since 1.0.0 47 | */ 48 | public function enqueueScripts() { 49 | // Enqueue CSS 50 | foreach ( 51 | [ 52 | [ 53 | 'deps' => [], 54 | 'handle' => 'plugin-name-frontend-css', 55 | 'media' => 'all', 56 | 'source' => plugins_url( '/assets/public/css/frontend.css', _THE_PLUGIN_NAME_PLUGIN_FILE ), // phpcs:disable ImportDetection.Imports.RequireImports.Symbol -- this constant is global 57 | 'version' => $this->plugin->version(), 58 | ], 59 | ] as $css ) { 60 | wp_enqueue_style( $css['handle'], $css['source'], $css['deps'], $css['version'], $css['media'] ); 61 | } 62 | // Enqueue JS 63 | foreach ( 64 | [ 65 | [ 66 | 'deps' => [], 67 | 'handle' => 'plugin-test-frontend-js', 68 | 'in_footer' => true, 69 | 'source' => plugins_url( '/assets/public/js/frontend.js', _THE_PLUGIN_NAME_PLUGIN_FILE ), // phpcs:disable ImportDetection.Imports.RequireImports.Symbol -- this constant is global 70 | 'version' => $this->plugin->version(), 71 | ], 72 | ] as $js ) { 73 | wp_enqueue_script( $js['handle'], $js['source'], $js['deps'], $js['version'], $js['in_footer'] ); 74 | } 75 | 76 | // Send variables to JS 77 | global $wp_query; 78 | 79 | // localize script and send variables 80 | wp_localize_script( 'plugin-test-frontend-js', 'plugin_frontend_script', 81 | [ 82 | 'plugin_frontend_url' => admin_url( 'admin-ajax.php' ), 83 | 'plugin_wp_query_vars' => $wp_query->query_vars, 84 | ] 85 | ); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/App/Frontend/Templates.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright {{author_copyright}} 8 | * @license {{author_license}} 9 | * @link {{author_url}} 10 | */ 11 | 12 | declare( strict_types = 1 ); 13 | 14 | namespace ThePluginName\App\Frontend; 15 | 16 | use ThePluginName\Common\Abstracts\Base; 17 | 18 | /** 19 | * Class Templates 20 | * 21 | * @package ThePluginName\App\Frontend 22 | * @since 1.0.0 23 | */ 24 | class Templates extends Base { 25 | /** 26 | * Internal use only: Store located template paths. 27 | * 28 | * @var array 29 | */ 30 | private $path_cache = []; 31 | 32 | /** 33 | * Initialize the class. 34 | * 35 | * @since 1.0.0 36 | */ 37 | public function init() { 38 | /** 39 | * This frontend class is only being instantiated in the frontend as requested in the Bootstrap class 40 | * 41 | * @see Requester::isFrontend() 42 | * @see Bootstrap::__construct 43 | * 44 | * Add plugin code here for template specific functions 45 | */ 46 | 47 | /** 48 | * Example code using the get template function with the use of arguments 49 | */ 50 | add_action( 'wp_footer', function () { 51 | $this->get( 'test-template', null, 52 | [ 53 | 'class' => 'user', 54 | 'data' => 55 | [ 'text' => 'with arguments' ], 56 | ] 57 | ); 58 | } ); 59 | } 60 | 61 | /** 62 | * Retrieve a template part, modified version of: 63 | * @url https://github.com/GaryJones/Gamajo-Template-Loader 64 | * 65 | * @param string $slug Template slug. 66 | * @param string $name Optional. Template variation name. Default null. 67 | * @param bool $load Optional. Whether to load template. Default true. 68 | * @return string 69 | * @since 1.0.0 70 | * 71 | */ 72 | public function get( $slug, $name = null, $args = [], $load = true ): string { 73 | // Execute code for this part. 74 | do_action( 'get_template_part_' . $slug, $slug, $name, $args ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound 75 | do_action( 'the_plugin_name_get_template_part_' . $slug, $slug, $name, $args ); 76 | // Get files names of templates, for given slug and name. 77 | $templates = $this->getFileNames( $slug, $name, $args ); 78 | // Return the part that is found. 79 | return $this->locate( $templates, $load, false, $args ); 80 | } 81 | 82 | /** 83 | * Given a slug and optional name, create the file names of templates, modified version of: 84 | * @url https://github.com/GaryJones/Gamajo-Template-Loader 85 | * 86 | * @param string $slug Template slug. 87 | * @param string $name Template variation name. 88 | * @param $args 89 | * @return array 90 | * @since 1.0.0 91 | */ 92 | protected function getFileNames( $slug, $name, $args ): array { 93 | $templates = []; 94 | if ( isset( $name ) ) { 95 | $templates[] = $slug . '-' . $name . '.php'; 96 | } 97 | $templates[] = $slug . '.php'; 98 | /** 99 | * Allow template choices to be filtered. 100 | * 101 | * The resulting array should be in the order of most specific first, to least specific last. 102 | * e.g. 0 => recipe-instructions.php, 1 => recipe.php 103 | * 104 | * @param array $templates Names of template files that should be looked for, for given slug and name. 105 | * @param string $slug Template slug. 106 | * @param string $name Template variation name. 107 | * @since 1.0.0 108 | * 109 | */ 110 | return apply_filters( 'the_plugin_name_get_template_part', $templates, $slug, $name, $args ); 111 | } 112 | 113 | /** 114 | * Retrieve the name of the highest priority template file that exists, modified version of: 115 | * @url https://github.com/GaryJones/Gamajo-Template-Loader 116 | * 117 | * Searches in the STYLESHEETPATH before TEMPLATEPATH so that themes which 118 | * inherit from a parent theme can just overload one file. If the template is 119 | * not found in either of those, it looks in the theme-compat folder last. 120 | * 121 | * @param string|array $template_names Template file(s) to search for, in order. 122 | * @param bool $load If true the template file will be loaded if it is found. 123 | * @param bool $require_once Whether to require_once or require. Default true. 124 | * Has no effect if $load is false. 125 | * @param array $args 126 | * @return string The template filename if one is located. 127 | * @since 1.0.0 128 | */ 129 | public function locate( $template_names, $load = false, $require_once = true, $args = [] ): string { 130 | // Use $template_names as a cache key - either first element of array or the variable itself if it's a string. 131 | $cache_key = is_array( $template_names ) ? $template_names[0] : $template_names; 132 | // If the key is in the cache array, we've already located this file. 133 | if ( isset( $this->path_cache[ $cache_key ] ) ) { 134 | $located = $this->path_cache[ $cache_key ]; 135 | } else { 136 | // No file found yet. 137 | $located = false; 138 | // Remove empty entries. 139 | $template_names = array_filter( (array) $template_names ); 140 | $template_paths = $this->getPaths(); 141 | // Try to find a template file. 142 | foreach ( $template_names as $template_name ) { 143 | // Trim off any slashes from the template name. 144 | $template_name = ltrim( $template_name, '/' ); 145 | // Try locating this template file by looping through the template paths. 146 | foreach ( $template_paths as $template_path ) { 147 | if ( file_exists( $template_path . $template_name ) ) { 148 | $located = $template_path . $template_name; 149 | // Store the template path in the cache. 150 | $this->path_cache[ $cache_key ] = $located; 151 | break 2; 152 | } 153 | } 154 | } 155 | } 156 | if ( $load && $located ) { 157 | load_template( $located, $require_once, $args ); 158 | } 159 | return $located; 160 | } 161 | 162 | /** 163 | * Return a list of paths to check for template locations, modified version of: 164 | * @url https://github.com/GaryJones/Gamajo-Template-Loader 165 | * 166 | * Default is to check in a child theme (if relevant) before a parent theme, so that themes which inherit from a 167 | * parent theme can just overload one file. If the template is not found in either of those, it looks in the 168 | * theme-compat folder last. 169 | * 170 | * @return mixed|void 171 | * @since 1.0.0 172 | * 173 | */ 174 | protected function getPaths(): array { 175 | $theme_directory = trailingslashit( $this->plugin->extTemplateFolder() ); 176 | 177 | $file_paths = [ 178 | 10 => trailingslashit( get_template_directory() ) . $theme_directory, 179 | 100 => $this->plugin->templatePath(), 180 | ]; 181 | // Only add this conditionally, so non-child themes don't redundantly check active theme twice. 182 | if ( get_stylesheet_directory() !== get_template_directory() ) { 183 | $file_paths[1] = trailingslashit( get_stylesheet_directory() ) . $theme_directory; 184 | } 185 | /** 186 | * Allow ordered list of template paths to be amended. 187 | * 188 | * @param array $var Default is directory in child theme at index 1, parent theme at 10, and plugin at 100. 189 | * @since 1.0.0 190 | * 191 | */ 192 | $file_paths = apply_filters( 'the_plugin_name_template_paths', $file_paths ); 193 | // Sort the file paths based on priority. 194 | ksort( $file_paths, SORT_NUMERIC ); 195 | return array_map( 'trailingslashit', $file_paths ); 196 | } 197 | } 198 | -------------------------------------------------------------------------------- /src/App/General/PostTypes.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright {{author_copyright}} 8 | * @license {{author_license}} 9 | * @link {{author_url}} 10 | */ 11 | 12 | declare( strict_types = 1 ); 13 | 14 | namespace ThePluginName\App\General; 15 | 16 | use ThePluginName\Common\Abstracts\Base; 17 | 18 | /** 19 | * Class PostTypes 20 | * 21 | * @package ThePluginName\App\General 22 | * @since 1.0.0 23 | */ 24 | class PostTypes extends Base { 25 | 26 | /** 27 | * Post type data 28 | */ 29 | public const POST_TYPE = [ 30 | 'id' => 'example-post-type', 31 | 'archive' => 'example-post-types', 32 | 'title' => 'Example Posts', 33 | 'singular' => 'Example Post', 34 | 'icon' => 'dashicons-format-chat', 35 | ]; 36 | 37 | /** 38 | * Initialize the class. 39 | * 40 | * @since 1.0.0 41 | */ 42 | public function init() { 43 | /** 44 | * This general class is always being instantiated as requested in the Bootstrap class 45 | * 46 | * @see Bootstrap::__construct 47 | * 48 | * Add plugin code here 49 | */ 50 | add_action( 'init', [ $this, 'register' ] ); 51 | } 52 | 53 | /** 54 | * Register post type 55 | * 56 | * @since 1.0.0 57 | */ 58 | public function register() { 59 | register_post_type( $this::POST_TYPE['id'], 60 | [ 61 | 'labels' => [ 62 | 'name' => $this::POST_TYPE['title'], 63 | 'singular_name' => $this::POST_TYPE['singular'], 64 | 'menu_name' => $this::POST_TYPE['title'], 65 | 'name_admin_bar' => $this::POST_TYPE['singular'], 66 | 'add_new' => sprintf( /* translators: %s: post type singular title */ __( 'New %s', 'the-plugin-name-text-domain' ), $this::POST_TYPE['singular'] ), 67 | 'add_new_item' => sprintf( /* translators: %s: post type singular title */ __( 'Add New %s', 'the-plugin-name-text-domain' ), $this::POST_TYPE['singular'] ), 68 | 'new_item' => sprintf( /* translators: %s: post type singular title */ __( 'New %s', 'the-plugin-name-text-domain' ), $this::POST_TYPE['singular'] ), 69 | 'edit_item' => sprintf( /* translators: %s: post type singular title */ __( 'Edit %s', 'the-plugin-name-text-domain' ), $this::POST_TYPE['singular'] ), 70 | 'view_item' => sprintf( /* translators: %s: post type singular title */ __( 'View %s', 'the-plugin-name-text-domain' ), $this::POST_TYPE['singular'] ), 71 | 'all_items' => sprintf( /* translators: %s: post type title */ __( 'All %s', 'the-plugin-name-text-domain' ), $this::POST_TYPE['title'] ), 72 | 'search_items' => sprintf( /* translators: %s: post type title */ __( 'Search %s', 'the-plugin-name-text-domain' ), $this::POST_TYPE['title'] ), 73 | ], 74 | 'public' => true, 75 | 'publicly_queryable' => true, 76 | 'has_archive' => $this::POST_TYPE['archive'], 77 | 'show_ui' => true, 78 | 'rewrite' => [ 79 | 'slug' => $this::POST_TYPE['archive'], 80 | 'with_front' => true, 81 | ], 82 | 'show_in_menu' => true, 83 | 'query_var' => true, 84 | 'capability_type' => 'post', 85 | 'menu_icon' => $this::POST_TYPE['icon'], 86 | 'supports' => [ 'title', 'editor', 'thumbnail' ], 87 | ] 88 | ); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/App/General/Queries.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright {{author_copyright}} 8 | * @license {{author_license}} 9 | * @link {{author_url}} 10 | */ 11 | 12 | declare( strict_types = 1 ); 13 | 14 | namespace ThePluginName\App\General; 15 | 16 | use ThePluginName\Common\Abstracts\Base; 17 | use ThePluginName\App\General\PostTypes; 18 | 19 | /** 20 | * Class Queries 21 | * 22 | * @package ThePluginName\App\General 23 | * @since 1.0.0 24 | */ 25 | class Queries extends Base { 26 | 27 | /** 28 | * Initialize the class. 29 | * 30 | * @since 1.0.0 31 | */ 32 | public function init() { 33 | /** 34 | * This general class is always being instantiated as requested in the Bootstrap class 35 | * 36 | * @see Bootstrap::__construct 37 | * 38 | * Add plugin code here 39 | */ 40 | } 41 | 42 | /** 43 | * @param $posts_count 44 | * @param string $orderby 45 | * @return \WP_Query 46 | */ 47 | public function getPosts( $posts_count, $orderby = 'date' ): \WP_Query { 48 | return new \WP_Query( 49 | [ 50 | 'post_type' => PostTypes::POST_TYPE['id'], 51 | 'post_status' => 'publish', 52 | 'order' => 'DESC', 53 | 'posts_per_page' => $posts_count, 54 | 'orderby' => $orderby, 55 | ] 56 | ); 57 | } 58 | 59 | /** 60 | * Example 61 | * 62 | * @return array 63 | */ 64 | public function getPostIds(): array { 65 | global $wpdb; 66 | return $wpdb->get_col( "select ID from {$wpdb->posts} LIMIT 3" ); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/App/General/Shortcodes.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright {{author_copyright}} 8 | * @license {{author_license}} 9 | * @link {{author_url}} 10 | */ 11 | 12 | declare( strict_types = 1 ); 13 | 14 | namespace ThePluginName\App\General; 15 | 16 | use ThePluginName\Common\Abstracts\Base; 17 | 18 | /** 19 | * Class Shortcodes 20 | * 21 | * @package ThePluginName\App\General 22 | * @since 1.0.0 23 | */ 24 | class Shortcodes extends Base { 25 | /** 26 | * Initialize the class. 27 | * 28 | * @since 1.0.0 29 | */ 30 | public function init() { 31 | /** 32 | * This general class is always being instantiated as requested in the Bootstrap class 33 | * 34 | * @see Bootstrap::__construct 35 | * 36 | * Add plugin code here 37 | */ 38 | 39 | add_shortcode( 'foobar', [ $this, 'foobarFunc' ] ); 40 | } 41 | 42 | /** 43 | * Shortcode example 44 | * 45 | * @param array $atts Parameters. 46 | * @return string 47 | * @since 1.0.0 48 | */ 49 | public function foobarFunc( array $atts ): string { 50 | shortcode_atts( 51 | [ 52 | 'foo' => 'something', 53 | 'bar' => 'something else', 54 | ], $atts 55 | ); 56 | return 'foo = ' . $atts['foo'] . '' . 57 | 'foo = ' . $atts['bar'] . ''; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/App/General/Widgets.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright {{author_copyright}} 8 | * @license {{author_license}} 9 | * @link {{author_url}} 10 | */ 11 | 12 | declare( strict_types = 1 ); 13 | 14 | namespace ThePluginName\App\General; 15 | 16 | use ThePluginName\Common\Abstracts\Base; 17 | 18 | /** 19 | * Class Widgets 20 | * 21 | * @package ThePluginName\App\General 22 | * @since 1.0.0 23 | */ 24 | class Widgets extends Base { 25 | 26 | /** 27 | * Initialize the class. 28 | * 29 | * @since 1.0.0 30 | */ 31 | public function init() { 32 | /** 33 | * This general class is always being instantiated as requested in the Bootstrap class 34 | * 35 | * @see Bootstrap::__construct 36 | * 37 | * Widget is registered from the Integrations folder, but it can also be registered 38 | * from the integration class file self 39 | * @see HTML_Widget::init() 40 | */ 41 | add_action( 'widgets_init', function () { 42 | register_widget( $this->plugin->namespace() . '\Integrations\Widget\HTML_Widget' ); 43 | } ); 44 | } 45 | } 46 | 47 | -------------------------------------------------------------------------------- /src/App/Rest/Example.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright {{author_copyright}} 8 | * @license {{author_license}} 9 | * @link {{author_url}} 10 | */ 11 | 12 | declare( strict_types = 1 ); 13 | 14 | namespace ThePluginName\App\Rest; 15 | 16 | use ThePluginName\Common\Abstracts\Base; 17 | 18 | /** 19 | * Class Example 20 | * 21 | * @package ThePluginName\App\Rest 22 | * @since 1.0.0 23 | */ 24 | class Example extends Base { 25 | 26 | /** 27 | * Initialize the class. 28 | * 29 | * @since 1.0.0 30 | */ 31 | public function init() { 32 | /** 33 | * This class is only being instantiated if REST_REQUEST is defined in the requester as requested in the Bootstrap class 34 | * 35 | * @see Requester::isRest() 36 | * @see Bootstrap::__construct 37 | */ 38 | 39 | if ( class_exists( 'WP_REST_Server' ) ) { 40 | add_action( 'rest_api_init', [ $this, 'addPluginRestApi' ] ); 41 | } 42 | } 43 | 44 | /** 45 | * @since 1.0.0 46 | */ 47 | public function addPluginRestApi() { 48 | $this->addCustomField(); 49 | $this->addCustomRoute(); 50 | } 51 | 52 | /** 53 | * Examples 54 | * 55 | * @since 1.0.0 56 | */ 57 | public function addCustomField() { 58 | register_rest_field( 59 | 'demo', 60 | $this->plugin->textDomain() . '_text', 61 | [ 62 | 'get_callback' => [ $this, 'getTextField' ], 63 | 'update_callback' => [ $this, 'updateTextField' ], 64 | 'schema' => [ 65 | 'description' => __( 'Text field demo of Post type', 'the-plugin-name-text-domain' ), 66 | 'type' => 'string', 67 | ], 68 | ] 69 | ); 70 | } 71 | 72 | /** 73 | * Examples 74 | * 75 | * @return void 76 | * @since 1.0.0 77 | */ 78 | public function addCustomRoute() { 79 | // Only an example with 2 parameters 80 | register_rest_route( 81 | 'wp/v2', 82 | '/calc', 83 | [ 84 | 'methods' => \WP_REST_Server::READABLE, 85 | 'callback' => [ $this, 'sum' ], 86 | 'args' => [ 87 | 'first' => [ 88 | 'default' => 10, 89 | 'sanitize_callback' => 'absint', 90 | ], 91 | 'second' => [ 92 | 'default' => 1, 93 | 'sanitize_callback' => 'absint', 94 | ], 95 | ], 96 | ] 97 | ); 98 | } 99 | 100 | /** 101 | * Examples 102 | * 103 | * @param array $post_obj Post ID. 104 | * @return string 105 | * @since 1.0.0 106 | */ 107 | public function getTextField( array $post_obj ): string { 108 | $post_id = $post_obj['id']; 109 | 110 | return get_post_meta( $post_id, $this->plugin->textDomain() . '_text', true ); 111 | } 112 | 113 | /** 114 | * Examples 115 | * 116 | * @param string $value Value. 117 | * @param \WP_Post $post Post object. 118 | * @param string $key Key. 119 | * @return \WP_Error 120 | * @since 1.0.0 121 | */ 122 | public function updateTextField( string $value, \WP_Post $post, string $key ): \WP_Error { 123 | $post_id = update_post_meta( $post->ID, $key, $value ); 124 | 125 | if ( false === $post_id ) { 126 | return new \WP_Error( 127 | 'rest_post_views_failed', 128 | \__( 'Failed to update post views.', 'the-plugin-name-text-domain' ), 129 | [ 'status' => 500 ] 130 | ); 131 | } 132 | 133 | return true; 134 | } 135 | 136 | /** 137 | * Examples 138 | * 139 | * @param array $data Values. 140 | * @return array 141 | * @since 1.0.0 142 | */ 143 | public function sum( array $data ): array { 144 | return [ 'result' => $data['first'] + $data['second'] ]; 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /src/Bootstrap.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright {{author_copyright}} 8 | * @license {{author_license}} 9 | * @link {{author_url}} 10 | */ 11 | 12 | declare( strict_types = 1 ); 13 | 14 | namespace ThePluginName; 15 | 16 | use ThePluginName\Common\Abstracts\Base; 17 | use ThePluginName\Common\Traits\Requester; 18 | use ThePluginName\Common\Utils\Errors; 19 | use ThePluginName\Config\Classes; 20 | use ThePluginName\Config\I18n; 21 | use ThePluginName\Config\Requirements; 22 | 23 | /** 24 | * Bootstrap the plugin 25 | * 26 | * @since 1.0.0 27 | */ 28 | final class Bootstrap extends Base { 29 | 30 | /** 31 | * Determine what we're requesting 32 | * 33 | * @see Requester 34 | */ 35 | use Requester; 36 | 37 | /** 38 | * Used to debug the Bootstrap class; this will print a visualised array 39 | * of the classes that are loaded with the total execution time if set true 40 | * 41 | * @var array 42 | */ 43 | public $bootstrap = [ 'debug' => false ]; 44 | 45 | /** 46 | * List of class to init 47 | * 48 | * @var array : classes 49 | */ 50 | public $class_list = []; 51 | 52 | /** 53 | * Composer autoload file list 54 | * 55 | * @var Composer\Autoload\ClassLoader 56 | */ 57 | public $composer; 58 | 59 | /** 60 | * Requirements class object 61 | * 62 | * @var Requirements 63 | */ 64 | protected $requirements; 65 | 66 | /** 67 | * I18n class object 68 | * 69 | * @var I18n 70 | */ 71 | protected $i18n; 72 | 73 | /** 74 | * Bootstrap constructor that 75 | * - Checks compatibility/plugin requirements 76 | * - Defines the locale for this plugin for internationalization 77 | * - Load the classes via Composer's class loader and initialize them on type of request 78 | * 79 | * @param \Composer\Autoload\ClassLoader $composer Composer autoload output. 80 | * @throws \Exception 81 | * @since 1.0.0 82 | */ 83 | public function __construct( $composer ) { 84 | parent::__construct(); 85 | $this->startExecutionTimer(); 86 | $this->checkRequirements(); 87 | $this->setLocale(); 88 | $this->getClassLoader( $composer ); 89 | $this->loadClasses( Classes::get() ); 90 | $this->debugger(); 91 | } 92 | 93 | /** 94 | * Check plugin requirements 95 | * 96 | * @since 1.0.0 97 | */ 98 | public function checkRequirements() { 99 | $set_timer = microtime( true ); 100 | $this->requirements = new Requirements(); 101 | $this->requirements->check(); 102 | $this->bootstrap['check_requirements'] = $this->stopExecutionTimer( $set_timer ); 103 | } 104 | 105 | /** 106 | * Define the locale for this plugin for internationalization. 107 | * 108 | * @since 1.0.0 109 | */ 110 | public function setLocale() { 111 | $set_timer = microtime( true ); 112 | $this->i18n = new I18n(); 113 | $this->i18n->load(); 114 | $this->bootstrap['set_locale'] = $this->stopExecutionTimer( $set_timer ); 115 | } 116 | 117 | /** 118 | * Get the class loader from Composer 119 | * 120 | * @param $composer 121 | * @since 1.0.0 122 | */ 123 | public function getClassLoader( $composer ) { 124 | $this->composer = $composer; 125 | } 126 | 127 | /** 128 | * Initialize the requested classes 129 | * 130 | * @param $classes : The loaded classes. 131 | * @since 1.0.0 132 | */ 133 | public function loadClasses( $classes ) { 134 | $set_timer = microtime( true ); 135 | foreach ( $classes as $class ) { 136 | if ( isset( $class['on_request'] ) && is_array( $class['on_request'] ) 137 | ) { 138 | foreach ( $class['on_request'] as $on_request ) { 139 | if ( ! $this->request( $on_request ) ) { 140 | continue; 141 | } 142 | } 143 | } elseif ( isset( $class['on_request'] ) && ! $this->request( $class['on_request'] ) 144 | ) { 145 | continue; 146 | } 147 | $this->getClasses( $class['init'] ); 148 | } 149 | $this->initClasses(); 150 | $this->bootstrap['initialized_classes']['timer'] = $this->stopExecutionTimer( $set_timer, 'Total execution time of initialized classes' ); 151 | } 152 | 153 | /** 154 | * Init the classes 155 | * 156 | * @since 1.0.0 157 | */ 158 | public function initClasses() { 159 | $this->class_list = \apply_filters( 'the_plugin_name_initialized_classes', $this->class_list ); 160 | foreach ( $this->class_list as $class ) { 161 | try { 162 | $set_timer = microtime( true ); 163 | // phpcs:ignore NeutronStandard.Functions.VariableFunctions.VariableFunction 164 | $this->bootstrap['initialized_classes'][ $class ] = new $class(); 165 | $this->bootstrap['initialized_classes'][ $class ]->init(); 166 | $this->bootstrap['initialized_classes'][ $class ] = $this->stopExecutionTimer( $set_timer ); 167 | } catch ( \Throwable $err ) { 168 | \do_action( 'the_plugin_name_class_initialize_failed', $err, $class ); 169 | Errors::wpDie( 170 | sprintf( /* translators: %s: php class namespace */ 171 | __( 'Could not load class "%s". The "init" method is probably missing or try a `composer dumpautoload -o` to refresh the autoloader.', 172 | 'the-plugin-name-text-domain' 173 | ), $class 174 | ), 175 | __( 'Plugin initialize failed', 'the-plugin-name-text-domain' ), 176 | __FILE__, $err 177 | ); 178 | } 179 | } 180 | } 181 | 182 | /** 183 | * Get classes based on the directory automatically using the Composer autoload 184 | * 185 | * @param string $namespace Class name to find. 186 | * @return array Return the classes. 187 | * @since 1.0.0 188 | */ 189 | public function getClasses( string $namespace ): array { 190 | $namespace = $this->plugin->namespace() . '\\' . $namespace; 191 | if ( is_object( $this->composer ) !== false ) { 192 | $classmap = $this->composer->getClassMap(); 193 | 194 | // First we're going to try to load the classes via Composer's Autoload 195 | // which will improve the performance. This is only possible if the Autoloader 196 | // has been optimized. 197 | if ( isset( $classmap[ $this->plugin->namespace() . '\\Bootstrap' ] ) ) { 198 | if ( ! isset( $this->bootstrap['initialized_classes']['load_by'] ) ) { 199 | $this->bootstrap['initialized_classes']['load_by'] = 'Autoloader'; 200 | } 201 | $classes = array_keys( $classmap ); 202 | foreach ( $classes as $class ) { 203 | if ( 0 !== strncmp( (string) $class, $namespace, strlen( $namespace ) ) ) { 204 | continue; 205 | } 206 | $this->class_list[] = $class; 207 | } 208 | return $this->class_list; 209 | } 210 | } 211 | 212 | // If the composer.json file is updated then Autoloader is not optimized and we 213 | // can't load classes via the Autoloader. The `composer dumpautoload -o` command needs to 214 | // to be called; in the mean time we're going to load the classes differently which will 215 | // be a bit slower. The plugin needs to be optimized before production-release 216 | // Errors::writeLog( 217 | // [ 218 | // 'title' => __( '{{The Plugin Name}} classes are not being loaded by Composer\'s Autoloader' ), 219 | // 'message' => __( 'Try a `composer dumpautoload -o` to optimize the autoloader that will improve the performance on autoloading itself.' ) 220 | // ] 221 | //); 222 | return $this->getByExtraction( $namespace ); 223 | } 224 | 225 | /** 226 | * Get classes by file extraction, will only run if autoload fails 227 | * 228 | * @param $namespace 229 | * @return array 230 | * @since 1.0.0 231 | */ 232 | public function getByExtraction( $namespace ): array { 233 | if ( ! isset( $this->bootstrap['initialized_classes']['load_by'] ) ) { 234 | $this->bootstrap['initialized_classes']['load_by'] = 'Extraction; Try a `composer dumpautoload -o` to optimize the autoloader.'; 235 | } 236 | $find_all_classes = []; 237 | foreach ( $this->filesFromThisDir() as $file ) { 238 | $file_data = [ 239 | // phpcs:disable 240 | // file_get_contents() is only discouraged by PHPCS for remote files 241 | 'tokens' => token_get_all( file_get_contents( $file->getRealPath() ) ), 242 | // phpcs:enable 243 | 'namespace' => '', 244 | ]; 245 | $find_all_classes = array_merge( $find_all_classes, $this->extractClasses( $file_data ) ); 246 | } 247 | $this->classBelongsTo( $find_all_classes, $namespace . '\\' ); 248 | return $this->class_list; 249 | } 250 | 251 | /** 252 | * Extract class from file, will only run if autoload fails 253 | * 254 | * @param $file_data 255 | * @param array $classes 256 | * @return array 257 | * @since 1.0.0 258 | */ 259 | public function extractClasses( $file_data, $classes = [] ): array { 260 | for ( $index = 0; isset( $file_data['tokens'][ $index ] ); $index++ ) { 261 | if ( ! isset( $file_data['tokens'][ $index ][0] ) ) { 262 | continue; 263 | } 264 | if ( T_NAMESPACE === $file_data['tokens'][ $index ][0] ) { 265 | $index += 2; // Skip namespace keyword and whitespace 266 | while ( isset( $file_data['tokens'][ $index ] ) && is_array( $file_data['tokens'][ $index ] ) ) { 267 | $file_data['namespace'] .= $file_data['tokens'][ $index++ ][1]; 268 | } 269 | } 270 | if ( T_CLASS === $file_data['tokens'][ $index ][0] && T_WHITESPACE === $file_data['tokens'][ $index + 1 ][0] && T_STRING === $file_data['tokens'][ $index + 2 ][0] ) { 271 | $index += 2; // Skip class keyword and whitespace 272 | // So it only works with 1 class per file (which should be psr-4 compliant) 273 | $classes[] = $file_data['namespace'] . '\\' . $file_data['tokens'][ $index ][1]; 274 | break; 275 | } 276 | } 277 | return $classes; 278 | } 279 | 280 | /** 281 | * Get all files from current dir, will only run if autoload fails 282 | * 283 | * @return mixed 284 | * @since 1.0.0 285 | */ 286 | public function filesFromThisDir(): \RegexIterator { 287 | $files = new \RecursiveIteratorIterator( new \RecursiveDirectoryIterator( __DIR__ ) ); 288 | $files = new \RegexIterator( $files, '/\.php$/' ); 289 | return $files; 290 | } 291 | 292 | /** 293 | * Checks if class belongs to namespace, will only run if autoload fails 294 | * 295 | * @param $classes 296 | * @param $namespace 297 | * @since 1.0.0 298 | */ 299 | public function classBelongsTo( $classes, $namespace ) { 300 | foreach ( $classes as $class ) { 301 | if ( strpos( $class, $namespace ) === 0 ) { 302 | $this->class_list[] = $class; 303 | } 304 | } 305 | } 306 | 307 | /** 308 | * Start the execution timer of the plugin 309 | * 310 | * @since 1.0.0 311 | */ 312 | public function startExecutionTimer() { 313 | if ( $this->bootstrap['debug'] === true ) { 314 | $this->bootstrap['execution_time']['start'] = microtime( true ); 315 | } 316 | } 317 | 318 | /** 319 | * @param $timer 320 | * @param string $tag 321 | * @return string 322 | * @since 1.0.0 323 | */ 324 | public function stopExecutionTimer( $timer, $tag = 'Execution time' ): string { 325 | if ( $this->bootstrap['debug'] === true ) { 326 | return 'Elapsed: ' . ( microtime( true ) - $this->bootstrap['execution_time']['start'] ) . ' | ' . $tag . ': ' . ( microtime( true ) - $timer ); 327 | } else { 328 | return ''; 329 | } 330 | } 331 | 332 | /** 333 | * Visual presentation of the classes that are loaded 334 | */ 335 | public function debugger() { 336 | if ( $this->bootstrap['debug'] === true ) { 337 | $this->bootstrap['execution_time'] = 338 | 'Total execution time in seconds: ' . ( microtime( true ) - $this->bootstrap['execution_time']['start'] ); 339 | add_action( 'shutdown', function () { 340 | ini_set( 'highlight.comment', '#969896; font-style: italic' ); 341 | ini_set( 'highlight.default', '#FFFFFF' ); 342 | ini_set( 'highlight.html', '#D16568; font-size: 13px; padding: 0; display: block;' ); 343 | ini_set( 'highlight.keyword', '#7FA3BC; font-weight: bold; padding:0;' ); 344 | ini_set( 'highlight.string', '#F2C47E' ); 345 | $output = highlight_string( "bootstrap, true ), true ); 346 | echo "
{$output}
"; 347 | } ); 348 | } 349 | } 350 | } 351 | -------------------------------------------------------------------------------- /src/Common/Abstracts/Base.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright {{author_copyright}} 8 | * @license {{author_license}} 9 | * @link {{author_url}} 10 | */ 11 | 12 | declare( strict_types = 1 ); 13 | 14 | namespace ThePluginName\Common\Abstracts; 15 | 16 | use ThePluginName\Config\Plugin; 17 | 18 | /** 19 | * The Base class which can be extended by other classes to load in default methods 20 | * 21 | * @package ThePluginName\Common\Abstracts 22 | * @since 1.0.0 23 | */ 24 | abstract class Base { 25 | /** 26 | * @var array : will be filled with data from the plugin config class 27 | * @see Plugin 28 | */ 29 | protected $plugin = []; 30 | 31 | /** 32 | * Base constructor. 33 | * 34 | * @since 1.0.0 35 | */ 36 | public function __construct() { 37 | $this->plugin = Plugin::init(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Common/Functions.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright {{author_copyright}} 8 | * @license {{author_license}} 9 | * @link {{author_url}} 10 | */ 11 | 12 | declare( strict_types = 1 ); 13 | 14 | namespace ThePluginName\Common; 15 | 16 | use ThePluginName\App\Frontend\Templates; 17 | use ThePluginName\Common\Abstracts\Base; 18 | 19 | /** 20 | * Main function class for external uses 21 | * 22 | * @see the_plugin_name() 23 | * @package ThePluginName\Common 24 | */ 25 | class Functions extends Base { 26 | /** 27 | * Get plugin data by using the_plugin_name()->getData() 28 | * 29 | * @return array 30 | * @since 1.0.0 31 | */ 32 | public function getData(): array { 33 | return $this->plugin->data(); 34 | } 35 | 36 | /** 37 | * Get the template instantiated class using the_plugin_name()->templates() 38 | * 39 | * @return Templates 40 | * @since 1.0.0 41 | */ 42 | public function templates(): Templates { 43 | return new Templates(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Common/Traits/Requester.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright {{author_copyright}} 8 | * @license {{author_license}} 9 | * @link {{author_url}} 10 | */ 11 | 12 | declare( strict_types = 1 ); 13 | 14 | namespace ThePluginName\Common\Traits; 15 | 16 | use ThePluginName\Common\Utils\Errors; 17 | 18 | /** 19 | * The requester trait to determine what we request; used to determine 20 | * which classes we instantiate in the Bootstrap class 21 | * 22 | * @see Bootstrap 23 | * 24 | * @package ThePluginName\Common\Traits 25 | * @since 1.0.0 26 | */ 27 | trait Requester { 28 | 29 | /** 30 | * What type of request is this? 31 | * 32 | * @param string $type admin, cron, cli, amp or frontend. 33 | * @return bool 34 | * @since 1.0.0 35 | */ 36 | public function request( string $type ): bool { 37 | switch ( $type ) { 38 | case 'installing_wp': 39 | return $this->isInstallingWp(); 40 | case 'frontend': 41 | return $this->isFrontend(); 42 | case 'backend': 43 | return $this->isAdminBackend(); 44 | case 'rest': 45 | return $this->isRest(); 46 | case 'cron': 47 | return $this->isCron(); 48 | case 'cli': 49 | return $this->isCli(); 50 | default: 51 | Errors::wpDie( 52 | sprintf( /* translators: %s: request function */ 53 | __( 'Unknown request type: %s', 'the-plugin-name-text-domain' ), 54 | $type 55 | ), 56 | __( 'Classes are not being correctly requested', 'the-plugin-name-text-domain' ), 57 | __FILE__ 58 | ); 59 | return false; 60 | } 61 | } 62 | 63 | /** 64 | * Is installing WP 65 | * 66 | * @return bool 67 | * @since 1.0.0 68 | */ 69 | public function isInstallingWp(): bool { 70 | return defined( 'WP_INSTALLING' ); 71 | } 72 | 73 | /** 74 | * Is frontend 75 | * 76 | * @return bool 77 | * @since 1.0.0 78 | */ 79 | public function isFrontend(): bool { 80 | return ! $this->isAdminBackend() && ! $this->isCron() && ! $this->isRest(); 81 | } 82 | 83 | /** 84 | * Is admin 85 | * 86 | * @return bool 87 | * @since 1.0.0 88 | */ 89 | public function isAdminBackend(): bool { 90 | return is_user_logged_in() && is_admin(); 91 | } 92 | 93 | /** 94 | * Is rest 95 | * 96 | * @return bool 97 | * @since 1.0.0 98 | */ 99 | public function isRest(): bool { 100 | return defined( 'REST_REQUEST' ); 101 | } 102 | 103 | /** 104 | * Is cron 105 | * 106 | * @return bool 107 | * @since 1.0.0 108 | */ 109 | public function isCron(): bool { 110 | return ( function_exists( 'wp_doing_cron' ) && wp_doing_cron() ) || defined( 'DOING_CRON' ); 111 | } 112 | 113 | /** 114 | * Is cli 115 | * 116 | * @return bool 117 | * @since 1.0.0 118 | */ 119 | public function isCli(): bool { 120 | return defined( 'WP_CLI' ) && WP_CLI; // phpcs:disable ImportDetection.Imports.RequireImports.Symbol -- this constant is global 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/Common/Traits/Singleton.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright {{author_copyright}} 8 | * @license {{author_license}} 9 | * @link {{author_url}} 10 | */ 11 | 12 | declare( strict_types = 1 ); 13 | 14 | namespace ThePluginName\Common\Traits; 15 | 16 | /** 17 | * The singleton skeleton trait to instantiate the class only once 18 | * 19 | * @package ThePluginName\Common\Traits 20 | * @since 1.0.0 21 | */ 22 | trait Singleton { 23 | private static $instance; 24 | 25 | final private function __construct() { 26 | } 27 | 28 | final private function __clone() { 29 | } 30 | 31 | final private function __wakeup() { 32 | } 33 | 34 | /** 35 | * @return self 36 | * @since 1.0.0 37 | */ 38 | final public static function init(): self { 39 | if ( ! self::$instance ) { 40 | self::$instance = new self(); 41 | } 42 | return self::$instance; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Common/Utils/Errors.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright {{author_copyright}} 8 | * @license {{author_license}} 9 | * @link {{author_url}} 10 | */ 11 | 12 | declare( strict_types = 1 ); 13 | 14 | namespace ThePluginName\Common\Utils; 15 | 16 | use ThePluginName\Config\Plugin; 17 | 18 | /** 19 | * Utility to show prettified wp_die errors, write debug logs as 20 | * string or array and to deactivate plugin and print a notice 21 | * 22 | * @package ThePluginName\Config 23 | * @since 1.0.0 24 | */ 25 | class Errors { 26 | 27 | /** 28 | * Get the plugin data in static form 29 | * 30 | * @return array 31 | * @since 1.0.0 32 | */ 33 | public static function getPluginData(): array { 34 | return Plugin::init()->data(); 35 | } 36 | 37 | /** 38 | * Prettified wp_die error function 39 | * 40 | * @param $message : The error message 41 | * @param string $subtitle : Specified title of the error 42 | * @param string $source : File source of the error 43 | * @param string $title : General title of the error 44 | * @param string $exception 45 | * @since 1.0.0 46 | */ 47 | public static function wpDie( $message = '', $subtitle = '', $source = '', $exception = '', $title = '' ) { 48 | if ( $message ) { 49 | $plugin = self::getPluginData(); 50 | $title = $title ? $title : $plugin['name'] . ' ' . $plugin['version'] . ' ' . __( '› Fatal Error', 'the-plugin-name-text-domain' ); 51 | Errors::writeLog( 52 | [ 53 | 'title' => $title . ' - ' . $subtitle, 54 | 'message' => $message, 55 | 'source' => $source, 56 | 'exception' => $exception, 57 | ] 58 | ); 59 | $source = $source ? '' . 60 | sprintf( /* translators: %s: file path */ 61 | __( 'Error source: %s', 'the-plugin-name-text-domain' ), $source 62 | ) . '

' : ''; 63 | $footer = $source . '' . $plugin['uri'] . ''; 64 | $message = '

' . $message . '

'; 65 | $message .= $exception ? '

Exception:
' . $exception . '

' : ''; 66 | $message = "

{$title}
{$subtitle}

{$message}

{$footer}

"; 67 | wp_die( $message, $title ); 68 | } else { 69 | wp_die(); 70 | } 71 | } 72 | 73 | /** 74 | * De-activates the plugin and shows notice error in back-end 75 | * 76 | * @param $message : The error message 77 | * @param string $subtitle : Specified title of the error 78 | * @param string $source : File source of the error 79 | * @param string $title : General title of the error 80 | * @param string $exception 81 | * @since 1.0.0 82 | */ 83 | public static function pluginDie( $message = '', $subtitle = '', $source = '', $exception = '', $title = '' ) { 84 | if ( $message ) { 85 | $plugin = self::getPluginData(); 86 | $title = $title ? $title : $plugin['name'] . ' ' . $plugin['version'] . ' ' . __( '› Plugin Disabled', 'the-plugin-name-text-domain' ); 87 | Errors::writeLog( 88 | [ 89 | 'title' => $title . ' - ' . $subtitle, 90 | 'message' => $message, 91 | 'source' => $source, 92 | 'exception' => $exception, 93 | ] 94 | ); 95 | $source = $source ? '' . 96 | sprintf( /* translators: %s: file path */ 97 | __( 'Error source: %s', 'the-plugin-name-text-domain' ), $source 98 | ) . ' - ' : ''; 99 | $footer = $source . '' . $plugin['uri'] . ''; 100 | $error = "

{$title}

{$subtitle}

{$message}


{$footer}

"; 101 | global $the_plugin_name_die_notice; 102 | $the_plugin_name_die_notice = $error; 103 | add_action( 'admin_notices', 104 | static function () { 105 | global $the_plugin_name_die_notice; 106 | echo wp_kses_post( 107 | sprintf( 108 | '

%s

', 109 | $the_plugin_name_die_notice 110 | ) 111 | ); 112 | } 113 | ); 114 | } 115 | add_action( 'admin_init', 116 | static function () { 117 | deactivate_plugins( plugin_basename( _THE_PLUGIN_NAME_PLUGIN_FILE ) ); // phpcs:disable ImportDetection.Imports.RequireImports.Symbol -- this constant is global 118 | } 119 | ); 120 | } 121 | 122 | /** 123 | * Writes a log if wp_debug is enables 124 | * 125 | * @param $log 126 | * @since 1.0.0 127 | */ 128 | public static function writeLog( $log ) { 129 | if ( true === WP_DEBUG ) { 130 | if ( is_array( $log ) || is_object( $log ) ) { 131 | error_log( print_r( $log, true ) ); 132 | } else { 133 | error_log( $log ); 134 | } 135 | } 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/Compatibility/Siteground/Example.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright {{author_copyright}} 8 | * @license {{author_license}} 9 | * @link {{author_url}} 10 | */ 11 | 12 | declare( strict_types = 1 ); 13 | 14 | namespace ThePluginName\Compatibility\Siteground; 15 | 16 | /** 17 | * Class Example 18 | * 19 | * @package ThePluginName\Compatibility\Siteground 20 | * @since 1.0.0 21 | */ 22 | class Example { 23 | 24 | /** 25 | * Initialize the class. 26 | * 27 | * @since 1.0.0 28 | */ 29 | public function init() { 30 | /** 31 | * Add 3rd party compatibility code here. 32 | * Compatibility classes instantiates after anything else 33 | * 34 | * @see Bootstrap::__construct 35 | */ 36 | add_filter( 'sgo_css_combine_exclude', [ $this, 'excludeCssCombine' ] ); 37 | } 38 | 39 | /** 40 | * Siteground optimizer compatibility. 41 | * 42 | * @param array $exclude_list 43 | * 44 | * @return array 45 | * @since 1.0.0 46 | */ 47 | public function excludeCssCombine( array $exclude_list ): array { 48 | $exclude_list[] = 'plugin-name-frontend-css'; 49 | 50 | return $exclude_list; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Config/Classes.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright {{author_copyright}} 8 | * @license {{author_license}} 9 | * @link {{author_url}} 10 | */ 11 | 12 | declare( strict_types = 1 ); 13 | 14 | namespace ThePluginName\Config; 15 | 16 | /** 17 | * This array is being used in ../Boostrap.php to instantiate the classes 18 | * 19 | * @package ThePluginName\Config 20 | * @since 1.0.0 21 | */ 22 | final class Classes { 23 | 24 | /** 25 | * Init the classes inside these folders based on type of request. 26 | * @see Requester for all the type of requests or to add your own 27 | */ 28 | public static function get(): array { 29 | // phpcs:disable 30 | // ignore for readable array values one a single line 31 | return [ 32 | [ 'init' => 'Integrations' ], 33 | [ 'init' => 'App\\General' ], 34 | [ 'init' => 'App\\Frontend', 'on_request' => 'frontend' ], 35 | [ 'init' => 'App\\Backend', 'on_request' => 'backend' ], 36 | [ 'init' => 'App\\Rest', 'on_request' => 'rest' ], 37 | [ 'init' => 'App\\Cli', 'on_request' => 'cli' ], 38 | [ 'init' => 'App\\Cron', 'on_request' => 'cron' ], 39 | [ 'init' => 'Compatibility' ], 40 | ]; 41 | // phpcs:enable 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Config/I18n.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright {{author_copyright}} 8 | * @license {{author_license}} 9 | * @link {{author_url}} 10 | */ 11 | 12 | declare( strict_types = 1 ); 13 | 14 | namespace ThePluginName\Config; 15 | 16 | use ThePluginName\Common\Abstracts\Base; 17 | 18 | /** 19 | * Internationalization and localization definitions 20 | * 21 | * @package ThePluginName\Config 22 | * @since 1.0.0 23 | */ 24 | final class I18n extends Base { 25 | /** 26 | * Load the plugin text domain for translation 27 | * @docs https://developer.wordpress.org/plugins/internationalization/how-to-internationalize-your-plugin/#loading-text-domain 28 | * 29 | * @since 1.0.0 30 | */ 31 | public function load() { 32 | load_plugin_textdomain( 33 | $this->plugin->textDomain(), 34 | false, 35 | dirname( plugin_basename( _THE_PLUGIN_NAME_PLUGIN_FILE ) ) . '/languages' // phpcs:disable ImportDetection.Imports.RequireImports.Symbol -- this constant is global 36 | ); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Config/Plugin.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright {{author_copyright}} 8 | * @license {{author_license}} 9 | * @link {{author_url}} 10 | */ 11 | 12 | declare( strict_types = 1 ); 13 | 14 | namespace ThePluginName\Config; 15 | 16 | use ThePluginName\Common\Traits\Singleton; 17 | 18 | /** 19 | * Plugin data which are used through the plugin, most of them are defined 20 | * by the root file meta data. The data is being inserted in each class 21 | * that extends the Base abstract class 22 | * 23 | * @see Base 24 | * @package ThePluginName\Config 25 | * @since 1.0.0 26 | */ 27 | final class Plugin { 28 | /** 29 | * Singleton trait 30 | */ 31 | use Singleton; 32 | 33 | /** 34 | * Get the plugin meta data from the root file and include own data 35 | * 36 | * @return array 37 | * @since 1.0.0 38 | */ 39 | public function data(): array { 40 | $plugin_data = apply_filters( 'the_plugin_name_plugin_data', [ 41 | 'settings' => get_option( 'the-plugin-name-settings' ), 42 | 'plugin_path' => untrailingslashit( 43 | plugin_dir_path( _THE_PLUGIN_NAME_PLUGIN_FILE ) // phpcs:disable ImportDetection.Imports.RequireImports.Symbol -- this constant is global 44 | ), 45 | 'plugin_template_folder' => 'templates', 46 | 'ext_template_folder' => 'the-plugin-name-templates', 47 | /** 48 | * Add extra data here 49 | */ 50 | ] ); 51 | return array_merge( 52 | apply_filters( 'the_plugin_name_plugin_meta_data', 53 | get_file_data( _THE_PLUGIN_NAME_PLUGIN_FILE, // phpcs:disable ImportDetection.Imports.RequireImports.Symbol -- this constant is global 54 | [ 55 | 'name' => 'Plugin Name', 56 | 'uri' => 'Plugin URI', 57 | 'description' => 'Description', 58 | 'version' => 'Version', 59 | 'author' => 'Author', 60 | 'author-uri' => 'Author URI', 61 | 'text-domain' => 'Text Domain', 62 | 'domain-path' => 'Domain Path', 63 | 'required-php' => 'Requires PHP', 64 | 'required-wp' => 'Requires WP', 65 | 'namespace' => 'Namespace', 66 | ], 'plugin' 67 | ) 68 | ), $plugin_data 69 | ); 70 | } 71 | 72 | /** 73 | * Get the plugin external template path 74 | * 75 | * @return string 76 | * @since 1.0.0 77 | */ 78 | public function pluginPath(): string { 79 | return $this->data()['plugin_path']; 80 | } 81 | 82 | /** 83 | * Get the plugin internal template path 84 | * 85 | * @return string 86 | * @since 1.0.0 87 | */ 88 | public function templatePath(): string { 89 | return $this->data()['plugin_path'] . '/' . $this->data()['plugin_template_folder']; 90 | } 91 | 92 | /** 93 | * Get the plugin internal template folder name 94 | * 95 | * @return string 96 | * @since 1.0.0 97 | */ 98 | public function templateFolder(): string { 99 | return $this->data()['plugin_template_folder']; 100 | } 101 | 102 | /** 103 | * Get the plugin external template path 104 | * 105 | * @return string 106 | * @since 1.0.0 107 | */ 108 | public function extTemplatePath(): string { 109 | return $this->data()['plugin_path'] . '/' . $this->data()['ext_template_folder']; 110 | } 111 | 112 | /** 113 | * Get the plugin external template path 114 | * 115 | * @return string 116 | * @since 1.0.0 117 | */ 118 | public function extTemplateFolder(): string { 119 | return $this->data()['ext_template_folder']; 120 | } 121 | 122 | /** 123 | * Get the plugin settings 124 | * 125 | * @return string 126 | * @since 1.0.0 127 | */ 128 | public function settings(): string { 129 | return $this->data()['settings']; 130 | } 131 | 132 | /** 133 | * Get the plugin version number 134 | * 135 | * @return string 136 | * @since 1.0.0 137 | */ 138 | public function version(): string { 139 | return $this->data()['version']; 140 | } 141 | 142 | /** 143 | * Get the required minimum PHP version 144 | * 145 | * @return string 146 | * @since 1.0.0 147 | */ 148 | public function requiredPhp(): string { 149 | return $this->data()['required-php']; 150 | } 151 | 152 | /** 153 | * Get the required minimum WP version 154 | * 155 | * @return string 156 | * @since 1.0.0 157 | */ 158 | public function requiredWp(): string { 159 | return $this->data()['required-wp']; 160 | } 161 | 162 | /** 163 | * Get the plugin name 164 | * 165 | * @return string 166 | * @since 1.0.0 167 | */ 168 | public function name(): string { 169 | return $this->data()['name']; 170 | } 171 | 172 | /** 173 | * Get the plugin url 174 | * 175 | * @return string 176 | * @since 1.0.0 177 | */ 178 | public function uri(): string { 179 | return $this->data()['uri']; 180 | } 181 | 182 | /** 183 | * Get the plugin description 184 | * 185 | * @return string 186 | * @since 1.0.0 187 | */ 188 | public function description(): string { 189 | return $this->data()['description']; 190 | } 191 | 192 | /** 193 | * Get the plugin author 194 | * 195 | * @return string 196 | * @since 1.0.0 197 | */ 198 | public function author(): string { 199 | return $this->data()['author']; 200 | } 201 | 202 | /** 203 | * Get the plugin author uri 204 | * 205 | * @return string 206 | * @since 1.0.0 207 | */ 208 | public function authorUri(): string { 209 | return $this->data()['author-uri']; 210 | } 211 | 212 | /** 213 | * Get the plugin text domain 214 | * 215 | * @return string 216 | * @since 1.0.0 217 | */ 218 | public function textDomain(): string { 219 | return $this->data()['text-domain']; 220 | } 221 | 222 | /** 223 | * Get the plugin domain path 224 | * 225 | * @return string 226 | * @since 1.0.0 227 | */ 228 | public function domainPath(): string { 229 | return $this->data()['domain-path']; 230 | } 231 | 232 | /** 233 | * Get the plugin namespace 234 | * 235 | * @return string 236 | * @since 1.0.0 237 | */ 238 | public function namespace(): string { 239 | return $this->data()['namespace']; 240 | } 241 | } 242 | -------------------------------------------------------------------------------- /src/Config/Requirements.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright {{author_copyright}} 8 | * @license {{author_license}} 9 | * @link {{author_url}} 10 | */ 11 | 12 | declare( strict_types = 1 ); 13 | 14 | namespace ThePluginName\Config; 15 | 16 | use ThePluginName\Common\Abstracts\Base; 17 | use ThePluginName\Common\Utils\Errors; 18 | 19 | /** 20 | * Check if any requirements are needed to run this plugin. We use the 21 | * "Requirements" package from "MicroPackage" to check if any PHP Extensions, 22 | * plugins, themes or PHP/WP version are required. 23 | * @docs https://github.com/micropackage/requirements 24 | * 25 | * @package ThePluginName\Config 26 | * @since 1.0.0 27 | */ 28 | final class Requirements extends Base { 29 | /** 30 | * Specifications for the requirements 31 | * 32 | * @return array : used to specify the requirements 33 | * @since 1.0.0 34 | */ 35 | public function specifications(): array { 36 | return apply_filters( 'the_plugin_name_plugin_requirements', [ 37 | 'php' => $this->plugin->requiredPhp(), 38 | 'php_extensions' => [ 39 | /** 40 | * 'mbstring' 41 | */ 42 | ], 43 | 'wp' => $this->plugin->requiredWp(), 44 | 'plugins' => [ 45 | /** 46 | * [ 47 | * 'file' => 'hello-dolly/hello.php', 48 | * 'name' => 'Hello Dolly', 49 | * 'version' => '1.5' 50 | * ], 51 | */ 52 | ], 53 | ] ); 54 | } 55 | 56 | /** 57 | * Plugin requirements checker 58 | * 59 | * @since 1.0.0 60 | */ 61 | public function check() { 62 | // We use "Requirements" if the package is required and installed by composer.json 63 | if ( class_exists( '\Micropackage\Requirements\Requirements' ) ) { 64 | $this->requirements = new \Micropackage\Requirements\Requirements( 65 | $this->plugin->name(), 66 | $this->specifications() 67 | ); 68 | if ( ! $this->requirements->satisfied() ) { 69 | // Print notice 70 | $this->requirements->print_notice(); 71 | // Kill plugin 72 | Errors::pluginDie(); 73 | } 74 | } else { 75 | // Else we do a version check based on version_compare 76 | $this->versionCompare(); 77 | } 78 | } 79 | 80 | /** 81 | * Compares PHP & WP versions and kills plugin if it's not compatible 82 | * 83 | * @since 1.0.0 84 | */ 85 | public function versionCompare() { 86 | foreach ( 87 | [ 88 | // PHP version check 89 | [ 90 | 'current' => phpversion(), 91 | 'compare' => $this->plugin->requiredPhp(), 92 | 'title' => __( 'Invalid PHP version', 'the-plugin-name-text-domain' ), 93 | 'message' => sprintf( /* translators: %1$1s: required php version, %2$2s: current php version */ 94 | __( 'You must be using PHP %1$1s or greater. You are currently using PHP %2$2s.', 'the-plugin-name-text-domain' ), 95 | $this->plugin->requiredPhp(), 96 | phpversion() 97 | ), 98 | ], 99 | // WP version check 100 | [ 101 | 'current' => get_bloginfo( 'version' ), 102 | 'compare' => $this->plugin->requiredWp(), 103 | 'title' => __( 'Invalid WordPress version', 'the-plugin-name-text-domain' ), 104 | 'message' => sprintf( /* translators: %1$1s: required wordpress version, %2$2s: current wordpress version */ 105 | __( 'You must be using WordPress %1$1s or greater. You are currently using WordPress %2$2s.', 'the-plugin-name-text-domain' ), 106 | $this->plugin->requiredWp(), 107 | get_bloginfo( 'version' ) 108 | ), 109 | ], 110 | ] as $compat_check ) { 111 | if ( version_compare( 112 | $compat_check['compare'], 113 | $compat_check['current'], 114 | '>=' 115 | ) ) { 116 | // Kill plugin 117 | Errors::pluginDie( 118 | $compat_check['message'], 119 | $compat_check['title'], 120 | plugin_basename( __FILE__ ) 121 | ); 122 | } 123 | } 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /src/Config/Setup.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright {{author_copyright}} 8 | * @license {{author_license}} 9 | * @link {{author_url}} 10 | */ 11 | 12 | declare( strict_types = 1 ); 13 | 14 | namespace ThePluginName\Config; 15 | 16 | use ThePluginName\Common\Traits\Singleton; 17 | 18 | /** 19 | * Plugin setup hooks (activation, deactivation, uninstall) 20 | * 21 | * @package ThePluginName\Config 22 | * @since 1.0.0 23 | */ 24 | final class Setup { 25 | /** 26 | * Singleton trait 27 | */ 28 | use Singleton; 29 | 30 | /** 31 | * Run only once after plugin is activated 32 | * @docs https://developer.wordpress.org/reference/functions/register_activation_hook/ 33 | */ 34 | public static function activation() { 35 | if ( ! current_user_can( 'activate_plugins' ) ) { 36 | return; 37 | } 38 | 39 | /** 40 | * Use this to add a database table after the plugin is activated for example 41 | */ 42 | 43 | // Clear the permalinks 44 | flush_rewrite_rules(); 45 | 46 | # Uncomment the following line to see the function in action 47 | # exit( var_dump( $_GET ) ); 48 | } 49 | 50 | /** 51 | * Run only once after plugin is deactivated 52 | * @docs https://developer.wordpress.org/reference/functions/register_deactivation_hook/ 53 | */ 54 | public static function deactivation() { 55 | if ( ! current_user_can( 'activate_plugins' ) ) { 56 | return; 57 | } 58 | 59 | /** 60 | * Use this to register a function which will be executed when the plugin is deactivated 61 | */ 62 | 63 | // Clear the permalinks 64 | flush_rewrite_rules(); 65 | 66 | # Uncomment the following line to see the function in action 67 | # exit( var_dump( $_GET ) ); 68 | } 69 | 70 | /** 71 | * Run only once after plugin is uninstalled 72 | * @docs https://developer.wordpress.org/reference/functions/register_uninstall_hook/ 73 | */ 74 | public static function uninstall() { 75 | if ( ! current_user_can( 'activate_plugins' ) ) { 76 | return; 77 | } 78 | 79 | /** 80 | * Use this to remove plugin data and residues after the plugin is uninstalled for example 81 | */ 82 | 83 | # Uncomment the following line to see the function in action 84 | # exit( var_dump( $_GET ) ); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/Integrations/Example/Api.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright {{author_copyright}} 8 | * @license {{author_license}} 9 | * @link {{author_url}} 10 | */ 11 | 12 | declare( strict_types = 1 ); 13 | 14 | namespace ThePluginName\Integrations\Example; 15 | 16 | /** 17 | * Class Api 18 | * 19 | * @package ThePluginName\Integrations\Example 20 | * @since 1.0.0 21 | */ 22 | class Api { 23 | 24 | /** 25 | * Initialize the class. 26 | * 27 | * @since 1.0.0 28 | */ 29 | public function init() { 30 | /** 31 | * Add integration code here. 32 | * Integration classes instantiates before anything else 33 | * 34 | * @see Bootstrap::__construct 35 | */ 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Integrations/Widget/HTML_Widget.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright {{author_copyright}} 8 | * @license {{author_license}} 9 | * @link {{author_url}} 10 | */ 11 | 12 | declare( strict_types = 1 ); 13 | 14 | namespace ThePluginName\Integrations\Widget; 15 | 16 | use ThePluginName\Config\Plugin; 17 | use WP_Widget; 18 | 19 | /** 20 | * Class HTML_Widget 21 | * 22 | * @package ThePluginName\Integrations\Widget 23 | */ 24 | class HTML_Widget extends WP_Widget { 25 | 26 | /** 27 | * @var array : will be filled with data from the plugin config class 28 | * @see Plugin 29 | */ 30 | protected $plugin = []; 31 | 32 | /** 33 | * Default instance. 34 | * 35 | * @var array 36 | */ 37 | protected $default_instance = [ 38 | 'title' => '', 39 | 'content' => '', 40 | ]; 41 | 42 | /** 43 | * Initialize the class. 44 | * 45 | * @since 1.0.0 46 | */ 47 | public function init() { 48 | /** 49 | * Integration classes instantiates before anything else 50 | * 51 | * @see Bootstrap::__construct 52 | * 53 | * Widget is registered via the app/general/widgets class, but it is also 54 | * possible to register from this class 55 | * @see Widgets 56 | */ 57 | } 58 | 59 | /** 60 | * Sets up a new HTML widget instance. 61 | * 62 | * @since 1.0.0 63 | */ 64 | public function __construct() { 65 | $this->plugin = Plugin::init(); 66 | $widget_ops = [ 67 | 'classname' => 'widget_html', 68 | 'description' => __( 'Displays HTML code with syntax highlighting.', 'the-plugin-name-text-domain' ), 69 | 'customize_selective_refresh' => true, 70 | ]; 71 | $control_ops = []; 72 | parent::__construct( 'the-plugin-name-text-domain', __( 'HTML Test Widget', 'the-plugin-name-text-domain' ), $widget_ops, $control_ops ); 73 | } 74 | 75 | /** 76 | * Outputs the content for the current widget instance. 77 | * 78 | * @param array $args Default widget arguments. 79 | * @param array $instance Settings for the current instance. 80 | * @since 1.0.0 81 | */ 82 | public function widget( $args, $instance ) { 83 | 84 | $instance = array_merge( $this->default_instance, $instance ); 85 | $content = $instance['content']; 86 | 87 | /** 88 | * Filters the content of the HTML Code widget. 89 | * 90 | * @param string $content The widget content. 91 | * @param array $instance Settings for the current widget. 92 | * @since 0.1.0 93 | */ 94 | $content = apply_filters( 'the_plugin_name_html_widget_content', $content, $instance, $this ); 95 | echo $args['before_widget']; 96 | echo $content; 97 | echo $args['after_widget']; 98 | } 99 | 100 | /** 101 | * Handles updating settings for the current widget instance. 102 | * 103 | * @param array $new_instance New settings for this instance. 104 | * @param array $old_instance Old settings for this instance. 105 | * @return array $instance Settings to save or bool false to cancel saving. 106 | * @since 1.0.0 107 | */ 108 | public function update( $new_instance, $old_instance ): array { 109 | $instance = array_merge( $this->default_instance, $old_instance ); 110 | if ( current_user_can( 'unfiltered_html' ) ) { 111 | $instance['content'] = $new_instance['content']; 112 | } else { 113 | $instance['content'] = wp_kses_post( $new_instance['content'] ); 114 | } 115 | return $instance; 116 | } 117 | 118 | /** 119 | * Outputs the HTML Code widget settings form. 120 | * 121 | * @param array $instance Current widget instance. 122 | * @return void 123 | * @since 1.0.0 124 | */ 125 | public function form( $instance ) { 126 | $instance = wp_parse_args( (array) $instance, $this->default_instance ); 127 | ?> 128 |

129 | 130 | 131 |

132 | 7 | * @copyright {{author_copyright}} 8 | * @license {{author_license}} 9 | * @link {{author_url}} 10 | */ 11 | ?> 12 |

13 | 20 |

21 | -------------------------------------------------------------------------------- /tests/PluginTestsBootstrap.php: -------------------------------------------------------------------------------- 1 | expectException(MyException::class, function() { 25 | * $this->doSomethingBad(); 26 | * }); 27 | * 28 | * $I->expectException(new MyException(), function() { 29 | * $this->doSomethingBad(); 30 | * }); 31 | * ``` 32 | * If you want to check message or exception code, you can pass them with exception instance: 33 | * ```php 34 | * expectException(new MyException("Don't do bad things"), function() { 37 | * $this->doSomethingBad(); 38 | * }); 39 | * ``` 40 | * 41 | * @deprecated Use expectThrowable() instead 42 | * @param \Exception|string $exception 43 | * @param callable $callback 44 | * @see \Codeception\Module\Asserts::expectException() 45 | */ 46 | public function expectException($exception, $callback) { 47 | return $this->getScenario()->runStep(new \Codeception\Step\Action('expectException', func_get_args())); 48 | } 49 | 50 | 51 | /** 52 | * [!] Method is generated. Documentation taken from corresponding module. 53 | * 54 | * Handles and checks throwables (Exceptions/Errors) called inside the callback function. 55 | * Either throwable class name or throwable instance should be provided. 56 | * 57 | * ```php 58 | * expectThrowable(MyThrowable::class, function() { 60 | * $this->doSomethingBad(); 61 | * }); 62 | * 63 | * $I->expectThrowable(new MyException(), function() { 64 | * $this->doSomethingBad(); 65 | * }); 66 | * ``` 67 | * If you want to check message or throwable code, you can pass them with throwable instance: 68 | * ```php 69 | * expectThrowable(new MyError("Don't do bad things"), function() { 72 | * $this->doSomethingBad(); 73 | * }); 74 | * ``` 75 | * 76 | * @param \Throwable|string $throwable 77 | * @param callable $callback 78 | * @see \Codeception\Module\Asserts::expectThrowable() 79 | */ 80 | public function expectThrowable($throwable, $callback) { 81 | return $this->getScenario()->runStep(new \Codeception\Step\Action('expectThrowable', func_get_args())); 82 | } 83 | 84 | 85 | /** 86 | * [!] Method is generated. Documentation taken from corresponding module. 87 | * 88 | * Asserts that a file does not exist. 89 | * 90 | * @param string $filename 91 | * @param string $message 92 | * @see \Codeception\Module\AbstractAsserts::assertFileNotExists() 93 | */ 94 | public function assertFileNotExists($filename, $message = "") { 95 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertFileNotExists', func_get_args())); 96 | } 97 | 98 | 99 | /** 100 | * [!] Method is generated. Documentation taken from corresponding module. 101 | * 102 | * Asserts that a value is greater than or equal to another value. 103 | * 104 | * @param $expected 105 | * @param $actual 106 | * @param string $message 107 | * @see \Codeception\Module\AbstractAsserts::assertGreaterOrEquals() 108 | */ 109 | public function assertGreaterOrEquals($expected, $actual, $message = "") { 110 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertGreaterOrEquals', func_get_args())); 111 | } 112 | 113 | 114 | /** 115 | * [!] Method is generated. Documentation taken from corresponding module. 116 | * 117 | * Asserts that a variable is empty. 118 | * 119 | * @param $actual 120 | * @param string $message 121 | * @see \Codeception\Module\AbstractAsserts::assertIsEmpty() 122 | */ 123 | public function assertIsEmpty($actual, $message = "") { 124 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertIsEmpty', func_get_args())); 125 | } 126 | 127 | 128 | /** 129 | * [!] Method is generated. Documentation taken from corresponding module. 130 | * 131 | * Asserts that a value is smaller than or equal to another value. 132 | * 133 | * @param $expected 134 | * @param $actual 135 | * @param string $message 136 | * @see \Codeception\Module\AbstractAsserts::assertLessOrEquals() 137 | */ 138 | public function assertLessOrEquals($expected, $actual, $message = "") { 139 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertLessOrEquals', func_get_args())); 140 | } 141 | 142 | 143 | /** 144 | * [!] Method is generated. Documentation taken from corresponding module. 145 | * 146 | * Asserts that a string does not match a given regular expression. 147 | * 148 | * @param string $pattern 149 | * @param string $string 150 | * @param string $message 151 | * @see \Codeception\Module\AbstractAsserts::assertNotRegExp() 152 | */ 153 | public function assertNotRegExp($pattern, $string, $message = "") { 154 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertNotRegExp', func_get_args())); 155 | } 156 | 157 | 158 | /** 159 | * [!] Method is generated. Documentation taken from corresponding module. 160 | * 161 | * Asserts that a string matches a given regular expression. 162 | * 163 | * @param string $pattern 164 | * @param string $string 165 | * @param string $message 166 | * @see \Codeception\Module\AbstractAsserts::assertRegExp() 167 | */ 168 | public function assertRegExp($pattern, $string, $message = "") { 169 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertRegExp', func_get_args())); 170 | } 171 | 172 | 173 | /** 174 | * [!] Method is generated. Documentation taken from corresponding module. 175 | * 176 | * Evaluates a PHPUnit\Framework\Constraint matcher object. 177 | * 178 | * @param $value 179 | * @param Constraint $constraint 180 | * @param string $message 181 | * @see \Codeception\Module\AbstractAsserts::assertThatItsNot() 182 | */ 183 | public function assertThatItsNot($value, $constraint, $message = "") { 184 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertThatItsNot', func_get_args())); 185 | } 186 | 187 | 188 | /** 189 | * [!] Method is generated. Documentation taken from corresponding module. 190 | * 191 | * Asserts that an array has a specified key. 192 | * 193 | * @param int|string $key 194 | * @param array|ArrayAccess $array 195 | * @param string $message 196 | * @see \Codeception\Module\AbstractAsserts::assertArrayHasKey() 197 | */ 198 | public function assertArrayHasKey($key, $array, $message = "") { 199 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertArrayHasKey', func_get_args())); 200 | } 201 | 202 | 203 | /** 204 | * [!] Method is generated. Documentation taken from corresponding module. 205 | * 206 | * Asserts that an array does not have a specified key. 207 | * 208 | * @param int|string $key 209 | * @param array|ArrayAccess $array 210 | * @param string $message 211 | * @see \Codeception\Module\AbstractAsserts::assertArrayNotHasKey() 212 | */ 213 | public function assertArrayNotHasKey($key, $array, $message = "") { 214 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertArrayNotHasKey', func_get_args())); 215 | } 216 | 217 | 218 | /** 219 | * [!] Method is generated. Documentation taken from corresponding module. 220 | * 221 | * Asserts that a class has a specified attribute. 222 | * 223 | * @param string $attributeName 224 | * @param string $className 225 | * @param string $message 226 | * @see \Codeception\Module\AbstractAsserts::assertClassHasAttribute() 227 | */ 228 | public function assertClassHasAttribute($attributeName, $className, $message = "") { 229 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertClassHasAttribute', func_get_args())); 230 | } 231 | 232 | 233 | /** 234 | * [!] Method is generated. Documentation taken from corresponding module. 235 | * 236 | * Asserts that a class has a specified static attribute. 237 | * 238 | * @param string $attributeName 239 | * @param string $className 240 | * @param string $message 241 | * @see \Codeception\Module\AbstractAsserts::assertClassHasStaticAttribute() 242 | */ 243 | public function assertClassHasStaticAttribute($attributeName, $className, $message = "") { 244 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertClassHasStaticAttribute', func_get_args())); 245 | } 246 | 247 | 248 | /** 249 | * [!] Method is generated. Documentation taken from corresponding module. 250 | * 251 | * Asserts that a class does not have a specified attribute. 252 | * 253 | * @param string $attributeName 254 | * @param string $className 255 | * @param string $message 256 | * @see \Codeception\Module\AbstractAsserts::assertClassNotHasAttribute() 257 | */ 258 | public function assertClassNotHasAttribute($attributeName, $className, $message = "") { 259 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertClassNotHasAttribute', func_get_args())); 260 | } 261 | 262 | 263 | /** 264 | * [!] Method is generated. Documentation taken from corresponding module. 265 | * 266 | * Asserts that a class does not have a specified static attribute. 267 | * 268 | * @param string $attributeName 269 | * @param string $className 270 | * @param string $message 271 | * @see \Codeception\Module\AbstractAsserts::assertClassNotHasStaticAttribute() 272 | */ 273 | public function assertClassNotHasStaticAttribute($attributeName, $className, $message = "") { 274 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertClassNotHasStaticAttribute', func_get_args())); 275 | } 276 | 277 | 278 | /** 279 | * [!] Method is generated. Documentation taken from corresponding module. 280 | * 281 | * Asserts that a haystack contains a needle. 282 | * 283 | * @param $needle 284 | * @param $haystack 285 | * @param string $message 286 | * @see \Codeception\Module\AbstractAsserts::assertContains() 287 | */ 288 | public function assertContains($needle, $haystack, $message = "") { 289 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertContains', func_get_args())); 290 | } 291 | 292 | 293 | /** 294 | * [!] Method is generated. Documentation taken from corresponding module. 295 | * 296 | * @param $needle 297 | * @param $haystack 298 | * @param string $message 299 | * @see \Codeception\Module\AbstractAsserts::assertContainsEquals() 300 | */ 301 | public function assertContainsEquals($needle, $haystack, $message = "") { 302 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertContainsEquals', func_get_args())); 303 | } 304 | 305 | 306 | /** 307 | * [!] Method is generated. Documentation taken from corresponding module. 308 | * 309 | * Asserts that a haystack contains only values of a given type. 310 | * 311 | * @param string $type 312 | * @param $haystack 313 | * @param bool|null $isNativeType 314 | * @param string $message 315 | * @see \Codeception\Module\AbstractAsserts::assertContainsOnly() 316 | */ 317 | public function assertContainsOnly($type, $haystack, $isNativeType = NULL, $message = "") { 318 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertContainsOnly', func_get_args())); 319 | } 320 | 321 | 322 | /** 323 | * [!] Method is generated. Documentation taken from corresponding module. 324 | * 325 | * Asserts that a haystack contains only instances of a given class name. 326 | * 327 | * @param string $className 328 | * @param $haystack 329 | * @param string $message 330 | * @see \Codeception\Module\AbstractAsserts::assertContainsOnlyInstancesOf() 331 | */ 332 | public function assertContainsOnlyInstancesOf($className, $haystack, $message = "") { 333 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertContainsOnlyInstancesOf', func_get_args())); 334 | } 335 | 336 | 337 | /** 338 | * [!] Method is generated. Documentation taken from corresponding module. 339 | * 340 | * Asserts the number of elements of an array, Countable or Traversable. 341 | * 342 | * @param int $expectedCount 343 | * @param Countable|iterable $haystack 344 | * @param string $message 345 | * @see \Codeception\Module\AbstractAsserts::assertCount() 346 | */ 347 | public function assertCount($expectedCount, $haystack, $message = "") { 348 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertCount', func_get_args())); 349 | } 350 | 351 | 352 | /** 353 | * [!] Method is generated. Documentation taken from corresponding module. 354 | * 355 | * Asserts that a directory does not exist. 356 | * 357 | * @param string $directory 358 | * @param string $message 359 | * @see \Codeception\Module\AbstractAsserts::assertDirectoryDoesNotExist() 360 | */ 361 | public function assertDirectoryDoesNotExist($directory, $message = "") { 362 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertDirectoryDoesNotExist', func_get_args())); 363 | } 364 | 365 | 366 | /** 367 | * [!] Method is generated. Documentation taken from corresponding module. 368 | * 369 | * Asserts that a directory exists. 370 | * 371 | * @param string $directory 372 | * @param string $message 373 | * @see \Codeception\Module\AbstractAsserts::assertDirectoryExists() 374 | */ 375 | public function assertDirectoryExists($directory, $message = "") { 376 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertDirectoryExists', func_get_args())); 377 | } 378 | 379 | 380 | /** 381 | * [!] Method is generated. Documentation taken from corresponding module. 382 | * 383 | * Asserts that a directory exists and is not readable. 384 | * 385 | * @param string $directory 386 | * @param string $message 387 | * @see \Codeception\Module\AbstractAsserts::assertDirectoryIsNotReadable() 388 | */ 389 | public function assertDirectoryIsNotReadable($directory, $message = "") { 390 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertDirectoryIsNotReadable', func_get_args())); 391 | } 392 | 393 | 394 | /** 395 | * [!] Method is generated. Documentation taken from corresponding module. 396 | * 397 | * Asserts that a directory exists and is not writable. 398 | * 399 | * @param string $directory 400 | * @param string $message 401 | * @see \Codeception\Module\AbstractAsserts::assertDirectoryIsNotWritable() 402 | */ 403 | public function assertDirectoryIsNotWritable($directory, $message = "") { 404 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertDirectoryIsNotWritable', func_get_args())); 405 | } 406 | 407 | 408 | /** 409 | * [!] Method is generated. Documentation taken from corresponding module. 410 | * 411 | * Asserts that a directory exists and is readable. 412 | * 413 | * @param string $directory 414 | * @param string $message 415 | * @see \Codeception\Module\AbstractAsserts::assertDirectoryIsReadable() 416 | */ 417 | public function assertDirectoryIsReadable($directory, $message = "") { 418 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertDirectoryIsReadable', func_get_args())); 419 | } 420 | 421 | 422 | /** 423 | * [!] Method is generated. Documentation taken from corresponding module. 424 | * 425 | * Asserts that a directory exists and is writable. 426 | * 427 | * @param string $directory 428 | * @param string $message 429 | * @see \Codeception\Module\AbstractAsserts::assertDirectoryIsWritable() 430 | */ 431 | public function assertDirectoryIsWritable($directory, $message = "") { 432 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertDirectoryIsWritable', func_get_args())); 433 | } 434 | 435 | 436 | /** 437 | * [!] Method is generated. Documentation taken from corresponding module. 438 | * 439 | * Asserts that a string does not match a given regular expression. 440 | * 441 | * @param string $pattern 442 | * @param string $string 443 | * @param string $message 444 | * @see \Codeception\Module\AbstractAsserts::assertDoesNotMatchRegularExpression() 445 | */ 446 | public function assertDoesNotMatchRegularExpression($pattern, $string, $message = "") { 447 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertDoesNotMatchRegularExpression', func_get_args())); 448 | } 449 | 450 | 451 | /** 452 | * [!] Method is generated. Documentation taken from corresponding module. 453 | * 454 | * Asserts that a variable is empty. 455 | * 456 | * @param $actual 457 | * @param string $message 458 | * @see \Codeception\Module\AbstractAsserts::assertEmpty() 459 | */ 460 | public function assertEmpty($actual, $message = "") { 461 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertEmpty', func_get_args())); 462 | } 463 | 464 | 465 | /** 466 | * [!] Method is generated. Documentation taken from corresponding module. 467 | * 468 | * Asserts that two variables are equal. 469 | * 470 | * @param $expected 471 | * @param $actual 472 | * @param string $message 473 | * @see \Codeception\Module\AbstractAsserts::assertEquals() 474 | */ 475 | public function assertEquals($expected, $actual, $message = "") { 476 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertEquals', func_get_args())); 477 | } 478 | 479 | 480 | /** 481 | * [!] Method is generated. Documentation taken from corresponding module. 482 | * 483 | * Asserts that two variables are equal (canonicalizing). 484 | * 485 | * @param $expected 486 | * @param $actual 487 | * @param string $message 488 | * @see \Codeception\Module\AbstractAsserts::assertEqualsCanonicalizing() 489 | */ 490 | public function assertEqualsCanonicalizing($expected, $actual, $message = "") { 491 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertEqualsCanonicalizing', func_get_args())); 492 | } 493 | 494 | 495 | /** 496 | * [!] Method is generated. Documentation taken from corresponding module. 497 | * 498 | * Asserts that two variables are equal (ignoring case). 499 | * 500 | * @param $expected 501 | * @param $actual 502 | * @param string $message 503 | * @see \Codeception\Module\AbstractAsserts::assertEqualsIgnoringCase() 504 | */ 505 | public function assertEqualsIgnoringCase($expected, $actual, $message = "") { 506 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertEqualsIgnoringCase', func_get_args())); 507 | } 508 | 509 | 510 | /** 511 | * [!] Method is generated. Documentation taken from corresponding module. 512 | * 513 | * Asserts that two variables are equal (with delta). 514 | * 515 | * @param $expected 516 | * @param $actual 517 | * @param float $delta 518 | * @param string $message 519 | * @see \Codeception\Module\AbstractAsserts::assertEqualsWithDelta() 520 | */ 521 | public function assertEqualsWithDelta($expected, $actual, $delta, $message = "") { 522 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertEqualsWithDelta', func_get_args())); 523 | } 524 | 525 | 526 | /** 527 | * [!] Method is generated. Documentation taken from corresponding module. 528 | * 529 | * Asserts that a condition is false. 530 | * 531 | * @param $condition 532 | * @param string $message 533 | * @see \Codeception\Module\AbstractAsserts::assertFalse() 534 | */ 535 | public function assertFalse($condition, $message = "") { 536 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertFalse', func_get_args())); 537 | } 538 | 539 | 540 | /** 541 | * [!] Method is generated. Documentation taken from corresponding module. 542 | * 543 | * Asserts that a file does not exist. 544 | * 545 | * @param string $filename 546 | * @param string $message 547 | * @see \Codeception\Module\AbstractAsserts::assertFileDoesNotExist() 548 | */ 549 | public function assertFileDoesNotExist($filename, $message = "") { 550 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertFileDoesNotExist', func_get_args())); 551 | } 552 | 553 | 554 | /** 555 | * [!] Method is generated. Documentation taken from corresponding module. 556 | * 557 | * Asserts that the contents of one file is equal to the contents of another file. 558 | * 559 | * @param string $expected 560 | * @param string $actual 561 | * @param string $message 562 | * @see \Codeception\Module\AbstractAsserts::assertFileEquals() 563 | */ 564 | public function assertFileEquals($expected, $actual, $message = "") { 565 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertFileEquals', func_get_args())); 566 | } 567 | 568 | 569 | /** 570 | * [!] Method is generated. Documentation taken from corresponding module. 571 | * 572 | * Asserts that the contents of one file is equal to the contents of another file (canonicalizing). 573 | * 574 | * @param $expected 575 | * @param $actual 576 | * @param string $message 577 | * @see \Codeception\Module\AbstractAsserts::assertFileEqualsCanonicalizing() 578 | */ 579 | public function assertFileEqualsCanonicalizing($expected, $actual, $message = "") { 580 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertFileEqualsCanonicalizing', func_get_args())); 581 | } 582 | 583 | 584 | /** 585 | * [!] Method is generated. Documentation taken from corresponding module. 586 | * 587 | * Asserts that the contents of one file is equal to the contents of another file (ignoring case). 588 | * 589 | * @param $expected 590 | * @param $actual 591 | * @param string $message 592 | * @see \Codeception\Module\AbstractAsserts::assertFileEqualsIgnoringCase() 593 | */ 594 | public function assertFileEqualsIgnoringCase($expected, $actual, $message = "") { 595 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertFileEqualsIgnoringCase', func_get_args())); 596 | } 597 | 598 | 599 | /** 600 | * [!] Method is generated. Documentation taken from corresponding module. 601 | * 602 | * Asserts that a file exists. 603 | * 604 | * @param string $filename 605 | * @param string $message 606 | * @see \Codeception\Module\AbstractAsserts::assertFileExists() 607 | */ 608 | public function assertFileExists($filename, $message = "") { 609 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertFileExists', func_get_args())); 610 | } 611 | 612 | 613 | /** 614 | * [!] Method is generated. Documentation taken from corresponding module. 615 | * 616 | * Asserts that a file exists and is not readable. 617 | * 618 | * @param string $file 619 | * @param string $message 620 | * @see \Codeception\Module\AbstractAsserts::assertFileIsNotReadable() 621 | */ 622 | public function assertFileIsNotReadable($file, $message = "") { 623 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertFileIsNotReadable', func_get_args())); 624 | } 625 | 626 | 627 | /** 628 | * [!] Method is generated. Documentation taken from corresponding module. 629 | * 630 | * Asserts that a file exists and is not writable. 631 | * 632 | * @param string $file 633 | * @param string $message 634 | * @see \Codeception\Module\AbstractAsserts::assertFileIsNotWritable() 635 | */ 636 | public function assertFileIsNotWritable($file, $message = "") { 637 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertFileIsNotWritable', func_get_args())); 638 | } 639 | 640 | 641 | /** 642 | * [!] Method is generated. Documentation taken from corresponding module. 643 | * 644 | * Asserts that a file exists and is readable. 645 | * 646 | * @param string $file 647 | * @param string $message 648 | * @see \Codeception\Module\AbstractAsserts::assertFileIsReadable() 649 | */ 650 | public function assertFileIsReadable($file, $message = "") { 651 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertFileIsReadable', func_get_args())); 652 | } 653 | 654 | 655 | /** 656 | * [!] Method is generated. Documentation taken from corresponding module. 657 | * 658 | * Asserts that a file exists and is writable. 659 | * 660 | * @param string $file 661 | * @param string $message 662 | * @see \Codeception\Module\AbstractAsserts::assertFileIsWritable() 663 | */ 664 | public function assertFileIsWritable($file, $message = "") { 665 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertFileIsWritable', func_get_args())); 666 | } 667 | 668 | 669 | /** 670 | * [!] Method is generated. Documentation taken from corresponding module. 671 | * 672 | * Asserts that the contents of one file is not equal to the contents of another file. 673 | * 674 | * @param $expected 675 | * @param $actual 676 | * @param string $message 677 | * @see \Codeception\Module\AbstractAsserts::assertFileNotEquals() 678 | */ 679 | public function assertFileNotEquals($expected, $actual, $message = "") { 680 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertFileNotEquals', func_get_args())); 681 | } 682 | 683 | 684 | /** 685 | * [!] Method is generated. Documentation taken from corresponding module. 686 | * 687 | * Asserts that the contents of one file is not equal to the contents of another file (canonicalizing). 688 | * 689 | * @param $expected 690 | * @param $actual 691 | * @param string $message 692 | * @see \Codeception\Module\AbstractAsserts::assertFileNotEqualsCanonicalizing() 693 | */ 694 | public function assertFileNotEqualsCanonicalizing($expected, $actual, $message = "") { 695 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertFileNotEqualsCanonicalizing', func_get_args())); 696 | } 697 | 698 | 699 | /** 700 | * [!] Method is generated. Documentation taken from corresponding module. 701 | * 702 | * Asserts that the contents of one file is not equal to the contents of another file (ignoring case). 703 | * 704 | * @param $expected 705 | * @param $actual 706 | * @param string $message 707 | * @see \Codeception\Module\AbstractAsserts::assertFileNotEqualsIgnoringCase() 708 | */ 709 | public function assertFileNotEqualsIgnoringCase($expected, $actual, $message = "") { 710 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertFileNotEqualsIgnoringCase', func_get_args())); 711 | } 712 | 713 | 714 | /** 715 | * [!] Method is generated. Documentation taken from corresponding module. 716 | * 717 | * Asserts that a variable is finite. 718 | * 719 | * @param $actual 720 | * @param string $message 721 | * @see \Codeception\Module\AbstractAsserts::assertFinite() 722 | */ 723 | public function assertFinite($actual, $message = "") { 724 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertFinite', func_get_args())); 725 | } 726 | 727 | 728 | /** 729 | * [!] Method is generated. Documentation taken from corresponding module. 730 | * 731 | * Asserts that a value is greater than another value. 732 | * 733 | * @param $expected 734 | * @param $actual 735 | * @param string $message 736 | * @see \Codeception\Module\AbstractAsserts::assertGreaterThan() 737 | */ 738 | public function assertGreaterThan($expected, $actual, $message = "") { 739 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertGreaterThan', func_get_args())); 740 | } 741 | 742 | 743 | /** 744 | * [!] Method is generated. Documentation taken from corresponding module. 745 | * 746 | * Asserts that a value is greater than or equal to another value. 747 | * 748 | * @param $expected 749 | * @param $actual 750 | * @param string $message 751 | * @see \Codeception\Module\AbstractAsserts::assertGreaterThanOrEqual() 752 | */ 753 | public function assertGreaterThanOrEqual($expected, $actual, $message = "") { 754 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertGreaterThanOrEqual', func_get_args())); 755 | } 756 | 757 | 758 | /** 759 | * [!] Method is generated. Documentation taken from corresponding module. 760 | * 761 | * Asserts that a variable is infinite. 762 | * 763 | * @param $actual 764 | * @param string $message 765 | * @see \Codeception\Module\AbstractAsserts::assertInfinite() 766 | */ 767 | public function assertInfinite($actual, $message = "") { 768 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertInfinite', func_get_args())); 769 | } 770 | 771 | 772 | /** 773 | * [!] Method is generated. Documentation taken from corresponding module. 774 | * 775 | * Asserts that a variable is of a given type. 776 | * 777 | * @param $expected 778 | * @param $actual 779 | * @param string $message 780 | * @see \Codeception\Module\AbstractAsserts::assertInstanceOf() 781 | */ 782 | public function assertInstanceOf($expected, $actual, $message = "") { 783 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertInstanceOf', func_get_args())); 784 | } 785 | 786 | 787 | /** 788 | * [!] Method is generated. Documentation taken from corresponding module. 789 | * 790 | * Asserts that a variable is of type array. 791 | * 792 | * @param $actual 793 | * @param string $message 794 | * @see \Codeception\Module\AbstractAsserts::assertIsArray() 795 | */ 796 | public function assertIsArray($actual, $message = "") { 797 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertIsArray', func_get_args())); 798 | } 799 | 800 | 801 | /** 802 | * [!] Method is generated. Documentation taken from corresponding module. 803 | * 804 | * Asserts that a variable is of type bool. 805 | * 806 | * @param $actual 807 | * @param string $message 808 | * @see \Codeception\Module\AbstractAsserts::assertIsBool() 809 | */ 810 | public function assertIsBool($actual, $message = "") { 811 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertIsBool', func_get_args())); 812 | } 813 | 814 | 815 | /** 816 | * [!] Method is generated. Documentation taken from corresponding module. 817 | * 818 | * Asserts that a variable is of type callable. 819 | * 820 | * @param $actual 821 | * @param string $message 822 | * @see \Codeception\Module\AbstractAsserts::assertIsCallable() 823 | */ 824 | public function assertIsCallable($actual, $message = "") { 825 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertIsCallable', func_get_args())); 826 | } 827 | 828 | 829 | /** 830 | * [!] Method is generated. Documentation taken from corresponding module. 831 | * 832 | * Asserts that a variable is of type resource and is closed. 833 | * 834 | * @param $actual 835 | * @param string $message 836 | * @see \Codeception\Module\AbstractAsserts::assertIsClosedResource() 837 | */ 838 | public function assertIsClosedResource($actual, $message = "") { 839 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertIsClosedResource', func_get_args())); 840 | } 841 | 842 | 843 | /** 844 | * [!] Method is generated. Documentation taken from corresponding module. 845 | * 846 | * Asserts that a variable is of type float. 847 | * 848 | * @param $actual 849 | * @param string $message 850 | * @see \Codeception\Module\AbstractAsserts::assertIsFloat() 851 | */ 852 | public function assertIsFloat($actual, $message = "") { 853 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertIsFloat', func_get_args())); 854 | } 855 | 856 | 857 | /** 858 | * [!] Method is generated. Documentation taken from corresponding module. 859 | * 860 | * Asserts that a variable is of type int. 861 | * 862 | * @param $actual 863 | * @param string $message 864 | * @see \Codeception\Module\AbstractAsserts::assertIsInt() 865 | */ 866 | public function assertIsInt($actual, $message = "") { 867 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertIsInt', func_get_args())); 868 | } 869 | 870 | 871 | /** 872 | * [!] Method is generated. Documentation taken from corresponding module. 873 | * 874 | * Asserts that a variable is of type iterable. 875 | * 876 | * @param $actual 877 | * @param string $message 878 | * @see \Codeception\Module\AbstractAsserts::assertIsIterable() 879 | */ 880 | public function assertIsIterable($actual, $message = "") { 881 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertIsIterable', func_get_args())); 882 | } 883 | 884 | 885 | /** 886 | * [!] Method is generated. Documentation taken from corresponding module. 887 | * 888 | * Asserts that a variable is not of type array. 889 | * 890 | * @param $actual 891 | * @param string $message 892 | * @see \Codeception\Module\AbstractAsserts::assertIsNotArray() 893 | */ 894 | public function assertIsNotArray($actual, $message = "") { 895 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertIsNotArray', func_get_args())); 896 | } 897 | 898 | 899 | /** 900 | * [!] Method is generated. Documentation taken from corresponding module. 901 | * 902 | * Asserts that a variable is not of type bool. 903 | * 904 | * @param $actual 905 | * @param string $message 906 | * @see \Codeception\Module\AbstractAsserts::assertIsNotBool() 907 | */ 908 | public function assertIsNotBool($actual, $message = "") { 909 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertIsNotBool', func_get_args())); 910 | } 911 | 912 | 913 | /** 914 | * [!] Method is generated. Documentation taken from corresponding module. 915 | * 916 | * Asserts that a variable is not of type callable. 917 | * 918 | * @param $actual 919 | * @param string $message 920 | * @see \Codeception\Module\AbstractAsserts::assertIsNotCallable() 921 | */ 922 | public function assertIsNotCallable($actual, $message = "") { 923 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertIsNotCallable', func_get_args())); 924 | } 925 | 926 | 927 | /** 928 | * [!] Method is generated. Documentation taken from corresponding module. 929 | * 930 | * Asserts that a variable is not of type resource. 931 | * 932 | * @param $actual 933 | * @param string $message 934 | * @see \Codeception\Module\AbstractAsserts::assertIsNotClosedResource() 935 | */ 936 | public function assertIsNotClosedResource($actual, $message = "") { 937 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertIsNotClosedResource', func_get_args())); 938 | } 939 | 940 | 941 | /** 942 | * [!] Method is generated. Documentation taken from corresponding module. 943 | * 944 | * Asserts that a variable is not of type float. 945 | * 946 | * @param $actual 947 | * @param string $message 948 | * @see \Codeception\Module\AbstractAsserts::assertIsNotFloat() 949 | */ 950 | public function assertIsNotFloat($actual, $message = "") { 951 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertIsNotFloat', func_get_args())); 952 | } 953 | 954 | 955 | /** 956 | * [!] Method is generated. Documentation taken from corresponding module. 957 | * 958 | * Asserts that a variable is not of type int. 959 | * 960 | * @param $actual 961 | * @param string $message 962 | * @see \Codeception\Module\AbstractAsserts::assertIsNotInt() 963 | */ 964 | public function assertIsNotInt($actual, $message = "") { 965 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertIsNotInt', func_get_args())); 966 | } 967 | 968 | 969 | /** 970 | * [!] Method is generated. Documentation taken from corresponding module. 971 | * 972 | * Asserts that a variable is not of type iterable. 973 | * 974 | * @param $actual 975 | * @param string $message 976 | * @see \Codeception\Module\AbstractAsserts::assertIsNotIterable() 977 | */ 978 | public function assertIsNotIterable($actual, $message = "") { 979 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertIsNotIterable', func_get_args())); 980 | } 981 | 982 | 983 | /** 984 | * [!] Method is generated. Documentation taken from corresponding module. 985 | * 986 | * Asserts that a variable is not of type numeric. 987 | * 988 | * @param $actual 989 | * @param string $message 990 | * @see \Codeception\Module\AbstractAsserts::assertIsNotNumeric() 991 | */ 992 | public function assertIsNotNumeric($actual, $message = "") { 993 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertIsNotNumeric', func_get_args())); 994 | } 995 | 996 | 997 | /** 998 | * [!] Method is generated. Documentation taken from corresponding module. 999 | * 1000 | * Asserts that a variable is not of type object. 1001 | * 1002 | * @param $actual 1003 | * @param string $message 1004 | * @see \Codeception\Module\AbstractAsserts::assertIsNotObject() 1005 | */ 1006 | public function assertIsNotObject($actual, $message = "") { 1007 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertIsNotObject', func_get_args())); 1008 | } 1009 | 1010 | 1011 | /** 1012 | * [!] Method is generated. Documentation taken from corresponding module. 1013 | * 1014 | * Asserts that a file/dir exists and is not readable. 1015 | * 1016 | * @param string $filename 1017 | * @param string $message 1018 | * @see \Codeception\Module\AbstractAsserts::assertIsNotReadable() 1019 | */ 1020 | public function assertIsNotReadable($filename, $message = "") { 1021 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertIsNotReadable', func_get_args())); 1022 | } 1023 | 1024 | 1025 | /** 1026 | * [!] Method is generated. Documentation taken from corresponding module. 1027 | * 1028 | * Asserts that a variable is not of type resource. 1029 | * 1030 | * @param $actual 1031 | * @param string $message 1032 | * @see \Codeception\Module\AbstractAsserts::assertIsNotResource() 1033 | */ 1034 | public function assertIsNotResource($actual, $message = "") { 1035 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertIsNotResource', func_get_args())); 1036 | } 1037 | 1038 | 1039 | /** 1040 | * [!] Method is generated. Documentation taken from corresponding module. 1041 | * 1042 | * Asserts that a variable is not of type scalar. 1043 | * 1044 | * @param $actual 1045 | * @param string $message 1046 | * @see \Codeception\Module\AbstractAsserts::assertIsNotScalar() 1047 | */ 1048 | public function assertIsNotScalar($actual, $message = "") { 1049 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertIsNotScalar', func_get_args())); 1050 | } 1051 | 1052 | 1053 | /** 1054 | * [!] Method is generated. Documentation taken from corresponding module. 1055 | * 1056 | * Asserts that a variable is not of type string. 1057 | * 1058 | * @param $actual 1059 | * @param string $message 1060 | * @see \Codeception\Module\AbstractAsserts::assertIsNotString() 1061 | */ 1062 | public function assertIsNotString($actual, $message = "") { 1063 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertIsNotString', func_get_args())); 1064 | } 1065 | 1066 | 1067 | /** 1068 | * [!] Method is generated. Documentation taken from corresponding module. 1069 | * 1070 | * Asserts that a file/dir exists and is not writable. 1071 | * 1072 | * @param $filename 1073 | * @param string $message 1074 | * @see \Codeception\Module\AbstractAsserts::assertIsNotWritable() 1075 | */ 1076 | public function assertIsNotWritable($filename, $message = "") { 1077 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertIsNotWritable', func_get_args())); 1078 | } 1079 | 1080 | 1081 | /** 1082 | * [!] Method is generated. Documentation taken from corresponding module. 1083 | * 1084 | * Asserts that a variable is of type numeric. 1085 | * 1086 | * @param $actual 1087 | * @param string $message 1088 | * @see \Codeception\Module\AbstractAsserts::assertIsNumeric() 1089 | */ 1090 | public function assertIsNumeric($actual, $message = "") { 1091 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertIsNumeric', func_get_args())); 1092 | } 1093 | 1094 | 1095 | /** 1096 | * [!] Method is generated. Documentation taken from corresponding module. 1097 | * 1098 | * Asserts that a variable is of type object. 1099 | * 1100 | * @param $actual 1101 | * @param string $message 1102 | * @see \Codeception\Module\AbstractAsserts::assertIsObject() 1103 | */ 1104 | public function assertIsObject($actual, $message = "") { 1105 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertIsObject', func_get_args())); 1106 | } 1107 | 1108 | 1109 | /** 1110 | * [!] Method is generated. Documentation taken from corresponding module. 1111 | * 1112 | * Asserts that a file/dir is readable. 1113 | * 1114 | * @param $filename 1115 | * @param string $message 1116 | * @see \Codeception\Module\AbstractAsserts::assertIsReadable() 1117 | */ 1118 | public function assertIsReadable($filename, $message = "") { 1119 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertIsReadable', func_get_args())); 1120 | } 1121 | 1122 | 1123 | /** 1124 | * [!] Method is generated. Documentation taken from corresponding module. 1125 | * 1126 | * Asserts that a variable is of type resource. 1127 | * 1128 | * @param $actual 1129 | * @param string $message 1130 | * @see \Codeception\Module\AbstractAsserts::assertIsResource() 1131 | */ 1132 | public function assertIsResource($actual, $message = "") { 1133 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertIsResource', func_get_args())); 1134 | } 1135 | 1136 | 1137 | /** 1138 | * [!] Method is generated. Documentation taken from corresponding module. 1139 | * 1140 | * Asserts that a variable is of type scalar. 1141 | * 1142 | * @param $actual 1143 | * @param string $message 1144 | * @see \Codeception\Module\AbstractAsserts::assertIsScalar() 1145 | */ 1146 | public function assertIsScalar($actual, $message = "") { 1147 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertIsScalar', func_get_args())); 1148 | } 1149 | 1150 | 1151 | /** 1152 | * [!] Method is generated. Documentation taken from corresponding module. 1153 | * 1154 | * Asserts that a variable is of type string. 1155 | * 1156 | * @param $actual 1157 | * @param string $message 1158 | * @see \Codeception\Module\AbstractAsserts::assertIsString() 1159 | */ 1160 | public function assertIsString($actual, $message = "") { 1161 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertIsString', func_get_args())); 1162 | } 1163 | 1164 | 1165 | /** 1166 | * [!] Method is generated. Documentation taken from corresponding module. 1167 | * 1168 | * Asserts that a file/dir exists and is writable. 1169 | * 1170 | * @param $filename 1171 | * @param string $message 1172 | * @see \Codeception\Module\AbstractAsserts::assertIsWritable() 1173 | */ 1174 | public function assertIsWritable($filename, $message = "") { 1175 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertIsWritable', func_get_args())); 1176 | } 1177 | 1178 | 1179 | /** 1180 | * [!] Method is generated. Documentation taken from corresponding module. 1181 | * 1182 | * Asserts that a string is a valid JSON string. 1183 | * 1184 | * @param string $actualJson 1185 | * @param string $message 1186 | * @see \Codeception\Module\AbstractAsserts::assertJson() 1187 | */ 1188 | public function assertJson($actualJson, $message = "") { 1189 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertJson', func_get_args())); 1190 | } 1191 | 1192 | 1193 | /** 1194 | * [!] Method is generated. Documentation taken from corresponding module. 1195 | * 1196 | * Asserts that two JSON files are equal. 1197 | * 1198 | * @param string $expectedFile 1199 | * @param string $actualFile 1200 | * @param string $message 1201 | * @see \Codeception\Module\AbstractAsserts::assertJsonFileEqualsJsonFile() 1202 | */ 1203 | public function assertJsonFileEqualsJsonFile($expectedFile, $actualFile, $message = "") { 1204 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertJsonFileEqualsJsonFile', func_get_args())); 1205 | } 1206 | 1207 | 1208 | /** 1209 | * [!] Method is generated. Documentation taken from corresponding module. 1210 | * 1211 | * Asserts that two JSON files are not equal. 1212 | * 1213 | * @param string $expectedFile 1214 | * @param string $actualFile 1215 | * @param string $message 1216 | * @see \Codeception\Module\AbstractAsserts::assertJsonFileNotEqualsJsonFile() 1217 | */ 1218 | public function assertJsonFileNotEqualsJsonFile($expectedFile, $actualFile, $message = "") { 1219 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertJsonFileNotEqualsJsonFile', func_get_args())); 1220 | } 1221 | 1222 | 1223 | /** 1224 | * [!] Method is generated. Documentation taken from corresponding module. 1225 | * 1226 | * Asserts that the generated JSON encoded object and the content of the given file are equal. 1227 | * 1228 | * @param string $expectedFile 1229 | * @param string $actualJson 1230 | * @param string $message 1231 | * @see \Codeception\Module\AbstractAsserts::assertJsonStringEqualsJsonFile() 1232 | */ 1233 | public function assertJsonStringEqualsJsonFile($expectedFile, $actualJson, $message = "") { 1234 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertJsonStringEqualsJsonFile', func_get_args())); 1235 | } 1236 | 1237 | 1238 | /** 1239 | * [!] Method is generated. Documentation taken from corresponding module. 1240 | * 1241 | * Asserts that two given JSON encoded objects or arrays are equal. 1242 | * 1243 | * @param string $expectedJson 1244 | * @param string $actualJson 1245 | * @param string $message 1246 | * @see \Codeception\Module\AbstractAsserts::assertJsonStringEqualsJsonString() 1247 | */ 1248 | public function assertJsonStringEqualsJsonString($expectedJson, $actualJson, $message = "") { 1249 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertJsonStringEqualsJsonString', func_get_args())); 1250 | } 1251 | 1252 | 1253 | /** 1254 | * [!] Method is generated. Documentation taken from corresponding module. 1255 | * 1256 | * Asserts that the generated JSON encoded object and the content of the given file are not equal. 1257 | * 1258 | * @param string $expectedFile 1259 | * @param string $actualJson 1260 | * @param string $message 1261 | * @see \Codeception\Module\AbstractAsserts::assertJsonStringNotEqualsJsonFile() 1262 | */ 1263 | public function assertJsonStringNotEqualsJsonFile($expectedFile, $actualJson, $message = "") { 1264 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertJsonStringNotEqualsJsonFile', func_get_args())); 1265 | } 1266 | 1267 | 1268 | /** 1269 | * [!] Method is generated. Documentation taken from corresponding module. 1270 | * 1271 | * Asserts that two given JSON encoded objects or arrays are not equal. 1272 | * 1273 | * @param string $expectedJson 1274 | * @param string $actualJson 1275 | * @param string $message 1276 | * @see \Codeception\Module\AbstractAsserts::assertJsonStringNotEqualsJsonString() 1277 | */ 1278 | public function assertJsonStringNotEqualsJsonString($expectedJson, $actualJson, $message = "") { 1279 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertJsonStringNotEqualsJsonString', func_get_args())); 1280 | } 1281 | 1282 | 1283 | /** 1284 | * [!] Method is generated. Documentation taken from corresponding module. 1285 | * 1286 | * Asserts that a value is smaller than another value. 1287 | * 1288 | * @param $expected 1289 | * @param $actual 1290 | * @param string $message 1291 | * @see \Codeception\Module\AbstractAsserts::assertLessThan() 1292 | */ 1293 | public function assertLessThan($expected, $actual, $message = "") { 1294 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertLessThan', func_get_args())); 1295 | } 1296 | 1297 | 1298 | /** 1299 | * [!] Method is generated. Documentation taken from corresponding module. 1300 | * 1301 | * Asserts that a value is smaller than or equal to another value. 1302 | * 1303 | * @param $expected 1304 | * @param $actual 1305 | * @param string $message 1306 | * @see \Codeception\Module\AbstractAsserts::assertLessThanOrEqual() 1307 | */ 1308 | public function assertLessThanOrEqual($expected, $actual, $message = "") { 1309 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertLessThanOrEqual', func_get_args())); 1310 | } 1311 | 1312 | 1313 | /** 1314 | * [!] Method is generated. Documentation taken from corresponding module. 1315 | * 1316 | * Asserts that a string matches a given regular expression. 1317 | * 1318 | * @param string $pattern 1319 | * @param string $string 1320 | * @param string $message 1321 | * @see \Codeception\Module\AbstractAsserts::assertMatchesRegularExpression() 1322 | */ 1323 | public function assertMatchesRegularExpression($pattern, $string, $message = "") { 1324 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertMatchesRegularExpression', func_get_args())); 1325 | } 1326 | 1327 | 1328 | /** 1329 | * [!] Method is generated. Documentation taken from corresponding module. 1330 | * 1331 | * Asserts that a variable is nan. 1332 | * 1333 | * @param $actual 1334 | * @param string $message 1335 | * @see \Codeception\Module\AbstractAsserts::assertNan() 1336 | */ 1337 | public function assertNan($actual, $message = "") { 1338 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertNan', func_get_args())); 1339 | } 1340 | 1341 | 1342 | /** 1343 | * [!] Method is generated. Documentation taken from corresponding module. 1344 | * 1345 | * Asserts that a haystack does not contain a needle. 1346 | * 1347 | * @param $needle 1348 | * @param $haystack 1349 | * @param string $message 1350 | * @see \Codeception\Module\AbstractAsserts::assertNotContains() 1351 | */ 1352 | public function assertNotContains($needle, $haystack, $message = "") { 1353 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertNotContains', func_get_args())); 1354 | } 1355 | 1356 | 1357 | /** 1358 | * [!] Method is generated. Documentation taken from corresponding module. 1359 | * 1360 | * 1361 | * @see \Codeception\Module\AbstractAsserts::assertNotContainsEquals() 1362 | */ 1363 | public function assertNotContainsEquals($needle, $haystack, $message = "") { 1364 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertNotContainsEquals', func_get_args())); 1365 | } 1366 | 1367 | 1368 | /** 1369 | * [!] Method is generated. Documentation taken from corresponding module. 1370 | * 1371 | * Asserts that a haystack does not contain only values of a given type. 1372 | * 1373 | * @param string $type 1374 | * @param $haystack 1375 | * @param bool|null $isNativeType 1376 | * @param string $message 1377 | * @see \Codeception\Module\AbstractAsserts::assertNotContainsOnly() 1378 | */ 1379 | public function assertNotContainsOnly($type, $haystack, $isNativeType = NULL, $message = "") { 1380 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertNotContainsOnly', func_get_args())); 1381 | } 1382 | 1383 | 1384 | /** 1385 | * [!] Method is generated. Documentation taken from corresponding module. 1386 | * 1387 | * Asserts the number of elements of an array, Countable or Traversable. 1388 | * 1389 | * @param int $expectedCount 1390 | * @param Countable|iterable $haystack 1391 | * @param string $message 1392 | * @see \Codeception\Module\AbstractAsserts::assertNotCount() 1393 | */ 1394 | public function assertNotCount($expectedCount, $haystack, $message = "") { 1395 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertNotCount', func_get_args())); 1396 | } 1397 | 1398 | 1399 | /** 1400 | * [!] Method is generated. Documentation taken from corresponding module. 1401 | * 1402 | * Asserts that a variable is not empty. 1403 | * 1404 | * @param $actual 1405 | * @param string $message 1406 | * @see \Codeception\Module\AbstractAsserts::assertNotEmpty() 1407 | */ 1408 | public function assertNotEmpty($actual, $message = "") { 1409 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertNotEmpty', func_get_args())); 1410 | } 1411 | 1412 | 1413 | /** 1414 | * [!] Method is generated. Documentation taken from corresponding module. 1415 | * 1416 | * Asserts that two variables are not equal. 1417 | * 1418 | * @param $expected 1419 | * @param $actual 1420 | * @param string $message 1421 | * @see \Codeception\Module\AbstractAsserts::assertNotEquals() 1422 | */ 1423 | public function assertNotEquals($expected, $actual, $message = "") { 1424 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertNotEquals', func_get_args())); 1425 | } 1426 | 1427 | 1428 | /** 1429 | * [!] Method is generated. Documentation taken from corresponding module. 1430 | * 1431 | * Asserts that two variables are not equal (canonicalizing). 1432 | * 1433 | * @param $expected 1434 | * @param $actual 1435 | * @param string $message 1436 | * @see \Codeception\Module\AbstractAsserts::assertNotEqualsCanonicalizing() 1437 | */ 1438 | public function assertNotEqualsCanonicalizing($expected, $actual, $message = "") { 1439 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertNotEqualsCanonicalizing', func_get_args())); 1440 | } 1441 | 1442 | 1443 | /** 1444 | * [!] Method is generated. Documentation taken from corresponding module. 1445 | * 1446 | * Asserts that two variables are not equal (ignoring case). 1447 | * 1448 | * @param $expected 1449 | * @param $actual 1450 | * @param string $message 1451 | * @see \Codeception\Module\AbstractAsserts::assertNotEqualsIgnoringCase() 1452 | */ 1453 | public function assertNotEqualsIgnoringCase($expected, $actual, $message = "") { 1454 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertNotEqualsIgnoringCase', func_get_args())); 1455 | } 1456 | 1457 | 1458 | /** 1459 | * [!] Method is generated. Documentation taken from corresponding module. 1460 | * 1461 | * Asserts that two variables are not equal (with delta). 1462 | * 1463 | * @param $expected 1464 | * @param $actual 1465 | * @param float $delta 1466 | * @param string $message 1467 | * @see \Codeception\Module\AbstractAsserts::assertNotEqualsWithDelta() 1468 | */ 1469 | public function assertNotEqualsWithDelta($expected, $actual, $delta, $message = "") { 1470 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertNotEqualsWithDelta', func_get_args())); 1471 | } 1472 | 1473 | 1474 | /** 1475 | * [!] Method is generated. Documentation taken from corresponding module. 1476 | * 1477 | * Asserts that a condition is not false. 1478 | * 1479 | * @param $condition 1480 | * @param string $message 1481 | * @see \Codeception\Module\AbstractAsserts::assertNotFalse() 1482 | */ 1483 | public function assertNotFalse($condition, $message = "") { 1484 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertNotFalse', func_get_args())); 1485 | } 1486 | 1487 | 1488 | /** 1489 | * [!] Method is generated. Documentation taken from corresponding module. 1490 | * 1491 | * Asserts that a variable is not of a given type. 1492 | * 1493 | * @param $expected 1494 | * @param $actual 1495 | * @param string $message 1496 | * @see \Codeception\Module\AbstractAsserts::assertNotInstanceOf() 1497 | */ 1498 | public function assertNotInstanceOf($expected, $actual, $message = "") { 1499 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertNotInstanceOf', func_get_args())); 1500 | } 1501 | 1502 | 1503 | /** 1504 | * [!] Method is generated. Documentation taken from corresponding module. 1505 | * 1506 | * Asserts that a variable is not null. 1507 | * 1508 | * @param $actual 1509 | * @param string $message 1510 | * @see \Codeception\Module\AbstractAsserts::assertNotNull() 1511 | */ 1512 | public function assertNotNull($actual, $message = "") { 1513 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertNotNull', func_get_args())); 1514 | } 1515 | 1516 | 1517 | /** 1518 | * [!] Method is generated. Documentation taken from corresponding module. 1519 | * 1520 | * Asserts that two variables do not have the same type and value. 1521 | * 1522 | * @param $expected 1523 | * @param $actual 1524 | * @param string $message 1525 | * @see \Codeception\Module\AbstractAsserts::assertNotSame() 1526 | */ 1527 | public function assertNotSame($expected, $actual, $message = "") { 1528 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertNotSame', func_get_args())); 1529 | } 1530 | 1531 | 1532 | /** 1533 | * [!] Method is generated. Documentation taken from corresponding module. 1534 | * 1535 | * Assert that the size of two arrays (or `Countable` or `Traversable` objects) is not the same. 1536 | * 1537 | * @param Countable|iterable $expected 1538 | * @param Countable|iterable $actual 1539 | * @param string $message 1540 | * @see \Codeception\Module\AbstractAsserts::assertNotSameSize() 1541 | */ 1542 | public function assertNotSameSize($expected, $actual, $message = "") { 1543 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertNotSameSize', func_get_args())); 1544 | } 1545 | 1546 | 1547 | /** 1548 | * [!] Method is generated. Documentation taken from corresponding module. 1549 | * 1550 | * Asserts that a condition is not true. 1551 | * 1552 | * @param $condition 1553 | * @param string $message 1554 | * @see \Codeception\Module\AbstractAsserts::assertNotTrue() 1555 | */ 1556 | public function assertNotTrue($condition, $message = "") { 1557 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertNotTrue', func_get_args())); 1558 | } 1559 | 1560 | 1561 | /** 1562 | * [!] Method is generated. Documentation taken from corresponding module. 1563 | * 1564 | * Asserts that a variable is null. 1565 | * 1566 | * @param $actual 1567 | * @param string $message 1568 | * @see \Codeception\Module\AbstractAsserts::assertNull() 1569 | */ 1570 | public function assertNull($actual, $message = "") { 1571 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertNull', func_get_args())); 1572 | } 1573 | 1574 | 1575 | /** 1576 | * [!] Method is generated. Documentation taken from corresponding module. 1577 | * 1578 | * Asserts that an object has a specified attribute. 1579 | * 1580 | * @param string $attributeName 1581 | * @param object $object 1582 | * @param string $message 1583 | * @see \Codeception\Module\AbstractAsserts::assertObjectHasAttribute() 1584 | */ 1585 | public function assertObjectHasAttribute($attributeName, $object, $message = "") { 1586 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertObjectHasAttribute', func_get_args())); 1587 | } 1588 | 1589 | 1590 | /** 1591 | * [!] Method is generated. Documentation taken from corresponding module. 1592 | * 1593 | * Asserts that an object does not have a specified attribute. 1594 | * 1595 | * @param string $attributeName 1596 | * @param object $object 1597 | * @param string $message 1598 | * @see \Codeception\Module\AbstractAsserts::assertObjectNotHasAttribute() 1599 | */ 1600 | public function assertObjectNotHasAttribute($attributeName, $object, $message = "") { 1601 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertObjectNotHasAttribute', func_get_args())); 1602 | } 1603 | 1604 | 1605 | /** 1606 | * [!] Method is generated. Documentation taken from corresponding module. 1607 | * 1608 | * Asserts that two variables have the same type and value. 1609 | * 1610 | * @param $expected 1611 | * @param $actual 1612 | * @param string $message 1613 | * @see \Codeception\Module\AbstractAsserts::assertSame() 1614 | */ 1615 | public function assertSame($expected, $actual, $message = "") { 1616 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertSame', func_get_args())); 1617 | } 1618 | 1619 | 1620 | /** 1621 | * [!] Method is generated. Documentation taken from corresponding module. 1622 | * 1623 | * Assert that the size of two arrays (or `Countable` or `Traversable` objects) is the same. 1624 | * 1625 | * @param Countable|iterable $expected 1626 | * @param Countable|iterable $actual 1627 | * @param string $message 1628 | * @see \Codeception\Module\AbstractAsserts::assertSameSize() 1629 | */ 1630 | public function assertSameSize($expected, $actual, $message = "") { 1631 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertSameSize', func_get_args())); 1632 | } 1633 | 1634 | 1635 | /** 1636 | * [!] Method is generated. Documentation taken from corresponding module. 1637 | * 1638 | * @param string $needle 1639 | * @param string $haystack 1640 | * @param string $message 1641 | * @see \Codeception\Module\AbstractAsserts::assertStringContainsString() 1642 | */ 1643 | public function assertStringContainsString($needle, $haystack, $message = "") { 1644 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertStringContainsString', func_get_args())); 1645 | } 1646 | 1647 | 1648 | /** 1649 | * [!] Method is generated. Documentation taken from corresponding module. 1650 | * 1651 | * 1652 | * @see \Codeception\Module\AbstractAsserts::assertStringContainsStringIgnoringCase() 1653 | */ 1654 | public function assertStringContainsStringIgnoringCase($needle, $haystack, $message = "") { 1655 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertStringContainsStringIgnoringCase', func_get_args())); 1656 | } 1657 | 1658 | 1659 | /** 1660 | * [!] Method is generated. Documentation taken from corresponding module. 1661 | * 1662 | * Asserts that a string ends not with a given suffix. 1663 | * 1664 | * @param string $suffix 1665 | * @param string $string 1666 | * @param string $message 1667 | * @see \Codeception\Module\AbstractAsserts::assertStringEndsNotWith() 1668 | */ 1669 | public function assertStringEndsNotWith($suffix, $string, $message = "") { 1670 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertStringEndsNotWith', func_get_args())); 1671 | } 1672 | 1673 | 1674 | /** 1675 | * [!] Method is generated. Documentation taken from corresponding module. 1676 | * 1677 | * Asserts that a string ends with a given suffix. 1678 | * 1679 | * @param string $suffix 1680 | * @param string $string 1681 | * @param string $message 1682 | * @see \Codeception\Module\AbstractAsserts::assertStringEndsWith() 1683 | */ 1684 | public function assertStringEndsWith($suffix, $string, $message = "") { 1685 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertStringEndsWith', func_get_args())); 1686 | } 1687 | 1688 | 1689 | /** 1690 | * [!] Method is generated. Documentation taken from corresponding module. 1691 | * 1692 | * Asserts that the contents of a string is equal to the contents of a file. 1693 | * 1694 | * @param string $expectedFile 1695 | * @param string $actualString 1696 | * @param string $message 1697 | * @see \Codeception\Module\AbstractAsserts::assertStringEqualsFile() 1698 | */ 1699 | public function assertStringEqualsFile($expectedFile, $actualString, $message = "") { 1700 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertStringEqualsFile', func_get_args())); 1701 | } 1702 | 1703 | 1704 | /** 1705 | * [!] Method is generated. Documentation taken from corresponding module. 1706 | * 1707 | * Asserts that the contents of a string is equal to the contents of a file (canonicalizing). 1708 | * 1709 | * @param string $expectedFile 1710 | * @param string $actualString 1711 | * @param string $message 1712 | * @see \Codeception\Module\AbstractAsserts::assertStringEqualsFileCanonicalizing() 1713 | */ 1714 | public function assertStringEqualsFileCanonicalizing($expectedFile, $actualString, $message = "") { 1715 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertStringEqualsFileCanonicalizing', func_get_args())); 1716 | } 1717 | 1718 | 1719 | /** 1720 | * [!] Method is generated. Documentation taken from corresponding module. 1721 | * 1722 | * Asserts that the contents of a string is equal to the contents of a file (ignoring case). 1723 | * 1724 | * @param string $expectedFile 1725 | * @param string $actualString 1726 | * @param string $message 1727 | * @see \Codeception\Module\AbstractAsserts::assertStringEqualsFileIgnoringCase() 1728 | */ 1729 | public function assertStringEqualsFileIgnoringCase($expectedFile, $actualString, $message = "") { 1730 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertStringEqualsFileIgnoringCase', func_get_args())); 1731 | } 1732 | 1733 | 1734 | /** 1735 | * [!] Method is generated. Documentation taken from corresponding module. 1736 | * 1737 | * Asserts that a string matches a given format string. 1738 | * 1739 | * @param string $format 1740 | * @param string $string 1741 | * @param string $message 1742 | * @see \Codeception\Module\AbstractAsserts::assertStringMatchesFormat() 1743 | */ 1744 | public function assertStringMatchesFormat($format, $string, $message = "") { 1745 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertStringMatchesFormat', func_get_args())); 1746 | } 1747 | 1748 | 1749 | /** 1750 | * [!] Method is generated. Documentation taken from corresponding module. 1751 | * 1752 | * Asserts that a string matches a given format file. 1753 | * 1754 | * @param string $formatFile 1755 | * @param string $string 1756 | * @param string $message 1757 | * @see \Codeception\Module\AbstractAsserts::assertStringMatchesFormatFile() 1758 | */ 1759 | public function assertStringMatchesFormatFile($formatFile, $string, $message = "") { 1760 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertStringMatchesFormatFile', func_get_args())); 1761 | } 1762 | 1763 | 1764 | /** 1765 | * [!] Method is generated. Documentation taken from corresponding module. 1766 | * 1767 | * @param string $needle 1768 | * @param string $haystack 1769 | * @param string $message 1770 | * @see \Codeception\Module\AbstractAsserts::assertStringNotContainsString() 1771 | */ 1772 | public function assertStringNotContainsString($needle, $haystack, $message = "") { 1773 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertStringNotContainsString', func_get_args())); 1774 | } 1775 | 1776 | 1777 | /** 1778 | * [!] Method is generated. Documentation taken from corresponding module. 1779 | * 1780 | * @param string $needle 1781 | * @param string $haystack 1782 | * @param string $message 1783 | * @see \Codeception\Module\AbstractAsserts::assertStringNotContainsStringIgnoringCase() 1784 | */ 1785 | public function assertStringNotContainsStringIgnoringCase($needle, $haystack, $message = "") { 1786 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertStringNotContainsStringIgnoringCase', func_get_args())); 1787 | } 1788 | 1789 | 1790 | /** 1791 | * [!] Method is generated. Documentation taken from corresponding module. 1792 | * 1793 | * Asserts that the contents of a string is not equal to the contents of a file. 1794 | * 1795 | * @param string $expectedFile 1796 | * @param string $actualString 1797 | * @param string $message 1798 | * @see \Codeception\Module\AbstractAsserts::assertStringNotEqualsFile() 1799 | */ 1800 | public function assertStringNotEqualsFile($expectedFile, $actualString, $message = "") { 1801 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertStringNotEqualsFile', func_get_args())); 1802 | } 1803 | 1804 | 1805 | /** 1806 | * [!] Method is generated. Documentation taken from corresponding module. 1807 | * 1808 | * Asserts that the contents of a string is not equal to the contents of a file (canonicalizing). 1809 | * @param string $expectedFile 1810 | * @param string $actualString 1811 | * @param string $message 1812 | * @see \Codeception\Module\AbstractAsserts::assertStringNotEqualsFileCanonicalizing() 1813 | */ 1814 | public function assertStringNotEqualsFileCanonicalizing($expectedFile, $actualString, $message = "") { 1815 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertStringNotEqualsFileCanonicalizing', func_get_args())); 1816 | } 1817 | 1818 | 1819 | /** 1820 | * [!] Method is generated. Documentation taken from corresponding module. 1821 | * 1822 | * Asserts that the contents of a string is not equal to the contents of a file (ignoring case). 1823 | * 1824 | * @param string $expectedFile 1825 | * @param string $actualString 1826 | * @param string $message 1827 | * @see \Codeception\Module\AbstractAsserts::assertStringNotEqualsFileIgnoringCase() 1828 | */ 1829 | public function assertStringNotEqualsFileIgnoringCase($expectedFile, $actualString, $message = "") { 1830 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertStringNotEqualsFileIgnoringCase', func_get_args())); 1831 | } 1832 | 1833 | 1834 | /** 1835 | * [!] Method is generated. Documentation taken from corresponding module. 1836 | * 1837 | * Asserts that a string does not match a given format string. 1838 | * 1839 | * @param string $format 1840 | * @param string $string 1841 | * @param string $message 1842 | * @see \Codeception\Module\AbstractAsserts::assertStringNotMatchesFormat() 1843 | */ 1844 | public function assertStringNotMatchesFormat($format, $string, $message = "") { 1845 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertStringNotMatchesFormat', func_get_args())); 1846 | } 1847 | 1848 | 1849 | /** 1850 | * [!] Method is generated. Documentation taken from corresponding module. 1851 | * 1852 | * Asserts that a string does not match a given format string. 1853 | * 1854 | * @param string $formatFile 1855 | * @param string $string 1856 | * @param string $message 1857 | * @see \Codeception\Module\AbstractAsserts::assertStringNotMatchesFormatFile() 1858 | */ 1859 | public function assertStringNotMatchesFormatFile($formatFile, $string, $message = "") { 1860 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertStringNotMatchesFormatFile', func_get_args())); 1861 | } 1862 | 1863 | 1864 | /** 1865 | * [!] Method is generated. Documentation taken from corresponding module. 1866 | * 1867 | * Asserts that a string starts not with a given prefix. 1868 | * 1869 | * @param string $prefix 1870 | * @param string $string 1871 | * @param string $message 1872 | * @see \Codeception\Module\AbstractAsserts::assertStringStartsNotWith() 1873 | */ 1874 | public function assertStringStartsNotWith($prefix, $string, $message = "") { 1875 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertStringStartsNotWith', func_get_args())); 1876 | } 1877 | 1878 | 1879 | /** 1880 | * [!] Method is generated. Documentation taken from corresponding module. 1881 | * 1882 | * Asserts that a string starts with a given prefix. 1883 | * 1884 | * @param string $prefix 1885 | * @param string $string 1886 | * @param string $message 1887 | * @see \Codeception\Module\AbstractAsserts::assertStringStartsWith() 1888 | */ 1889 | public function assertStringStartsWith($prefix, $string, $message = "") { 1890 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertStringStartsWith', func_get_args())); 1891 | } 1892 | 1893 | 1894 | /** 1895 | * [!] Method is generated. Documentation taken from corresponding module. 1896 | * 1897 | * Evaluates a PHPUnit\Framework\Constraint matcher object. 1898 | * 1899 | * @param $value 1900 | * @param Constraint $constraint 1901 | * @param string $message 1902 | * @see \Codeception\Module\AbstractAsserts::assertThat() 1903 | */ 1904 | public function assertThat($value, $constraint, $message = "") { 1905 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertThat', func_get_args())); 1906 | } 1907 | 1908 | 1909 | /** 1910 | * [!] Method is generated. Documentation taken from corresponding module. 1911 | * 1912 | * Asserts that a condition is true. 1913 | * 1914 | * @param $condition 1915 | * @param string $message 1916 | * @see \Codeception\Module\AbstractAsserts::assertTrue() 1917 | */ 1918 | public function assertTrue($condition, $message = "") { 1919 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertTrue', func_get_args())); 1920 | } 1921 | 1922 | 1923 | /** 1924 | * [!] Method is generated. Documentation taken from corresponding module. 1925 | * 1926 | * Asserts that two XML files are equal. 1927 | * 1928 | * @param string $expectedFile 1929 | * @param string $actualFile 1930 | * @param string $message 1931 | * @see \Codeception\Module\AbstractAsserts::assertXmlFileEqualsXmlFile() 1932 | */ 1933 | public function assertXmlFileEqualsXmlFile($expectedFile, $actualFile, $message = "") { 1934 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertXmlFileEqualsXmlFile', func_get_args())); 1935 | } 1936 | 1937 | 1938 | /** 1939 | * [!] Method is generated. Documentation taken from corresponding module. 1940 | * 1941 | * Asserts that two XML files are not equal. 1942 | * 1943 | * @param string $expectedFile 1944 | * @param string $actualFile 1945 | * @param string $message 1946 | * @see \Codeception\Module\AbstractAsserts::assertXmlFileNotEqualsXmlFile() 1947 | */ 1948 | public function assertXmlFileNotEqualsXmlFile($expectedFile, $actualFile, $message = "") { 1949 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertXmlFileNotEqualsXmlFile', func_get_args())); 1950 | } 1951 | 1952 | 1953 | /** 1954 | * [!] Method is generated. Documentation taken from corresponding module. 1955 | * 1956 | * Asserts that two XML documents are equal. 1957 | * 1958 | * @param string $expectedFile 1959 | * @param DOMDocument|string $actualXml 1960 | * @param string $message 1961 | * @see \Codeception\Module\AbstractAsserts::assertXmlStringEqualsXmlFile() 1962 | */ 1963 | public function assertXmlStringEqualsXmlFile($expectedFile, $actualXml, $message = "") { 1964 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertXmlStringEqualsXmlFile', func_get_args())); 1965 | } 1966 | 1967 | 1968 | /** 1969 | * [!] Method is generated. Documentation taken from corresponding module. 1970 | * 1971 | * Asserts that two XML documents are equal. 1972 | * 1973 | * @param DOMDocument|string $expectedXml 1974 | * @param DOMDocument|string $actualXml 1975 | * @param string $message 1976 | * @see \Codeception\Module\AbstractAsserts::assertXmlStringEqualsXmlString() 1977 | */ 1978 | public function assertXmlStringEqualsXmlString($expectedXml, $actualXml, $message = "") { 1979 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertXmlStringEqualsXmlString', func_get_args())); 1980 | } 1981 | 1982 | 1983 | /** 1984 | * [!] Method is generated. Documentation taken from corresponding module. 1985 | * 1986 | * Asserts that two XML documents are not equal. 1987 | * 1988 | * @param string $expectedFile 1989 | * @param DOMDocument|string $actualXml 1990 | * @param string $message 1991 | * @see \Codeception\Module\AbstractAsserts::assertXmlStringNotEqualsXmlFile() 1992 | */ 1993 | public function assertXmlStringNotEqualsXmlFile($expectedFile, $actualXml, $message = "") { 1994 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertXmlStringNotEqualsXmlFile', func_get_args())); 1995 | } 1996 | 1997 | 1998 | /** 1999 | * [!] Method is generated. Documentation taken from corresponding module. 2000 | * 2001 | * Asserts that two XML documents are not equal. 2002 | * 2003 | * @param DOMDocument|string $expectedXml 2004 | * @param DOMDocument|string $actualXml 2005 | * @param string $message 2006 | * @see \Codeception\Module\AbstractAsserts::assertXmlStringNotEqualsXmlString() 2007 | */ 2008 | public function assertXmlStringNotEqualsXmlString($expectedXml, $actualXml, $message = "") { 2009 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertXmlStringNotEqualsXmlString', func_get_args())); 2010 | } 2011 | 2012 | 2013 | /** 2014 | * [!] Method is generated. Documentation taken from corresponding module. 2015 | * 2016 | * Fails a test with the given message. 2017 | * 2018 | * @param string $message 2019 | * @see \Codeception\Module\AbstractAsserts::fail() 2020 | */ 2021 | public function fail($message = "") { 2022 | return $this->getScenario()->runStep(new \Codeception\Step\Action('fail', func_get_args())); 2023 | } 2024 | 2025 | 2026 | /** 2027 | * [!] Method is generated. Documentation taken from corresponding module. 2028 | * 2029 | * Mark the test as incomplete. 2030 | * 2031 | * @param string $message 2032 | * @see \Codeception\Module\AbstractAsserts::markTestIncomplete() 2033 | */ 2034 | public function markTestIncomplete($message = "") { 2035 | return $this->getScenario()->runStep(new \Codeception\Step\Action('markTestIncomplete', func_get_args())); 2036 | } 2037 | 2038 | 2039 | /** 2040 | * [!] Method is generated. Documentation taken from corresponding module. 2041 | * 2042 | * Mark the test as skipped. 2043 | * 2044 | * @param string $message 2045 | * @see \Codeception\Module\AbstractAsserts::markTestSkipped() 2046 | */ 2047 | public function markTestSkipped($message = "") { 2048 | return $this->getScenario()->runStep(new \Codeception\Step\Action('markTestSkipped', func_get_args())); 2049 | } 2050 | } 2051 | -------------------------------------------------------------------------------- /tests/_support/_generated/WpunitTesterActions.php: -------------------------------------------------------------------------------- 1 | getPluginsFolder(); 27 | * $hello = $this->getPluginsFolder('hello.php'); 28 | * ``` 29 | * 30 | * @param string $path A relative path to append to te plugins directory absolute path. 31 | * 32 | * @return string The absolute path to the `pluginsFolder` path or the same with a relative path appended if `$path` 33 | * is provided. 34 | * 35 | * @throws ModuleConfigException If the path to the plugins folder does not exist. 36 | * @see \Codeception\Module\WPLoader::getPluginsFolder() 37 | */ 38 | public function getPluginsFolder($path = "") { 39 | return $this->getScenario()->runStep(new \Codeception\Step\Action('getPluginsFolder', func_get_args())); 40 | } 41 | 42 | 43 | /** 44 | * [!] Method is generated. Documentation taken from corresponding module. 45 | * 46 | * Accessor method to get the object storing the factories for things. 47 | * This methods gives access to the same factories provided by the 48 | * [Core test suite](https://make.wordpress.org/core/handbook/testing/automated-testing/writing-phpunit-tests/). 49 | * 50 | * @return FactoryStore A factory store, proxy to get hold of the Core suite object 51 | * factories. 52 | * 53 | * @example 54 | * ```php 55 | * $postId = $I->factory()->post->create(); 56 | * $userId = $I->factory()->user->create(['role' => 'administrator']); 57 | * ``` 58 | * 59 | * @link https://make.wordpress.org/core/handbook/testing/automated-testing/writing-phpunit-tests/ 60 | * @see \Codeception\Module\WPLoader::factory() 61 | */ 62 | public function factory() { 63 | return $this->getScenario()->runStep(new \Codeception\Step\Action('factory', func_get_args())); 64 | } 65 | 66 | 67 | /** 68 | * [!] Method is generated. Documentation taken from corresponding module. 69 | * 70 | * Returns the absolute path to the WordPress content directory. 71 | * 72 | * @example 73 | * ```php 74 | * $content = $this->getContentFolder(); 75 | * $themes = $this->getContentFolder('themes'); 76 | * $twentytwenty = $this->getContentFolder('themes/twentytwenty'); 77 | * ``` 78 | * 79 | * @param string $path An optional path to append to the content directory absolute path. 80 | * 81 | * @return string The content directory absolute path, or a path in it. 82 | * 83 | * @throws ModuleConfigException If the path to the content directory cannot be resolved. 84 | * @see \Codeception\Module\WPLoader::getContentFolder() 85 | */ 86 | public function getContentFolder($path = "") { 87 | return $this->getScenario()->runStep(new \Codeception\Step\Action('getContentFolder', func_get_args())); 88 | } 89 | 90 | 91 | /** 92 | * [!] Method is generated. Documentation taken from corresponding module. 93 | * 94 | * Starts the debug of all WordPress filters and actions. 95 | * 96 | * The method hook on `all` filters and actions to debug their value. 97 | * 98 | * @example 99 | * ```php 100 | * // Start debugging all WordPress filters and action final and initial values. 101 | * $this->startWpFiltersDebug(); 102 | * 103 | * // Run some code firing filters and debug them. 104 | * 105 | * // Stop debugging all WordPress filters and action final and initial values. 106 | * $this->stopWpFiltersDebug(); 107 | * ``` 108 | * 109 | * @param callable|null $format A callback function to format the arguments debug output; the callback will receive 110 | * the array of arguments as input. 111 | * 112 | * @return void 113 | * @see \Codeception\Module\WPLoader::startWpFiltersDebug() 114 | */ 115 | public function startWpFiltersDebug($format = NULL) { 116 | return $this->getScenario()->runStep(new \Codeception\Step\Action('startWpFiltersDebug', func_get_args())); 117 | } 118 | 119 | 120 | /** 121 | * [!] Method is generated. Documentation taken from corresponding module. 122 | * 123 | * Stops the debug of all WordPress filters and actions. 124 | * 125 | * @example 126 | * ```php 127 | * // Start debugging all WordPress filters and action final and initial values. 128 | * $this->startWpFiltersDebug(); 129 | * 130 | * // Run some code firing filters and debug them. 131 | * 132 | * // Stop debugging all WordPress filters and action final and initial values. 133 | * $this->stopWpFiltersDebug(); 134 | * ``` 135 | * 136 | * @return void 137 | * @see \Codeception\Module\WPLoader::stopWpFiltersDebug() 138 | */ 139 | public function stopWpFiltersDebug() { 140 | return $this->getScenario()->runStep(new \Codeception\Step\Action('stopWpFiltersDebug', func_get_args())); 141 | } 142 | 143 | 144 | /** 145 | * [!] Method is generated. Documentation taken from corresponding module. 146 | * 147 | * Debugs a single WordPress filter initial call using Codeception debug functions. 148 | * 149 | * The output will show following the selected output verbosity (`--debug` and `-vvv` CLI options). 150 | * 151 | * @example 152 | * ```php 153 | * // Start debugging all WordPress filters initial value. 154 | * add_filter('all', [$this,'debugWpFilterInitial']); 155 | * 156 | * // Run some code firing filters and debug them. 157 | * 158 | * // Stop debugging all WordPress filters initial value. 159 | * remove_filter('all', [$this,'debugWpFilterInitial']); 160 | * ``` 161 | * 162 | * @param mixed ...$args The filter call arguments. 163 | * 164 | * @return mixed The filter input value, unchanged. 165 | * @see \Codeception\Module\WPLoader::debugWpFilterInitial() 166 | */ 167 | public function debugWpFilterInitial($args = null) { 168 | return $this->getScenario()->runStep(new \Codeception\Step\Action('debugWpFilterInitial', func_get_args())); 169 | } 170 | 171 | 172 | /** 173 | * [!] Method is generated. Documentation taken from corresponding module. 174 | * 175 | * Debugs a single WordPress filter final call using Codeception debug functions. 176 | * 177 | * The output will show following the selected output verbosity (`--debug` and `-vvv` CLI options). 178 | * 179 | * @example 180 | * ```php 181 | * // Start debugging all WordPress filters final value. 182 | * add_filter('all', [$this,'debugWpFilterFinal']); 183 | * 184 | * // Run some code firing filters and debug them. 185 | * 186 | * // Stop debugging all WordPress filters final value. 187 | * remove_filter('all', [$this,'debugWpFilterFinal']); 188 | * ``` 189 | * 190 | * @param mixed ...$args The filter call arguments. 191 | * 192 | * @return mixed The filter input value, unchanged. 193 | * @see \Codeception\Module\WPLoader::debugWpFilterFinal() 194 | */ 195 | public function debugWpFilterFinal($args = null) { 196 | return $this->getScenario()->runStep(new \Codeception\Step\Action('debugWpFilterFinal', func_get_args())); 197 | } 198 | 199 | 200 | /** 201 | * [!] Method is generated. Documentation taken from corresponding module. 202 | * 203 | * Debugs a single WordPress action initial call using Codeception debug functions. 204 | * 205 | * The output will show following the selected output verbosity (`--debug` and `-vvv` CLI options). 206 | * 207 | * @example 208 | * ```php 209 | * // Start debugging all WordPress actions initial value. 210 | * add_action('all', [$this,'debugWpActionInitial']); 211 | * 212 | * // Run some code firing actions and debug them. 213 | * 214 | * // Stop debugging all WordPress actions initial value. 215 | * remove_action('all', [$this,'debugWpActionInitial']); 216 | * ``` 217 | * 218 | * @param mixed ...$args The action call arguments. 219 | * 220 | * @return void 221 | * @see \Codeception\Module\WPLoader::debugWpActionInitial() 222 | */ 223 | public function debugWpActionInitial($args = null) { 224 | return $this->getScenario()->runStep(new \Codeception\Step\Action('debugWpActionInitial', func_get_args())); 225 | } 226 | 227 | 228 | /** 229 | * [!] Method is generated. Documentation taken from corresponding module. 230 | * 231 | * Debugs a single WordPress action final call using Codeception debug functions. 232 | * 233 | * The output will show following the selected output verbosity (`--debug` and `-vvv` CLI options). 234 | * 235 | * @example 236 | * ```php 237 | * // Start debugging all WordPress actions final value. 238 | * add_action('all', [$this,'debugWpActionFinal']); 239 | * 240 | * // Run some code firing actions and debug them. 241 | * 242 | * // Stop debugging all WordPress actions final value. 243 | * remove_action('all', [$this,'debugWpActionFinal']); 244 | * ``` 245 | * 246 | * @param mixed ...$args The action call arguments. 247 | * 248 | * @return void 249 | * @see \Codeception\Module\WPLoader::debugWpActionFinal() 250 | */ 251 | public function debugWpActionFinal($args = null) { 252 | return $this->getScenario()->runStep(new \Codeception\Step\Action('debugWpActionFinal', func_get_args())); 253 | } 254 | } 255 | -------------------------------------------------------------------------------- /tests/acceptance.suite.yml: -------------------------------------------------------------------------------- 1 | # Codeception Test Suite Configuration 2 | # 3 | # Suite for acceptance tests. 4 | # Perform tests in browser using the WPWebDriver or WPBrowser. 5 | # Use WPDb to set up your initial database fixture. 6 | # If you need both WPWebDriver and WPBrowser tests - create a separate suite. 7 | 8 | actor: AcceptanceTester 9 | modules: 10 | enabled: 11 | - WPDb 12 | - WPBrowser 13 | - \Helper\Acceptance 14 | config: 15 | WPDb: 16 | dsn: '%TEST_SITE_DB_DSN%' 17 | user: '%TEST_SITE_DB_USER%' 18 | password: '%TEST_SITE_DB_PASSWORD%' 19 | dump: 'tests/_data/dump.sql' 20 | #import the dump before the tests; this means the test site database will be repopulated before the tests. 21 | populate: true 22 | # re-import the dump between tests; this means the test site database will be repopulated between the tests. 23 | cleanup: true 24 | waitlock: 10 25 | url: '%TEST_SITE_WP_URL%' 26 | urlReplacement: true #replace the hardcoded dump URL with the one above 27 | tablePrefix: '%TEST_SITE_TABLE_PREFIX%' 28 | WPBrowser: 29 | url: '%TEST_SITE_WP_URL%' 30 | adminUsername: '%TEST_SITE_ADMIN_USERNAME%' 31 | adminPassword: '%TEST_SITE_ADMIN_PASSWORD%' 32 | adminPath: '%TEST_SITE_WP_ADMIN_PATH%' 33 | headers: 34 | X_TEST_REQUEST: 1 35 | X_WPBROWSER_REQUEST: 1 -------------------------------------------------------------------------------- /tests/functional.suite.yml: -------------------------------------------------------------------------------- 1 | # Codeception Test Suite Configuration 2 | # 3 | # Suite for functional tests 4 | # Emulate web requests and make WordPress process them 5 | 6 | actor: FunctionalTester 7 | modules: 8 | enabled: 9 | - WPDb 10 | - WPBrowser 11 | # - WPFilesystem 12 | - Asserts 13 | - \Helper\Functional 14 | config: 15 | WPDb: 16 | dsn: '%TEST_SITE_DB_DSN%' 17 | user: '%TEST_SITE_DB_USER%' 18 | password: '%TEST_SITE_DB_PASSWORD%' 19 | dump: 'tests/_data/dump.sql' 20 | populate: true 21 | cleanup: true 22 | waitlock: 10 23 | url: '%TEST_SITE_WP_URL%' 24 | urlReplacement: true 25 | tablePrefix: '%TEST_SITE_TABLE_PREFIX%' 26 | WPBrowser: 27 | url: '%TEST_SITE_WP_URL%' 28 | adminUsername: '%TEST_SITE_ADMIN_USERNAME%' 29 | adminPassword: '%TEST_SITE_ADMIN_PASSWORD%' 30 | adminPath: '%TEST_SITE_WP_ADMIN_PATH%' 31 | headers: 32 | X_TEST_REQUEST: 1 33 | X_WPBROWSER_REQUEST: 1 34 | 35 | WPFilesystem: 36 | wpRootFolder: '%WP_ROOT_FOLDER%' 37 | plugins: '/wp-content/plugins' 38 | mu-plugins: '/wp-content/mu-plugins' 39 | themes: '/wp-content/themes' 40 | uploads: '/wp-content/uploads' -------------------------------------------------------------------------------- /tests/unit.suite.yml: -------------------------------------------------------------------------------- 1 | # Codeception Test Suite Configuration 2 | # 3 | # Suite for unit tests not relying WordPress code. 4 | 5 | actor: UnitTester 6 | modules: 7 | enabled: 8 | - Asserts 9 | - \Helper\Unit 10 | step_decorators: ~ -------------------------------------------------------------------------------- /tests/unit/RandomNameTest.php: -------------------------------------------------------------------------------- 1 | randomName(); 33 | self::assertNotNull($name); 34 | } 35 | } -------------------------------------------------------------------------------- /tests/wpunit.suite.yml: -------------------------------------------------------------------------------- 1 | # Codeception Test Suite Configuration 2 | # 3 | # Suite for unit or integration tests that require WordPress functions and classes. 4 | 5 | actor: WpunitTester 6 | modules: 7 | enabled: 8 | - WPLoader 9 | - \Helper\Wpunit 10 | config: 11 | WPLoader: 12 | wpRootFolder: "%WP_ROOT_FOLDER%" 13 | dbName: "%TEST_DB_NAME%" 14 | dbHost: "%TEST_DB_HOST%" 15 | dbUser: "%TEST_DB_USER%" 16 | dbPassword: "%TEST_DB_PASSWORD%" 17 | tablePrefix: "%TEST_TABLE_PREFIX%" 18 | domain: "%TEST_SITE_WP_DOMAIN%" 19 | adminEmail: "%TEST_SITE_ADMIN_EMAIL%" 20 | title: "WP-Strap" 21 | plugins: ['the-plugin-name/the-plugin-name.php'] 22 | activatePlugins: ['the-plugin-name/the-plugin-name.php'] -------------------------------------------------------------------------------- /tests/wpunit/RandomPostTest.php: -------------------------------------------------------------------------------- 1 | root_dir = dirname( dirname( dirname( __FILE__ ) ) ); 22 | } 23 | 24 | public function tearDown(): void 25 | { 26 | // Your tear down methods here. 27 | 28 | // Then... 29 | parent::tearDown(); 30 | } 31 | 32 | // Tests 33 | public function test_it_works() 34 | { 35 | $post = static::factory()->post->create_and_get(); 36 | $this->assertInstanceOf(\WP_Post::class, $post); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /the-plugin-name.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright {{author_copyright}} 8 | * @license {{author_license}} 9 | * @link {{author_url}} 10 | * 11 | * Plugin Name: {{The Plugin Name}} 12 | * Plugin URI: {{plugin_url}} 13 | * Description: {{plugin_description}} 14 | * Version: {{version}} 15 | * Author: {{author_name}} 16 | * Author URI: {{author_url}} 17 | * Text Domain: the-plugin-name-text-domain 18 | * Domain Path: /languages 19 | * Requires PHP: 7.1 20 | * Requires WP: 5.5.0 21 | * Namespace: ThePluginName 22 | */ 23 | 24 | declare( strict_types = 1 ); 25 | 26 | /** 27 | * Define the default root file of the plugin 28 | * 29 | * @since 1.0.0 30 | */ 31 | const _THE_PLUGIN_NAME_PLUGIN_FILE = __FILE__; 32 | 33 | /** 34 | * Load PSR4 autoloader 35 | * 36 | * @since 1.0.0 37 | */ 38 | $the_plugin_name_autoloader = require plugin_dir_path( _THE_PLUGIN_NAME_PLUGIN_FILE ) . 'vendor/autoload.php'; 39 | 40 | /** 41 | * Setup hooks (activation, deactivation, uninstall) 42 | * 43 | * @since 1.0.0 44 | */ 45 | register_activation_hook( __FILE__, [ 'ThePluginName\Config\Setup', 'activation' ] ); 46 | register_deactivation_hook( __FILE__, [ 'ThePluginName\Config\Setup', 'deactivation' ] ); 47 | register_uninstall_hook( __FILE__, [ 'ThePluginName\Config\Setup', 'uninstall' ] ); 48 | 49 | /** 50 | * Bootstrap the plugin 51 | * 52 | * @since 1.0.0 53 | */ 54 | if ( ! class_exists( '\ThePluginName\Bootstrap' ) ) { 55 | wp_die( __( '{{The Plugin Name}} is unable to find the Bootstrap class.', 'the-plugin-name-text-domain' ) ); 56 | } 57 | add_action( 58 | 'plugins_loaded', 59 | static function () use ( $the_plugin_name_autoloader ) { 60 | /** 61 | * @see \ThePluginName\Bootstrap 62 | */ 63 | try { 64 | new \ThePluginName\Bootstrap( $the_plugin_name_autoloader ); 65 | } catch ( Exception $e ) { 66 | wp_die( __( '{{The Plugin Name}} is unable to run the Bootstrap class.', 'the-plugin-name-text-domain' ) ); 67 | } 68 | } 69 | ); 70 | 71 | /** 72 | * Create a main function for external uses 73 | * 74 | * @return \ThePluginName\Common\Functions 75 | * @since 1.0.0 76 | */ 77 | function the_plugin_name(): \ThePluginName\Common\Functions { 78 | return new \ThePluginName\Common\Functions(); 79 | } 80 | --------------------------------------------------------------------------------