diff --git a/.github/workflows/phpcs.yml b/.github/workflows/phpcs.yml new file mode 100644 index 0000000..44779ef --- /dev/null +++ b/.github/workflows/phpcs.yml @@ -0,0 +1,38 @@ +name: PHPCS + +on: + pull_request: + paths: + - '**.php' + - 'composer.json' + - 'phpcs.xml.dist' + - '.github/workflows/phpcs.yml' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + phpcs: + name: "Lint PHP ${{ matrix.php }}" + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + php: [ '8.2', '8.3', '8.4' ] + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # 2.37.2 + with: + php-version: ${{ matrix.php }} + tools: composer, cs2pr + + - run: composer install --no-progress --prefer-dist + + # Only the first (lowest) version annotates the PR, to avoid duplicate comments. + - if: strategy.job-index == 0 + run: composer phpcs -- -q --report=checkstyle | cs2pr + + - if: strategy.job-index != 0 + run: composer phpcs -- --no-colors diff --git a/.wp-env.json b/.wp-env.json new file mode 100644 index 0000000..8d1c700 --- /dev/null +++ b/.wp-env.json @@ -0,0 +1,15 @@ +{ + "port": 6368, + "phpVersion": "8.2", + "testsEnvironment": false, + "config": { + "SCRIPT_DEBUG": true, + "WP_DEBUG_DISPLAY": false, + "WP_DEBUG": true, + "WP_DEVELOPMENT_MODE": "plugin" + }, + "plugins": [ + ".", + "https://downloads.wordpress.org/plugin/query-monitor.zip" + ] +} diff --git a/README.md b/README.md index 88effcc..ee32c40 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,24 @@ This guide explains how to create and customize a mega menu using the HM Mega Me This plugin provides a flexible, code-light way to build and customize mega menus in WordPress! +## Local Environment + +This project uses [wp-env](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-env/) to run a lightweight, containerized WordPress instance at [localhost:6368](http://localhost:6368) for testing purposes. The default username for the localhost environment is `admin`, with the password `password`. Run `npm run build` (or `npm start`) first so the block assets exist. + +These commands can be used to interact with the environment: + +Command | Purpose +---- | ---- +`npm run env:start` | Start the local environment at http://localhost:6368 +`npm run env:bootstrap` | Seed demo "Products" and "Resources" mega menus into the Twenty Twenty-Five header (safe to re-run) +`npm run env:stop` | Turn off the local environment +`npm run env:cli -- wp ...` | Run WP-CLI commands within the environment +`npm run env:logs` | Open (and tail) the error logs for the application‡ +`npm run env:db` | Open the database in the mysql command line +`npm run env:destroy` | Fully destroy the local environment (deletes container database) + +‡ This command deliberately filters out GET/OPTIONS/HEAD/POST/PUT access log entries + ## Release Process Merges to `main` will automatically build to the `release` branch. diff --git a/bin/bootstrap-env.php b/bin/bootstrap-env.php new file mode 100644 index 0000000..373769a --- /dev/null +++ b/bin/bootstrap-env.php @@ -0,0 +1,151 @@ + $postarr['post_type'], + 'name' => $postarr['post_name'], + 'post_status' => 'any', + 'posts_per_page' => 1, + 'fields' => 'ids', + ] ); + + if ( $existing ) { + $postarr['ID'] = $existing[0]; + } + + $post_id = wp_insert_post( wp_slash( $postarr + [ 'post_status' => 'publish' ] ), true ); + + if ( is_wp_error( $post_id ) ) { + WP_CLI::error( $post_id ); + } + + return $post_id; +} + +/** + * Build demo template part content: one column of links per heading. + * + * @param array $columns Map of column heading => list of link labels. + * @return string Block markup. + */ +function hm_mega_menu_bootstrap_menu_content( array $columns ) : string { + $markup = ''; + + foreach ( $columns as $heading => $links ) { + $items = ''; + foreach ( $links as $link ) { + $items .= sprintf( '
  • %s
  • ', esc_html( $link ) ); + } + + $markup .= sprintf( + '

    %s

    ', + esc_html( $heading ), + $items + ); + } + + return '
    ' + . $markup + . '
    '; +} + +$theme = get_stylesheet(); + +$menus = [ + 'mega-menu-products' => [ + 'title' => 'Mega Menu: Products', + 'block' => [ + 'label' => 'Products', + 'width' => 'wide', + ], + 'columns' => [ + 'Hardware' => [ 'Laptops', 'Phones', 'Accessories' ], + 'Software' => [ 'Editor', 'Hosting', 'Analytics' ], + 'Services' => [ 'Support', 'Training' ], + ], + ], + 'mega-menu-resources' => [ + 'title' => 'Mega Menu: Resources', + 'block' => [ + 'label' => 'Resources', + 'labelColor' => '#c0392b', + 'width' => 'content', + 'justifyMenu' => 'right', + ], + 'columns' => [ + 'Learn' => [ 'Documentation', 'Tutorials' ], + 'Community' => [ 'Forums', 'Events' ], + ], + ], +]; + +$nav_items = ''; + +foreach ( $menus as $slug => $menu ) { + $part_id = hm_mega_menu_bootstrap_upsert_post( [ + 'post_type' => 'wp_template_part', + 'post_name' => $slug, + 'post_title' => $menu['title'], + 'post_content' => hm_mega_menu_bootstrap_menu_content( $menu['columns'] ), + ] ); + wp_set_object_terms( $part_id, $theme, 'wp_theme' ); + wp_set_object_terms( $part_id, 'menu', 'wp_template_part_area' ); + + $nav_items .= sprintf( + '', + wp_json_encode( $menu['block'] + [ 'menuSlug' => $slug ] ) + ); + + WP_CLI::log( sprintf( 'Template part "%s": %d', $slug, $part_id ) ); +} + +$nav_items .= ''; + +$nav_id = hm_mega_menu_bootstrap_upsert_post( [ + 'post_type' => 'wp_navigation', + 'post_name' => 'mega-menu-demo', + 'post_title' => 'Mega Menu Demo', + 'post_content' => $nav_items, +] ); +WP_CLI::log( sprintf( 'Navigation "mega-menu-demo": %d', $nav_id ) ); + +// Override the theme header, pointing its Navigation block at the demo menu. +$header = WP_Block_Patterns_Registry::get_instance()->get_registered( $theme . '/header' ); +if ( ! $header ) { + WP_CLI::error( sprintf( 'No "%s/header" pattern found; the bootstrap targets Twenty Twenty-Five.', $theme ) ); +} + +$header_content = preg_replace( '/ + . + + + */node_modules/* + */vendor/* + */build/* + + + + + + + + + + + + + diff --git a/src/render.php b/src/render.php index 3332797..8e2a55c 100644 --- a/src/render.php +++ b/src/render.php @@ -1,9 +1,15 @@ '; -$toggle_icon = ''; ?> -
  • data-wp-interactive='{"namespace": "hm-blocks/hm-mega-menu-block" }' data-wp-context='{ "menuOpenedBy": {} }' data-wp-on-document--keydown="actions.handleMenuKeydown" data-wp-on-document--click="actions.handleOutsideClick" data-wp-on-document--focusin="actions.handleOutsideFocus" data-wp-watch="callbacks.initMenu"> +
  • data-wp-interactive='{"namespace": "hm-blocks/hm-mega-menu-block" }' data-wp-context='{ "menuOpenedBy": {} }' data-wp-on-document--keydown="actions.handleMenuKeydown" data-wp-on-document--click="actions.handleOutsideClick" data-wp-on-document--focusin="actions.handleOutsideFocus" data-wp-watch="callbacks.initMenu"> - -
    - +
    + -