Skip to content

Development

Noah Mason edited this page Nov 28, 2022 · 16 revisions

Development Overview

This plugin uses Composer to manage dependencies and development scripting, and Git for version control. Several Composer scripts and Git hooks are included in order to make development easier. It is recommended to use Microsoft Visual Studio Code (VSCode) as an IDE as there are also recommended plugins and settings that are bundled with this package that will allow for PHP Intellisense, live linting and live autoformatting of code when developing WP Backstage.

Requirements

  • PHP 7.4+
  • Git 2.29+
  • Composer 2.4+
  • WordPress 5.8+

Setting Up Development

  • Spin up a local WordPress environment using Local by Flywheel.
  • Clone the plugin's repository to the WordPress install's plugins directory at wp-content/plugins.
  • Navigate to the "Plugins" screen in the WordPress admin dashboard.
  • Locate WP Backstage in the plugins list and click "Activate" to activate the plugin.

Note: Though the plugin attempts to flush the WordPress rewrite rules on activation and deactivation, it is good practice to flush the rewrite rules manually by navigating to the permalink settings page at "Settings -> Permalinks" and clicking "Save".

Enabling Tests

Tests can be enabled by declaring theme support for wp-backstage and setting tests-enabled to true. This will automatically enable all test configurations that come bundled with WP Backstage. Once this is added, navigate to "Settings -> Permalinks" and hit "Save" to flush the rewrite rules. It is good practice to flush the rewrite rules whenever you turn the tests on or off (or whenever any post type or taxonomy configuration changes).

add_theme_support( 'wp-backstage', array(
    'tests-enabled' => true,
) );

Git Hooks

The repository comes with a pre-commit hook, found in the root of the project, that runs a build and adds the output to the commit automatically. This means that the developer rarely, if ever, needs to run a build. The developer can just write, and commit, ensuring that the translation file and generated API reference will always be in sync with the committed code.

Note: WP Backstage keeps the git hook scripts in the root of the project. When making changes to the pre-commit file, it is necessary to use the update-hooks script to actually install them into the .git/hooks directory. This is done automatically upon installing or updating dependencies with Composer.

Bumping the version

The version needs to be updated manually, both in the README.md file, and the php file comment at the top of the main wp-backstage.php file.

Development Commands

The following is a list of all development commands available to be run with Composer. In most cases, these will be run for the developer in the normal course of development by using Composer and Git hooks.

Install dependencies

After installing or updating, Composer will run the update-hooks script which will install Git hooks like pre-commit.

composer install

Run a build

This will run both the build-pot and build-docs scripts.

composer run build

Build the translation file

This will use the WP CLI's i18n command to build the languages/wp-backstage.pot file.

composer run build-pot

Build the API reference

This will use phpDocumentor to generate an API reference for the plugin automatically using the code and doc blocks. The output will be placed in /docs/reference.

composer run build-docs

Clean build

Runs the clean-pot and clean-docs scripts, removing all built files.

composer run clean

Clean the translation file

Removes the languages/wp-backstage.pot file.

composer run clean-pot

Clean the API reference

Recursively remove all files from and including the docs/reference directory.

composer run clean-docs

Update git hooks

Install the Git hooks like pre-commit found in the root of the project to the .git/hooks directory. After making updates to the pre-commit hook file found in the root, run this command to install it. This allows for simpler management of the Git hook scripts. Runs the remove-hooks and add-hooks scripts.

composer run update-hooks

Add git hooks

Add the Git hooks like pre-commit found in the root of the project to the .git/hooks directory. Typically, the update-hooks script should be used instead to install the Git hooks, as it will run the remove-hooks script to remove existing hooks before installing the new ones.

composer run add-hooks

Remove git hooks

Remove all Git hooks from the .git/hooks directory.

composer run remove-hooks

Lint all code

Runs the lint-php script.

composer run lint

Lint php files

Uses PHP Code Sniffer (phpcs) managed by the configuration found in the phpcs.xml file to lint php files using the WordPress coding standards.

composer run lint-php

Fix and format all code

Runs the fix-php script.

composer run fix

Fix and format php files

Uses PHP Code Sniffer's Code Beautifier and Fixer (phpcbf) managed by the configuration found in the phpcs.xml file to fix and format php files using the WordPress coding standards.

composer run fix-php

Developing Fields

When adding a new field type, there are a few things to consider in order to make the field type work in all situations; including the customizer, movable and collapsible UI elements, etc.

Field Development Checklist

  • Add a render_{field_type} method to the WP_Backstage_Component class.
  • Add a case for {field_type} using the render_{field_type} method to the WP_Backstage_Component::render_field_by_type() method.
  • Add a $default_${field_type}_args variable to the WP_Backstage_Component class if the field has extra arguments.
  • Add {field_type} to the $non_regular_text_fields array variable on the WP_Backstage_Component class if necessary.
  • Add {field_type} to the $remove_label_for_fields array variable on the WP_Backstage_Component class if necessary.
  • Add {field_type} to the $textarea_control_fields array variable on the WP_Backstage_Component class if necessary.
  • Add a sanitize_{field_type} method to the WP_Backstage_Component class.
  • Add a case for {field_type} using the sanitize_{field_type} method to the WP_Backstage_Component::sanitize_field() method.
  • Add a case for {field_type} referencing the sanitize_{field_type} method to the WP_Backstage_Component::get_sanitize_callback() method.
  • Add a case for {field_type} to format the value to the WP_Backstage_Component::format_field_value() method.
  • Add a case for {field_type} to the setControlElementValue() JS function in WP_Backstage::inline_nav_menu_item_customizer_script() method.
  • Add a case for {field_type} to the initControlElementChangeHandler() JS function in WP_Backstage::inline_nav_menu_item_customizer_script() method.
  • If necessary, add an inline_{field_type}_style method to the WP_Backstage class, and hook to admin_print_styles.
  • If necessary, add an inline_{field_type}_script method to the WP_Backstage class, and hook to admin_print_footer_scripts. This should attach functionality to the window.wpBackstage.{fieldType} object and should have at minimum an init and initAll method. These methods should then be triggered in the inline JS functions for all components in the WP_Backstage class. See Field JavaScript for boilerplate code.
  • Add test examples to the $all_fields array in the wp_backstage_init() function in examples/tests.php file.
  • Add documentation to the Fields Wiki.

Field JavaScript

<script 
id="wp_backstage_{field_type}_script"
type="text/javascript">

    (function($) {

        function init(field = null) {
            const fieldId = field.getAttribute('data-field-id');
            const input = field.querySelector('#' + fieldId);

            // Initialize the field.
        }

        function destroy(field = null) {
            const fieldId = field.getAttribute('data-field-id');
            const input = field.querySelector('#' + fieldId);
            
            // Destroy the field.
        }

        function initAll(container = null) {
            container = container || document;
            const fields = container.querySelectorAll('.wp-backstage-field--type-{field-type}');
            if (fields && (fields.length > 0)) {
                for (var i = 0; i < fields.length; i++) {
                    init(fields[i]);
                }
            }
        }

        function destroyAll(container = null) {
            container = container || document;
            const fields = container.querySelectorAll('.wp-backstage-field--type-{field-type}');
            if (fields && (fields.length > 0)) {
                for (var i = 0; i < fields.length; i++) {
                    destroy(fields[i]);
                }
            }
        }

        window.wpBackstage.{fieldType} = Object.assign(window.wpBackstage.{fieldType}, {
            initAll: initAll,
            init: init,
            destroyAll: destroyAll,
            destroy: destroy,
        });

    })(jQuery);

</script>

Note: Replace {field_type} with the field type in snake case. Replace {fieldType} with the field type in camel case. Replace {field-type} with the the field type in param case.