diff --git a/.gitignore b/.gitignore index ff87634..40b878d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1 @@ -vendor/ node_modules/ \ No newline at end of file diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..aabca49 --- /dev/null +++ b/composer.lock @@ -0,0 +1,169 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "4dab38fa2dcb106e4f136a0273e46552", + "packages": [ + { + "name": "abuyoyo/adminmenupage", + "version": "0.20", + "source": { + "type": "git", + "url": "https://github.com/abuyoyo/AdminMenuPage.git", + "reference": "07d98f2c1f0b71340aaf0fae0783dfecec201e97" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/abuyoyo/AdminMenuPage/zipball/07d98f2c1f0b71340aaf0fae0783dfecec201e97", + "reference": "07d98f2c1f0b71340aaf0fae0783dfecec201e97", + "shasum": "" + }, + "suggest": { + "abuyoyo/plugincore": "~0.18", + "cmb2/cmb2": "~2.9" + }, + "type": "library", + "autoload": { + "files": [ + "wph_admin_page.php" + ], + "psr-4": { + "WPHelper\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "WordPress admin menu page helper class", + "support": { + "issues": "https://github.com/abuyoyo/AdminMenuPage/issues", + "source": "https://github.com/abuyoyo/AdminMenuPage/tree/0.20" + }, + "time": "2022-07-28T22:56:37+00:00" + }, + { + "name": "abuyoyo/plugincore", + "version": "0.20", + "source": { + "type": "git", + "url": "https://github.com/abuyoyo/PluginCore.git", + "reference": "0f8de7be654880adc850610f045f22cd7923c3cc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/abuyoyo/PluginCore/zipball/0f8de7be654880adc850610f045f22cd7923c3cc", + "reference": "0f8de7be654880adc850610f045f22cd7923c3cc", + "shasum": "" + }, + "require": { + "abuyoyo/adminmenupage": "~0.20", + "yahnis-elsts/plugin-update-checker": "~4.12" + }, + "type": "library", + "autoload": { + "psr-4": { + "WPHelper\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "WordPress plugin core helper class", + "support": { + "issues": "https://github.com/abuyoyo/PluginCore/issues", + "source": "https://github.com/abuyoyo/PluginCore/tree/0.20" + }, + "time": "2022-07-29T00:00:00+00:00" + }, + { + "name": "abuyoyo/screen-meta-links", + "version": "0.11", + "source": { + "type": "git", + "url": "https://github.com/abuyoyo/screen-meta-links.git", + "reference": "04e3c892f0c6095b4c31a489e06336f0917128d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/abuyoyo/screen-meta-links/zipball/04e3c892f0c6095b4c31a489e06336f0917128d3", + "reference": "04e3c892f0c6095b4c31a489e06336f0917128d3", + "shasum": "" + }, + "type": "library", + "autoload": { + "files": [ + "screen-meta-links.php" + ] + }, + "description": "API for adding custom screen-meta-links alongside the 'Screen Options' and 'Help' links.", + "support": { + "source": "https://github.com/abuyoyo/screen-meta-links/tree/0.11", + "issues": "https://github.com/abuyoyo/screen-meta-links/issues" + }, + "time": "2022-05-18T01:18:24+00:00" + }, + { + "name": "yahnis-elsts/plugin-update-checker", + "version": "v4.13", + "source": { + "type": "git", + "url": "https://github.com/YahnisElsts/plugin-update-checker.git", + "reference": "6eb27a6911e0e0880d09e5b11f577d3f688f7da7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/YahnisElsts/plugin-update-checker/zipball/6eb27a6911e0e0880d09e5b11f577d3f688f7da7", + "reference": "6eb27a6911e0e0880d09e5b11f577d3f688f7da7", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": ">=5.2.0" + }, + "type": "library", + "autoload": { + "files": [ + "load-v4p13.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Yahnis Elsts", + "email": "whiteshadow@w-shadow.com", + "homepage": "http://w-shadow.com/", + "role": "Developer" + } + ], + "description": "A custom update checker for WordPress plugins and themes. Useful if you can't host your plugin in the official WP repository but still want it to support automatic updates.", + "homepage": "https://github.com/YahnisElsts/plugin-update-checker/", + "keywords": [ + "automatic updates", + "plugin updates", + "theme updates", + "wordpress" + ], + "support": { + "issues": "https://github.com/YahnisElsts/plugin-update-checker/issues", + "source": "https://github.com/YahnisElsts/plugin-update-checker/tree/v4.13" + }, + "time": "2022-07-29T12:36:25+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [], + "plugin-api-version": "2.1.0" +} diff --git a/notice-manager.php b/notice-manager.php index dd8794a..d07b54f 100644 --- a/notice-manager.php +++ b/notice-manager.php @@ -12,6 +12,8 @@ defined( 'ABSPATH' ) || die( 'No soup for you!' ); use WPHelper\PluginCore; +require_once 'vendor/autoload.php'; + /** * Bootstrap plugin and admin page (Tools > Notice Manager) */ diff --git a/vendor/abuyoyo/adminmenupage/CHANGELOG.md b/vendor/abuyoyo/adminmenupage/CHANGELOG.md new file mode 100644 index 0000000..66f19db --- /dev/null +++ b/vendor/abuyoyo/adminmenupage/CHANGELOG.md @@ -0,0 +1,143 @@ +# Changelog +WPHelper\AdminMenuPage + +## 0.20 + +### Added +- Add SettingsPage section option `desciption-container`. Accepts `card` div, `notice`, `notice-info` and `none`. +- Sanitize SettingsPage text, url and email fields. + +## 0.19 + +### Added +- SettingsPage supports `text`, `url`, `email` fields. +- CMB2_OptionsPage supports all admin menu top-level slugs. + +### Fixed +- Fixed PHP fatal error: cannot redeclare function `wph_extra_plugin_headers()`. + +### Changed +- If CMB2 plugin is not activated - show missing plugin card on `cmb2` and `cmb2-tabs` pages. + +## 0.18 + +### Added + +- Add `wrap` parameter to output WordPress admin `.wrap` template. Accepts `simple` and `sidebar`. +- Accept `plugin_info = true` to output default plugin info meta box and wrap. +- Add `Last Update` and `Release Date` optional headers to WordPress theme headers (Used in plugin info-box). + +### Changed +- All classes are pluggable. +- Prevent direct access if not withing WordPress environment. + +## 0.17 + +### Changed + +- Various improvements to CMB2 settings pages. +- Make use of CMB2 2.9.0's `options_page_tab_nav_output()` to render tabs on non-CMB2 pages. +- Plugins can provide their own plugin info-box render callback. +- Parent item's first sub-menu page (itself) uses item's `tab_title` instead of `menu_title` + +### Added +- Add action `wphelper/adminpage/plugin_info_box/$slug` to render plugin info-box. +- Add `Last Update` and `Release Date` optional headers to WordPress plugin headers (Used in plugin info-box). + +## 0.16 + +### Fixed + +- Fix CMB2 "multi" options page to actually override fields. + +### Changed + +- Add CMB2 fields directly in options array instead of using `add_field` method. + +## 0.15 + +### Changed + +- Restore deprecated param to SettingsPage constructor and add `_deprecated_argument` message. + +## 0.14 + +### Added + +- Add CMB2 Options-page delegation. Allows adding CMB2 options page. +- Add CMB2 Options "multi" page. Allows CMB2 options page that saves each field to its own row in options table. +- Supports CMB2 tabs in CMB2 option-pages. +- Add Plugin Info metabox to CMB2 tables. + +### Changed + +- Deprecate `AdminPage->setup` - add `_doing_it_wrong` message. +- Admin Page method `bootstrap()` runs on `init` hook instead of constructor. Allows setter functions to have effect. + +## 0.13 + +### Added + +- Add `methods` option to load functions on `load-{hook_suffix}` hook. +- Add `get_hook_suffix()` getter method (`hook_suffix` variable is no longer public). + +## v0.12 + +### Changed + +- New `AdminPage` class. +- Deprecate class `AdminMenuPage` in favor of `AdminPage`. +- Restructure source files. + +## v0.11 + +### Added + +- Setting Page - class and template for registering WordPress settings page. +- Options_Menu - use WordPress core `add_options_page` to register page. + +### Changed + +- No longer require call to `setup()` method. Bootstrap into WordPress from constructor method. + +## v0.10 + +### Added + +- Styles - enqueue styles to registered admin page + +## v0.9 + +### Changed + +- Don't use extract() in constructor +- Use setter methods for all variables + +### Fixed + +- Fix PHP notices: undefined property + +## v0.8 + +### Fixed + +- Removed calls to AdminNotice causing errors. + +## v0.7 + +### Fixed + +- Fixed error when no scripts are added + +### Changed + +- Accept `render_cb` and `render_tpl` args. Use `render` method instead of `template` +- Print default template if no callback or template provided + +## v0.6 + +### Added + +- Initial public release +- Register and print top-level or submenu pages to WordPress admin menu +- Enqueue scripts to registered admin page diff --git a/vendor/abuyoyo/adminmenupage/LICENSE b/vendor/abuyoyo/adminmenupage/LICENSE new file mode 100644 index 0000000..3644397 --- /dev/null +++ b/vendor/abuyoyo/adminmenupage/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2019, abuyoyo +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/vendor/abuyoyo/adminmenupage/README.md b/vendor/abuyoyo/adminmenupage/README.md new file mode 100644 index 0000000..80508f0 --- /dev/null +++ b/vendor/abuyoyo/adminmenupage/README.md @@ -0,0 +1,54 @@ +# WPHelper \ AdminMenuPage + +> Helper class for simple admin menu page registration in WordPress. + +## Requirements +* PHP >= 7.4 +* [Composer](https://getcomposer.org/) +* [WordPress](https://wordpress.org) + +## Installation + +Install with [Composer](https://getcomposer.org/) as a library. + +```PHP +// Require the Composer autoloader anywhere in your code. +require __DIR__ . '/vendor/autoload.php'; + +``` + +WPHelper\AdminMenuPage uses [PSR-4](https://www.php-fig.org/psr/psr-4/) to autoload. + +OR + +Install as WordPress plugin and activate. + +## Basic Usage + +```PHP +// Import AdminPage. +use WPHelper\AdminPage; + +// Register the admin menu page. +$args = [ + 'title' => 'The Tile of My Page', // title - passed to add_menu_page + 'menu_title' => 'Page Title', // menu_title - passed to add_menu_page (optional - will use title if none provided) + 'capability' => 'manage_options', // capability - passed to add_menu_page (optional - will default to 'manage_options') + 'slug' => 'my_page', // slug - passed to add_menu_page + 'template' => 'tpl/my_admin_page.php', // template - include file to print the page. wrapped in callback and passed to add_menu_page + 'parent' => 'parent_page_slug'; // optional - slug of parent page if creating submenu + 'icon_url' => $icon_url; // optional - icon url passed to add_menu_page/add_submenu_page + 'position' => 4; // optional - passed to add_menu_page + 'scripts' => [ // optional - script parameters passed to enqueue_scripts. Will only enqueue scripts on admin page + [ 'script_handle', 'js/myscript.js', ['jquery'], false, true ], + [ 'another_script', 'js/my_other_script.js', ['jquery', 'script_handle'], false, true ] + ]; +]; + +// Register the admin menu page. +$admin_menu_page = new AdminPage( $args ); +$admin_menu_page->setup(); + +// That's it. We're done. +// This function can be called from anywhere. No need to wrap in any hook. +``` diff --git a/vendor/abuyoyo/adminmenupage/composer.json b/vendor/abuyoyo/adminmenupage/composer.json new file mode 100644 index 0000000..091062e --- /dev/null +++ b/vendor/abuyoyo/adminmenupage/composer.json @@ -0,0 +1,19 @@ +{ + "name": "abuyoyo/adminmenupage", + "description": "WordPress admin menu page helper class", + "type": "library", + "version": "0.20", + "license": "BSD-3-Clause", + "suggest": { + "abuyoyo/plugincore": "~0.18", + "cmb2/cmb2": "~2.9" + }, + "autoload": { + "psr-4": { + "WPHelper\\" : "src/" + }, + "files": [ + "wph_admin_page.php" + ] + } +} \ No newline at end of file diff --git a/vendor/abuyoyo/adminmenupage/src/AdminMenuPage.php b/vendor/abuyoyo/adminmenupage/src/AdminMenuPage.php new file mode 100644 index 0000000..5fff7fc --- /dev/null +++ b/vendor/abuyoyo/adminmenupage/src/AdminMenuPage.php @@ -0,0 +1,19 @@ +plugin_core ) ) + $this->plugin_core( $options->plugin_core ); + + if ( isset( $options->title ) ) + $this->title( $options->title ); + + /** + * @todo move this to bootstrap() + */ + if ( ! isset( $options->menu_title ) ) + $options->menu_title = $options->title; + + if ( isset( $options->menu_title ) ) + $this->menu_title( $options->menu_title ); + + if ( isset( $options->capability ) ) + $this->capability( $options->capability ); + + if ( isset( $options->slug ) ) + $this->slug( $options->slug ); + + if ( isset( $options->plugin_info ) ){ // before render() + $this->plugin_info( $options->plugin_info ); + } + + if ( isset( $options->wrap ) ){ // before render() + $this->wrap( $options->wrap ); + } + + if ( isset( $options->render ) ) // dev + $this->render( $options->render ); + + if ( isset( $options->render_cb ) ) // dev - deprecate? + $this->render_cb( $options->render_cb ); + + if ( isset( $options->render_tpl ) ) // dev - deprecate? + $this->render_tpl( $options->render_tpl ); + + if (true) + $this->render(); // render anyway - will use default tpl if render is empty + + if (true) + $this->wrap(); // set wrap anyway - will set to 'none' if empty + + if ( isset( $options->parent ) ) + $this->parent( $options->parent ); + + if ( isset( $options->icon_url ) ) + $this->icon_url( $options->icon_url ); + + if ( isset( $options->position ) ) + $this->position( $options->position ); + + if ( isset( $options->scripts ) ) + $this->scripts( $options->scripts ); + + if ( isset( $options->styles ) ) + $this->styles( $options->styles ); + + if ( isset( $options->methods ) ) + $this->methods( $options->methods ); + + if ( isset( $options->settings ) ) + $this->settings( $options->settings ); + + /** + * Bootstrap on init. Do not call directly from constructor. + * That way setter functions can be called after instance is created. + */ + add_action( 'init', [ $this, 'bootstrap' ] ); + } + + /** + * Setter - title + * WordPress admin menu param + * + * @access private + */ + private function title( $title ) { + $this->title = $title; + } + + /** + * Setter - menu_title + * WordPress admin menu param + * + * @access private + */ + private function menu_title( $menu_title ) { + $this->menu_title = $menu_title; + } + + /** + * Setter - capability + * WordPress admin menu param + * + * @access private + */ + private function capability( $capability ) { + $this->capability = $capability; + } + + /** + * Setter - slug + * WordPress admin menu param + * + * @access private + */ + private function slug( $slug ) { + $this->slug = $slug; + } + + /** + * Setter - parent + * WordPress admin menu param + * + * @access private + */ + private function parent( $parent ) { + switch( $parent ) { + case 'options': + case 'settings': + case 'options-general.php': + $this->parent = 'options-general.php'; + break; + default: + $this->parent = $parent; + break; + } + } + + /** + * Setter - icon_url + * WordPress admin menu param + * + * @access private + */ + private function icon_url( $icon_url ) { + $this->icon_url = $icon_url; + } + + + /** + * Setter - position + * WordPress admin menu param + * + * @access private + */ + private function position( $position ) { + $this->position = $position; + } + + /** + * Setter - render + * Sets render cb or tpl + * + * accepts: + * presets: 'settings-page', 'cmb2', 'cmb2-tabs', 'render_cb', 'render_tpl' + * callback: A callable function that prints page. + * readable: A template file + * + * @access private + */ + private function render( $render=null ) { + if ( 'settings-page' == $render ) { + $this->render_tpl( __DIR__ . '/tpl/settings-form.php' ); + $this->render = $this->render ?? $render; // 'settings-page' + } else if ( 'cmb2' == $render || 'cmb2-tabs' == $render ) { + + // validate + if ( ! defined( 'CMB2_LOADED' ) ){ + $this->render_tpl( __DIR__ . '/tpl/cmb2-unavailable.php' ); + $this->render = $this->render ?? 'render_tpl'; + } else { + $this->delegate_hookup = true; + + if ( ! empty( $this->plugin_core ) || ! empty( $this->plugin_info ) ){ + $this->render_tpl( __DIR__ . '/tpl/cmb2_options_page-plugin_info.php' ); + } else { + $this->render_tpl( __DIR__ . '/tpl/cmb2_options_page.php' ); + } + + $this->render = $this->render ?? $render; // 'cmb2' || 'cmb2-tabs' + } + + } else if( is_callable( $render ) ) { + $this->render_cb( $render ); + $this->render = $this->render ?? 'render_cb'; + } else if ( is_readable( $render ) ) { + $this->render_tpl( $render ); + $this->render = $this->render ?? 'render_tpl'; + } else { + $this->render_tpl( __DIR__ . '/tpl/default.php' ); + $this->render = $this->render ?? 'render_tpl'; + } + } + + /** + * Setter - render_cb + * + * if $this->render == 'render_cb' + * set callback funtion in $this->render_cb + * + * @access private + */ + private function render_cb($render_cb){ + + // we already have it + if ( $this->render_cb ) + return; + + if( is_callable( $render_cb ) ) + $this->render_cb = $render_cb; + + } + + /** + * Setter - render_tpl + * + * if $this->render == 'render_tpl' + * save template filename to $this->render_tpl + * + * @access private + */ + private function render_tpl($render_tpl){ + + // we already have it + if ($this->render_tpl) + return; + + if( is_readable( $render_tpl ) ) + $this->render_tpl = $render_tpl; + + } + + /** + * Setter - wrap + * + * Set wrap type. + * Default: none + * + * @access private + */ + private function wrap($wrap=null){ + + // we already have it + if ($this->wrap) + return; + + if ( ! empty($wrap) ){ + $this->wrap = 'simple'; + } else { + $this->wrap = 'none'; + } + + if ( 'sidebar' == $wrap ){ + $this->wrap = 'sidebar'; + } + + // if plugin_info == true we set to sidebar regardless of passed $wrap parameter + if ( ! empty($this->plugin_info) ){ + $this->wrap = 'sidebar'; + } + + if ( 'settings-page' == $this->render ){ + if ( empty($this->plugin_info) ){ + $this->wrap = 'simple'; + } + } + + } + + /** + * Setter - plugin_info + * + * accepts: + * callable: Function that prints plugin info box + * boolean true (or non-empty value): print default + * + * @access private + */ + private function plugin_info( $plugin_info ){ + + // we already have it + if ( $this->plugin_info ) + return; + + if( is_callable( $plugin_info ) ) + $this->plugin_info = $plugin_info; + + // if true-y value passed and PluginCore class exists - set to true + else if (!empty($plugin_info) && class_exists('WPHelper\PluginCore')) + $this->plugin_info = true; + } + + /** + * Setter - scripts + * Scripts to enqueue on admin page + * + * @access private + */ + private function scripts($scripts){ + $this->scripts = $scripts; + } + + /** + * Setter - styles + * Styles to enqueue on admin page + * + * @access private + */ + private function styles($styles){ + $this->styles = $styles; + } + + /** + * Setter - methods + * Callables to run on 'load-{$hook_suffix}' + * + * @access private + */ + function methods($methods){ + $this->methods = $methods; + } + + function plugin_core($plugin_core){ + if ( is_a( $plugin_core, 'WPHelper\PluginCore') ){ + $this->plugin_core = $plugin_core; + } + } + + function settings($settings){ + $this->settings = $settings; + } + + /** + * Getter - Options + * Array representation of $this object. + * + * @return array options + * + * @todo add new properties (like plugin_info) + */ + public function options(){ + $options = [ + 'title' => $this->title, + 'menu_title' => $this->menu_title, + 'capability' => $this->capability, + 'slug' => $this->slug, + 'parent' => $this->parent, + 'icon_url' => $this->icon_url, + 'position' => $this->position, + 'render' => $this->render, // render_cb | render_tpl | settings-page | cmb2 | cmb2-tabs + 'render_cb' => $this->render_cb, + 'render_tpl' => $this->render_tpl, + 'settings' => $this->settings, + 'plugin_core' => $this->plugin_core, + ]; + + return $options; + } + + /** + * REGISTER MENU - NOOP/DEPRECATE NOTICE + * + * Empty function. Kept here for backward-compatibility purposes. + * + * All setup operations are now made in the constructor. This function is empty and will be deprecated. + * + * This runs for all registers + * hook_suffix not defined yet + * + * inside WPHelper namespace + * \get_current_screen() function not defined + * \current_action() also???? + */ + function setup(){ + _doing_it_wrong( __METHOD__, 'Deprecated. Noop/no-op. This function will be removed in v1.0', '0.14' ); + } + + /** + * Set default user capability if none provided + * + * Finish constructing object after all info is available + * + * @hook 'init' + * @access private + * + * @return void + */ + public function bootstrap(){ + + if ( ! $this->capability ) + $this->capability = 'manage_options'; + + if ( $this->render == 'settings-page' ){ + + $this->settings_page = new SettingsPage($this); + $this->settings_page->setup(); + + } + + add_action( "wphelper/adminpage/plugin_info_box/{$this->slug}" , [ $this , 'render_plugin_info_box' ] ); + + // if ( $this->delegate_hookup ){ + if ( 'cmb2' == $this->render || 'cmb2-tabs' == $this->render ){ + + if ( isset( $this->settings['options_type'] ) && $this->settings['options_type'] == 'multi' ) { + $this->cmb2_page = new CMB2_OptionsPage_Multi( $this ); + } else { + $this->cmb2_page = new CMB2_OptionsPage( $this ); + } + + /** + * @todo Perhpaps this can hook on admin_init - right after admin_menu has finished + * @todo CMB2 options-page does not return page_hook/hook_suffix - MUST validate + */ + add_action ( 'admin_menu' , [ $this , '_bootstrap_admin_page' ], 12 ); + + // skip add_menu_page + return; + } + + // if ( ! $this->delegate_hookup ){ + add_action ( 'admin_menu' , [ $this , 'add_menu_page' ], 11 ); + add_action ( 'admin_menu' , [ $this , '_bootstrap_admin_page' ], 12 ); + + } + + /** + * Add WordPress toplevel or submenu page + */ + public function add_menu_page(){ + + switch ( $this->parent ){ + case null: + case '': + $this->hook_suffix = add_menu_page( + $this->title, + $this->menu_title, + $this->capability, + $this->slug, + [ $this , 'render_admin_page' ], + $this->icon_url, + $this->position + ); + break; + case 'options': + case 'settings': + case 'options-general.php': + $this->hook_suffix = add_options_page( + $this->title, + $this->menu_title, + $this->capability, + $this->slug, + [ $this , 'render_admin_page' ] + ); + break; + default: + $this->hook_suffix = add_submenu_page( + $this->parent, + $this->title, + $this->menu_title, + $this->capability, + $this->slug, + [ $this , 'render_admin_page' ] + ); + break; + } + + } + + + /** + * + */ + public function validate_page_hook(){ + + /** + * hack! + * This is ad hoc validation - should do this earlier + */ + if ( empty( $this->slug ) ){ + $this->slug = $this->settings['option_key']; + } + + if ( empty( $this->hook_suffix ) ){ + $this->hook_suffix = get_plugin_page_hookname( $this->slug, $this->parent ); + } + + } + + /** + * REGISTER ADMIN PAGE + * + * hook_suffix is KNOWN + * get_current_screen() is NOT + * + * Runs for EVERY AdminPage instance + * AdminNotice->onPage() works + * + * @hook admin_menu priority 12 + * @access private + * + * @todo move this function to admin_init - after admin_menu has finished + */ + public function _bootstrap_admin_page(){ + + /** + * @todo perhaps run this on 'admin_init' + */ + $this->validate_page_hook(); + + add_action ( 'load-' . $this->hook_suffix , [ $this , '_admin_page_setup' ] ); + + foreach ( $this->methods as $method ){ + if( is_callable( $method ) ){ + add_action ( 'load-' . $this->hook_suffix , $method ); + } + } + } + + /** + * SHOW ADMIN PAGE + * + * current_screen IS AVAILABLE + * + * Only runs on actual screen showing + * AdminNotice->onPage() redundant + * + * @hook load-{$hook_suffix} + * @access private + */ + public function _admin_page_setup(){ + + if ( $this->scripts ) + add_action( 'admin_enqueue_scripts', [ $this, 'admin_enqueue_scripts' ] ); + + if ( $this->styles ) + add_action( 'admin_enqueue_scripts', [ $this, 'admin_enqueue_styles' ] ); + } + + /** + * admin_enqueue_scripts + * Enqueue user-provided scripts on admin page. + * + * @hook admin_enqueue_scripts + * @access private + */ + public function admin_enqueue_scripts( $hook ) { + + // redundant + // this only gets called on load-{$this->hook_suffix} anyway + if( $hook != $this->hook_suffix ) { + return; + } + + if ( ! $this->scripts) + return; + + foreach ( $this->scripts as $script_args ){ + wp_enqueue_script( ...$script_args ); + } + + } + + /** + * admin_enqueue_styles + * Enqueue user-provided styles on admin page. + * + * @hook admin_enqueue_styles + * @access private + */ + public function admin_enqueue_styles( $hook ) { + + // redundant + // this only gets called on load-{$this->hook_suffix} anyway + if( $hook != $this->hook_suffix ) { + return; + } + + if ( ! $this->styles) + return; + + foreach ( $this->styles as $style_args ){ + wp_enqueue_style( ...$style_args ); + } + + } + + /** + * Getter - capability + * Get the capability required to view the admin page. + * + * @return string + */ + public function get_capability() + { + return $this->capabailty; + } + + /** + * Getter - menu_title + * Get the title of the admin page in the WordPress admin menu. + * + * @return string + */ + public function get_menu_title() + { + return $this->menu_title; + } + + /** + * Getter - title + * Get the title of the admin page. + * + * @return string + */ + public function get_title() + { + return $this->title; + } + + /** + * Getter - parent / parent_slug + * Get the parent slug of the admin page. + * + * @return string + */ + public function get_parent_slug() + { + return $this->parent; + } + + /** + * Getter - hook_suffix + * Get the hook suffix provided by WordPress when registering menu page.. + * + * @return string + * + * @todo Throw Exception|WP_Error if called before 'current_screen' hook. + */ + public function get_hook_suffix() + { + return $this->hook_suffix; + } + + /** + * Getter - slug + * Get the slug used by the admin page. + * + * @return string + */ + public function get_slug() + { + return $this->slug; + } + + /** + * Getter - render_tpl + * Get the render template. + * + * @return string + */ + public function get_render_tpl() + { + return $this->render_tpl; + } + + /** + * Render Admin Page + * Render the top section of the plugin's admin page. + * + * This callback function used as $callback parameter in add_menu_page() + * + * @access public + */ + public function render_admin_page() + { + // @todo if render callback supplied - add shortcircuit hook here + // execute render callback and return early + + if ( 'none' != $this->wrap ){ + ob_start(); + } + + if ( isset( $this->render_cb ) && is_callable( $this->render_cb ) ) { + call_user_func( $this->render_cb ); + } else if ( isset( $this->render_tpl ) && is_readable( $this->render_tpl ) ) { + include $this->render_tpl; + } + + if ( 'none' != $this->wrap ){ + $ob_content = ob_get_clean(); + + switch ( $this->wrap ){ + case ( 'simple' ): + include 'tpl/wrap-simple.php'; + break; + case ( 'sidebar' ): + include 'tpl/wrap-sidebar.php'; + break; + default: + break; + } + + } + } + + /** + * Render plugin info metabox + * + * Call user-provided callable. + * Or else attempt to create PluginInfoMetaBox class from $this->plugin_core and call its render function. + * + * @access private? + * + * @todo See if this function should be public API or only run on action hook + * @todo deprecate public use - use wphelper/adminpage/plugin_info_box/{$this->slug} instead + */ + public function render_plugin_info_box(){ + + if ( isset( $this->plugin_info ) && is_callable( $this->plugin_info ) ) { + call_user_func( $this->plugin_info ); + } else { + if ( ! empty( $this->plugin_core ) && empty( $this->plugin_info_meta_box ) ){ + $this->plugin_info_meta_box = new PluginInfoMetaBox( $this->plugin_core ); + } + $this->plugin_info_meta_box->plugin_info_box(); + } + + } +} +endif; \ No newline at end of file diff --git a/vendor/abuyoyo/adminmenupage/src/CMB2_OptionsPage.php b/vendor/abuyoyo/adminmenupage/src/CMB2_OptionsPage.php new file mode 100644 index 0000000..2601922 --- /dev/null +++ b/vendor/abuyoyo/adminmenupage/src/CMB2_OptionsPage.php @@ -0,0 +1,243 @@ +admin_page = $admin_page; + + $admin_options = $this->admin_page->options(); + + $settings = $admin_options['settings']; + + $settings['object_types'] = [ 'options-page' ]; + $settings['display_cb'] ??= [ $this, 'options_page_output' ]; + + $settings['option_key'] ??= ( $settings['option_name'] ?? ( $settings['id'] ?? $admin_options['slug'] ) ); + $settings['title'] ??= $admin_options['title']; + $settings['menu_title'] ??= $admin_options['menu_title']; + $settings['parent_slug'] ??= $admin_options['parent']; + $settings['position'] ??= $admin_options['position']; + $settings['icon_url'] ??= $admin_options['icon_url']; + $settings['capability'] ??= $admin_options['capability']; + + /** + * CMB2 must have admin menu page slug same as option key :( + */ + $settings['id'] = $settings['option_key']; + + unset( $settings['option_name'] ); + + /** + * CMB2 only accepts url slug + * + * @todo export parent_slug convertion to dedicated method + */ + switch ( $settings['parent_slug'] ) { + case 'dashboard': + $settings['parent_slug'] = 'index.php'; + break; + case 'posts': + $settings['parent_slug'] = 'edit.php'; + break; + case 'media': + $settings['parent_slug'] = 'upload.php'; + break; + case 'pages': + $settings['parent_slug'] = 'edit.php?post_type=page'; + break; + case 'comments': + $settings['parent_slug'] = 'edit-comments.php'; + break; + case 'themes': + case 'appearance': // Official WordPress designation + $settings['parent_slug'] = 'themes.php'; + break; + case 'plugins': + $settings['parent_slug'] = 'plugins.php'; + break; + case 'users': + $settings['parent_slug'] = 'users.php'; + break; + case 'options': + case 'settings': // Official WordPress designation + $settings['parent_slug'] = 'options-general.php'; + break; + case 'tools': + $settings['parent_slug'] = 'tools.php'; + break; + case 'network': + case 'network_settings': + $settings['parent_slug'] = 'settings.php'; + break; + case null: + break; + default: + if ( post_type_exists( $settings['parent_slug'] ) ){ + $settings['parent_slug'] = "edit.php?post_type={$settings['parent_slug']}"; + } + break; + } + + if ( $admin_options['render'] == 'cmb2-tabs' ){ + $settings['tab_group'] ??= $settings['parent_slug'] ?? $settings['id']; + $settings['tab_title'] ??= $settings['menu_title']; + } + + if ( isset( $settings['fields'] ) ){ + $this->fields = $settings['fields']; + /** + * @todo revisit this - might not need to unset fields + */ + unset( $settings['fields'] ); + } + + /** + * If args are formatted for SettingsPage we convert to CMB2 options format + * Convert nested sections=>fields to straight title, fields, title, fields. + * + * @todo export this to dedicated method + */ + if ( isset( $settings['sections'] ) ){ + $this->fields = []; + foreach ( $settings['sections'] as $section ){ + $title_field = []; + if ( $id = $section['id'] ?? $section['slug'] ){ + $title_field['id'] = $id; + } + if ( $name = $section['name'] ?? $section['title'] ){ + $title_field['name'] = $name; + } + if ( $desc = $section['desc'] ?? $section['description'] ){ + $title_field['desc'] = $desc; + } + if ( ! empty($title_field)){ + $title_field['type'] = 'title'; + $this->fields[] = $title_field; + } + + foreach ($section['fields'] as $field){ + $field = $this->convert_field_to_cmb2_field($field); + $this->fields[] = $field; + } + } + unset( $settings['sections'] ); + } + + + /** + * Special provision for cmb2-switch + */ + if ( ! class_exists( 'CMB2_Switch_Button' ) ){ + array_walk( + $this->fields, + function( &$field ){ + if ( $field['type'] == 'switch'){ + $field['type'] = 'checkbox'; + } + } + ); + } + + // re-insert fields back into settings + $settings['fields'] = $this->fields; + + $this->cmb2_options = $settings; + + // register parent pages before sub-menu pages + $priority = empty( $settings['parent_slug'] ) ? 9 : 10; + + add_action( 'cmb2_admin_init', [ $this, 'register_metabox' ], $priority ); + + /** + * @todo add 'submenu' field and functionality to WPHelper\AdminPage + * @todo reverse control/flow - so 'tab title' inherits/defaults to AdminPage 'submenu' field if exists. + */ + if ( empty( $settings['parent_slug'] ) && $settings['menu_title'] != $settings['tab_title'] ){ + add_action('admin_menu', [ $this, 'replace_submenu_title'], 11 ); + } + + } + + public function register_metabox(){ + $this->cmb = new CMB2( $this->cmb2_options ); + } + + /** + * Display options-page output. To override, set 'display_cb' box property. + * + * @param CMB2_Options_Hook $hookup - instance of Options Page Hookup class (caller of this function) + * + * @see CMB2_Options_Hook + */ + public function options_page_output( $hookup ) { + include $this->admin_page->get_render_tpl(); + } + + + private function convert_field_to_cmb2_field( $field ){ + + $field['id'] ??= $field['slug'] ?? null; + $field['name'] ??= $field['title'] ?? null; + $field['desc'] ??= $field['description'] ?? null; + + unset( $field['slug'] ); + unset( $field['title'] ); + unset( $field['description'] ); + + return array_filter($field); + } + + + /** + * Replace submenu title of parent item with tab title + * + * @todo add 'submenu' field and functionality to WPHelper\PluginCore + */ + public function replace_submenu_title(){ + + remove_submenu_page( $this->cmb2_options['id'], $this->cmb2_options['id'] );// Remove the default submenu so we can add our customized version. + add_submenu_page( + $this->cmb2_options['id'], + $this->cmb2_options['title'], + $this->cmb2_options['tab_title'], + $this->cmb2_options['capability'], + $this->cmb2_options['id'], + '', + 0, + ); + } +} +endif; \ No newline at end of file diff --git a/vendor/abuyoyo/adminmenupage/src/CMB2_OptionsPage_Multi.php b/vendor/abuyoyo/adminmenupage/src/CMB2_OptionsPage_Multi.php new file mode 100644 index 0000000..919c60b --- /dev/null +++ b/vendor/abuyoyo/adminmenupage/src/CMB2_OptionsPage_Multi.php @@ -0,0 +1,30 @@ +cmb2_override_fields( $this->fields ); + } +} +endif; \ No newline at end of file diff --git a/vendor/abuyoyo/adminmenupage/src/CMB2_Override_Meta.php b/vendor/abuyoyo/adminmenupage/src/CMB2_Override_Meta.php new file mode 100644 index 0000000..4074e23 --- /dev/null +++ b/vendor/abuyoyo/adminmenupage/src/CMB2_Override_Meta.php @@ -0,0 +1,56 @@ +plugin_core = $plugin_core; + } + + /** + * PLUGIN INFO BOX + * + * Display plugin info meta-box on admin pages + * + * @since iac_engine 1.1.0 + * @since iac_engine 1.2.0 plugin_info_box now a function + * @since iac_engine 1.3.0 use 'Last Update' header + */ + function plugin_info_box(){ + + $plugin_data = get_plugin_data( $this->plugin_core->file() , false ); // false = no markup (i think) + + + $last_update = $plugin_data['Last Update'] ?: $plugin_data['Release Date']; + $last_update = DateTime::createFromFormat('Y_m_d', $last_update); + + // $last_update = new DateTime('now'); + // $last_update->add(new DateInterval('P1D')); + // $last_update->add(new DateInterval('P2D')); + if ($last_update): + $diff = (int) abs( time() - $last_update->format('U') ); + + if ( $diff < (DAY_IN_SECONDS) ){ + $update_message = 'Today'; + }elseif ($diff < (2 * DAY_IN_SECONDS)){ + $update_message = 'Yesterday'; + }else{ + $update_message = human_time_diff($last_update->format('U')) . ' ago'; + } + else: + $update_message = ''; + endif; + + include __DIR__ . $this->tpl; + } +} +endif; \ No newline at end of file diff --git a/vendor/abuyoyo/adminmenupage/src/SettingsPage.php b/vendor/abuyoyo/adminmenupage/src/SettingsPage.php new file mode 100644 index 0000000..1606aa0 --- /dev/null +++ b/vendor/abuyoyo/adminmenupage/src/SettingsPage.php @@ -0,0 +1,327 @@ +admin_page = $admin_page; + + $admin_options = $admin_page->options(); + $settings = $admin_options['settings']; + + $this->page = $admin_options['slug']; + + $this->option_name = $settings['option_name'] ?? str_replace( '-', '_' , strtolower( $this->page ) ); + + $this->option_group = $settings['option_group'] ?? $this->page . '_option_group'; + + foreach ( $settings['sections'] as $section ) { + // extract fields + foreach ( $section['fields'] as $field ){ + $field['section_id'] = $section['id']; // create back-reference in field to section. ( @see add_settings_field() ) + $this->fields[] = $field; + } + unset( $section['fields'] ); + $this->sections[] = $section; // save without fields + } + } + + function setup() { + add_action( 'admin_init', [ $this, 'register_settings' ] ); + } + + public function register_settings() { + register_setting( + $this->option_group, // $option_group - A settings group name. Must exist prior to the register_setting call. This must match the group name in settings_fields() + $this->option_name, // $option_name - The name of an option to sanitize and save. + [ $this,'sanitize_settings' ] // $sanitize_callback - A callback function that sanitizes the option's value. (see also: built-in php callbacks) + ); + + foreach ( $this->sections as $section ){ + add_settings_section( + $section['id'], // $id - Slug-name to identify the section. Used in the 'id' attribute of tags. + $section['title'] ?? null, // $title - Formatted title of the section. Shown as the heading for the section. + $this->section_description_cb( $section ), // $callback - Function that echos out any content at the top of the section (between heading and fields). + $this->page // $page - The slug-name of the settings page on which to show the section. + //Built-in pages include 'general', 'reading', 'writing', 'discussion', 'media', etc. + ); + } + + foreach ( $this->fields as $field ) { + add_settings_field( + $field['id'], + $field['title'], + [ $this, "print_{$field['type']}" ], + $this->page, // can built-in pages: (general, reading, writing, ...) + $field['section_id'], + $field //send setting array as $args for print function + ); + } + + } + + /** + * Print text input field + * Support field type 'text' + * + * @since 0.11 + */ + function print_checkbox( $field ) { + extract($field); + + $options = get_option( $this->option_name ); + + $input_tag = sprintf( + '', + $id, + $this->option_name, + $description, + checked( ( $options[$id] ?? false ), '1', false) + ); + + /** + * Allow plugins to directly manipulate field HTML + */ + $input_tag = apply_filters( 'wphelper/settings_page/input_checkbox', $input_tag, $field, $this->option_name, $options ); + + echo $input_tag; + + } + + /** + * Print text input field + * Support field type 'text' + * + * @since 0.19 + */ + function print_text( $field ) { + extract($field); + + $options = get_option( $this->option_name ); + + $input_tag = sprintf( + '', + $id, + $this->option_name, + $default + ); + + if ( ! empty( $description ) ) { + $input_tag .= sprintf( + '

%2$s

', + $id, + $description + ); + } + + /** + * Allow plugins to directly manipulate field HTML + */ + $input_tag = apply_filters( 'wphelper/settings_page/input_text', $input_tag, $field, $this->option_name, $options ); + + echo $input_tag; + + } + + /** + * Print url input field + * Support field type 'url' + * + * @since 0.19 + */ + function print_url( $field ){ + extract($field); + + $options = get_option( $this->option_name ); + + $input_tag = sprintf( + '', + $id, + $this->option_name, + $default + ); + + if ( ! empty( $description ) ) { + $input_tag .= sprintf( + '

%2$s

', + $id, + $description + ); + } + + /** + * Allow plugins to directly manipulate field HTML + */ + $input_tag = apply_filters( 'wphelper/settings_page/input_url', $input_tag, $field, $this->option_name, $options ); + + echo $input_tag; + + } + + /** + * Print email input field + * Support field type 'email' + * + * @since 0.19 + */ + function print_email( $field ){ + extract($field); + + $options = get_option( $this->option_name ); + + $input_tag = sprintf( + '', + $id, + $this->option_name, + $default + ); + + if ( ! empty( $description ) ) { + $input_tag .= sprintf( + '

%2$s

', + $id, + $description + ); + } + + /** + * Allow plugins to directly manipulate field HTML + */ + $input_tag = apply_filters( 'wphelper/settings_page/input_email', $input_tag, $field, $this->option_name, $options ); + + echo $input_tag; + + } + + /** + * Sanitizes entire $options array. + */ + function sanitize_settings( $options ) { + $new_options = []; + + foreach( $options as $id => $option ) { + $field = reset( + array_filter( + $this->fields, + fn($item) => $item['id'] == $id + ) + ); + switch ( $field['type'] ){ + case 'checkbox': + $new_options[$id] = $option == 1 ? 1 : 0; + break; + case 'text': + $new_options[$id] = sanitize_text_field( $option ); + break; + case 'email': + $new_options[$id] = sanitize_email( $option ); + break; + case 'url': + $new_options[$id] = sanitize_url( $option ); + break; + default: + break; + } + } + + return $new_options; + } + + function section_description_cb( $section ) { + if ( ! empty( $section['description'] ) ) { + switch ( $section[ 'description_container' ] ?? '' ){ + case 'card': + $container = '
%s
'; + break; + case 'notice': + case 'notice-info': + $container = '

%s

'; + break; + case 'none': + $container = '%s'; + break; + default: + $container = '

%s

'; + break; + } + return fn() => printf( $container, $section['description'] ); + } + } +} +endif; \ No newline at end of file diff --git a/vendor/abuyoyo/adminmenupage/src/tpl/cmb-form.php b/vendor/abuyoyo/adminmenupage/src/tpl/cmb-form.php new file mode 100644 index 0000000..2ebaad6 --- /dev/null +++ b/vendor/abuyoyo/adminmenupage/src/tpl/cmb-form.php @@ -0,0 +1,15 @@ + +
+ + options_page_metabox(); ?> + cmb->prop( 'save_button' ) ), 'primary', 'submit-cmb' ); ?> +
\ No newline at end of file diff --git a/vendor/abuyoyo/adminmenupage/src/tpl/cmb-title.php b/vendor/abuyoyo/adminmenupage/src/tpl/cmb-title.php new file mode 100644 index 0000000..569778e --- /dev/null +++ b/vendor/abuyoyo/adminmenupage/src/tpl/cmb-title.php @@ -0,0 +1,9 @@ +cmb->prop( 'title' ) ) { + echo '

' . wp_kses_post( $this->cmb->prop( 'title' ) ) . '

'; +} \ No newline at end of file diff --git a/vendor/abuyoyo/adminmenupage/src/tpl/cmb2-unavailable.php b/vendor/abuyoyo/adminmenupage/src/tpl/cmb2-unavailable.php new file mode 100644 index 0000000..fec2537 --- /dev/null +++ b/vendor/abuyoyo/adminmenupage/src/tpl/cmb2-unavailable.php @@ -0,0 +1,9 @@ +
+

+ +
+

CMB2 Plugin Missing

+

CMB2 plugin is required to display this page. +
Download and activate CMB2 plugin. +

+
\ No newline at end of file diff --git a/vendor/abuyoyo/adminmenupage/src/tpl/cmb2_options_page-plugin_info.php b/vendor/abuyoyo/adminmenupage/src/tpl/cmb2_options_page-plugin_info.php new file mode 100644 index 0000000..35d5074 --- /dev/null +++ b/vendor/abuyoyo/adminmenupage/src/tpl/cmb2_options_page-plugin_info.php @@ -0,0 +1,42 @@ + + +
+ + + + +
+
+ + +
+
+ +
+
+ + +
+
+ admin_page->get_slug()}"); ?> +
+
+
+
+
+
\ No newline at end of file diff --git a/vendor/abuyoyo/adminmenupage/src/tpl/cmb2_options_page.php b/vendor/abuyoyo/adminmenupage/src/tpl/cmb2_options_page.php new file mode 100644 index 0000000..f803a81 --- /dev/null +++ b/vendor/abuyoyo/adminmenupage/src/tpl/cmb2_options_page.php @@ -0,0 +1,13 @@ + +
+ + + +
\ No newline at end of file diff --git a/vendor/abuyoyo/adminmenupage/src/tpl/default.php b/vendor/abuyoyo/adminmenupage/src/tpl/default.php new file mode 100644 index 0000000..9131945 --- /dev/null +++ b/vendor/abuyoyo/adminmenupage/src/tpl/default.php @@ -0,0 +1,17 @@ +
+

+ +
+

WPHelper\AdminPage

+

Please provide a template file or callback function to render this page +
Like so: +

+
new WPHelper\AdminPage(
+	[
+		'slug'     => 'slug?>',
+		'title'    => 'title?>',
+		'render' => 'callback_or_tpl_file',
+	]
+);
+
+
\ No newline at end of file diff --git a/vendor/abuyoyo/adminmenupage/src/tpl/plugin_info_meta_box.php b/vendor/abuyoyo/adminmenupage/src/tpl/plugin_info_meta_box.php new file mode 100644 index 0000000..028ca03 --- /dev/null +++ b/vendor/abuyoyo/adminmenupage/src/tpl/plugin_info_meta_box.php @@ -0,0 +1,27 @@ + + +
+

Plugin Info

+
+

+

+ Version:
+ Author:
+ GitHub:
+ Last Updated: +

+
+ +
\ No newline at end of file diff --git a/vendor/abuyoyo/adminmenupage/src/tpl/settings-form.php b/vendor/abuyoyo/adminmenupage/src/tpl/settings-form.php new file mode 100644 index 0000000..725a73a --- /dev/null +++ b/vendor/abuyoyo/adminmenupage/src/tpl/settings-form.php @@ -0,0 +1,14 @@ + +
+ settings_page->option_group );// Print hidden setting fields + do_settings_sections( $this->get_slug() );// Print title, info callback and form-table + submit_button(); + ?> +
\ No newline at end of file diff --git a/vendor/abuyoyo/adminmenupage/src/tpl/tab-nav.php b/vendor/abuyoyo/adminmenupage/src/tpl/tab-nav.php new file mode 100644 index 0000000..0d41046 --- /dev/null +++ b/vendor/abuyoyo/adminmenupage/src/tpl/tab-nav.php @@ -0,0 +1,17 @@ +get_tab_group_tabs(); + +if ( count( $tabs ) > 1 ){ + $hookup->options_page_tab_nav_output(); +} \ No newline at end of file diff --git a/vendor/abuyoyo/adminmenupage/src/tpl/wrap-sidebar.php b/vendor/abuyoyo/adminmenupage/src/tpl/wrap-sidebar.php new file mode 100644 index 0000000..caa493b --- /dev/null +++ b/vendor/abuyoyo/adminmenupage/src/tpl/wrap-sidebar.php @@ -0,0 +1,31 @@ + +
+

+ +
+
+ + +
+
+ +
+
+ + +
+
+ get_slug()}"); ?> +
+
+
+
+
+
\ No newline at end of file diff --git a/vendor/abuyoyo/adminmenupage/src/tpl/wrap-simple.php b/vendor/abuyoyo/adminmenupage/src/tpl/wrap-simple.php new file mode 100644 index 0000000..cfdf6b7 --- /dev/null +++ b/vendor/abuyoyo/adminmenupage/src/tpl/wrap-simple.php @@ -0,0 +1,10 @@ + +
+

+ + +
\ No newline at end of file diff --git a/vendor/abuyoyo/adminmenupage/wph_admin_page.php b/vendor/abuyoyo/adminmenupage/wph_admin_page.php new file mode 100644 index 0000000..d5bf74b --- /dev/null +++ b/vendor/abuyoyo/adminmenupage/wph_admin_page.php @@ -0,0 +1,34 @@ += 7.4 + +## 0.18 +Release Date: May 22, 2022 + +### Changed + +- Class `PluginCore` is pluggable. +- Prevent direct PHP script execution if not accessed within the WordPress environment. + +### Fixed + +- Include `plugin.php` if function `get_plugin_data` does not exist. This could case critical failure. + +## 0.17 +Release Date: Feb 7, 2021 + +### Added + +- Pass instance of `PluginCore` to `AdminPage` if current version supports it (used in Plugin Info Metabox generation). + +## 0.16 + +### Fixed + +- Upgrade callback `upgrade_cb` will execute when only single plugin is updated. + +## 0.15 + +### Changed + +- Use `new WPHelper\AdminPage()` (WPHelper\AdminMenuPage >= 0.12) instead of deprecated `AdminMenuPage`. +- Do not hook `Puc_v4_Factory::buildUpdateChecker` on `admin_init`. Run in plugin's global scope. + +## 0.14 + +### Added + +- Add `admin_page` option to create a WPHelper\AdminMenuPage instance. +- Add `plugin_data` variable with WordPress core `get_plugin_data()` object. Use header data if no slug or title provided. + +### Fixed +- Fix PHP defines when `const` not provided. + +## 0.13.3 +- Fix `upgrade_cb` function handling. + +## 0.13.2 +- Fix `upgrade_cb_wrapper` function. + +## 0.13.1 +- Update `composer.json` version. + +## 0.13 +- Fix `upgrade_cb_wrapper` function. + +## 0.12 +- Add upgrade_cb wrapper function that conducts sanity-checks before calling `upgrade_cb` callback provided. +- Add `plugin_basename()` getter/setter function and `plugin_basename` variable. +- Add changelog. + +## 0.11 +- Add `upgrade_cb` option - callable function to run on WordPress `upgrader_process_complete` hook. + +## 0.10 +- Fix undefined index PHP notices introduced in version 0.9 + +## 0.9 +- Add automatic plugin update checker using `yahnis-elsts/plugin-update-checker` library. + +## 0.8 +- Fix wrong `plugin_basename` constant. + +## 0.7 +- Don't use `extarct` in constructor +- Add sanity checks and normalize getter/setter functions +- Add `file()` getter function. + +## 0.6 +- Add `path()`, `url()` getter/setter functions. +- Add `name()` getter function. + +## 0.5 +- Initial release. +- Defines `PLUGINNAME_URL`, `_PATH`, `_DIR`, `_BASENAME`, `_FILE` constants for plugin. +- Registers plugin activation, deactivation and uninstall hook if callbacks provided. +- Static function `PluginCore::get($slug)` will return instance of PluginCore registered with `$slug`. Thus PluginCore can be initiated without polluting global scope. diff --git a/vendor/abuyoyo/plugincore/LICENSE b/vendor/abuyoyo/plugincore/LICENSE new file mode 100644 index 0000000..3644397 --- /dev/null +++ b/vendor/abuyoyo/plugincore/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2019, abuyoyo +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/vendor/abuyoyo/plugincore/PluginCore.php b/vendor/abuyoyo/plugincore/PluginCore.php new file mode 100644 index 0000000..ba81104 --- /dev/null +++ b/vendor/abuyoyo/plugincore/PluginCore.php @@ -0,0 +1,469 @@ +plugin_file( $plugin_file ); + + if ( is_array( $options ) && ! empty( $options ) ) { + + $options = (object) $options; + + if ( isset( $options->title ) ) { + $this->title( $options->title ); + }else{ + $this->title(); // get title from header plugin_data + } + + if ( isset( $options->slug ) ) { + $this->slug( $options->slug ); + }else{ + $this->slug(); // guess slug from plugin basename + } + + if ( isset( $options->const ) ) { + $this->const( $options->const ); + }else{ + $this->const(); + } + + if ( isset( $options->admin_page ) ) { + $this->admin_page( $options->admin_page ); + } + + if ( isset( $options->activate_cb ) ) + $this->activate_cb( $options->activate_cb ); + + if ( isset( $options->deactivate_cb ) ) + $this->deactivate_cb( $options->deactivate_cb ); + + if ( isset( $options->uninstall_cb ) ) + $this->uninstall_cb( $options->uninstall_cb ); + + if ( isset( $options->upgrade_cb ) ) + $this->upgrade_cb( $options->upgrade_cb ); + + if ( isset( $options->update_checker ) ) { + $this->update_checker( $options->update_checker ); + } + } + + $this->setup(); + + } + + /** + * Define plugin constants (_PATH, _URL, _BASENAME, _FILE etc.) + * Register activation, deactivation, uninstall, upgrade hooks. + * Init PUC update checker. + * Add PluginCore instance to static $cores + * + * @todo rename method bootstrap() + * @todo set plugin_dir_path, plugin_basename as accessible public variables (available thru methods atm) + */ + function setup() { + + // init path and url + // redundant init() and path() are getter/setter methods. + $this->path(); + $this->url(); + + define( $this->const() . '_PATH', $this->path() ); + define( $this->const() . '_DIR', $this->path() ); + + define( $this->const() . '_URL', $this->url() ); + define( $this->const() . '_BASENAME', $this->plugin_basename() ); + + define( $this->const() . '_PLUGIN_FILE', $this->plugin_file ); + define( $this->const() . '_FILE', $this->plugin_file ); + + $this->register_hooks(); + + self::$cores[ $this->slug() ] = $this; // using slug() method + + + if ( $this->update_checker == true ) { + // run early - before Puc_v4p8_Scheduler->maybeCheckForUpdates() [admin_init 10] + // hooking on admin_init does not work with wp_plugin_updates as it requires user logged-in + // add_action( 'admin_init', [$this, 'init_update_checker'], 9 ); + $this->init_update_checker(); + } + } + + private function register_hooks() { + + if ( ! empty( $this->activate_cb ) ) // && is_callable() ? + register_activation_hook( $this->plugin_file, $this->activate_cb ); + + if ( ! empty( $this->deactivate_cb ) ) + register_deactivation_hook( $this->plugin_file, $this->deactivate_cb ); + + if ( ! empty( $this->uninstall_cb ) ) + register_uninstall_hook( $this->plugin_file, $this->uninstall_cb ); + + if ( ! empty( $this->upgrade_cb ) ) + add_action( 'upgrader_process_complete', [ $this, 'upgrade_cb_wrapper' ], 10, 2 ); + } + + /** + * Getter/Setter - title + * Plugin title. + * If none provided - plugin header Title will be used. + * + * @param string|null $title + * @return string $this->title + */ + public function title( $title = null ) { + + if ( ! empty( $title ) ) { + $title = esc_html( $title ); + $this->title = $title; + } + + if ( empty( $this->title ) ) { + $this->plugin_data(); + $this->title = $this->plugin_data['Title']; + } + + return $this->title; + } + + /** + * Wrapper function for $this->title() + */ + public function name( $title = null ) { + return $this->title( $title ); + } + + /** + * Getter/Setter - slug + * Plugin slug. + * If none provided - plugin file basename will be used + * + * @param string|null $slug + * @return string $this->slug + */ + public function slug( $slug = null ) { + // doing it this way means slug can only be set once. + return $this->slug ??= $slug ?: basename( $this->plugin_file, '.php' ); + } + + /** + * Setter - plugin_file (also Getter - kinda) + * Plugin file fully qualified path. + * + * @param string $plugin_file - Path to plugin file + * @return string $this->plugin_file + */ + public function plugin_file( $plugin_file ) { + $this->plugin_file = $plugin_file; + return $this->plugin_file; + } + + /** + * GETTER function. NOT a wrapper + * Might have to rethink this + * used by test-plugin update_checker + * + * @todo revisit this + */ + public function file() { + return $this->plugin_file; + } + + + public function plugin_data() { + if ( empty( $this->plugin_data ) ) { + $this->plugin_data = get_plugin_data( $this->plugin_file, false); + } + return $this->plugin_data; + } + + /** + * Getter/Setter - const + * Prefix of plugin specific defines (PLUGIN_NAME_PATH etc.) + * If not provided - plugin slug will be uppercased. + * + * @param string|null $const (string should be uppercased) + * @return string $this->const + */ + public function const( $const = null ) { + + // if $const provided - use that + if ( ! empty( $const ) ) { + $this->const = $const; + } + + // if no $const provided - generate from slug() + if ( empty( $this->const ) ) { + $this->const = str_replace( '-', '_' , strtoupper( $this->slug() ) ); // using slug() getter/setter + } + + return $this->const; + } + + public function admin_page( $admin_page ) { + if ( empty( $admin_page['slug'] ) ) { + $admin_page['slug'] = $this->slug(); + } + if ( empty( $admin_page['title'] ) ) { + $admin_page['title'] = $this->title(); + } + + $this->admin_page = new AdminPage( $admin_page ); + + if ( method_exists( $this->admin_page, 'plugin_core' ) ) { + $this->admin_page->plugin_core( $this ); + } + + return $this->admin_page; + } + + + public function path() { + if ( empty( $this->path ) ) + $this->path = plugin_dir_path( $this->plugin_file ); + return $this->path; + } + + public function url() { + if ( empty( $this->url ) ) + $this->url = plugin_dir_url( $this->plugin_file ); + return $this->url; + } + + public function plugin_basename() { + if ( empty( $this->plugin_basename ) ) + $this->plugin_basename = plugin_basename( $this->plugin_file ); + return $this->plugin_basename; + } + + private function activate_cb( $activate_cb ) { + // test is_callable() ? or is it too soon? + $this->activate_cb = $activate_cb; + } + + private function deactivate_cb( $deactivate_cb ) { + // test is_callable() ? or is it too soon? + $this->deactivate_cb = $deactivate_cb; + } + + private function uninstall_cb( $uninstall_cb ) { + // test is_callable() ? or is it too soon? + $this->uninstall_cb = $uninstall_cb; + } + + private function upgrade_cb( $upgrade_cb ) { + // test is_callable() ? or is it too soon? + $this->upgrade_cb = $upgrade_cb; + } + + private function update_checker( $update_checker ) { + // Puc_v4_Factory::buildUpdateChecker + if ( empty( $update_checker ) ) { + $this->update_checker = false; + }else{ + if ( is_bool( $update_checker ) ) { + $this->update_checker = $update_checker; + } + + if ( is_string( $update_checker ) ) { + $this->update_checker = true; + $this->update_repo_uri = $update_checker; + } + + if ( is_array( $update_checker ) ) { + $this->update_checker = true; + + if ( isset( $update_checker['uri'] ) ) { + $this->update_repo_uri = $update_checker['uri']; + } + if ( isset( $update_checker['auth'] ) ) { + $this->update_auth = $update_checker['auth']; + } + + if ( isset( $update_checker['branch'] ) ) { + $this->update_branch = $update_checker['branch']; + } + } + } + } + + public function init_update_checker() { + + if ( ! class_exists('Puc_v4_Factory') ) + return; + + if ( ! isset( $this->update_repo_uri ) ) { + $this->plugin_data(); + + if ( isset( $this->plugin_data['PluginURI'] ) ) + $this->update_repo_uri = $this->plugin_data['PluginURI']; + else + return; + } + // wp_dump($this); + $update_checker = Puc_v4_Factory::buildUpdateChecker( + $this->update_repo_uri, + $this->plugin_file, + $this->slug() // using slug() + ); + + //Optional: If you're using a private repository, specify the access token like this: + if ( isset( $this->update_auth ) ) + $update_checker->setAuthentication( $this->update_auth ); + + //Optional: Set the branch that contains the stable release. + if ( isset( $this->update_branch ) ) + $update_checker->setBranch( $this->update_branch ); + + } + + /** + * upgrade_cb_wrapper + * + * This function only called if upgrade_cb is set (@see register_hooks()) + * This function called on upgrader_process_complete + * sanity-checks if our plugin was upgraded + * if so - calls upgrade_cb provided by our plugin + */ + public function upgrade_cb_wrapper( $upgrader_object, $options ) { + if( + $options['action'] == 'update' // has upgrade taken place + && + $options['type'] == 'plugin' // is it a plugin upgrade + && + ( + ( + isset( $options['plugins'] ) // is list of plugins upgraded + && + in_array( $this->plugin_basename(), $options['plugins']) // is our plugin in that list + ) + || + ( // single plugin updated + isset( $options['plugin'] ) + && + $this->plugin_basename() == $options['plugin'] + ) + ) + ) { + call_user_func( $this->upgrade_cb, $upgrader_object, $options ); + } + } + +} +endif; \ No newline at end of file diff --git a/vendor/abuyoyo/plugincore/README.md b/vendor/abuyoyo/plugincore/README.md new file mode 100644 index 0000000..3805b57 --- /dev/null +++ b/vendor/abuyoyo/plugincore/README.md @@ -0,0 +1,85 @@ +# WPHelper \ PluginCore + +> Helper class for registering plugins. + +Plugin Boilerplates and boilerplate generator are a hassle. The file structure they impose is way too cumbersome (and redundant) to push into every single plugin. WPHelper\PluginCore replaces boilerplates with one simple class (usually hidden away somewhere in your ``vendor/`` dir). + +[WPHelper\AdminMenuPage](https://github.com/abuyoyo/AdminMenuPage) can be used to register and generate admin menus if your plugin requires that. + +## Requirements +* PHP >= 7.4 +* [Composer](https://getcomposer.org/) +* [WordPress](https://wordpress.org) + +## Installation + +Install with [Composer](https://getcomposer.org/) or just drop PluginCore.php into your plugin folder and require it. + +```PHP +// Require the Composer autoloader anywhere in your code. +require __DIR__ . '/vendor/autoload.php'; + +``` + +OR + +```PHP +// Require the class file directly from your plugin. +require_once __DIR__ . 'PluginCore.php'; + +``` + + +WPHelper\PluginCore uses [PSR-4](https://www.php-fig.org/psr/psr-4/) to autoload. + +## Basic Usage + +WpHelper/PluginCore replaces the many plugin core skeleton generators out there. Just add these lines of code at the top of your plugin file and you're good to go. + +WpHelper/PluginCore will define %PLUGIN%_BASENAME, %PLUGIN%_PATH, %PLUGIN%_URL, %PLUGIN%_FILE constants available to your code. + +```PHP +/* + * Plugin Name: My Awesome Plugin + * Description: Plugin's description. + * Version: 1.0.0 + */ + +// Import PluginCore. +use WPHelper\PluginCore; + +// Register the plugin +$args = [ + 'title' => 'My Awesome Plugin', + 'slug' => 'my-awesome-plugin', + 'const' => 'MYPLUGIN' // Optional - slug used to define constants: MYPLUGIN_DIR, MYPLUGIN_URL etc. (if not provided will use 'slug' in ALLCAPS) + 'activate_cb' => 'activate_callback' // Optional - Provide a callable function to run on activation + 'deactivate_cb' => 'deactivate_callback' // Optional - Provide a callable function to run on deactivation + 'uninstall_cb' => 'uninstall_callback' // Optional - (@todo) Consider using uninstall.php and not this plugin. This plugin can run in the global scope and cause problems +]; + +// Setup plugin constants and activation/deactivation hooks +$my_plugin_core = new PluginCore( __FILE__, $args ); + +// Start writing your code here.. +``` + +### Constants + +WPHelper\PluginCore defines constants for use in your code. Where ``__FILE__`` is the filename provided to the class and ``%PLUGIN%`` is the ``'const_slug'`` provided. +Like so: + +```PHP +define( '%PLUGIN%_URL', plugin_dir_url( __FILE__ ) ); +define( '%PLUGIN%_FILE', __FILE__ ); +``` + +These are the constants defined by WPHelper\PluginCore. There are some redundancies to account for different conventions. + +* %PLUGIN%_PATH: ``plugin_dir_path( __FILE__ ) )`` +* %PLUGIN%_DIR: ``plugin_dir_path( __FILE__ ) )`` +* %PLUGIN%_URL: ``plugin_dir_url( __FILE__ ) )`` +* %PLUGIN%_URI: ``plugin_dir_url( __FILE__ ) )`` +* %PLUGIN%_BASENAME: ``plugin_basename( __FILE__ ) )`` +* %PLUGIN%_FILE: ``__FILE__`` +* %PLUGIN%_PLUGIN_FILE: ``__FILE__`` diff --git a/vendor/abuyoyo/plugincore/composer.json b/vendor/abuyoyo/plugincore/composer.json new file mode 100644 index 0000000..b9da83f --- /dev/null +++ b/vendor/abuyoyo/plugincore/composer.json @@ -0,0 +1,17 @@ +{ + "name": "abuyoyo/plugincore", + "description": "WordPress plugin core helper class", + "type": "library", + "version": "0.20", + "time": "2022-07-29", + "license": "BSD-3-Clause", + "require": { + "yahnis-elsts/plugin-update-checker": "~4.12", + "abuyoyo/adminmenupage": "~0.20" + }, + "autoload": { + "psr-4": { + "WPHelper\\" : "" + } + } +} \ No newline at end of file diff --git a/vendor/abuyoyo/screen-meta-links/.github/workflows/create-github-release.yml b/vendor/abuyoyo/screen-meta-links/.github/workflows/create-github-release.yml new file mode 100644 index 0000000..b61fa37 --- /dev/null +++ b/vendor/abuyoyo/screen-meta-links/.github/workflows/create-github-release.yml @@ -0,0 +1,38 @@ +# Create Github Release +# v1.0 +# Create Github release on tag push +# - Use tag name as release title +# - Use CHANGELOG.md log entry as body + +on: + push: + # Sequence of patterns matched against refs/tags + tags: + - '*' # Match any tag + +name: Create Release + +jobs: + build: + name: Create Release + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v2 + - name: Get Changelog Entry + id: changelog_reader + uses: mindsers/changelog-reader-action@v1.1.0 + with: + version: ${{ github.ref }} + path: ./CHANGELOG.md + - name: Create Release + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ github.ref }} + release_name: ${{ github.ref }} + body: ${{ steps.changelog_reader.outputs.log_entry }} # This pulls from the GET CHANGELOG ENTRY step above, referencing it's ID to get its outputs object, which include a `log_entry`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps + draft: false + prerelease: false \ No newline at end of file diff --git a/vendor/abuyoyo/screen-meta-links/.gitignore b/vendor/abuyoyo/screen-meta-links/.gitignore new file mode 100644 index 0000000..8911b7a --- /dev/null +++ b/vendor/abuyoyo/screen-meta-links/.gitignore @@ -0,0 +1,2 @@ +demo/* +demo/ diff --git a/vendor/abuyoyo/screen-meta-links/CHANGELOG.md b/vendor/abuyoyo/screen-meta-links/CHANGELOG.md new file mode 100644 index 0000000..9676cab --- /dev/null +++ b/vendor/abuyoyo/screen-meta-links/CHANGELOG.md @@ -0,0 +1,38 @@ +# Screen Meta Links + +API for adding custom `screen-meta-links` links and panels alongside the 'Screen Options' and 'Help' links on the WordPress admin page. + +## [0.11](https://github.com/abuyoyo/screen-meta-links/releases/tag/0.11) + +### Removed +- Drop support for `add_screen_meta_link`. This is a backward-incopatible change! + +### Added +- New API function `wph_add_screen_meta_panel` replaces `add_screen_meta_link`. + +### Changed +- Style is printed in inline style tag. + +### Fixed +- Fix conflict with other plugins importing `add_screen_meta_link` such as `broken-link-checker` (issue #1). + +## [0.10](https://github.com/abuyoyo/screen-meta-links/releases/tag/0.10) + +### Added +- Add `composer.json` file. Library can be imported as composer library. +- Add `CHANGELOG.md` file +- Github action - create release on push tag. + +## [0.9](https://github.com/abuyoyo/screen-meta-links/releases/tag/0.9) +- Initial release. +- Modified fork of Janis Elsts' library function `add_screen_meta_link`. + +### Added +- Library can be imported as WordPress plugin. +- Ability to insert panels to screen-meta-links. +- Inline (render-blocking) javascript adds meta-links panel and button\link at run-time. Before `screenMeta.init()` script in WordPress's `common.js`. Allowing for full integration. + + +### Changed +- Add optional `panel` parameter to function `add_screen_meta_link`. This is backward-compatible with Janis Elsts' function of the same name, and any plugins using the original function. +- Rewrite screen-meta-link registration process. Optimized for performance. diff --git a/vendor/abuyoyo/screen-meta-links/README.md b/vendor/abuyoyo/screen-meta-links/README.md new file mode 100644 index 0000000..abb549f --- /dev/null +++ b/vendor/abuyoyo/screen-meta-links/README.md @@ -0,0 +1,60 @@ +# Screen Meta Links API + +> Easily add screen-meta-links panels to WordPress admin pages + +## Description + +API for adding custom screen-meta-links alongside the "Screen Options" and "Help" links on WordPress admin pages. + +This library uses render-blocking javascript to get get around WordPress's lack of API for adding tabs to the screen-meta-links. + +## Installation + +### WordPress Plugin +Screen-Meta-Links API can be installed as a WordPress plugin by dropping this directory into the `plugins` directory and activating from the Plugins page. + +### Library +Screen-Meta-Links can also be used as library by using Composer + +```bash +composer install abuyoyo\screen-meta-links +``` + +## Compatibility with original Screen-Meta-Links classes + +- $page parameter accepts single string or array of strings. Either file string `index.php` or name `dashboard`. Use `*` to display panel on all pages. Empty string will disable panel on all pages. +- If only `$href` is provided without corresponding `$panel` - a simple link will be added. +- If both `$href` and `$panel` are provided - a button and panel are added. + +## Usage + +```php + +/** + * Add a new link to the screen meta area. + * + * This function can be called on current_screen hook (priority < 100) or earlier (admin_init is fine) + * Plugin begins heavy-lifting (filtering and processing) on current_screen priority 100 + * + * @param string $id - Link ID. Should be unique and a valid HTML ID attribute. + * @param string $text - Link text. The text appearing on the tab. + * @param string $href - Optional. Link URL to be used if no panel is provided + * Support for `add_screen_meta_link` original usage. + * @param string|string[] $page - The page(s) where you want to add the link. + * @param array $attributes - Optional. Additional attributes for the link tag. + * Add 'aria-controls' => "{$id}-wrap" to toggle panel + * @param callback $panel - Optional. Callback should echo screen-meta panel HTML content. + * + * @return void + */ +wph_add_screen_meta_panel( $id, $text, $href, $page, $attributes, $panel ); + +``` + +### The `$page` Parameter + +The `$page` parameter accepts a string or array of strings. +Accepts `page`, `post`, `dashboard` etc. +Or actual file name: `post.php`, `index.php` etc. (`index.php` and `dashboard` will resolve to the same page). +Accepts custom page id's: `toplevel_page_my-plugin` etc. +Accepts wildcard: `*` - This will add the meta-screen-panel to all admin pages. diff --git a/vendor/abuyoyo/screen-meta-links/composer.json b/vendor/abuyoyo/screen-meta-links/composer.json new file mode 100644 index 0000000..cc2d5a8 --- /dev/null +++ b/vendor/abuyoyo/screen-meta-links/composer.json @@ -0,0 +1,8 @@ +{ + "name": "abuyoyo/screen-meta-links", + "description": "API for adding custom screen-meta-links alongside the 'Screen Options' and 'Help' links.", + "type": "library", + "autoload": { + "files": ["screen-meta-links.php"] + } +} \ No newline at end of file diff --git a/vendor/abuyoyo/screen-meta-links/css/screen_meta_links.css b/vendor/abuyoyo/screen-meta-links/css/screen_meta_links.css new file mode 100644 index 0000000..ff25966 --- /dev/null +++ b/vendor/abuyoyo/screen-meta-links/css/screen_meta_links.css @@ -0,0 +1,16 @@ +.custom-screen-meta-link-wrap { + float: right; + height: 28px; + margin: 0 0 0 6px; + border: 1px solid #ddd; + border-top: none; + background: #fff; + box-shadow: 0 1px 1px -1px rgba(0,0,0,.1); + +} + + +.site-health #screen-meta{ + margin: 0; +} + diff --git a/vendor/abuyoyo/screen-meta-links/js/screen-meta-links.js b/vendor/abuyoyo/screen-meta-links/js/screen-meta-links.js new file mode 100644 index 0000000..6ab6888 --- /dev/null +++ b/vendor/abuyoyo/screen-meta-links/js/screen-meta-links.js @@ -0,0 +1,51 @@ + + +(function($, links, panels){ + 'use strict' + + $(document).on('ready', function(){ + var container = $('#screen-meta-links'); + var container_panels = $('#screen-meta'); + var linkTag; //if we have a panel it's a button - otherwise it's a link anchor + debugger; + if (!container.length){ + container = $('
') + .attr({ + 'id' : 'screen-meta-links' + }); + container.insertAfter('#screen-meta'); + } + + $.each( links, function( i, element ) { + + if (panels[i]){ + container_panels.append( + $('
') + .attr({ + 'id' : element.id + '-wrap', + 'class' : 'hidden', + 'tabindex' : '-1', + 'aria-label' : element.text + ' Tab' + }) + .html(panels[i]) + ); + + linkTag = '