Compare commits
88 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
00ab82a35d | ||
|
|
51cfce0071 | ||
|
|
416039449f | ||
|
|
e548158c15 | ||
|
|
41a42d3a2a | ||
|
|
b6aca366b2 | ||
|
|
7cc5b6de5a | ||
|
|
ca68f59a28 | ||
|
|
a3040b6c47 | ||
|
|
b99be56795 | ||
|
|
3458b724be | ||
|
|
57fb24aa22 | ||
|
|
42db8f67df | ||
|
|
1cd273bded | ||
|
|
2c166a33a8 | ||
|
|
1321d35bdf | ||
|
|
7cf7b477bc | ||
|
|
42e26c9a4f | ||
|
|
920dd0b683 | ||
|
|
fa4099a6dd | ||
|
|
2efc23c123 | ||
|
|
03473b957c | ||
|
|
ff4a8f542b | ||
|
|
93afbe9b5b | ||
|
|
bbec303755 | ||
|
|
24d4e54ca8 | ||
|
|
c0ca10a9c0 | ||
|
|
0f13626dab | ||
|
|
320496722d | ||
|
|
a856f85cb8 | ||
|
|
fcee298dab | ||
|
|
abedf94f24 | ||
|
|
873b9abdd0 | ||
|
|
20eda54314 | ||
|
|
e9a5f8f71e | ||
|
|
1d060b9a22 | ||
|
|
9d574615e8 | ||
|
|
4229406ec8 | ||
|
|
acf477a0c0 | ||
|
|
2bdd4b24b7 | ||
|
|
bc1a864dd1 | ||
|
|
bffd39afe5 | ||
|
|
1cbb0a5aea | ||
|
|
72684cf182 | ||
|
|
10b24ea86f | ||
|
|
d083cd3032 | ||
|
|
476d140f3f | ||
|
|
4810fe9400 | ||
|
|
e42a6561a6 | ||
|
|
0484250f45 | ||
|
|
ae634c10b1 | ||
|
|
650fd54176 | ||
|
|
5035df9615 | ||
|
|
c72d8b3882 | ||
|
|
d3e004a53e | ||
|
|
1980a2c749 | ||
|
|
03dfe6c442 | ||
|
|
4ce87fe808 | ||
|
|
95dac048fa | ||
|
|
ff37df4180 | ||
|
|
cecbea8148 | ||
|
|
330fdd2430 | ||
|
|
1355d280ea | ||
|
|
e1f113ba7d | ||
|
|
dfe9bdb23e | ||
|
|
55dbd0d1bf | ||
|
|
6a96430da9 | ||
|
|
242dcdee2b | ||
|
|
4ab77a5a45 | ||
|
|
f01cdbf2b0 | ||
|
|
1d813a48c9 | ||
|
|
a7c43b60a4 | ||
|
|
f51ad078c6 | ||
|
|
8bab6cc126 | ||
|
|
23f2241dda | ||
|
|
36a79a5f5e | ||
|
|
296051fac1 | ||
|
|
28ac8f941b | ||
|
|
eabafb460f | ||
|
|
d48631c4f6 | ||
|
|
2362cb37df | ||
|
|
a2c3e60f87 | ||
|
|
57c54c756a | ||
|
|
ba26708c9f | ||
|
|
51a493926b | ||
|
|
5c5788c87d | ||
|
|
770b2cc43d | ||
|
|
1d343e7dee |
2
.gitignore
vendored
2
.gitignore
vendored
@ -1 +1 @@
|
||||
vendor/
|
||||
node_modules/
|
||||
110
CHANGELOG.md
110
CHANGELOG.md
@ -1,5 +1,115 @@
|
||||
# Notice Manager Changelog
|
||||
|
||||
## 0.27
|
||||
|
||||
Release date: Sep 7 2024
|
||||
|
||||
### Dependencies
|
||||
- Composer config: `prepend-autoloader: false` - Give precedence to other composer installations if present.
|
||||
|
||||
## 0.26
|
||||
|
||||
Release date: Sep 1 2024
|
||||
|
||||
### Changed
|
||||
- Use Mutation Observer instead of deprecated `DOMNodeRemoved` event.
|
||||
|
||||
### Added
|
||||
- Add method `NoticeManager.bootstrap()` to initialize Notice manager.
|
||||
|
||||
## 0.25
|
||||
|
||||
Release date: Feb 18 2024
|
||||
|
||||
### Fixed
|
||||
- Fix fatal error `Class "WPHelper\MetaBox" not found` due to dependency `abuyoyo/adminmenupage` < 0.29 not requiring dependency `abuyoyo/metabox`.
|
||||
|
||||
### Dependencies
|
||||
- Library WPHelper\AdminPage (`abuyoyo/adminmenupage`) updated to 0.29. Requires `abuyoyo/metabox`.
|
||||
|
||||
## 0.24
|
||||
|
||||
Release date: Oct 4 2023
|
||||
|
||||
### Fixed
|
||||
- Set `WPHelper\PluginCore` option `update_checker` to true. If library Plugin-Update-Checker is installed, allows updates from repo.
|
||||
|
||||
### Dependencies
|
||||
- Library WPHelper\PluginCore (`abuyoyo/plugincore`) updated to 0.27. Supports both Plugin-Update-Checker v5 and v4.
|
||||
|
||||
## 0.23
|
||||
|
||||
### Fixed
|
||||
- Fix `.plugin-count` bullet styling issue.
|
||||
- Fix 0-count panel caused by collecting `.hidden` notices.
|
||||
- Fix wrong priority color `.plugin-count` bullet caused by collecting `.hidden` notices.
|
||||
- Fix empty notices-panel removing all screen-meta-link panels.
|
||||
|
||||
## 0.22
|
||||
|
||||
### Fixed
|
||||
- Do not collect `.theme-info` notices.
|
||||
- Fix `vendor/autoload` include path.
|
||||
|
||||
## 0.21
|
||||
|
||||
### Fixed
|
||||
- Fix PHP 8.2 deprecated optional parameter before required parameter. Fixed upstream in `abuyoyo/screen-meta-links ~0.13`.
|
||||
|
||||
### Dependencies
|
||||
- Update library `abuyoyo/screen-meta-links` to version 0.13.
|
||||
|
||||
## 0.20
|
||||
|
||||
### Minor
|
||||
- Just another version bump (composer.json as well).
|
||||
|
||||
## 0.19
|
||||
|
||||
### Added
|
||||
- Add 'Distraction Free' option.
|
||||
|
||||
## 0.18
|
||||
|
||||
### Minor
|
||||
- Version bump everywhere.
|
||||
|
||||
## 0.17
|
||||
|
||||
### Removed
|
||||
- Remove plugin update checker.
|
||||
- Remove 3rd party libraries.
|
||||
|
||||
## 0.16
|
||||
|
||||
### Added
|
||||
- Add plugin action link to Notice Manager settings page.
|
||||
|
||||
## 0.15
|
||||
|
||||
### Added
|
||||
- Add BSD 3-Clause License file.
|
||||
- Add `vendor` directory and require `vendor/autoload.php`.
|
||||
- Add `Update URI` header to plugin to avoid conflict with wp.org repo plugin of the same name.
|
||||
|
||||
### Changed
|
||||
- Convert stylesheet to SCSS and use `node-sass` to render css file.
|
||||
- Better option descriptions on settings page.
|
||||
- Readme file - add detailed plugin description.
|
||||
- Support `.notice-error` class.
|
||||
- Do not count hidden notices in `.plugin-count` bullet.
|
||||
|
||||
## 0.14
|
||||
|
||||
### Added
|
||||
- Added `above_title` setting - move all scripts above title.
|
||||
- Added `.plugin_count` bullet to panel tab - showing number of notices in panel and priority.
|
||||
|
||||
### Changed
|
||||
- Improve "jumpy" notices when page is loaded with certain setting combinations by selectively setting css `display: none` to notices not in their expected location.
|
||||
- Improve integration between different options (eg. `above_title` with `auto-collect`).
|
||||
- Option `auto-collapse` will not automatically collapse panel if an error notice is showing.
|
||||
|
||||
## 0.13
|
||||
|
||||
### Changed
|
||||
|
||||
29
LICENSE
Normal file
29
LICENSE
Normal file
@ -0,0 +1,29 @@
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2022, 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.
|
||||
31
README.md
31
README.md
@ -1,3 +1,32 @@
|
||||
# Notice Manager
|
||||
|
||||
Manage notices on WordPress admin pages. Adds 'Notices' screen-meta-link.
|
||||
Collect WordPress admin notices into 'Notices' panel.
|
||||
Notice Manager adds a 'Notices' panel alongside the 'Help' and 'Screen Option' collapsible panels. Notices are collected into the fold-out panel at the top of the page - making for a smoother and more accessible experience.
|
||||
|
||||
## Activation
|
||||
|
||||
Upon plugin activation, Notice Manager adds a setting page **Settings > Notice Manager** with various options. All options need to be enabled manually from that page.
|
||||
|
||||
## About
|
||||
|
||||
Notice Manager attempts to address some of the issues with WordPress's current notices implementation - the `admin_notices` hook system and accompanying scripts (I'm looking at you `common.js`!)
|
||||
|
||||
Notice Manager addresses the following issues:
|
||||
- WordPress core's `common.js` script moves some of the notices below the title, while leaving other notices above the title (eg. `update-nag`). This is confusing and non-accessible. Notice Manager moves all notices together - either above the title or into the 'Notices' panel.
|
||||
- WordPress core moves notices after they've already been printed on the page, Creating a jumpy experience. This is only partially addressed by Notice Manager as `common.js` functionality cannot be overridden/disabled currently. Notice Manager is less jumpy as it hides notices before they are in their final position.
|
||||
- Opinionated: Notices should not appear below the title. Oftentimes the notices on a page are not related directly to the page being viewed. Having the title and the content uninterrupted by notices is arguably more accessible and makes for a smoother user experience.
|
||||
|
||||
### Minimalist Ethic
|
||||
|
||||
Notice Manager represents a minimalist approach to the issues and does not preclude other solutions being developed currently.
|
||||
- Notice Manager does not invent any new UI on WordPress's admin side. It bootstraps WordPress's already existing and familiar `screen-meta-links` collapsing panels (The 'Help' and 'Screen Options' panels). More on that below.
|
||||
- Notice Manager does not affect how plugins interact with WordPress core notice system. Notice Manager simply collects notices already printed to the page. It supports all plugins using the current `admin_notices` hook(s).
|
||||
- Notice Manager does not change notices appearance. It simply moves them around in much the same way core's `common.js` does.
|
||||
- Notice Manager works with what exists now.
|
||||
- Notice Manager preserves backward compatibility.
|
||||
|
||||
### Screen Meta Links
|
||||
|
||||
WordPress does not currently allow plugin authors a way to add panels and content to the `screen-meta-links` - apart from interacting with the hardcoded Screen Meta 'Help' and 'Screen Options' panels.
|
||||
|
||||
Notice Manager uses a library (`abuyoyo/screen-meta-links`) that employs render-blocking JavaScript and PHP to generate new panels on page load. This could be developed as its own separate feature using PHP only and a hook system - to allow plugin authors to interface and add their own panels to WordPress's Screen Meta panels. However that is beyond the scope of this plugin.
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
"name": "abuyoyo/notice-manager",
|
||||
"description": "Manage notices on WordPress admin pages. Adds 'Notices' screen-meta-link.",
|
||||
"type": "wordpress-plugin",
|
||||
"version": "0.27",
|
||||
"repositories": [
|
||||
{
|
||||
"type": "vcs",
|
||||
@ -9,7 +10,11 @@
|
||||
}
|
||||
],
|
||||
"require":{
|
||||
"abuyoyo/screen-meta-links": "~0.11",
|
||||
"abuyoyo/plugincore": "~0.14"
|
||||
"abuyoyo/screen-meta-links": "~0.13",
|
||||
"abuyoyo/plugincore": "~0.27",
|
||||
"abuyoyo/adminmenupage": "~0.29"
|
||||
},
|
||||
"config": {
|
||||
"prepend-autoloader": false
|
||||
}
|
||||
}
|
||||
153
composer.lock
generated
Normal file
153
composer.lock
generated
Normal file
@ -0,0 +1,153 @@
|
||||
{
|
||||
"_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": "b1a74cf1316f5dd317f70efeb60d9f4d",
|
||||
"packages": [
|
||||
{
|
||||
"name": "abuyoyo/adminmenupage",
|
||||
"version": "0.29",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/abuyoyo/AdminMenuPage.git",
|
||||
"reference": "4cd47d5217ca25ed17af76f5fdbab3cab3b37ef8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/abuyoyo/AdminMenuPage/zipball/4cd47d5217ca25ed17af76f5fdbab3cab3b37ef8",
|
||||
"reference": "4cd47d5217ca25ed17af76f5fdbab3cab3b37ef8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"abuyoyo/metabox": "~0.8"
|
||||
},
|
||||
"suggest": {
|
||||
"abuyoyo/plugincore": "~0.26",
|
||||
"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.29"
|
||||
},
|
||||
"time": "2023-10-05T00:00:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "abuyoyo/metabox",
|
||||
"version": "0.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/abuyoyo/MetaBox.git",
|
||||
"reference": "98cb4c30db4c366c0d273985eb9c31ffa1cd78f9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/abuyoyo/MetaBox/zipball/98cb4c30db4c366c0d273985eb9c31ffa1cd78f9",
|
||||
"reference": "98cb4c30db4c366c0d273985eb9c31ffa1cd78f9",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"WPHelper\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"description": "WordPress metabox helper class",
|
||||
"support": {
|
||||
"issues": "https://github.com/abuyoyo/MetaBox/issues",
|
||||
"source": "https://github.com/abuyoyo/MetaBox/tree/0.8"
|
||||
},
|
||||
"time": "2023-07-18T19:14:03+00:00"
|
||||
},
|
||||
{
|
||||
"name": "abuyoyo/plugincore",
|
||||
"version": "0.27",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/abuyoyo/PluginCore.git",
|
||||
"reference": "d730a674cbe2dc92e60ace8e25a2e0e3fdeee3e6"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/abuyoyo/PluginCore/zipball/d730a674cbe2dc92e60ace8e25a2e0e3fdeee3e6",
|
||||
"reference": "d730a674cbe2dc92e60ace8e25a2e0e3fdeee3e6",
|
||||
"shasum": ""
|
||||
},
|
||||
"suggest": {
|
||||
"abuyoyo/adminmenupage": "~0.27",
|
||||
"yahnis-elsts/plugin-update-checker": "~5.2"
|
||||
},
|
||||
"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.27"
|
||||
},
|
||||
"time": "2022-10-03T00:00:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "abuyoyo/screen-meta-links",
|
||||
"version": "0.13",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/abuyoyo/screen-meta-links.git",
|
||||
"reference": "b324cef9eb5825d04ffa17f771237b7deca5cd01"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/abuyoyo/screen-meta-links/zipball/b324cef9eb5825d04ffa17f771237b7deca5cd01",
|
||||
"reference": "b324cef9eb5825d04ffa17f771237b7deca5cd01",
|
||||
"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.13",
|
||||
"issues": "https://github.com/abuyoyo/screen-meta-links/issues"
|
||||
},
|
||||
"time": "2023-08-08T22:37:03+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [],
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": [],
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": true,
|
||||
"platform": [],
|
||||
"platform-dev": [],
|
||||
"plugin-api-version": "2.3.0"
|
||||
}
|
||||
@ -1,60 +0,0 @@
|
||||
:not(.wrap) ~ div.updated,
|
||||
:not(.wrap) ~ div.error,
|
||||
:not(.wrap) ~ div.notice,
|
||||
:not(.wrap) ~ div.update-nag{
|
||||
margin: 5px 20px 15px 2px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#meta-link-notices-wrap {
|
||||
margin: 0;
|
||||
/* padding: 8px 20px 12px; */
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#meta-link-notices-wrap > button.notice-dismiss {
|
||||
position: relative;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.notice_container{
|
||||
padding: 9px 0px 1px 0px;
|
||||
background-color: gainsboro;
|
||||
}
|
||||
|
||||
.notice_container.empty{
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.notice_container > div.updated,
|
||||
.notice_container > div.error,
|
||||
.notice_container > div.notice,
|
||||
.notice_container > div.update-nag{
|
||||
margin: 5px 12px 15px 12px;
|
||||
}
|
||||
|
||||
|
||||
/* ngfb update-nag override */
|
||||
div.ngfb-notice.update-nag {
|
||||
display: none !important; /* not working - need to remove with js */
|
||||
/* restore normal formatting */
|
||||
/* margin-top: 25px; */
|
||||
border: 0px;
|
||||
/* border-left: 4px solid #ffba00; */
|
||||
border-left: 4px solid #00a0d2;
|
||||
}
|
||||
|
||||
.ngfb-notice.update-nag .notice-message {
|
||||
max-width: 100%;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.ngfb-notice.update-nag p, .ngfb-notice.update-nag ul, .ngfb-notice.update-nag ol {
|
||||
text-align: left !important;
|
||||
font-size: 13px !important;
|
||||
line-height: 1.5;
|
||||
margin: 1em 0 !important;
|
||||
opacity: 0.5;
|
||||
}
|
||||
59
css/notice-manager.css
Normal file
59
css/notice-manager.css
Normal file
@ -0,0 +1,59 @@
|
||||
:not(.wrap) ~ div.notice, :not(.wrap) ~ div.updated,
|
||||
:not(.wrap) ~ div.error,
|
||||
:not(.wrap) ~ div.notice-error,
|
||||
:not(.wrap) ~ div.update-nag {
|
||||
margin: 5px 20px 15px 2px; }
|
||||
|
||||
.notices-auto-collect #wpbody-content > div.notice, .notices-auto-collect #wpbody-content > div.updated,
|
||||
.notices-auto-collect #wpbody-content > div.error,
|
||||
.notices-auto-collect #wpbody-content > div.notice-error,
|
||||
.notices-auto-collect #wpbody-content > div.update-nag,
|
||||
.notices-auto-collect .wrap > div.notice,
|
||||
.notices-auto-collect .wrap > div.updated,
|
||||
.notices-auto-collect .wrap > div.error,
|
||||
.notices-auto-collect .wrap > div.notice-error,
|
||||
.notices-auto-collect .wrap > div.update-nag,
|
||||
.notices-above-title .wrap > div.notice,
|
||||
.notices-above-title .wrap > div.updated,
|
||||
.notices-above-title .wrap > div.error,
|
||||
.notices-above-title .wrap > div.notice-error,
|
||||
.notices-above-title .wrap > div.update-nag {
|
||||
display: none; }
|
||||
|
||||
#meta-link-notices-wrap {
|
||||
margin: 0;
|
||||
position: relative; }
|
||||
#meta-link-notices-wrap > button.notice-dismiss {
|
||||
position: relative;
|
||||
display: flex;
|
||||
width: 100%; }
|
||||
|
||||
.notice_container {
|
||||
padding: 9px 0px 1px 0px;
|
||||
background-color: gainsboro; }
|
||||
.notice_container.empty {
|
||||
padding: 0; }
|
||||
.notice_container > div.notice, .notice_container > div.updated,
|
||||
.notice_container > div.error,
|
||||
.notice_container > div.notice-error,
|
||||
.notice_container > div.update-nag {
|
||||
margin: 5px 12px 15px 12px !important; }
|
||||
|
||||
#meta-link-notices .plugin-count {
|
||||
display: inline-block;
|
||||
box-sizing: border-box;
|
||||
margin: 1px 0 -1px 2px;
|
||||
padding: 0 5px;
|
||||
min-width: 18px;
|
||||
height: 18px;
|
||||
border-radius: 9px;
|
||||
background-color: #72aee6;
|
||||
color: #fff;
|
||||
font-size: 11px;
|
||||
line-height: 1.6;
|
||||
text-align: center;
|
||||
z-index: 26; }
|
||||
#meta-link-notices .plugin-count.warning {
|
||||
background-color: #dba617; }
|
||||
#meta-link-notices .plugin-count.error {
|
||||
background-color: #d63638; }
|
||||
@ -2,147 +2,232 @@
|
||||
* NoticeManager class/module
|
||||
*
|
||||
*/
|
||||
var NoticeManager = (function ($, document) {
|
||||
let options = window.notice_manager_options;
|
||||
const NoticeManager = function ($) {
|
||||
|
||||
const selectors_notice = [
|
||||
"div.notice",
|
||||
"div.updated",
|
||||
]
|
||||
|
||||
const selectors_warning = [
|
||||
"div.notice-warning",
|
||||
"div.update-nag",
|
||||
]
|
||||
|
||||
const selectors_error = [
|
||||
"div.error",
|
||||
"div.notice-error",
|
||||
]
|
||||
|
||||
const selectors_all = selectors_notice.concat(selectors_warning, selectors_error)
|
||||
|
||||
const selectors_skip = [
|
||||
".inline",
|
||||
".below-h2",
|
||||
".theme-info .notice",
|
||||
".hidden",
|
||||
]
|
||||
|
||||
// wait function used with autoCollapse
|
||||
let wait = function (ms) {
|
||||
var dfd = $.Deferred();
|
||||
setTimeout(dfd.resolve, ms); //callback, timeout till callback
|
||||
return dfd.promise();
|
||||
};
|
||||
const wait = function (ms) {
|
||||
var dfd = $.Deferred()
|
||||
setTimeout(dfd.resolve, ms) //callback, timeout till callback
|
||||
return dfd.promise()
|
||||
}
|
||||
|
||||
let notices;
|
||||
const options = window.notice_manager_options
|
||||
|
||||
let button;
|
||||
let panel;
|
||||
let haveClosed;
|
||||
let dismissNoticesButton;
|
||||
let notices
|
||||
|
||||
// bootstrap
|
||||
// some of these need to run BEFORE document.ready - don't know why really
|
||||
button = $("#meta-link-notices");
|
||||
panel = $("#meta-link-notices-wrap");
|
||||
haveClosed = false;
|
||||
dismissNoticesButton = $("#meta-link-notices-wrap button.notice-dismiss");
|
||||
let button
|
||||
let panel
|
||||
let dismissNoticesButton
|
||||
|
||||
dismissNoticesButton.on("click", () => {
|
||||
screenMeta.close(panel, button);
|
||||
NoticeManager.collectNotices();
|
||||
});
|
||||
|
||||
//original wp focus on click function
|
||||
button.on("focus.scroll-into-view", (e) => {
|
||||
if (e.target.scrollIntoView) e.target.scrollIntoView(false);
|
||||
});
|
||||
|
||||
// scroll page to top when closing notice panel
|
||||
// cannot convert to arrow function - uses this
|
||||
// could use event.target instead
|
||||
button.on("click", function () {
|
||||
haveClosed = true;
|
||||
if ($(this).hasClass("screen-meta-active")) {
|
||||
// $(window).scrollTop(true);
|
||||
} else {
|
||||
// wait (500).then(function(){ //still jumpy sometimes - but scrolls to correct position 400 ~ 600
|
||||
// $(window).scrollTop(true);
|
||||
// });
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* document.on.ready
|
||||
*/
|
||||
$(() => {
|
||||
|
||||
console.log("NoticeManager.on.ready");
|
||||
console.log("options");
|
||||
console.log(options);
|
||||
|
||||
// bootstrap notices
|
||||
// get all notices that are not explicily marked as `.inline` or `.below-h2`
|
||||
// we add .update-nag.inline for WordPress Update notice
|
||||
notices = $("div.updated, div.error, div.notice")
|
||||
.not(".inline, .below-h2")
|
||||
.add("div.update-nag");
|
||||
|
||||
/**
|
||||
* Remove panel if there are no notices on this page
|
||||
*/
|
||||
NoticeManager.maybeRemoveNoticesPanel();
|
||||
|
||||
if (options.auto_collect) {
|
||||
NoticeManager.collectNotices();
|
||||
} else {
|
||||
/**
|
||||
* Move ALL notices above page title.
|
||||
* Default no-panel action - override WordPress moving notices BELOW title.
|
||||
* I HATE it when WordPress moves notices below title.
|
||||
*
|
||||
* comment this line out to completely restore WordPress functionality when auto_collect is off
|
||||
*/
|
||||
notices.insertBefore(".wrap:first");
|
||||
}
|
||||
|
||||
/**
|
||||
* auto-open notices panel
|
||||
*/
|
||||
if (button.length) {
|
||||
panel.toggle();
|
||||
button.addClass("screen-meta-active");
|
||||
screenMeta.open(panel, button);
|
||||
}
|
||||
|
||||
/**
|
||||
* auto-close notices panel after short delay
|
||||
* only auto-close if we have not interacted (opened/closed) with panel previously
|
||||
*/
|
||||
if (options.auto_collapse) {
|
||||
wait(4000).then(() => {
|
||||
if (!haveClosed) {
|
||||
screenMeta.close(panel, button);
|
||||
}
|
||||
});
|
||||
}
|
||||
}); // end document.on.ready
|
||||
|
||||
// prevent jumpy scrollRestoration on reload page
|
||||
// fixed below on 'beforeunload'
|
||||
// if (history.scrollRestoration) {
|
||||
// history.scrollRestoration = 'manual';
|
||||
//}
|
||||
/**
|
||||
* Set history.scrollTop to prevent jump on page refresh when scrollRestoration = auto
|
||||
*/
|
||||
$(window).on("beforeunload", () => {
|
||||
history.pushState(
|
||||
{ scrollTop: document.body.scrollTop },
|
||||
document.title,
|
||||
document.location.pathname
|
||||
);
|
||||
});
|
||||
let haveClosed // set to true on first close/collect
|
||||
let panelObserver
|
||||
|
||||
return {
|
||||
bootstrap: () => {
|
||||
|
||||
// Init selectors
|
||||
button = $("#meta-link-notices")
|
||||
panel = $("#meta-link-notices-wrap")
|
||||
dismissNoticesButton = $("#meta-link-notices-wrap button.notice-dismiss")
|
||||
|
||||
// bootstrap notices
|
||||
// get all notices that are not explicitly marked as `.inline` or `.below-h2`
|
||||
// we add .update-nag.inline for WordPress Update notice
|
||||
notices = $(selectors_all.join(', '))
|
||||
.not(selectors_skip.join(', '))
|
||||
.add("div.update-nag")
|
||||
|
||||
// Set state
|
||||
haveClosed = false
|
||||
|
||||
dismissNoticesButton.on("click", () => {
|
||||
screenMeta.close(panel, button)
|
||||
if (!haveClosed) {
|
||||
NoticeManager.collectNotices()
|
||||
}
|
||||
NoticeManager.addCounter()
|
||||
})
|
||||
|
||||
//original wp focus on click function
|
||||
button.on("focus.scroll-into-view", (e) => {
|
||||
if (e.target.scrollIntoView) e.target.scrollIntoView(false)
|
||||
})
|
||||
|
||||
// scroll page to top when closing notice panel
|
||||
// function used to work with $(this)
|
||||
// using e.target instead
|
||||
// not sure if this should perhaps be e.currentTarget
|
||||
button.on("click", (e) => {
|
||||
if ($(e.target).hasClass("screen-meta-active")) {
|
||||
if (haveClosed) {
|
||||
NoticeManager.addCounter()
|
||||
}
|
||||
|
||||
// $(window).scrollTop(true)
|
||||
} else {
|
||||
NoticeManager.removeCounter()
|
||||
|
||||
// wait (500).then(function(){ //still jumpy sometimes - but scrolls to correct position 400 ~ 600
|
||||
// $(window).scrollTop(true)
|
||||
// })
|
||||
}
|
||||
})
|
||||
|
||||
// prevent jumpy scrollRestoration on reload page
|
||||
// fixed below on 'beforeunload'
|
||||
// if (history.scrollRestoration) {
|
||||
// history.scrollRestoration = 'manual'
|
||||
//}
|
||||
/**
|
||||
* Set history.scrollTop to prevent jump on page refresh when scrollRestoration = auto
|
||||
*/
|
||||
$(window).on('beforeunload', () => history.pushState(
|
||||
{ scrollTop: document.body.scrollTop },
|
||||
document.title,
|
||||
document.location.pathname
|
||||
)
|
||||
)
|
||||
|
||||
/**
|
||||
* Remove panel if there are no notices on this page
|
||||
*/
|
||||
if (options.screen_panel) {
|
||||
NoticeManager.maybeRemoveNoticesPanel()
|
||||
}
|
||||
|
||||
if (options.screen_panel && options.auto_collect) {
|
||||
NoticeManager.collectNotices()
|
||||
} else {
|
||||
if (options.above_title) {
|
||||
NoticeManager.moveAboveTitle()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* auto-open notices panel
|
||||
*/
|
||||
if (button.length && !options.distraction_free) {
|
||||
panel.toggle()
|
||||
button.addClass("screen-meta-active")
|
||||
screenMeta.open(panel, button)
|
||||
}
|
||||
|
||||
/**
|
||||
* auto-close notices panel after short delay
|
||||
* only auto-close if we have collected notices previously
|
||||
* only auto-close if no error messages
|
||||
*/
|
||||
if (options.auto_collapse && !options.distraction_free) {
|
||||
wait(4000).then(() => {
|
||||
if (haveClosed && NoticeManager.getNoticesTopPriority() != 'error') {
|
||||
screenMeta.close(panel, button)
|
||||
NoticeManager.addCounter()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (options.distraction_free) {
|
||||
NoticeManager.addCounterWhenClosed()
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
getNotices: () => notices,
|
||||
|
||||
getNoticesTopPriority: () => {
|
||||
if (notices.filter(":visible").filter(selectors_error.join(", ")).length)
|
||||
return 'error'
|
||||
if (notices.filter(":visible").filter(selectors_warning.join(", ")).length)
|
||||
return 'warning'
|
||||
return 'info'
|
||||
},
|
||||
|
||||
/**
|
||||
* .filter(":visible") unreliable when closed
|
||||
*
|
||||
* @returns {string} top priority
|
||||
*/
|
||||
getNoticesTopPriorityWhenClosed: () => {
|
||||
if (notices.filter(selectors_error.join(", ")).length)
|
||||
return 'error'
|
||||
if (notices.filter(selectors_warning.join(", ")).length)
|
||||
return 'warning'
|
||||
return 'info'
|
||||
},
|
||||
|
||||
/**
|
||||
* Collect notices into panel.
|
||||
* Remove dismiss-notices button.
|
||||
*/
|
||||
collectNotices: () => {
|
||||
notices.appendTo(".notice_container").eq(0);
|
||||
$(".notice_container").removeClass("empty"); // .empty removes padding
|
||||
notices.appendTo(".notice_container").eq(0)
|
||||
$(".notice_container").removeClass("empty") // .empty removes padding
|
||||
|
||||
haveClosed = true // initial collection has occurred.
|
||||
|
||||
/**
|
||||
* When dismissible notices are dismissed, check if any notices are left on page.
|
||||
* If no notices are left - remove Notice Panel entirely
|
||||
*/
|
||||
$(document).on("DOMNodeRemoved", ".notice.is-dismissible", (e) => {
|
||||
panelObserver = new MutationObserver(() => {
|
||||
notices = panel
|
||||
.find("div.updated, div.error, div.notice, div.update-nag")
|
||||
.filter(":visible");
|
||||
NoticeManager.maybeRemoveNoticesPanel();
|
||||
.find(selectors_all.join(", "))
|
||||
.filter(":visible")
|
||||
NoticeManager.maybeRemoveNoticesPanel()
|
||||
});
|
||||
panelObserver.observe(panel.get(0), { childList: true, subtree: true }); // only run once
|
||||
|
||||
},
|
||||
|
||||
addCounter: () => {
|
||||
if (!button.children('.plugin-count').length) {
|
||||
button.append(
|
||||
$("<span/>").text(notices.filter(":visible").length).attr({
|
||||
class: "plugin-count",
|
||||
}).addClass(NoticeManager.getNoticesTopPriority())
|
||||
)
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* cannot rely on filter(:visible)
|
||||
*/
|
||||
addCounterWhenClosed: () => {
|
||||
if (!button.children('.plugin-count').length) {
|
||||
button.append(
|
||||
$("<span/>").text(notices.length).attr({
|
||||
class: "plugin-count",
|
||||
}).addClass(NoticeManager.getNoticesTopPriorityWhenClosed())
|
||||
)
|
||||
}
|
||||
},
|
||||
|
||||
removeCounter: () => {
|
||||
button.children(".plugin-count").remove()
|
||||
},
|
||||
|
||||
/**
|
||||
@ -151,14 +236,26 @@ var NoticeManager = (function ($, document) {
|
||||
*/
|
||||
maybeRemoveNoticesPanel: () => {
|
||||
if (!notices.length) {
|
||||
screenMeta.close(panel, button);
|
||||
screenMeta.close(panel, button)
|
||||
|
||||
$("#meta-link-notices-link-wrap").detach();
|
||||
$("#meta-link-notices-wrap").detach();
|
||||
$("#meta-link-notices-link-wrap").detach()
|
||||
$("#meta-link-notices-wrap").detach()
|
||||
|
||||
if (!$("#screen-meta-links").children().length)
|
||||
$("#screen-meta-links").detach();
|
||||
if ($("#screen-meta-links").children().length == 0) {
|
||||
$("#screen-meta-links").detach()
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
}(jQuery,document) )
|
||||
|
||||
/**
|
||||
* Move ALL notices above page title.
|
||||
* Default no-panel action - override WordPress moving notices BELOW title.
|
||||
* I HATE it when WordPress moves notices below title.
|
||||
*/
|
||||
moveAboveTitle: () => {
|
||||
notices.insertBefore(".wrap:first")
|
||||
},
|
||||
}
|
||||
}(jQuery);
|
||||
|
||||
jQuery(NoticeManager.bootstrap);
|
||||
@ -1,64 +1,98 @@
|
||||
<?php
|
||||
/**
|
||||
* Plugin Name: Notice Manager
|
||||
* Description: Manage notices on WordPress admin pages. Adds 'Notices' screen-meta-link.
|
||||
* Version: 0.13
|
||||
* Description: Manage notices on WordPress admin pages. Adds 'Notices' screen-meta-link panel to collect notices from page.
|
||||
* Version: 0.27
|
||||
* Author: abuyoyo
|
||||
* Author URI: https://github.com/abuyoyo/
|
||||
* Plugin URI: https://github.com/abuyoyo/notice-manager
|
||||
* Update URI: https://github.com/abuyoyo/notice-manager
|
||||
*/
|
||||
defined( 'ABSPATH' ) || die( 'No soup for you!' );
|
||||
|
||||
/**
|
||||
* Dependencies
|
||||
* Allow all other auto-loaders to fail before including our own.
|
||||
*/
|
||||
if (
|
||||
! class_exists( 'WPHelper\PluginCore' )
|
||||
||
|
||||
! class_exists( 'WPHelper\AdminPage' )
|
||||
||
|
||||
! function_exists( 'wph_add_screen_meta_panel' )
|
||||
)
|
||||
{
|
||||
if ( file_exists( __DIR__ . '/vendor/autoload.php' ) ){
|
||||
require_once __DIR__ . '/vendor/autoload.php';
|
||||
}
|
||||
}
|
||||
|
||||
use WPHelper\PluginCore;
|
||||
|
||||
/**
|
||||
* Print setting page
|
||||
* Bootstrap plugin and admin page (Tools > Notice Manager)
|
||||
*/
|
||||
new PluginCore(
|
||||
__FILE__,
|
||||
[
|
||||
'update_checker' => true,
|
||||
'action_links' => [
|
||||
'settings' => [
|
||||
'text' => 'Settings',
|
||||
'href' => 'menu_page' // reserved option_name
|
||||
],
|
||||
],
|
||||
'admin_page' => [
|
||||
'parent' => 'options',
|
||||
'render' => 'settings-page', // built-in settings page
|
||||
'plugin_info' => true,
|
||||
// 'plugin_info' => true, // disable on public repo
|
||||
'settings' => [
|
||||
'option_name' => 'notice_manager', // option_name used in wp_options table
|
||||
'sections' => [
|
||||
[
|
||||
'id' => 'notice_manager',
|
||||
// 'title' => 'N',
|
||||
'description' => 'Setup How notice manager functions.',
|
||||
'description' => 'Setup Notice Manager options.',
|
||||
'description_container' => 'notice-info',
|
||||
'fields' => [
|
||||
[
|
||||
'id' => 'above_title',
|
||||
'title' => 'Above Title',
|
||||
'type' => 'checkbox',
|
||||
'description' => 'Simply move all notices above title. WordPress core moves notices below title using script. This script moves them back over the title. This option does not move notices into panel.',
|
||||
],
|
||||
[
|
||||
'id' => 'screen_panel',
|
||||
'title' => 'Notices Panel',
|
||||
'type' => 'checkbox',
|
||||
'description' => 'Enable\disable screen-meta-links \'Notices\' panel.',
|
||||
'description' => 'Enable Screen Meta \'Notices\' panel. User can collect notices into collapsible panel.',
|
||||
],
|
||||
[
|
||||
'id' => 'auto_collect',
|
||||
'title' => 'Auto-Collect Notices',
|
||||
'type' => 'checkbox',
|
||||
'description' => 'Automatic collection of notices into panel.',
|
||||
'description' => 'If Notices panel is enabled - auto-collect notices into panel on page load.',
|
||||
],
|
||||
[
|
||||
'id' => 'auto_collapse',
|
||||
'title' => 'Auto-collapse Panel',
|
||||
'title' => 'Auto-Collapse Panel',
|
||||
'type' => 'checkbox',
|
||||
'description' => 'Notices panel will stay open for a few seconds on page load, and then close automatically.',
|
||||
'description' => 'If auto-collect is enabled - Notices panel will stay open for a few seconds on page load, and then close automatically. Panel will not auto-collapse if it contains `error` level notices.',
|
||||
],
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
[
|
||||
'id' => 'distraction_free',
|
||||
'title' => 'Distraction Free',
|
||||
'type' => 'checkbox',
|
||||
'description' => 'Notice Panel is closed on page load. Requires auto_collect.'
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
'update_checker' => true, // If Plugin Update Checker library is available - allow updates/auto-updates.
|
||||
],
|
||||
);
|
||||
|
||||
require_once 'src/NoticeManager.php';
|
||||
|
||||
|
||||
add_action('plugins_loaded', function(){
|
||||
new NoticeManager();
|
||||
});
|
||||
add_action( 'plugins_loaded', fn() => new NoticeManager() );
|
||||
1671
package-lock.json
generated
Normal file
1671
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
24
package.json
Normal file
24
package.json
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "notice-manager",
|
||||
"version": "0.18.0",
|
||||
"description": "Manage notices on WordPress admin pages. Adds 'Notices' screen-meta-link.",
|
||||
"author": "abuyoyo",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/abuyoyo/notice-manager.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/abuyoyo/notice-manager/issues"
|
||||
},
|
||||
"homepage": "https://github.com/abuyoyo/notice-manager#readme",
|
||||
"scripts": {
|
||||
"start": "node-sass scss/ -o css/",
|
||||
"build": "node-sass scss/ -o css/",
|
||||
"watch": "node-sass -w scss/ -o css/",
|
||||
"sass": "node-sass -w scss/ -o css/",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"node-sass": "^4.9.3"
|
||||
}
|
||||
}
|
||||
71
scss/notice-manager.scss
Normal file
71
scss/notice-manager.scss
Normal file
@ -0,0 +1,71 @@
|
||||
div.updated,
|
||||
div.error,
|
||||
div.notice-error,
|
||||
div.update-nag {
|
||||
@extend div.notice;
|
||||
}
|
||||
|
||||
div.notice {
|
||||
:not(.wrap) ~ & {
|
||||
margin: 5px 20px 15px 2px;
|
||||
}
|
||||
|
||||
// This should only be used if auto-collect/above-title is enabled
|
||||
// classes .notices-auto-collect, .notices-above-title added to body tag by plugin
|
||||
.notices-auto-collect #wpbody-content > &,
|
||||
.notices-auto-collect .wrap > &,
|
||||
.notices-above-title .wrap > & {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
#meta-link-notices-wrap {
|
||||
margin: 0;
|
||||
// padding: 8px 20px 12px;
|
||||
position: relative;
|
||||
|
||||
> button.notice-dismiss {
|
||||
position: relative;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.notice_container {
|
||||
padding: 9px 0px 1px 0px;
|
||||
background-color: gainsboro;
|
||||
|
||||
&.empty {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
> div.notice {
|
||||
margin: 5px 12px 15px 12px !important; // Override plugins custom css
|
||||
}
|
||||
}
|
||||
|
||||
#meta-link-notices .plugin-count {
|
||||
display: inline-block;
|
||||
// vertical-align: top;
|
||||
box-sizing: border-box;
|
||||
margin: 1px 0 -1px 2px;
|
||||
padding: 0 5px;
|
||||
min-width: 18px;
|
||||
height: 18px;
|
||||
border-radius: 9px;
|
||||
background-color: #72aee6;
|
||||
color: #fff;
|
||||
font-size: 11px;
|
||||
line-height: 1.6;
|
||||
text-align: center;
|
||||
z-index: 26;
|
||||
|
||||
&.warning {
|
||||
background-color: #dba617;
|
||||
}
|
||||
|
||||
&.error {
|
||||
background-color: #d63638;
|
||||
}
|
||||
}
|
||||
|
||||
@ -22,17 +22,23 @@ class NoticeManager{
|
||||
|
||||
function __construct(){
|
||||
// exit early if not admin page
|
||||
if ( !is_admin() )
|
||||
if ( ! is_admin() )
|
||||
return;
|
||||
|
||||
$this->options = get_option( 'notice_manager');
|
||||
$this->options = get_option( 'notice_manager' );
|
||||
|
||||
add_action( 'admin_enqueue_scripts' , [ $this , 'admin_enqueues' ] );
|
||||
|
||||
if ( ! empty( $this->options['screen_panel'] ) ){
|
||||
add_action( 'admin_init' , [ $this , 'register_notice_manager_panel' ] );
|
||||
}else{
|
||||
array_walk($this->options,function(&$item){$item=0;});
|
||||
|
||||
if ( ! empty( $this->options['auto_collect'] ) ){
|
||||
add_filter( 'admin_body_class', fn($classes) => $classes . ' notices-auto-collect' );
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! empty( $this->options['above_title'] ) ){
|
||||
add_filter( 'admin_body_class', fn($classes) => $classes . ' notices-above-title' );
|
||||
}
|
||||
|
||||
}
|
||||
@ -40,7 +46,7 @@ class NoticeManager{
|
||||
function admin_enqueues(){
|
||||
wp_enqueue_script( 'notice_manager_panel', NOTICE_MANAGER_URL . 'js/notice_manager_panel.js' , null, false , true );
|
||||
wp_localize_script( 'notice_manager_panel', 'notice_manager_options', $this->options );
|
||||
wp_enqueue_style( 'admin_notices', NOTICE_MANAGER_URL . 'css/admin_notices.css' );
|
||||
wp_enqueue_style( 'admin_notices', NOTICE_MANAGER_URL . 'css/notice-manager.css' );
|
||||
}
|
||||
|
||||
|
||||
|
||||
225
vendor/abuyoyo/adminmenupage/CHANGELOG.md
vendored
Normal file
225
vendor/abuyoyo/adminmenupage/CHANGELOG.md
vendored
Normal file
@ -0,0 +1,225 @@
|
||||
# Changelog
|
||||
WPHelper\AdminMenuPage
|
||||
|
||||
## 0.29
|
||||
Release date: Oct 5 2023
|
||||
|
||||
### Fixed
|
||||
- `composer.json` - Require `abuyoyo/metabox`. WPHelper\Metabox has been a required library since 0.25.
|
||||
|
||||
### Dependencies
|
||||
- lib: WPHelper\Metabox (`abuyoyo/metabox`) ~0.8.
|
||||
|
||||
## 0.28
|
||||
Release date: Oct 4 2023
|
||||
|
||||
### Added
|
||||
- Option `parent` accepts `tools` as shorthand for `tools.php`.
|
||||
- Add link to Install Plugin page in "CMB2 plugin missing" template.
|
||||
|
||||
## 0.27
|
||||
Release date: Sep 10 2023
|
||||
|
||||
### Fixed
|
||||
- Fix nav-tabs appearing on pages without `tab_group`.
|
||||
|
||||
## 0.26
|
||||
Release date: Jun 20 2023
|
||||
|
||||
### Added
|
||||
- Add `allow_on_front` setting to CMB2 pages. Hooks metabox on `cmb2_init` instead of `cmb2_admin_init`.
|
||||
- If defined `WPH_DEBUG` add WPHelper classes debug information to plugin info meta box.
|
||||
|
||||
## 0.25
|
||||
Release date: Jun 9 2023
|
||||
|
||||
### Added
|
||||
- Non-CMB2 pages can be added to CMB2 tab groups. New options `tab_group` and `tab_title`
|
||||
|
||||
### Changed
|
||||
- New method `render_plugin_info_meta_box`. Deprecate `render_plugin_info_box`.
|
||||
- Plugin info meta box rendered using `WPHelper\MetaBox`.
|
||||
|
||||
### Fixed
|
||||
- Fix several PHP undefined variable warnings.
|
||||
|
||||
### Internal
|
||||
- Setting pages/wrap template uses WordPress Core `do_meta_boxes` to render `side` meta boxes div.
|
||||
- Add variables to `AdminPage::options()` array.
|
||||
- Multiple code refactoring and template restructuring.
|
||||
|
||||
## 0.24
|
||||
Release date: Jan 28 2023
|
||||
|
||||
### Fixed
|
||||
- Fix plugin info meta box when no PluginCore is available.
|
||||
- Fix PHP deprecated notice.
|
||||
|
||||
## 0.23
|
||||
Release date: Jan 15 2023
|
||||
|
||||
### Added
|
||||
- Add action hook `wphelper/plugin_info_meta_box/{$slug}` to modify and render plugin info meta box.
|
||||
- Add support for `textarea` input field in SettingsPage.
|
||||
- Add `sanitize_callback` option - allow plugins to supply their own sanitize function.
|
||||
- Add `render` to fields - allow plugins to supply their own render callback for fields.
|
||||
- Add `placeholder` to fields - allow plugins to supply placeholder values for fields.
|
||||
|
||||
### Fixed
|
||||
- Fix default value handling for fields.
|
||||
|
||||
### Internal
|
||||
- Rename `tpl/` template parts.
|
||||
- Minor changes and fixes.
|
||||
|
||||
## 0.22
|
||||
Release date: Jan 1 2023
|
||||
|
||||
### Fixed
|
||||
- Fix error when `plugin_info = true` but `plugin_core` is not set.
|
||||
|
||||
## 0.21
|
||||
|
||||
### Fixed
|
||||
- Minor fixes.
|
||||
|
||||
## 0.20
|
||||
|
||||
### Added
|
||||
- Add SettingsPage section option `description-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
|
||||
- Fix 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
|
||||
29
vendor/abuyoyo/adminmenupage/LICENSE
vendored
Normal file
29
vendor/abuyoyo/adminmenupage/LICENSE
vendored
Normal file
@ -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.
|
||||
53
vendor/abuyoyo/adminmenupage/README.md
vendored
Normal file
53
vendor/abuyoyo/adminmenupage/README.md
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
# 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/my_script.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 );
|
||||
|
||||
// That's it. We're done.
|
||||
// This function can be called from anywhere. No need to wrap in any hook.
|
||||
```
|
||||
23
vendor/abuyoyo/adminmenupage/composer.json
vendored
Normal file
23
vendor/abuyoyo/adminmenupage/composer.json
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
"name": "abuyoyo/adminmenupage",
|
||||
"description": "WordPress admin menu page helper class",
|
||||
"type": "library",
|
||||
"version": "0.29",
|
||||
"time": "2023-10-05",
|
||||
"license": "BSD-3-Clause",
|
||||
"require": {
|
||||
"abuyoyo/metabox": "~0.8"
|
||||
},
|
||||
"suggest": {
|
||||
"abuyoyo/plugincore": "~0.26",
|
||||
"cmb2/cmb2": "~2.9"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"WPHelper\\" : "src/"
|
||||
},
|
||||
"files": [
|
||||
"wph_admin_page.php"
|
||||
]
|
||||
}
|
||||
}
|
||||
19
vendor/abuyoyo/adminmenupage/src/AdminMenuPage.php
vendored
Normal file
19
vendor/abuyoyo/adminmenupage/src/AdminMenuPage.php
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
namespace WPHelper;
|
||||
|
||||
defined( 'ABSPATH' ) || die( 'No soup for you!' );
|
||||
|
||||
if ( ! class_exists( AdminMenuPage::class ) ):
|
||||
/**
|
||||
* AdminMenuPage
|
||||
*
|
||||
* Deprecated class. Use AdminPage instead.
|
||||
*
|
||||
* @author abuyoyo
|
||||
* @since 0.12
|
||||
*
|
||||
*/
|
||||
class AdminMenuPage extends AdminPage{
|
||||
|
||||
}
|
||||
endif;
|
||||
1062
vendor/abuyoyo/adminmenupage/src/AdminPage.php
vendored
Normal file
1062
vendor/abuyoyo/adminmenupage/src/AdminPage.php
vendored
Normal file
File diff suppressed because it is too large
Load Diff
268
vendor/abuyoyo/adminmenupage/src/CMB2_OptionsPage.php
vendored
Normal file
268
vendor/abuyoyo/adminmenupage/src/CMB2_OptionsPage.php
vendored
Normal file
@ -0,0 +1,268 @@
|
||||
<?php
|
||||
namespace WPHelper;
|
||||
|
||||
defined( 'ABSPATH' ) || die( 'No soup for you!' );
|
||||
|
||||
use CMB2;
|
||||
use CMB2_Options_Hookup;
|
||||
|
||||
if ( ! class_exists( CMB2_OptionsPage::class ) ):
|
||||
/**
|
||||
* CMB2_OptionsPage
|
||||
*
|
||||
* Helper class
|
||||
* Create WordPress Setting page using CMB2 Options Hookup.
|
||||
*
|
||||
* @author abuyoyo
|
||||
*
|
||||
* @see CMB2_Options_Hookup::options_page_output and 'display_cb' - to manipulate tabs
|
||||
*
|
||||
* @todo add 'submenu' field and functionality (rename first submenu item) to WPHelper\AdminPage
|
||||
*/
|
||||
class CMB2_OptionsPage{
|
||||
|
||||
/**
|
||||
* @var AdminPage $admin_page
|
||||
*/
|
||||
public $admin_page;
|
||||
|
||||
/**
|
||||
* @var array $fields
|
||||
*/
|
||||
protected $fields;
|
||||
|
||||
/**
|
||||
* @var CMB2 $cmb
|
||||
*/
|
||||
private $cmb;
|
||||
|
||||
/**
|
||||
* @var array $cmb2_options
|
||||
*/
|
||||
protected $cmb2_options;
|
||||
|
||||
/**
|
||||
* @param AdminPage $admin_page
|
||||
*/
|
||||
function __construct( $admin_page ){
|
||||
|
||||
$this->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'];
|
||||
// @todo Only if cmb2-tabs
|
||||
$settings['tab_title'] ??= $admin_options['tab_title'] ?? $settings['submenu_title'] ?? $settings['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 conversion to dedicated method
|
||||
* @todo perhaps move this to AdminPage::parent() 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'];
|
||||
}
|
||||
|
||||
$this->fields = $settings['fields'] ?? [];
|
||||
/**
|
||||
* @todo revisit this - might not need to unset fields
|
||||
*/
|
||||
if ( isset( $settings['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;
|
||||
|
||||
if ( $settings['allow_on_front'] ?? false ){
|
||||
add_action( 'cmb2_init', [ $this, 'register_metabox' ], $priority );
|
||||
} else {
|
||||
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_Hookup $hookup - instance of Options Page Hookup class (caller of this function)
|
||||
*
|
||||
* @see CMB2_Options_Hookup
|
||||
*/
|
||||
public function options_page_output( $hookup ) {
|
||||
|
||||
$options = $this->admin_page->options();
|
||||
|
||||
if ( ! empty( $options['plugin_core'] ) || ! empty( $options['plugin_info'] ) ){
|
||||
include __DIR__ . '/tpl/wrap-cmb2-sidebar.php';
|
||||
} else {
|
||||
include __DIR__ . '/tpl/wrap-cmb2-simple.php';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
34
vendor/abuyoyo/adminmenupage/src/CMB2_OptionsPage_Multi.php
vendored
Normal file
34
vendor/abuyoyo/adminmenupage/src/CMB2_OptionsPage_Multi.php
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
namespace WPHelper;
|
||||
|
||||
defined( 'ABSPATH' ) || die( 'No soup for you!' );
|
||||
|
||||
if ( ! class_exists( CMB2_OptionsPage_Multi::class ) ):
|
||||
|
||||
// Require dependency CMB2_Override_Meta
|
||||
if ( ! trait_exists( CMB2_Override_Meta::class ) ) {
|
||||
require_once __DIR__ . '/CMB2_Override_Meta.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* CMB2_OptionsPage - MULTI
|
||||
*
|
||||
* Helper class
|
||||
* Custom CMB2 Options page - saves each field as separate option in Options table.
|
||||
* Create WordPress Setting page using CMB2 Options Hookup.
|
||||
*
|
||||
* @author abuyoyo
|
||||
*
|
||||
* @todo - Rename class from MULTI to something more descriptive
|
||||
*/
|
||||
class CMB2_OptionsPage_Multi extends CMB2_OptionsPage{
|
||||
use CMB2_Override_Meta;
|
||||
|
||||
function __construct( $admin_page )
|
||||
{
|
||||
parent::__construct( $admin_page );
|
||||
|
||||
$this->cmb2_override_fields( $this->fields );
|
||||
}
|
||||
}
|
||||
endif;
|
||||
56
vendor/abuyoyo/adminmenupage/src/CMB2_Override_Meta.php
vendored
Normal file
56
vendor/abuyoyo/adminmenupage/src/CMB2_Override_Meta.php
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
namespace WPHelper;
|
||||
|
||||
defined( 'ABSPATH' ) || die( 'No soup for you!' );
|
||||
|
||||
if ( ! trait_exists( CMB2_Override_Meta::class ) ):
|
||||
/**
|
||||
* CMB2 Options page override meta
|
||||
*
|
||||
* Override default cmb2 meta.
|
||||
* Saves each field as separate option in wp_options table
|
||||
*/
|
||||
trait CMB2_Override_Meta{
|
||||
|
||||
function cmb2_override_fields( $fields ){
|
||||
foreach( $fields as $field ){
|
||||
add_filter( "cmb2_override_{$field['id']}_meta_value", [ $this, 'cmb2_override_get' ], 10, 4 );
|
||||
add_filter( "cmb2_override_{$field['id']}_meta_save", [ $this, 'cmb2_override_save' ], 10, 4 );
|
||||
add_filter( "cmb2_override_{$field['id']}_meta_remove", [ $this, 'cmb2_override_delete' ], 10, 4 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* cmb2_override_meta_value
|
||||
*
|
||||
*/
|
||||
function cmb2_override_get( $override, $args, $field_args, $field ) {
|
||||
return get_option( $field_args['field_id'], '' );
|
||||
}
|
||||
|
||||
/**
|
||||
* cmb2_override_meta_save
|
||||
*
|
||||
*/
|
||||
function cmb2_override_save( $override, $args, $field_args, $field ) {
|
||||
// Here, we're storing the data to the options table, but you can store to any data source here.
|
||||
// If to a custom table, you can use the $args['id'] as the reference id.
|
||||
$updated = update_option( $field_args['id'], $args['value'], false );
|
||||
return !! $updated;
|
||||
}
|
||||
|
||||
/**
|
||||
* cmb2_override_meta_remove
|
||||
*
|
||||
*/
|
||||
function cmb2_override_delete( $override, $args, $field_args, $field ) {
|
||||
// Here, we're removing from the options table, but you can query to remove from any data source here.
|
||||
// If from a custom table, you can use the $args['id'] to query against.
|
||||
// (If we do "delete_option", then our default value will be re-applied, which isn't desired.)
|
||||
$updated = update_option( $field_args['id'], '' );
|
||||
// $updated = update_option( $field_args['field_id'], '' );
|
||||
return !! $updated;
|
||||
}
|
||||
|
||||
}
|
||||
endif;
|
||||
116
vendor/abuyoyo/adminmenupage/src/PluginInfoMetaBox.php
vendored
Normal file
116
vendor/abuyoyo/adminmenupage/src/PluginInfoMetaBox.php
vendored
Normal file
@ -0,0 +1,116 @@
|
||||
<?php
|
||||
namespace WPHelper;
|
||||
|
||||
use DateTime;
|
||||
|
||||
if ( ! class_exists( PluginInfoMetaBox::class ) ):
|
||||
/**
|
||||
* Plugin Info Metabox
|
||||
*
|
||||
* Get instance of PluginCore
|
||||
* Render default plugin info box template.
|
||||
*
|
||||
* @since 0.14
|
||||
*/
|
||||
class PluginInfoMetaBox{
|
||||
|
||||
private $tpl = '/tpl/plugin_info_meta_box.php';
|
||||
|
||||
private $tpl_inside = '/tpl/plugin_info_meta_box-inside.php';
|
||||
|
||||
private $tpl_debug = '/tpl/plugin_info_meta_box-wph_debug.php';
|
||||
|
||||
/**
|
||||
* @var PluginCore
|
||||
*/
|
||||
public $plugin_core;
|
||||
|
||||
function __construct( PluginCore $plugin_core )
|
||||
{
|
||||
$this->plugin_core = $plugin_core;
|
||||
|
||||
/**
|
||||
* Allow plugins to render or modify plugin info box
|
||||
*
|
||||
* Call: do_action('wphelper/plugin_info_meta_box/{$slug}')
|
||||
* action used in AdminPage::render_plugin_info_meta_box()
|
||||
*
|
||||
* @since 0.23
|
||||
*/
|
||||
add_action( "wphelper/plugin_info_meta_box/{$this->plugin_core->slug()}", [ $this, 'plugin_info_box' ] );
|
||||
|
||||
add_action( "wphelper/plugin_info_meta_box/inside/{$this->plugin_core->slug()}", [ $this, 'inside' ] );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup args used in template.
|
||||
*
|
||||
* @todo move 'repo' setup to method from template
|
||||
*/
|
||||
function setup_template_args() {
|
||||
|
||||
$plugin_data = $this->plugin_core->plugin_data();
|
||||
|
||||
|
||||
$last_update = $plugin_data['Last Update'] ?: $plugin_data['Release Date'];
|
||||
$last_update = DateTime::createFromFormat('Y_m_d', $last_update);
|
||||
|
||||
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 = '';
|
||||
}
|
||||
return compact('plugin_data','update_message');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @since 0.14 PluginInfoMetaBox::plugin_info_box()
|
||||
*
|
||||
* @todo rename method render()
|
||||
*/
|
||||
function plugin_info_box(){
|
||||
$args = $this->setup_template_args();
|
||||
extract($args);
|
||||
include __DIR__ . $this->tpl;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Only print meta-box .inside
|
||||
* No header.
|
||||
*/
|
||||
function inside(){
|
||||
$args = $this->setup_template_args();
|
||||
extract($args);
|
||||
include __DIR__ . $this->tpl_inside;
|
||||
}
|
||||
|
||||
/**
|
||||
* WPHelper classes debug info
|
||||
*
|
||||
* Prints inside Plugin Info Meta Box
|
||||
*
|
||||
* @since 0.26
|
||||
*/
|
||||
function wph_debug() {
|
||||
include __DIR__ . $this->tpl_debug;
|
||||
}
|
||||
}
|
||||
endif;
|
||||
377
vendor/abuyoyo/adminmenupage/src/SettingsPage.php
vendored
Normal file
377
vendor/abuyoyo/adminmenupage/src/SettingsPage.php
vendored
Normal file
@ -0,0 +1,377 @@
|
||||
<?php
|
||||
namespace WPHelper;
|
||||
|
||||
defined( 'ABSPATH' ) || die( 'No soup for you!' );
|
||||
|
||||
use function register_setting;
|
||||
use function add_settings_section;
|
||||
use function add_settings_field;
|
||||
use function checked;
|
||||
use function get_option;
|
||||
|
||||
if ( ! class_exists( SettingsPage::class ) ):
|
||||
/**
|
||||
* SettingsPage
|
||||
*
|
||||
* Helper class
|
||||
* Create WordPress Setting page.
|
||||
*
|
||||
* @author abuyoyo
|
||||
*
|
||||
* @since 0.11
|
||||
*/
|
||||
class SettingsPage{
|
||||
|
||||
/**
|
||||
* AdminPage instance that called this class
|
||||
*
|
||||
* @var AdminPage $admin_page instance
|
||||
*/
|
||||
protected $admin_page;
|
||||
|
||||
/**
|
||||
* Page slug to display sections
|
||||
*
|
||||
* @var string $page
|
||||
*/
|
||||
public $page;
|
||||
|
||||
/**
|
||||
* option_name key used in wp_options table
|
||||
*
|
||||
* @var string $option_name
|
||||
*/
|
||||
protected $option_name;
|
||||
|
||||
/**
|
||||
* option_group used by register_setting() and settings_fields()
|
||||
*
|
||||
* @var string $option_group
|
||||
*/
|
||||
public $option_group;
|
||||
|
||||
/**
|
||||
* Sections
|
||||
*
|
||||
* @var array[] $sections
|
||||
*/
|
||||
public $sections = [];
|
||||
|
||||
/**
|
||||
* Fields
|
||||
*
|
||||
* @var array[] $fields
|
||||
*/
|
||||
public $fields = [];
|
||||
|
||||
/**
|
||||
* Sanitize Callback
|
||||
*
|
||||
* @var Callable $sanitize_callback
|
||||
*/
|
||||
public $sanitize_callback;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param AdminPage $admin_page instance
|
||||
* @param null $settings deprecated
|
||||
*/
|
||||
public function __construct( $admin_page, $settings = null )
|
||||
{
|
||||
|
||||
if ( ! empty( $settings ) ) {
|
||||
_deprecated_argument( __FUNCTION__, '3.0.0' );
|
||||
}
|
||||
|
||||
// save reference to caller instance
|
||||
$this->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';
|
||||
|
||||
$this->sanitize_callback = $settings['sanitize_callback'] ?? null;
|
||||
|
||||
// PHP Warning: foreach() argument must be of type array|object
|
||||
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() )
|
||||
$field['name'] = $this->option_name . '[' . $field['id'] . ']';
|
||||
$this->fields[] = $field;
|
||||
}
|
||||
unset( $section['fields'] );
|
||||
$this->sections[] = $section; // save without fields
|
||||
}
|
||||
|
||||
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_callback ?? [ $this,'sanitize_settings' ] // callback ?? fallback // $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'],
|
||||
$field['render'] ?? [ $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 checkbox input field
|
||||
* Support field type 'checkbox'
|
||||
*
|
||||
* @since 0.11
|
||||
*/
|
||||
function print_checkbox( $field ) {
|
||||
extract($field);
|
||||
|
||||
$options = get_option( $this->option_name );
|
||||
|
||||
$input_tag = sprintf(
|
||||
'<label for="%1$s">
|
||||
<input name="%2$s" type="checkbox" id="%1$s" aria-describedby="%1$s-description" value="1" %4$s />
|
||||
%3$s
|
||||
</label>',
|
||||
$id,
|
||||
$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(
|
||||
'<input name="%2$s" type="text" id="%1$s" aria-describedby="%1$s-description" value="%3$s" placeholder="%4$s" class="regular-text">',
|
||||
$id,
|
||||
$name,
|
||||
$options[$id] ?: $default ?? '',
|
||||
$placeholder ?? ''
|
||||
);
|
||||
|
||||
if ( ! empty( $description ) ) {
|
||||
$input_tag .= sprintf(
|
||||
'<p class="description" id="%1$s-description">%2$s</p>',
|
||||
$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(
|
||||
'<input name="%2$s" type="url" id="%1$s" aria-describedby="%1$s-description" placeholder="%4$s" value="%3$s" class="regular-text code ">',
|
||||
$id,
|
||||
$name,
|
||||
$options[$id] ?: $default ?? '',
|
||||
$placeholder ?? ''
|
||||
);
|
||||
|
||||
if ( ! empty( $description ) ) {
|
||||
$input_tag .= sprintf(
|
||||
'<p class="description" id="%1$s-description">%2$s</p>',
|
||||
$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(
|
||||
'<input name="%2$s" type="email" id="%1$s" aria-describedby="%1$s-description" placeholder="%4$s" value="%3$s" class="regular-text ltr">',
|
||||
$id,
|
||||
$name,
|
||||
$options[$id] ?: $default ?? '',
|
||||
$placeholder ?? ''
|
||||
);
|
||||
|
||||
if ( ! empty( $description ) ) {
|
||||
$input_tag .= sprintf(
|
||||
'<p class="description" id="%1$s-description">%2$s</p>',
|
||||
$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;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Print email input field
|
||||
* Support field type 'email'
|
||||
*
|
||||
* @since 0.23
|
||||
*/
|
||||
function print_textarea( $field ){
|
||||
extract($field);
|
||||
|
||||
$options = get_option( $this->option_name );
|
||||
|
||||
$textarea = sprintf(
|
||||
'<textarea class="regular-text" rows="5" id="%1$s-description" name="%2$s" placeholder="%4$s">%3$s</textarea>',
|
||||
$id,
|
||||
$name,
|
||||
$options[$id] ?: $default ?? '',
|
||||
$placeholder ?? ''
|
||||
);
|
||||
|
||||
if ( ! empty( $description ) ) {
|
||||
$textarea .= sprintf(
|
||||
'<p class="description" id="%1$s-description">%2$s</p>',
|
||||
$id,
|
||||
$description
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow plugins to directly manipulate field HTML
|
||||
*/
|
||||
$textarea = apply_filters( 'wphelper/settings_page/textarea', $textarea, $field, $this->option_name, $options );
|
||||
|
||||
echo $textarea;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitizes entire $options array.
|
||||
*/
|
||||
function sanitize_settings( $options ) {
|
||||
$new_options = [];
|
||||
|
||||
foreach( $options as $id => $option ) {
|
||||
$field = current(
|
||||
array_filter(
|
||||
$this->fields,
|
||||
fn($item) => $item['id'] == $id
|
||||
)
|
||||
);
|
||||
switch ( $field['type'] ) {
|
||||
case 'checkbox':
|
||||
$new_options[$id] = $option == 1 ? 1 : 0;
|
||||
break;
|
||||
case 'text':
|
||||
case 'textarea':
|
||||
$new_options[$id] = sanitize_text_field( $option );
|
||||
break;
|
||||
case 'email':
|
||||
$new_options[$id] = sanitize_email( $option );
|
||||
break;
|
||||
case 'url':
|
||||
$new_options[$id] = esc_url_raw( $option );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $new_options;
|
||||
}
|
||||
|
||||
function section_description_cb( $section ) {
|
||||
if ( ! empty( $section['description'] ) ) {
|
||||
switch ( $section[ 'description_container' ] ?? '' ){
|
||||
case 'card':
|
||||
$container = '<div class="card">%s</div>';
|
||||
break;
|
||||
case 'notice':
|
||||
case 'notice-info':
|
||||
$container = '<div class="notice notice-info inline"><p>%s</p></div>';
|
||||
break;
|
||||
case 'none':
|
||||
$container = '%s';
|
||||
break;
|
||||
default:
|
||||
$container = '<p>%s</p>';
|
||||
break;
|
||||
}
|
||||
return fn() => printf( $container, $section['description'] );
|
||||
}
|
||||
}
|
||||
}
|
||||
endif;
|
||||
15
vendor/abuyoyo/adminmenupage/src/tpl/form-basic.php
vendored
Normal file
15
vendor/abuyoyo/adminmenupage/src/tpl/form-basic.php
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
/**
|
||||
* Settings-Page settings form
|
||||
*
|
||||
* Print WordPress settings form and submit button.
|
||||
*/
|
||||
?>
|
||||
<form method="post" action="options.php">
|
||||
<?php
|
||||
/** @var WPHelper\AdminPage $this */
|
||||
settings_fields( $this->settings_page->option_group );// Print hidden setting fields
|
||||
do_settings_sections( $this->settings_page->page );// Print title, info callback and form-table
|
||||
submit_button();
|
||||
?>
|
||||
</form>
|
||||
15
vendor/abuyoyo/adminmenupage/src/tpl/form-cmb2.php
vendored
Normal file
15
vendor/abuyoyo/adminmenupage/src/tpl/form-cmb2.php
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
/**
|
||||
* Template form.cmb-form
|
||||
*
|
||||
* Print form tag used by CMB2 options page.
|
||||
*
|
||||
* @var WPHelper\CMB2_Options_Page $this
|
||||
* @var CMB2_Options_Hook $hookup
|
||||
*/
|
||||
?>
|
||||
<form class="cmb-form" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" method="POST" id="<?php echo $this->cmb->cmb_id; ?>" enctype="multipart/form-data" encoding="multipart/form-data">
|
||||
<input type="hidden" name="action" value="<?php echo esc_attr( $hookup->option_key ); ?>">
|
||||
<?php $hookup->options_page_metabox(); ?>
|
||||
<?php submit_button( esc_attr( $this->cmb->prop( 'save_button' ) ), 'primary', 'submit-cmb' ); ?>
|
||||
</form>
|
||||
37
vendor/abuyoyo/adminmenupage/src/tpl/plugin_info_meta_box-inside.php
vendored
Normal file
37
vendor/abuyoyo/adminmenupage/src/tpl/plugin_info_meta_box-inside.php
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
/**
|
||||
* Plugin Info Metabox - .inside
|
||||
*/
|
||||
?>
|
||||
<h3 style="font-weight: 100; font-size: 1.5em;"><?php echo $plugin_data['Name']; ?></h3>
|
||||
<p>
|
||||
<?php if ( ! empty( $plugin_data['Version'] ) ): ?>
|
||||
Version: <?php echo $plugin_data['Version']; ?><br/>
|
||||
<?php endif; ?>
|
||||
<?php if ( ! empty( $plugin_data['Author'] ) ): ?>
|
||||
Author:
|
||||
<?php if ( ! empty( $plugin_data['AuthorURI'] ) ): ?>
|
||||
<a href="<?php echo $plugin_data['AuthorURI'] ?>"><?php echo $plugin_data['Author']; ?></a><br/>
|
||||
<?php else: ?>
|
||||
<?php echo $plugin_data['Author']; ?><br/>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
<?php if ( ! empty( $plugin_data['UpdateURI'] ) || ! empty( $plugin_data['PluginURI'] ) ): ?>
|
||||
Repo: <a href="<?php echo $plugin_data['UpdateURI'] ?: $plugin_data['PluginURI']; ?>">
|
||||
<?php echo $plugin_data['TextDomain'] ?? $this->$plugin_core->slug(); ?>
|
||||
</a><br/>
|
||||
<?php endif; ?>
|
||||
<?php if ( ! empty( $update_message ) ): ?>
|
||||
Last Updated: <?php echo $update_message; ?>
|
||||
<?php endif; ?>
|
||||
</p>
|
||||
<?php
|
||||
/**
|
||||
* Print WPHelper debug info in plugin info meta box
|
||||
*
|
||||
* @since 0.26
|
||||
*/
|
||||
if ( defined('WPH_DEBUG') && WPH_DEBUG ) {
|
||||
/** @var WPHelper\PluginInfoMetaBox $this */
|
||||
$this->wph_debug();
|
||||
}
|
||||
84
vendor/abuyoyo/adminmenupage/src/tpl/plugin_info_meta_box-wph_debug.php
vendored
Normal file
84
vendor/abuyoyo/adminmenupage/src/tpl/plugin_info_meta_box-wph_debug.php
vendored
Normal file
@ -0,0 +1,84 @@
|
||||
<?php
|
||||
/**
|
||||
* Plugin Info Metabox - .wph-debug
|
||||
*
|
||||
* @since 0.26
|
||||
*/
|
||||
|
||||
use WPHelper\AdminPage;
|
||||
use WPHelper\MetaBox;
|
||||
use WPHelper\PluginCore;
|
||||
use WPHelper\Utility\Singleton;
|
||||
use WPHelper\DatabaseTable;
|
||||
|
||||
if (class_exists(AdminPage::class)){
|
||||
$wph_admin_ref = new ReflectionClass(AdminPage::class);
|
||||
$wph_admin_file = $wph_admin_ref->getFileName();
|
||||
$wph_admin_composer = json_decode(file_get_contents( dirname( dirname( $wph_admin_file ) ) . '/composer.json' )) ;
|
||||
}
|
||||
|
||||
if (class_exists(PluginCore::class)){
|
||||
$wph_pc_ref = new ReflectionClass(PluginCore::class);
|
||||
$wph_pc_file = $wph_pc_ref->getFileName();
|
||||
$wph_pc_composer = json_decode(file_get_contents( dirname( $wph_pc_file ) . '/composer.json' )) ;
|
||||
}
|
||||
|
||||
if (class_exists(MetaBox::class)){
|
||||
$wph_mb_ref = new ReflectionClass(MetaBox::class);
|
||||
$wph_mb_file = $wph_mb_ref->getFileName();
|
||||
$wph_mb_composer = json_decode(file_get_contents( dirname( $wph_mb_file ) . '/composer.json' )) ;
|
||||
}
|
||||
|
||||
if (trait_exists(Singleton::class)){
|
||||
$wph_util_ref = new ReflectionClass(Singleton::class);
|
||||
$wph_util_file = $wph_util_ref->getFileName();
|
||||
$wph_util_composer = json_decode(file_get_contents( dirname( dirname( $wph_util_file ) ) . '/composer.json' )) ;
|
||||
}
|
||||
|
||||
if (class_exists(DatabaseTable::class)){
|
||||
$wph_db_ref = new ReflectionClass(DatabaseTable::class);
|
||||
$wph_db_file = $wph_db_ref->getFileName();
|
||||
$wph_db_composer = json_decode(file_get_contents( dirname( $wph_db_file ) . '/composer.json' )) ;
|
||||
}
|
||||
?>
|
||||
<style>
|
||||
.inside {
|
||||
word-wrap: break-word;
|
||||
}
|
||||
</style>
|
||||
<?php if ( ! empty( $wph_admin_composer ) ): ?>
|
||||
<hr>
|
||||
<p>
|
||||
AdminPage: <?php echo $wph_admin_composer->version; ?><br/>
|
||||
Location: <?php echo $wph_admin_file; ?><br/>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ( ! empty( $wph_pc_composer ) ): ?>
|
||||
<hr>
|
||||
<p>
|
||||
PluginCore: <?php echo $wph_pc_composer->version; ?><br/>
|
||||
Location: <?php echo $wph_pc_file; ?><br/>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ( ! empty( $wph_mb_composer ) ): ?>
|
||||
<hr>
|
||||
<p>
|
||||
MetaBox: <?php echo $wph_mb_composer->version; ?><br/>
|
||||
Location: <?php echo $wph_mb_file; ?><br/>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ( ! empty( $wph_util_composer ) ): ?>
|
||||
<hr>
|
||||
<p>
|
||||
Utility: <?php echo $wph_util_composer->version; ?><br/>
|
||||
Location: <?php echo $wph_util_file; ?><br/>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ( ! empty( $wph_db_composer ) ): ?>
|
||||
<hr>
|
||||
<p>
|
||||
DatabaseTable: <?php echo $wph_db_composer->version; ?><br/>
|
||||
Location: <?php echo $wph_db_file; ?><br/>
|
||||
<?php endif; ?>
|
||||
|
||||
</p>
|
||||
12
vendor/abuyoyo/adminmenupage/src/tpl/plugin_info_meta_box.php
vendored
Normal file
12
vendor/abuyoyo/adminmenupage/src/tpl/plugin_info_meta_box.php
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
/**
|
||||
* Plugin Info Metabox
|
||||
*/
|
||||
?>
|
||||
<div id="plugin_info" class="postbox">
|
||||
<h2 style="border-bottom: 1px solid #eee;"><span>Plugin Info</span></h2>
|
||||
<div class="inside">
|
||||
<?php include __DIR__ . '/plugin_info_meta_box-inside.php'; ?>
|
||||
</div><!-- .inside -->
|
||||
|
||||
</div><!-- .postbox -->
|
||||
41
vendor/abuyoyo/adminmenupage/src/tpl/sidebar-add-meta-boxes.php
vendored
Normal file
41
vendor/abuyoyo/adminmenupage/src/tpl/sidebar-add-meta-boxes.php
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
/**
|
||||
* Bootstrap WordPress core meta-boxes to generate metaboxes
|
||||
*
|
||||
* @var WPHelper\AdminPage $this
|
||||
*/
|
||||
?>
|
||||
<style>
|
||||
/*
|
||||
we don't actually have draggable/movable metaboxes
|
||||
.hide-if-no-js / hidden classes would help
|
||||
*/
|
||||
.handle-actions {
|
||||
display: none;
|
||||
}
|
||||
.postbox .postbox-header .hndle {
|
||||
cursor: unset;
|
||||
}
|
||||
</style>
|
||||
<?php
|
||||
/**
|
||||
* Allow meta-boxes to hook to this page ('side' context).
|
||||
*
|
||||
*
|
||||
*/
|
||||
do_action('add_meta_boxes', $this->get_hook_suffix(), 'side' );
|
||||
|
||||
/**
|
||||
* Remove 'Featured Image' meta-box added by core.
|
||||
*
|
||||
* @see register_and_do_post_meta_boxes() (wp-admin/includes/meta-boxes.php)
|
||||
* @todo Investigate why $thumbnail_support returns true for our pages.
|
||||
*/
|
||||
remove_meta_box( 'postimagediv', $this->get_hook_suffix(), 'side' );
|
||||
|
||||
/**
|
||||
* Render meta-boxes
|
||||
*
|
||||
* Renders div.meta-box-sortables
|
||||
*/
|
||||
do_meta_boxes( $this->get_hook_suffix(), 'side', null );
|
||||
17
vendor/abuyoyo/adminmenupage/src/tpl/tab-nav-cmb2.php
vendored
Normal file
17
vendor/abuyoyo/adminmenupage/src/tpl/tab-nav-cmb2.php
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
/**
|
||||
* Template - Tabs navigation row
|
||||
*
|
||||
* Print tabs navigation row.
|
||||
*
|
||||
* @var CMB2_Options_Hookup $hookup
|
||||
*/
|
||||
if ( ! isset( $hookup ) ){
|
||||
return;
|
||||
}
|
||||
|
||||
$tabs = $hookup->get_tab_group_tabs();
|
||||
|
||||
if ( count( $tabs ) > 1 ){
|
||||
$hookup->options_page_tab_nav_output();
|
||||
}
|
||||
9
vendor/abuyoyo/adminmenupage/src/tpl/tab-nav-simple.php
vendored
Normal file
9
vendor/abuyoyo/adminmenupage/src/tpl/tab-nav-simple.php
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
/**
|
||||
* Template - Tabs navigation row
|
||||
*
|
||||
* Print tabs navigation row.
|
||||
*
|
||||
* @var WPHelper\AdminPage $this
|
||||
*/
|
||||
do_action( "wphelper/adminpage/tab_nav/{$this->tab_group}" );
|
||||
9
vendor/abuyoyo/adminmenupage/src/tpl/title-cmb2.php
vendored
Normal file
9
vendor/abuyoyo/adminmenupage/src/tpl/title-cmb2.php
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
/**
|
||||
* Template for CMB2 page title
|
||||
*
|
||||
* @var WPHelper\CMB2_OptionsPage $this
|
||||
*/
|
||||
if ( $this->cmb->prop( 'title' ) ) {
|
||||
echo '<h2>' . wp_kses_post( $this->cmb->prop( 'title' ) ) . '</h2>';
|
||||
}
|
||||
42
vendor/abuyoyo/adminmenupage/src/tpl/wrap-cmb2-sidebar.php
vendored
Normal file
42
vendor/abuyoyo/adminmenupage/src/tpl/wrap-cmb2-sidebar.php
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
/**
|
||||
* Template for CMB2 Options Page
|
||||
*
|
||||
* @var WPHelper\CMB2_OptionsPage $this
|
||||
* @var CMB2_Options_Hookup $hookup
|
||||
*/
|
||||
?>
|
||||
<style>
|
||||
/*
|
||||
* fix top container alignment issues when using 2 columns
|
||||
* This assumes first item is a title item
|
||||
*/
|
||||
.cmb2-options-page .cmb2-wrap .cmb-type-title:first-of-type {
|
||||
margin-top: 0;
|
||||
}
|
||||
</style>
|
||||
<div class="wrap cmb2-options-page option-<?php echo esc_attr( sanitize_html_class( $hookup->option_key ) ); ?>">
|
||||
|
||||
<?php include 'title-cmb2.php' ?>
|
||||
<?php include 'tab-nav-cmb2.php' ?>
|
||||
|
||||
<div id="poststuff">
|
||||
<div id="post-body" class="metabox-holder columns-2">
|
||||
|
||||
<!-- main content -->
|
||||
<div id="post-body-content">
|
||||
<div class="meta-box-sortables ui-sortable tabs-content">
|
||||
<?php include 'form-cmb2.php' ?>
|
||||
</div><!-- .meta-box-sortables -->
|
||||
</div><!-- #post-body-content -->
|
||||
|
||||
<!-- sidebar -->
|
||||
<div id="postbox-container-1" class="postbox-container">
|
||||
<div class="meta-box-sortables">
|
||||
<?php do_action("wphelper/adminpage/plugin_info_box/{$this->admin_page->get_slug()}"); ?>
|
||||
</div><!-- .meta-box-sortables -->
|
||||
</div><!-- #postbox-container-1 .postbox-container -->
|
||||
</div><!-- #post-body -->
|
||||
<div class="clear"></div>
|
||||
</div><!-- #poststuff -->
|
||||
</div><!-- .wrap -->
|
||||
13
vendor/abuyoyo/adminmenupage/src/tpl/wrap-cmb2-simple.php
vendored
Normal file
13
vendor/abuyoyo/adminmenupage/src/tpl/wrap-cmb2-simple.php
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
/**
|
||||
* Template for CMB2 Options Page
|
||||
*
|
||||
* @var WPHelper\CMB2_OptionsPage $this
|
||||
* @var CMB2_Options_Hookup $hookup
|
||||
*/
|
||||
?>
|
||||
<div class="wrap cmb2-options-page option-<?php echo esc_attr( sanitize_html_class( $hookup->option_key ) ); ?>">
|
||||
<?php include 'title-cmb2.php' ?>
|
||||
<?php include 'tab-nav-cmb2.php' ?>
|
||||
<?php include 'form-cmb2.php' ?>
|
||||
</div>
|
||||
9
vendor/abuyoyo/adminmenupage/src/tpl/wrap-cmb2-unavailable.php
vendored
Normal file
9
vendor/abuyoyo/adminmenupage/src/tpl/wrap-cmb2-unavailable.php
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
<div class="wrap">
|
||||
<h1><?= get_admin_page_title() ?></h1>
|
||||
|
||||
<div class="card">
|
||||
<h3>CMB2 Plugin Missing</h3>
|
||||
<p>CMB2 plugin is required to display this page.
|
||||
<br>Please install and activate <a href="<?php echo admin_url('plugin-install.php?s=cmb2&tab=search') ?>">CMB2 plugin</a>.
|
||||
</div>
|
||||
</div>
|
||||
24
vendor/abuyoyo/adminmenupage/src/tpl/wrap-default.php
vendored
Normal file
24
vendor/abuyoyo/adminmenupage/src/tpl/wrap-default.php
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
/**
|
||||
* WordPress admin 'wrap' div
|
||||
*
|
||||
* @var WPHelper\AdminPage $this
|
||||
*/
|
||||
?>
|
||||
<div class="wrap">
|
||||
<h1><?= get_admin_page_title() ?></h1>
|
||||
|
||||
<div class="card">
|
||||
<h3>WPHelper\AdminPage</h3>
|
||||
<p>Please provide a template file or callback function to render this page
|
||||
<br />Like so:
|
||||
</p>
|
||||
<pre><code style="display: block;">new WPHelper\AdminPage(
|
||||
[
|
||||
'slug' => '<?=$this->slug?>',
|
||||
'title' => '<?=$this->title?>',
|
||||
<strong><em>'render' => 'callback_or_tpl_file',</em></strong>
|
||||
]
|
||||
);</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
29
vendor/abuyoyo/adminmenupage/src/tpl/wrap-sidebar.php
vendored
Normal file
29
vendor/abuyoyo/adminmenupage/src/tpl/wrap-sidebar.php
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
/**
|
||||
* Template for CMB2 Options Page
|
||||
*
|
||||
* @var string $ob_content - Render template or callback
|
||||
* @var WPHelper\AdminPage $this
|
||||
*/
|
||||
?>
|
||||
<div class="wrap">
|
||||
<h1><?= get_admin_page_title() ?></h1>
|
||||
<?php include 'tab-nav-simple.php' ?>
|
||||
<div id="poststuff">
|
||||
<div id="post-body" class="metabox-holder columns-2">
|
||||
|
||||
<!-- main content -->
|
||||
<div id="post-body-content">
|
||||
<div class="meta-box-sortables ui-sortable tabs-content">
|
||||
<?php echo $ob_content ?>
|
||||
</div><!-- .meta-box-sortables -->
|
||||
</div><!-- #post-body-content -->
|
||||
|
||||
<!-- sidebar -->
|
||||
<div id="postbox-container-1" class="postbox-container">
|
||||
<?php include 'sidebar-add-meta-boxes.php'; ?>
|
||||
</div><!-- #postbox-container-1 .postbox-container -->
|
||||
</div><!-- #post-body -->
|
||||
<div class="clear"></div>
|
||||
</div><!-- #poststuff -->
|
||||
</div><!-- .wrap -->
|
||||
12
vendor/abuyoyo/adminmenupage/src/tpl/wrap-simple.php
vendored
Normal file
12
vendor/abuyoyo/adminmenupage/src/tpl/wrap-simple.php
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
/**
|
||||
* Simple wrap
|
||||
*
|
||||
* @var string $ob_content - Render template or callback
|
||||
*/
|
||||
?>
|
||||
<div class="wrap">
|
||||
<h1><?= get_admin_page_title() ?></h1>
|
||||
<?php include 'tab-nav-simple.php' ?>
|
||||
<?php echo $ob_content; ?>
|
||||
</div>
|
||||
34
vendor/abuyoyo/adminmenupage/wph_admin_page.php
vendored
Normal file
34
vendor/abuyoyo/adminmenupage/wph_admin_page.php
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
/**
|
||||
* Plugin Name: WPHelper/Admin-Page
|
||||
*/
|
||||
defined( 'ABSPATH' ) || die( 'No soup for you!' );
|
||||
|
||||
if ( ! function_exists( 'wph_extra_plugin_headers' ) ):
|
||||
/**
|
||||
* WPHelper Extra Plugin Headers
|
||||
*
|
||||
* Adds 'Last Update' and 'Release Date' header option to plugins
|
||||
* Used in plugin info-box
|
||||
* Can be used by all plugins
|
||||
*/
|
||||
function wph_extra_plugin_headers( $headers ){
|
||||
|
||||
if ( empty( $headers ) ){
|
||||
$headers = [];
|
||||
}
|
||||
|
||||
if ( ! in_array( 'Last Update', $headers ) ){
|
||||
$headers[] = 'Last Update';
|
||||
}
|
||||
|
||||
if ( ! in_array( 'Release Date', $headers ) ){
|
||||
$headers[] = 'Release Date';
|
||||
}
|
||||
|
||||
return $headers;
|
||||
|
||||
}
|
||||
add_filter( 'extra_plugin_headers', 'wph_extra_plugin_headers' );
|
||||
add_filter( 'extra_theme_headers', 'wph_extra_plugin_headers' );
|
||||
endif;
|
||||
38
vendor/abuyoyo/metabox/.github/workflows/create-github-release.yml
vendored
Normal file
38
vendor/abuyoyo/metabox/.github/workflows/create-github-release.yml
vendored
Normal file
@ -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
|
||||
26
vendor/abuyoyo/metabox/CHANGELOG.md
vendored
Normal file
26
vendor/abuyoyo/metabox/CHANGELOG.md
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
# Changelog
|
||||
WPHelper\MetaBox
|
||||
|
||||
## 0.8
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix `Metabox::render()` callback arguments. Callback is passed `$data_object` and `$box`.
|
||||
|
||||
## 0.7
|
||||
|
||||
### Fixed
|
||||
|
||||
- Validate `is_callable(render_cb)` before `call_user_func` call.
|
||||
|
||||
## 0.6
|
||||
|
||||
### Added
|
||||
|
||||
- Accept callable `render_cb` as well as readable `render_tpl` as render template.
|
||||
|
||||
## 0.5
|
||||
|
||||
### Added
|
||||
|
||||
- Basic Metabox API.
|
||||
220
vendor/abuyoyo/metabox/MetaBox.php
vendored
Normal file
220
vendor/abuyoyo/metabox/MetaBox.php
vendored
Normal file
@ -0,0 +1,220 @@
|
||||
<?php
|
||||
namespace WPHelper;
|
||||
|
||||
use function wp_parse_args;
|
||||
use function add_action;
|
||||
use function add_meta_box;
|
||||
/**
|
||||
* MetaBox
|
||||
*
|
||||
* Object-Oriented WordPress meta box creator.
|
||||
*
|
||||
* @author abuyoyo
|
||||
* @version 0.8
|
||||
*/
|
||||
class MetaBox
|
||||
{
|
||||
/**
|
||||
* Screen context where the meta box should display.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $context;
|
||||
|
||||
/**
|
||||
* The ID of the meta box.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* The display priority of the meta box.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $priority;
|
||||
|
||||
/**
|
||||
* Screens where this meta box will appear.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
private $screens;
|
||||
|
||||
/**
|
||||
* Path to the template used to display the content of the meta box.
|
||||
*
|
||||
* @var string filename
|
||||
*/
|
||||
private $render_tpl;
|
||||
|
||||
/**
|
||||
* Path to the template used to display the content of the meta box.
|
||||
*
|
||||
* @var callable
|
||||
*/
|
||||
private $render_cb;
|
||||
|
||||
/**
|
||||
* The title of the meta box.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $title;
|
||||
|
||||
/**
|
||||
* Hook where this meta box will be added.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $hook;
|
||||
|
||||
/**
|
||||
* Array of $args to be sent to callback function's second parameter
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $args;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $id
|
||||
* @param string $template
|
||||
* @param string $title
|
||||
* @param string $context
|
||||
* @param string $priority
|
||||
* @param string[] $screens
|
||||
*/
|
||||
public function __construct($options)
|
||||
{
|
||||
// should throw error if required fields (id, title) not given
|
||||
// template is actually optional
|
||||
|
||||
$defaults = [
|
||||
'context' => 'advanced',
|
||||
'priority' => 'default',
|
||||
'screens' => [],
|
||||
'args' => null,
|
||||
'hook' => 'add_meta_boxes',
|
||||
];
|
||||
|
||||
$options = wp_parse_args( $options, $defaults );
|
||||
extract($options);
|
||||
|
||||
$this->context = $context;
|
||||
$this->id = $id;
|
||||
$this->priority = $priority;
|
||||
$this->screens = $screens;
|
||||
$this->render_tpl = isset( $template ) ? rtrim( $template, '/' ) : '';
|
||||
$this->render_cb = $render ?? '';
|
||||
$this->title = $title;
|
||||
$this->hook = $hook;
|
||||
$this->args = $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add metabox at given hook.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add()
|
||||
{
|
||||
add_action( $this->hook, [ $this, 'wp_add_metabox' ] );
|
||||
}
|
||||
|
||||
public function wp_add_metabox(){
|
||||
add_meta_box(
|
||||
$this->id,
|
||||
$this->title,
|
||||
[ $this, 'render' ], // $this->render_tpl | $this->render_cb
|
||||
$this->screens,
|
||||
$this->context,
|
||||
$this->priority,
|
||||
$this->args
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the callable that will render the content of the meta box.
|
||||
*
|
||||
* @return callable
|
||||
*/
|
||||
public function get_callback()
|
||||
{
|
||||
return [ $this, 'render' ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the screen context where the meta box should display.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_context()
|
||||
{
|
||||
return $this->context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ID of the meta box.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_id()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the display priority of the meta box.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_priority()
|
||||
{
|
||||
return $this->priority;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the screen(s) where the meta box will appear.
|
||||
*
|
||||
* @return array|string|WP_Screen
|
||||
*/
|
||||
public function get_screens()
|
||||
{
|
||||
return $this->screens;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the title of the meta box.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_title()
|
||||
{
|
||||
return $this->title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the content of the meta box using a PHP template.
|
||||
* Callback passed to to add_meta_box()
|
||||
*
|
||||
* @see do_meta_boxes()
|
||||
*
|
||||
* @param mixed $data_object Object that's the focus of the current screen. eg. WP_Post|WP_Comment
|
||||
* @param array $box Meta-box data [id, title, callback, args] (@see global $wp_meta_boxes)
|
||||
*/
|
||||
public function render( $data_object, $box )
|
||||
{
|
||||
if ( ! is_readable( $this->render_tpl ) && ! is_callable( $this->render_cb ) ){
|
||||
return;
|
||||
}
|
||||
|
||||
if ( is_callable( $this->render_cb ) ){
|
||||
call_user_func( $this->render_cb, $data_object, $box );
|
||||
} else if ( isset( $this->render_tpl ) ){
|
||||
include $this->render_tpl;
|
||||
}
|
||||
}
|
||||
}
|
||||
1
vendor/abuyoyo/metabox/README.md
vendored
Normal file
1
vendor/abuyoyo/metabox/README.md
vendored
Normal file
@ -0,0 +1 @@
|
||||
# WPHelper\MetaBox
|
||||
12
vendor/abuyoyo/metabox/composer.json
vendored
Normal file
12
vendor/abuyoyo/metabox/composer.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "abuyoyo/metabox",
|
||||
"description": "WordPress metabox helper class",
|
||||
"type": "library",
|
||||
"version": "0.8",
|
||||
"license": "BSD-3-Clause",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"WPHelper\\" : ""
|
||||
}
|
||||
}
|
||||
}
|
||||
150
vendor/abuyoyo/plugincore/CHANGELOG.md
vendored
Normal file
150
vendor/abuyoyo/plugincore/CHANGELOG.md
vendored
Normal file
@ -0,0 +1,150 @@
|
||||
# WPHelper\PluginCore Changelog
|
||||
|
||||
## 0.27
|
||||
Release Date: Oct 3, 2023
|
||||
|
||||
### Added
|
||||
- Support Plugin Update Checker v5 as well as v4. Create class alias `WPHelper\PucFactory` for `YahnisElsts\PluginUpdateChecker\v5\PucFactory` if available. Fallback to `Puc_v4_Factory`.
|
||||
|
||||
## 0.26
|
||||
Release Date: Jun 9, 2023
|
||||
|
||||
### Fixed
|
||||
- Fix passing PluginCore instance to AdminPage constructor in `admin_page()` method.
|
||||
|
||||
## 0.25
|
||||
Release Date: Feb 3, 2023
|
||||
|
||||
### Added
|
||||
- Property `token` and method `token`. Lowercase underscore token to be used as variable name.
|
||||
|
||||
## 0.24
|
||||
Release Date: Jan 13, 2023
|
||||
|
||||
### Added
|
||||
- Static `get_by_file` method. Get PluginCore instance by plugin filename.
|
||||
|
||||
## 0.23
|
||||
Release Date: Aug 8, 2022
|
||||
|
||||
### Fixed
|
||||
- Minor fixes.
|
||||
|
||||
## 0.22
|
||||
Release Date: Aug 8, 2022
|
||||
|
||||
### Removed
|
||||
- Remove all dependencies. No require.
|
||||
|
||||
## 0.21
|
||||
Release Date: Aug 5, 2022
|
||||
|
||||
### Added
|
||||
|
||||
- Add `action_links` option. Accepts standard `plugin_action_links_` callback filter function. Alternatively accepts array of links. links can be HTML tag strings (`'<a href="/link">Link</a>'`) or arrays with keys `href` and `text`. Special use case `'href' => 'menu_page'` available for quick Settings link generation.
|
||||
|
||||
### Changed
|
||||
- Plugin updater - prefer plugin header `Update URI` for plugin update checker, if no URI provided in options.
|
||||
- Validate class `WPHelper\AdminPage` exists - required for `admin_page` option/settings.
|
||||
- Significant code cleanup, notes, doc blocks and reorganizing of PluginCore class.
|
||||
|
||||
## 0.20
|
||||
Release Date: Jul 29, 2022
|
||||
|
||||
### Changed
|
||||
|
||||
- Update `composer.json` dependencies - `abuyoyo/adminmenupage ~0.20`.
|
||||
|
||||
## 0.19
|
||||
Release Date: Jul 27, 2022
|
||||
|
||||
### Changed
|
||||
|
||||
- Update `composer.json` dependencies.
|
||||
- Require PHP >= 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 `extract` 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.
|
||||
29
vendor/abuyoyo/plugincore/LICENSE
vendored
Normal file
29
vendor/abuyoyo/plugincore/LICENSE
vendored
Normal file
@ -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.
|
||||
698
vendor/abuyoyo/plugincore/PluginCore.php
vendored
Normal file
698
vendor/abuyoyo/plugincore/PluginCore.php
vendored
Normal file
@ -0,0 +1,698 @@
|
||||
<?php
|
||||
namespace WPHelper;
|
||||
|
||||
defined( 'ABSPATH' ) || die( 'No soup for you!' );
|
||||
|
||||
if ( ! class_exists( 'WPHelper/PluginCore' ) ):
|
||||
|
||||
// require dependency get_plugin_data()
|
||||
if( ! function_exists( 'get_plugin_data' ) ) {
|
||||
require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
|
||||
}
|
||||
|
||||
/**
|
||||
* PluginCore
|
||||
*
|
||||
* Helper Class for creating WordPress Plugins
|
||||
*
|
||||
* (@see README.md)
|
||||
*
|
||||
* @version 0.27
|
||||
*/
|
||||
class PluginCore {
|
||||
|
||||
/**
|
||||
* @var string Plugin filename
|
||||
*/
|
||||
private $plugin_file;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $title;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $slug;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $const;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $token;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $path;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $url;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $plugin_basename;
|
||||
|
||||
/**
|
||||
* @var array plugin header metadata
|
||||
*/
|
||||
private $plugin_data;
|
||||
|
||||
/**
|
||||
* @var callable
|
||||
*/
|
||||
public $activate_cb;
|
||||
|
||||
/**
|
||||
* @var callable
|
||||
*/
|
||||
public $deactivate_cb;
|
||||
|
||||
/**
|
||||
* @var callable
|
||||
*/
|
||||
public $uninstall_cb;
|
||||
|
||||
/**
|
||||
* @var callable
|
||||
*/
|
||||
public $upgrade_cb;
|
||||
|
||||
/**
|
||||
* @var array|callable
|
||||
*/
|
||||
public $action_links;
|
||||
|
||||
/**
|
||||
* @var AdminPage
|
||||
*/
|
||||
public $admin_page;
|
||||
|
||||
/**
|
||||
* @var \Puc_v4p10_Plugin_UpdateChecker
|
||||
*/
|
||||
private $update_checker;
|
||||
|
||||
/**
|
||||
* @var string Repo uri
|
||||
*/
|
||||
private $update_repo_uri;
|
||||
|
||||
/**
|
||||
* @var string Repo authentication key
|
||||
*/
|
||||
private $update_auth;
|
||||
|
||||
/**
|
||||
* @var string Repo branch
|
||||
*/
|
||||
private $update_branch;
|
||||
|
||||
/**
|
||||
* Static array of all PluginCore instances
|
||||
* Used in PluginCore::get($slug)
|
||||
*
|
||||
* @var array[PluginCore] Instances of PluginCore
|
||||
*/
|
||||
private static $cores = [];
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve instance of PluginCore by plugin slug.
|
||||
*
|
||||
* @since 0.5
|
||||
*
|
||||
* @param string $slug - Plugin slug
|
||||
* @return PluginCore - Instance of specific plugin.
|
||||
*/
|
||||
static public function get( $slug ) {
|
||||
return self::$cores[ $slug ] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve instance of PluginCore by plugin __FILE__.
|
||||
*
|
||||
* @since 0.24
|
||||
*
|
||||
* @param string $filename - Plugin filename
|
||||
* @return PluginCore - Instance of specific plugin.
|
||||
*/
|
||||
static public function get_by_file( $filename ) {
|
||||
return current(
|
||||
array_filter(
|
||||
self::$cores,
|
||||
fn($core) => $core->file() == $filename
|
||||
)
|
||||
) ?: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @since 0.1
|
||||
* @since 0.2 Accept filename as first param and options array as optional param
|
||||
*/
|
||||
function __construct( $plugin_file, $options = null ) {
|
||||
|
||||
$this->plugin_file( $plugin_file );
|
||||
|
||||
if ( is_array( $options ) && ! empty( $options ) ) {
|
||||
|
||||
$options = (object) $options;
|
||||
|
||||
$this->title( $options->title ?? null ); // fallback: get title from header plugin_data
|
||||
|
||||
$this->slug( $options->slug ?? null ); // fallback: guess slug from plugin basename
|
||||
|
||||
$this->const( $options->const ?? null ); // fallback: generate const from slug
|
||||
|
||||
$this->token( $options->token ?? null ); // fallback: generate token from slug
|
||||
|
||||
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->action_links ) )
|
||||
$this->action_links( $options->action_links );
|
||||
|
||||
if ( isset( $options->admin_page ) )
|
||||
$this->admin_page( $options->admin_page ); // creates AdminPage instance
|
||||
|
||||
if ( isset( $options->update_checker ) )
|
||||
$this->update_checker( $options->update_checker );
|
||||
|
||||
}
|
||||
|
||||
$this->bootstrap();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Bootstrap
|
||||
*
|
||||
* Setup url, path, plugin_basename variables
|
||||
* Add PluginCore instance to static $cores
|
||||
* Define plugin constants (_PATH, _URL, _BASENAME, _FILE etc.)
|
||||
* Register activation, deactivation, uninstall, upgrade hooks.
|
||||
* Init PUC update checker.
|
||||
*
|
||||
* @since 0.1 setup()
|
||||
* @since 0.21 bootstrap()
|
||||
*
|
||||
* @todo set plugin_dir_path, plugin_basename as accessible public variables (available thru methods atm)
|
||||
*/
|
||||
private function bootstrap() {
|
||||
|
||||
// validate basic variables (in case no options array were given)
|
||||
$this->title();
|
||||
$this->slug();
|
||||
$this->const();
|
||||
|
||||
// set variables
|
||||
$this->path();
|
||||
$this->url();
|
||||
$this->plugin_basename();
|
||||
|
||||
/**
|
||||
* Add this PluginCore instance to static list of PluginCore instances (key = slug).
|
||||
* @see static function get()
|
||||
*/
|
||||
self::$cores[ $this->slug ] = $this;
|
||||
|
||||
// define constants
|
||||
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();
|
||||
|
||||
$this->add_plugin_action_links();
|
||||
|
||||
if ( $this->update_checker === true ) {
|
||||
$this->build_update_checker();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register activation/deactivation/uninstall/upgrade hooks
|
||||
*
|
||||
* @since 0.5
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @since 0.1
|
||||
*
|
||||
* @param string|null $title
|
||||
* @return string $this->title
|
||||
*/
|
||||
public function title( $title = null ) {
|
||||
return $this->title ??= esc_html( $title ) ?: $this->plugin_data()['Title'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper function for $this->title()
|
||||
*
|
||||
* @since 0.6
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
public function name( $title = null ) {
|
||||
_doing_it_wrong( __METHOD__, 'Use PluginCore::title instead.', '0.21' );
|
||||
return $this->title( $title );
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter/Setter - slug
|
||||
* Plugin slug.
|
||||
* If none provided - plugin file basename will be used
|
||||
*
|
||||
* @since 0.1
|
||||
*
|
||||
* @param string|null $slug
|
||||
* @return string $this->slug
|
||||
*/
|
||||
public function slug( $slug = null ) {
|
||||
return $this->slug ??= $slug ?: basename( $this->plugin_file, '.php' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter - plugin_file (also Getter - kinda)
|
||||
* Plugin file fully qualified path.
|
||||
*
|
||||
* @since 0.1
|
||||
*
|
||||
* @param string $plugin_file - Path to plugin file
|
||||
* @return string $this->plugin_file
|
||||
*/
|
||||
public function plugin_file( $plugin_file ) {
|
||||
return $this->plugin_file ??= $plugin_file;
|
||||
}
|
||||
|
||||
/**
|
||||
* GETTER function. NOT a wrapper
|
||||
* Might have to rethink this
|
||||
* used by test-plugin update_checker
|
||||
*
|
||||
* @since 0.7
|
||||
*
|
||||
* @todo revisit this
|
||||
*/
|
||||
public function file() {
|
||||
return $this->plugin_file;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Getter/Setter - plugin data array
|
||||
*
|
||||
* @since 0.14
|
||||
*/
|
||||
public function plugin_data() {
|
||||
return $this->plugin_data ??= get_plugin_data( $this->plugin_file, false ); // false = no markup (i think)
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter/Setter - const
|
||||
* Prefix of plugin specific defines (PLUGIN_NAME_PATH etc.)
|
||||
* If not provided - plugin slug will be uppercase.
|
||||
*
|
||||
* @since 0.4
|
||||
*
|
||||
* @param string|null $const (string should be uppercase)
|
||||
* @return string $this->const
|
||||
*/
|
||||
public function const( $const = null ) {
|
||||
return $this->const ??= $const ?: str_replace( '-', '_' , strtoupper( $this->slug() ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter/Setter - token
|
||||
* Create a single-token slug (convert to underscore + lowercase).
|
||||
*
|
||||
* @since 0.25
|
||||
*
|
||||
* @param string|null $token (string will be normalized)
|
||||
* @return string $this->token
|
||||
*/
|
||||
public function token( $token = null ) {
|
||||
return $this->token ??= str_replace( '-', '_' , strtolower( $token ?: $this->slug() ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter/setter
|
||||
*
|
||||
* @since 0.6
|
||||
*/
|
||||
public function path() {
|
||||
return $this->path ??= plugin_dir_path( $this->plugin_file );
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter/Setter
|
||||
*
|
||||
* @since 0.6
|
||||
*/
|
||||
public function url() {
|
||||
return $this->url ??= plugin_dir_url( $this->plugin_file );
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter/Setter
|
||||
*
|
||||
* @since 0.12
|
||||
*/
|
||||
public function plugin_basename() {
|
||||
return $this->plugin_basename ??= plugin_basename( $this->plugin_file );
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter - Activation callback
|
||||
* Callback runs on 'register_activation_hook'
|
||||
* PluginCore does not validate. Authors must ensure valid callback.
|
||||
*
|
||||
* @since 0.4
|
||||
*
|
||||
* @param callable $activate_cb - Activation callback
|
||||
*
|
||||
* @access private
|
||||
*/
|
||||
private function activate_cb( $activate_cb ) {
|
||||
$this->activate_cb = $activate_cb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter - Deactivation callback
|
||||
* Callback runs on 'register_deactivation_hook'
|
||||
* PluginCore does not validate. Authors must ensure valid callback.
|
||||
*
|
||||
* @since 0.4
|
||||
*
|
||||
* @param callable $deactivate_cb - Deactivation callback.
|
||||
*
|
||||
* @access private
|
||||
*/
|
||||
private function deactivate_cb( $deactivate_cb ) {
|
||||
$this->deactivate_cb = $deactivate_cb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter - Uninstall callback
|
||||
* Callback runs on 'register_uninstall_hook'
|
||||
* PluginCore does not validate. Authors must ensure valid callback.
|
||||
*
|
||||
* @since 0.4
|
||||
*
|
||||
* @param callable $uninstall_cb - Uninstall callback.
|
||||
*
|
||||
* @access private
|
||||
*/
|
||||
private function uninstall_cb( $uninstall_cb ) {
|
||||
$this->uninstall_cb = $uninstall_cb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter - Upgrade callback
|
||||
* Callback runs on 'upgrader_process_complete' hook - only for our plugin.
|
||||
* Runs inside wrapper function that ensures our plugin was updated.
|
||||
* (@see upgrade_cb_wrapper() below)
|
||||
*
|
||||
* PluginCore does not validate. Authors must ensure valid callback.
|
||||
*
|
||||
* @since 0.11
|
||||
*
|
||||
* @param callable $upgrade_cb - Upgrade callback.
|
||||
*
|
||||
* @access private
|
||||
*/
|
||||
private function upgrade_cb( $upgrade_cb ) {
|
||||
$this->upgrade_cb = $upgrade_cb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter - Plugin action links
|
||||
*
|
||||
* Add links to plugin action links on Plugins page.
|
||||
* Accepts callable hooked to 'plugin_action_links_{$plugin}'
|
||||
* Alternatively accepts array of key => string/HTML tag (eg. [ 'settings' => '<a href="foo" />' ] )
|
||||
* Alternatively accepts array of key => [ 'text' => 'My Link', 'href' => 'foo' ]
|
||||
* Special case: Settings Page
|
||||
* [ 'settings' => [ 'href' => 'menu_page', 'text' => 'Settings' ] ] will generate link to plugin menu page url (@see menu_page_url() )
|
||||
* (@see add_plugin_action_links() below)
|
||||
*
|
||||
* @since 0.21
|
||||
*
|
||||
* @param callable|array $action_links - filter function or custom action links array
|
||||
*
|
||||
* @todo perhaps have separate action_links_array + action_links_cb variables
|
||||
*/
|
||||
private function action_links( $action_links ) {
|
||||
$this->action_links = $action_links;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter/Setter - AdminPage
|
||||
*
|
||||
* Construct AdminPage instance for plugin.
|
||||
*
|
||||
* @since 0.14
|
||||
* @since 0.17 - Pass instance of PluginCore to AdminPage (~0.14)
|
||||
*
|
||||
* @param array $admin_page - AdminPage settings array
|
||||
* @return AdminPage
|
||||
*/
|
||||
public function admin_page( $admin_page ) {
|
||||
|
||||
if ( ! class_exists( AdminPage::class ) )
|
||||
return;
|
||||
|
||||
if ( ! isset( $this->admin_page ) ){
|
||||
|
||||
// validate
|
||||
$admin_page['slug'] ??= $this->slug();
|
||||
$admin_page['title'] ??= $this->title();
|
||||
$admin_page['plugin_core'] ??= $this;
|
||||
|
||||
$this->admin_page = new AdminPage( $admin_page );
|
||||
}
|
||||
|
||||
return $this->admin_page;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter
|
||||
*
|
||||
* Setup info used by PucFactory
|
||||
*
|
||||
* set $update_checker (bool)
|
||||
* set $update_repo_uri (string)
|
||||
* set $update_auth (optional)
|
||||
* set $update_branch (optional)
|
||||
*
|
||||
* @since 0.9
|
||||
*
|
||||
* @param bool|string|array $update_checker
|
||||
*/
|
||||
private function update_checker( $update_checker ) {
|
||||
|
||||
if ( empty( $update_checker ) ) {
|
||||
$this->update_checker = false;
|
||||
}
|
||||
|
||||
if ( is_bool( $update_checker ) ) {
|
||||
$this->update_checker = $update_checker;
|
||||
}
|
||||
|
||||
// option 'update_checker' accepts string - repo uri
|
||||
if ( is_string( $update_checker ) ) {
|
||||
$this->update_checker = true;
|
||||
$this->update_repo_uri = $update_checker;
|
||||
}
|
||||
|
||||
// option 'update_checker' accepts array: ['uri'=> , 'auth'=>, 'branch'=> ]
|
||||
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'];
|
||||
}
|
||||
}
|
||||
|
||||
// Use plugin header 'UpdateURI' or fallback to 'PluginURI'
|
||||
// call plugin_data() to init var plugin_data
|
||||
$this->update_repo_uri ??= $this->plugin_data()['UpdateURI'] ?: $this->plugin_data['PluginURI'] ?: null;
|
||||
|
||||
// validate
|
||||
// If no repo uri - update checker is disabled.
|
||||
if ( empty( $this->update_repo_uri ) ) {
|
||||
$this->update_checker = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Init Puc update checker instance
|
||||
*
|
||||
* @since 0.9 init_update_checker()
|
||||
* @since 0.21 build_update_checker()
|
||||
* @since 0.27 Create class alias WPHelper\PucFactory - support plugin-update-checker v4 & v5
|
||||
*
|
||||
* @uses PucFactory::buildUpdateChecker
|
||||
*/
|
||||
private function build_update_checker() {
|
||||
|
||||
/**
|
||||
* Create class alias WPHelper\PucFactory
|
||||
* Support YahnisElsts\PluginUpdateChecker v4 | v5
|
||||
*
|
||||
* @since 0.27
|
||||
*/
|
||||
if ( ! class_exists( 'WPHelper\PucFactory' ) ) {
|
||||
if ( class_exists( 'YahnisElsts\PluginUpdateChecker\v5\PucFactory' ) ) {
|
||||
$actual_puc = 'YahnisElsts\PluginUpdateChecker\v5\PucFactory';
|
||||
} else if ( class_exists( 'Puc_v4_Factory' ) ) {
|
||||
$actual_puc = 'Puc_v4_Factory';
|
||||
}
|
||||
if ( ! empty( $actual_puc ) ) {
|
||||
class_alias( $actual_puc, 'WPHelper\PucFactory' );
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'WPHelper\PucFactory' ) )
|
||||
return;
|
||||
|
||||
$update_checker = PucFactory::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
|
||||
*
|
||||
* @since 0.12
|
||||
*/
|
||||
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 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add plugin_action_links
|
||||
*
|
||||
* Parse action_links (callable or array).
|
||||
* Generate callback if action_links provided as array.
|
||||
* Add callback to 'plugin_action_links_{$plugin}' hook.
|
||||
*
|
||||
* @since 0.21
|
||||
*
|
||||
* @access private
|
||||
*/
|
||||
private function add_plugin_action_links() {
|
||||
if ( empty( $this->action_links ) )
|
||||
return;
|
||||
|
||||
if ( is_callable( $this->action_links ) ) { // default - pass a filter method
|
||||
$action_links_cb = $this->action_links;
|
||||
} else if ( is_array( $this->action_links ) ) { // array of links - PluginCore will do the heavy lifting
|
||||
$action_links_cb = function( $links ) {
|
||||
foreach( $this->action_links as $key => $link ) {
|
||||
if ( is_string( $link ) ) { // we assume a straight HTML tag string
|
||||
$links[ $key ] = $link; // just print it
|
||||
} else if ( is_array( $link ) ) { // accepts ['href'=>'/my-href', 'text'=>'My Action Link']
|
||||
$links[ $key ] = sprintf(
|
||||
'<a href="%s">%s</a>',
|
||||
$link['href'] == 'menu_page' // reserved parameter value
|
||||
? esc_url( menu_page_url( $this->slug, false ) )
|
||||
: $link['href'],
|
||||
$link['text'],
|
||||
);
|
||||
}
|
||||
}
|
||||
return $links;
|
||||
};
|
||||
}
|
||||
|
||||
add_filter( 'plugin_action_links_' . $this->plugin_basename(), $action_links_cb );
|
||||
}
|
||||
|
||||
}
|
||||
endif;
|
||||
95
vendor/abuyoyo/plugincore/README.md
vendored
Normal file
95
vendor/abuyoyo/plugincore/README.md
vendored
Normal file
@ -0,0 +1,95 @@
|
||||
# WPHelper \ PluginCore
|
||||
|
||||
> Helper class for registering WordPress 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', // Optional - will fallback to plugin header Plugin Name.
|
||||
'slug' => 'my-awesome-plugin', // Optional - will generate slug based on plugin header Plugin Name
|
||||
'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
|
||||
new PluginCore( __FILE__, $args );
|
||||
|
||||
// Start writing your code here..
|
||||
include '/foo.php';
|
||||
add_action( 'plugins_loaded' function() {
|
||||
// whatever..
|
||||
});
|
||||
```
|
||||
|
||||
### Constants
|
||||
|
||||
WPHelper\PluginCore defines constants for use in your code. Where ``__FILE__`` is the filename provided to the class and ``%PLUGIN%`` is the ``'const'`` option.
|
||||
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%_BASENAME: ``plugin_basename( __FILE__ ) )``
|
||||
* %PLUGIN%_FILE: ``__FILE__``
|
||||
* %PLUGIN%_PLUGIN_FILE: ``__FILE__``
|
||||
|
||||
### Get Instance
|
||||
|
||||
All PluginCore instances can be referenced anywhere in your code using static method `get()` and the plugin slug. Available on `plugins_loaded` hook or later.
|
||||
```PHP
|
||||
PluginCore::get('my-awesome-plugin'); // returns PluginCore instance constructed with slug 'my-awesome-plugin'
|
||||
```
|
||||
17
vendor/abuyoyo/plugincore/composer.json
vendored
Normal file
17
vendor/abuyoyo/plugincore/composer.json
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "abuyoyo/plugincore",
|
||||
"description": "WordPress plugin core helper class",
|
||||
"type": "library",
|
||||
"version": "0.27",
|
||||
"time": "2022-10-03",
|
||||
"license": "BSD-3-Clause",
|
||||
"suggest": {
|
||||
"yahnis-elsts/plugin-update-checker": "~5.2",
|
||||
"abuyoyo/adminmenupage": "~0.27"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"WPHelper\\" : ""
|
||||
}
|
||||
}
|
||||
}
|
||||
38
vendor/abuyoyo/screen-meta-links/.github/workflows/create-github-release.yml
vendored
Normal file
38
vendor/abuyoyo/screen-meta-links/.github/workflows/create-github-release.yml
vendored
Normal file
@ -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
|
||||
2
vendor/abuyoyo/screen-meta-links/.gitignore
vendored
Normal file
2
vendor/abuyoyo/screen-meta-links/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
demo/*
|
||||
demo/
|
||||
48
vendor/abuyoyo/screen-meta-links/CHANGELOG.md
vendored
Normal file
48
vendor/abuyoyo/screen-meta-links/CHANGELOG.md
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
# 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.13](https://github.com/abuyoyo/screen-meta-links/releases/tag/0.13)
|
||||
|
||||
### Fixed
|
||||
- Fix PHP 8.2 depreacted: Optional parameter declared before required parameter.
|
||||
|
||||
## [0.12](https://github.com/abuyoyo/screen-meta-links/releases/tag/0.12)
|
||||
|
||||
### Fixed
|
||||
- Fix PHP notice: Constant already defined.
|
||||
|
||||
## [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.
|
||||
60
vendor/abuyoyo/screen-meta-links/README.md
vendored
Normal file
60
vendor/abuyoyo/screen-meta-links/README.md
vendored
Normal file
@ -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.
|
||||
8
vendor/abuyoyo/screen-meta-links/composer.json
vendored
Normal file
8
vendor/abuyoyo/screen-meta-links/composer.json
vendored
Normal file
@ -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"]
|
||||
}
|
||||
}
|
||||
16
vendor/abuyoyo/screen-meta-links/css/screen_meta_links.css
vendored
Normal file
16
vendor/abuyoyo/screen-meta-links/css/screen_meta_links.css
vendored
Normal file
@ -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;
|
||||
}
|
||||
|
||||
51
vendor/abuyoyo/screen-meta-links/js/screen-meta-links.js
vendored
Normal file
51
vendor/abuyoyo/screen-meta-links/js/screen-meta-links.js
vendored
Normal file
@ -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 = $('<div />')
|
||||
.attr({
|
||||
'id' : 'screen-meta-links'
|
||||
});
|
||||
container.insertAfter('#screen-meta');
|
||||
}
|
||||
|
||||
$.each( links, function( i, element ) {
|
||||
|
||||
if (panels[i]){
|
||||
container_panels.append(
|
||||
$('<div />')
|
||||
.attr({
|
||||
'id' : element.id + '-wrap',
|
||||
'class' : 'hidden',
|
||||
'tabindex' : '-1',
|
||||
'aria-label' : element.text + ' Tab'
|
||||
})
|
||||
.html(panels[i])
|
||||
);
|
||||
|
||||
linkTag = '<button />';
|
||||
}else{
|
||||
linkTag = '<a />';
|
||||
}
|
||||
|
||||
container.append(
|
||||
$('<div />')
|
||||
.attr({
|
||||
'id' : element.id + '-link-wrap',
|
||||
'class' : 'hide-if-no-js screen-meta-toggle custom-screen-meta-link-wrap'
|
||||
})
|
||||
.append( $( linkTag, element) )
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
})( jQuery, sml.links, sml.panels );
|
||||
373
vendor/abuyoyo/screen-meta-links/screen-meta-links.php
vendored
Normal file
373
vendor/abuyoyo/screen-meta-links/screen-meta-links.php
vendored
Normal file
@ -0,0 +1,373 @@
|
||||
<?php
|
||||
/**
|
||||
* Plugin Name: abuyoyo / Screen Meta Links
|
||||
* Description: API for adding custom screen-meta-links alongside the "Screen Options" and "Help" links.
|
||||
* Version: 0.13
|
||||
* Author: abuyoyo
|
||||
* Author URI: https://github.com/abuyoyo
|
||||
* Plugin URI: https://github.com/abuyoyo/screen-meta-links
|
||||
*/
|
||||
/**
|
||||
* TODO:
|
||||
*
|
||||
* if panel exists add 'aria-controls' attribute if none supplied
|
||||
* if no panel exists render anchor tag instead of button
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
! defined( 'SML_FILE' ) && define ( 'SML_FILE', __FILE__ );
|
||||
! defined( 'SML_URL' ) && define ( 'SML_URL' , plugin_dir_url( __FILE__ ) );
|
||||
! defined( 'SML_PATH' ) && define ( 'SML_PATH', plugin_dir_path( __FILE__ ) );
|
||||
|
||||
if ( ! class_exists('Screen_Meta_Links') ):
|
||||
|
||||
|
||||
class Screen_Meta_Links {
|
||||
|
||||
protected static $instance = null;
|
||||
|
||||
static $registered_requests;
|
||||
static $links;
|
||||
static $panels;
|
||||
static $counter;
|
||||
|
||||
static $debug = false;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function __construct(){
|
||||
global $iac_eng_settings;
|
||||
|
||||
self::$registered_requests = array();
|
||||
self::$links = array();
|
||||
self::$panels = array();
|
||||
|
||||
self::$counter = -1;
|
||||
|
||||
if( defined( 'DEBUG_SCREEN_META_LINKS' ) ){
|
||||
self::$debug = true;
|
||||
}
|
||||
|
||||
// inline solution
|
||||
add_action( 'current_screen' , [ $this, 'setup_current_screen_meta_links' ], 100 );
|
||||
add_action( 'admin_notices', [ $this, 'append_meta_links' ] ); // print inline sml script
|
||||
add_action( 'admin_head', [ $this, 'print_inline_style'] );
|
||||
|
||||
// external load solution
|
||||
// add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_scripts' ] );
|
||||
// add_action( 'admin_print_styles', [ $this, 'add_link_styles' ] ); //admin_enqueue_styles too early
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Instance
|
||||
*
|
||||
* @return self::$instance
|
||||
*/
|
||||
public static function get_instance() {
|
||||
if (null == self::$instance) {
|
||||
self::$instance = new self;
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Register a new link (and optional panel) to the screen-meta area.
|
||||
*
|
||||
* Do not call this method directly. Instead, use the global add_screen_meta_link() function.
|
||||
*
|
||||
* @param string $id - Link ID. Should be unique and a valid value for a HTML ID attribute.
|
||||
* @param string $text - Link text.
|
||||
* @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 print out screen-meta panel contents
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register_request($id, $text, $href='', $page='', $attributes = null, $panel=''){
|
||||
self::$counter++;
|
||||
self::$registered_requests[self::$counter] = compact( 'id', 'text', 'href', 'page', 'attributes', 'panel');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Setup all requests hooked to this screen
|
||||
*
|
||||
* @hook current_screen
|
||||
*/
|
||||
public function setup_current_screen_meta_links( $screen ){
|
||||
foreach(self::$registered_requests as $request_index => $args){
|
||||
$this->process_request($request_index, $args['id'], $args['text'], $args['href'], $args['page'], $args['attributes'], $args['panel']);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* process_request
|
||||
*
|
||||
* @todo sanitize user input!
|
||||
* @todo maybe don't use compact()
|
||||
*/
|
||||
private function process_request($request_index, $id, $text, $href, $page='', $attributes = null, $panel=''){
|
||||
|
||||
if ( ! $this->show_on_this_screen($id, $page) ){
|
||||
return;
|
||||
}
|
||||
|
||||
if ( is_null($attributes) )
|
||||
$attributes = array();
|
||||
if ( !is_array($attributes) )
|
||||
$attributes = array($attributes);
|
||||
|
||||
if ($panel)
|
||||
$link = compact('id', 'text' );
|
||||
else
|
||||
$link = compact('id', 'text', 'href' );
|
||||
|
||||
$link = array_merge($link, $attributes);
|
||||
|
||||
if ( empty($link['class']) )
|
||||
$link['class'] = '';
|
||||
$link['class'] = 'show-settings custom-screen-meta-link ' . $link['class'];
|
||||
|
||||
if ($panel)
|
||||
$link['class'] = 'button ' . $link['class'];
|
||||
|
||||
self::$links[$request_index] = $link;
|
||||
|
||||
|
||||
if ($panel){
|
||||
ob_start();
|
||||
call_user_func($panel);
|
||||
$panel = ob_get_clean();
|
||||
|
||||
self::$panels[$request_index] = $panel;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Test if registered link should be displayed on this screen
|
||||
*
|
||||
* @param $id
|
||||
* @param string|string[] $pages - list of hook_suffix or screen id to show screen-meta-link on
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
private function show_on_this_screen($id, $pages){
|
||||
global $hook_suffix;
|
||||
|
||||
if ( ! is_array( $pages ) ){
|
||||
$pages = [ $pages ];
|
||||
}
|
||||
|
||||
$screen = convert_to_screen($hook_suffix);
|
||||
$add_to_current_page = false;
|
||||
foreach( $pages as $k => $page ){
|
||||
if ( ! $page )//ignore empty string. otherwise - will return same as '*' (on screen->id test)
|
||||
continue;
|
||||
|
||||
$page_as_screen = convert_to_screen($page);
|
||||
if ( $page == $hook_suffix || $page_as_screen->id == $screen->id || $page == '*' ){
|
||||
$add_to_current_page = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $add_to_current_page;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* DISABLED/UNUSED
|
||||
*
|
||||
* Enqueueing does not work.
|
||||
* Instead we add our script and data inline using append_meta_links().
|
||||
*
|
||||
* @see append_meta_links()
|
||||
*/
|
||||
public function enqueue_scripts(){
|
||||
if ( empty(self::$links) ){
|
||||
return;
|
||||
}
|
||||
|
||||
wp_enqueue_script( 'screen_meta_links', SML_URL . 'js/screen-meta-links.js', 'jquery' );
|
||||
wp_localize_script( 'screen_meta_links', 'sml', [ 'links' => self::$links, 'panels' => self::$panels ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the JS that appends the custom meta links to the page.
|
||||
* Hooked on 'admin_notices' action.
|
||||
*
|
||||
* This is very much a render-blocking script
|
||||
* Runs here before the wp script that inits screen-meta-links runs
|
||||
* (enqueueing external script w/ localized variables failed to add listener to button)
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function append_meta_links(){
|
||||
|
||||
if ( empty(self::$links) ){
|
||||
return;
|
||||
}
|
||||
|
||||
// ---------------------[meta-screen-links script]-----------------------
|
||||
?>
|
||||
<script type="text/javascript">
|
||||
(function($, links, panels){
|
||||
|
||||
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
|
||||
|
||||
if (!container.length){
|
||||
container = $('<div />')
|
||||
.attr({
|
||||
'id' : 'screen-meta-links'
|
||||
});
|
||||
container.insertAfter('#screen-meta');
|
||||
}
|
||||
|
||||
$.each( links, function( i, element ) {
|
||||
|
||||
if (panels[i]){
|
||||
container_panels.append(
|
||||
$('<div />')
|
||||
.attr({
|
||||
'id' : element.id + '-wrap',
|
||||
'class' : 'hidden',
|
||||
'tabindex' : '-1',
|
||||
'aria-label' : element.text + ' Tab'
|
||||
})
|
||||
.html(panels[i])
|
||||
);
|
||||
|
||||
linkTag = '<button />';
|
||||
}else{
|
||||
linkTag = '<a />';
|
||||
}
|
||||
|
||||
container.append(
|
||||
$('<div />')
|
||||
.attr({
|
||||
'id' : element.id + '-link-wrap',
|
||||
'class' : 'hide-if-no-js screen-meta-toggle custom-screen-meta-link-wrap'
|
||||
})
|
||||
.append( $( linkTag, element) )
|
||||
);
|
||||
});
|
||||
|
||||
})(
|
||||
jQuery,
|
||||
<?php echo json_encode(self::$links); ?>,
|
||||
<?php echo json_encode(self::$panels); ?> );
|
||||
</script>
|
||||
|
||||
<?php
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* DISABLED/UNUSED
|
||||
*
|
||||
* Output the CSS code for custom screen meta links. Required because WP only
|
||||
* has styles for specific meta links (by #id), not meta links in general.
|
||||
*
|
||||
* Callback for 'admin_print_styles'.
|
||||
*
|
||||
* This function is unused because we cannot reliably obtain URL of css file.
|
||||
* Instead we add inline style using print_inline_style().
|
||||
*
|
||||
* @see print_inline_style
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function add_link_styles(){
|
||||
//Don't output the CSS if there are no custom meta links for this page.
|
||||
if ( empty(self::$links) )
|
||||
return;
|
||||
|
||||
wp_enqueue_style( 'screen-meta-links' , SML_URL . 'css/screen_meta_links.css');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Output inline style tag.
|
||||
*
|
||||
* Output the CSS code for custom screen meta links. Required because WP only
|
||||
* has styles for specific meta links (by #id), not meta links in general.
|
||||
*
|
||||
* @hook admin_head
|
||||
*/
|
||||
public function print_inline_style(){
|
||||
|
||||
//Don't output the CSS if there are no custom meta links for this page.
|
||||
if ( empty(self::$links) )
|
||||
return;
|
||||
|
||||
ob_start();
|
||||
include SML_PATH . 'css/screen_meta_links.css';
|
||||
$css = ob_get_clean();
|
||||
|
||||
echo '<style>';
|
||||
echo $css;
|
||||
echo '</style>';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
endif;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* DEMO
|
||||
*
|
||||
* A separate editable demo file
|
||||
* For debugging purposes
|
||||
*
|
||||
*/
|
||||
if( defined('DEMO_SCREEN_META_LINKS') ){
|
||||
include plugin_dir_path( __FILE__ ) . 'demo/demo_screen_meta_links.php' ;
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'wph_add_screen_meta_panel' ) ):
|
||||
/**
|
||||
* Add a new link+panel 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 value for a HTML ID attribute.
|
||||
* @param string $text - Link text.
|
||||
* @param string $href - Optional. Link URL to be used if no panel is provided
|
||||
* @param string|array $page - Optional. The page(s) where you want to add the link. Accepts wildcard '*'. If left empty will not add to any page.
|
||||
* @param array $attributes - Optional. Additional attributes for the link tag. Add 'aria-controls' => "{$id}-wrap" to toggle panel
|
||||
* @param callback $panel - Optional. Callback should print out screen-meta panel contents
|
||||
* @return void
|
||||
*
|
||||
* @todo Remove $href parameter and functionailty
|
||||
* @todo $page should not be optional. We need to remove $href first.
|
||||
*/
|
||||
function wph_add_screen_meta_panel( $id, $text, $href = '', $page = '', $attributes = null, $panel = '' ){
|
||||
|
||||
static $sml_instance = null;
|
||||
if ( null === $sml_instance){
|
||||
$sml_instance = Screen_Meta_Links::get_instance();
|
||||
}
|
||||
|
||||
$sml_instance->register_request($id, $text, $href, $page, $attributes, $panel);
|
||||
|
||||
}
|
||||
endif;
|
||||
25
vendor/autoload.php
vendored
Normal file
25
vendor/autoload.php
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
// autoload.php @generated by Composer
|
||||
|
||||
if (PHP_VERSION_ID < 50600) {
|
||||
if (!headers_sent()) {
|
||||
header('HTTP/1.1 500 Internal Server Error');
|
||||
}
|
||||
$err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
|
||||
if (!ini_get('display_errors')) {
|
||||
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
|
||||
fwrite(STDERR, $err);
|
||||
} elseif (!headers_sent()) {
|
||||
echo $err;
|
||||
}
|
||||
}
|
||||
trigger_error(
|
||||
$err,
|
||||
E_USER_ERROR
|
||||
);
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/composer/autoload_real.php';
|
||||
|
||||
return ComposerAutoloaderInita13a895834453aad32a897cc456c73ff::getLoader();
|
||||
579
vendor/composer/ClassLoader.php
vendored
Normal file
579
vendor/composer/ClassLoader.php
vendored
Normal file
@ -0,0 +1,579 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer\Autoload;
|
||||
|
||||
/**
|
||||
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
|
||||
*
|
||||
* $loader = new \Composer\Autoload\ClassLoader();
|
||||
*
|
||||
* // register classes with namespaces
|
||||
* $loader->add('Symfony\Component', __DIR__.'/component');
|
||||
* $loader->add('Symfony', __DIR__.'/framework');
|
||||
*
|
||||
* // activate the autoloader
|
||||
* $loader->register();
|
||||
*
|
||||
* // to enable searching the include path (eg. for PEAR packages)
|
||||
* $loader->setUseIncludePath(true);
|
||||
*
|
||||
* In this example, if you try to use a class in the Symfony\Component
|
||||
* namespace or one of its children (Symfony\Component\Console for instance),
|
||||
* the autoloader will first look for the class under the component/
|
||||
* directory, and it will then fallback to the framework/ directory if not
|
||||
* found before giving up.
|
||||
*
|
||||
* This class is loosely based on the Symfony UniversalClassLoader.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
* @see https://www.php-fig.org/psr/psr-0/
|
||||
* @see https://www.php-fig.org/psr/psr-4/
|
||||
*/
|
||||
class ClassLoader
|
||||
{
|
||||
/** @var \Closure(string):void */
|
||||
private static $includeFile;
|
||||
|
||||
/** @var string|null */
|
||||
private $vendorDir;
|
||||
|
||||
// PSR-4
|
||||
/**
|
||||
* @var array<string, array<string, int>>
|
||||
*/
|
||||
private $prefixLengthsPsr4 = array();
|
||||
/**
|
||||
* @var array<string, list<string>>
|
||||
*/
|
||||
private $prefixDirsPsr4 = array();
|
||||
/**
|
||||
* @var list<string>
|
||||
*/
|
||||
private $fallbackDirsPsr4 = array();
|
||||
|
||||
// PSR-0
|
||||
/**
|
||||
* List of PSR-0 prefixes
|
||||
*
|
||||
* Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2')))
|
||||
*
|
||||
* @var array<string, array<string, list<string>>>
|
||||
*/
|
||||
private $prefixesPsr0 = array();
|
||||
/**
|
||||
* @var list<string>
|
||||
*/
|
||||
private $fallbackDirsPsr0 = array();
|
||||
|
||||
/** @var bool */
|
||||
private $useIncludePath = false;
|
||||
|
||||
/**
|
||||
* @var array<string, string>
|
||||
*/
|
||||
private $classMap = array();
|
||||
|
||||
/** @var bool */
|
||||
private $classMapAuthoritative = false;
|
||||
|
||||
/**
|
||||
* @var array<string, bool>
|
||||
*/
|
||||
private $missingClasses = array();
|
||||
|
||||
/** @var string|null */
|
||||
private $apcuPrefix;
|
||||
|
||||
/**
|
||||
* @var array<string, self>
|
||||
*/
|
||||
private static $registeredLoaders = array();
|
||||
|
||||
/**
|
||||
* @param string|null $vendorDir
|
||||
*/
|
||||
public function __construct($vendorDir = null)
|
||||
{
|
||||
$this->vendorDir = $vendorDir;
|
||||
self::initializeIncludeClosure();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, list<string>>
|
||||
*/
|
||||
public function getPrefixes()
|
||||
{
|
||||
if (!empty($this->prefixesPsr0)) {
|
||||
return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, list<string>>
|
||||
*/
|
||||
public function getPrefixesPsr4()
|
||||
{
|
||||
return $this->prefixDirsPsr4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<string>
|
||||
*/
|
||||
public function getFallbackDirs()
|
||||
{
|
||||
return $this->fallbackDirsPsr0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<string>
|
||||
*/
|
||||
public function getFallbackDirsPsr4()
|
||||
{
|
||||
return $this->fallbackDirsPsr4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, string> Array of classname => path
|
||||
*/
|
||||
public function getClassMap()
|
||||
{
|
||||
return $this->classMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, string> $classMap Class to filename map
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addClassMap(array $classMap)
|
||||
{
|
||||
if ($this->classMap) {
|
||||
$this->classMap = array_merge($this->classMap, $classMap);
|
||||
} else {
|
||||
$this->classMap = $classMap;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-0 directories for a given prefix, either
|
||||
* appending or prepending to the ones previously set for this prefix.
|
||||
*
|
||||
* @param string $prefix The prefix
|
||||
* @param list<string>|string $paths The PSR-0 root directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add($prefix, $paths, $prepend = false)
|
||||
{
|
||||
$paths = (array) $paths;
|
||||
if (!$prefix) {
|
||||
if ($prepend) {
|
||||
$this->fallbackDirsPsr0 = array_merge(
|
||||
$paths,
|
||||
$this->fallbackDirsPsr0
|
||||
);
|
||||
} else {
|
||||
$this->fallbackDirsPsr0 = array_merge(
|
||||
$this->fallbackDirsPsr0,
|
||||
$paths
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$first = $prefix[0];
|
||||
if (!isset($this->prefixesPsr0[$first][$prefix])) {
|
||||
$this->prefixesPsr0[$first][$prefix] = $paths;
|
||||
|
||||
return;
|
||||
}
|
||||
if ($prepend) {
|
||||
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||
$paths,
|
||||
$this->prefixesPsr0[$first][$prefix]
|
||||
);
|
||||
} else {
|
||||
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||
$this->prefixesPsr0[$first][$prefix],
|
||||
$paths
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-4 directories for a given namespace, either
|
||||
* appending or prepending to the ones previously set for this namespace.
|
||||
*
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param list<string>|string $paths The PSR-4 base directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addPsr4($prefix, $paths, $prepend = false)
|
||||
{
|
||||
$paths = (array) $paths;
|
||||
if (!$prefix) {
|
||||
// Register directories for the root namespace.
|
||||
if ($prepend) {
|
||||
$this->fallbackDirsPsr4 = array_merge(
|
||||
$paths,
|
||||
$this->fallbackDirsPsr4
|
||||
);
|
||||
} else {
|
||||
$this->fallbackDirsPsr4 = array_merge(
|
||||
$this->fallbackDirsPsr4,
|
||||
$paths
|
||||
);
|
||||
}
|
||||
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
|
||||
// Register directories for a new namespace.
|
||||
$length = strlen($prefix);
|
||||
if ('\\' !== $prefix[$length - 1]) {
|
||||
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||
}
|
||||
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||
$this->prefixDirsPsr4[$prefix] = $paths;
|
||||
} elseif ($prepend) {
|
||||
// Prepend directories for an already registered namespace.
|
||||
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||
$paths,
|
||||
$this->prefixDirsPsr4[$prefix]
|
||||
);
|
||||
} else {
|
||||
// Append directories for an already registered namespace.
|
||||
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||
$this->prefixDirsPsr4[$prefix],
|
||||
$paths
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-0 directories for a given prefix,
|
||||
* replacing any others previously set for this prefix.
|
||||
*
|
||||
* @param string $prefix The prefix
|
||||
* @param list<string>|string $paths The PSR-0 base directories
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function set($prefix, $paths)
|
||||
{
|
||||
if (!$prefix) {
|
||||
$this->fallbackDirsPsr0 = (array) $paths;
|
||||
} else {
|
||||
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-4 directories for a given namespace,
|
||||
* replacing any others previously set for this namespace.
|
||||
*
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param list<string>|string $paths The PSR-4 base directories
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setPsr4($prefix, $paths)
|
||||
{
|
||||
if (!$prefix) {
|
||||
$this->fallbackDirsPsr4 = (array) $paths;
|
||||
} else {
|
||||
$length = strlen($prefix);
|
||||
if ('\\' !== $prefix[$length - 1]) {
|
||||
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||
}
|
||||
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||
$this->prefixDirsPsr4[$prefix] = (array) $paths;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns on searching the include path for class files.
|
||||
*
|
||||
* @param bool $useIncludePath
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setUseIncludePath($useIncludePath)
|
||||
{
|
||||
$this->useIncludePath = $useIncludePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Can be used to check if the autoloader uses the include path to check
|
||||
* for classes.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getUseIncludePath()
|
||||
{
|
||||
return $this->useIncludePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns off searching the prefix and fallback directories for classes
|
||||
* that have not been registered with the class map.
|
||||
*
|
||||
* @param bool $classMapAuthoritative
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setClassMapAuthoritative($classMapAuthoritative)
|
||||
{
|
||||
$this->classMapAuthoritative = $classMapAuthoritative;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should class lookup fail if not found in the current class map?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isClassMapAuthoritative()
|
||||
{
|
||||
return $this->classMapAuthoritative;
|
||||
}
|
||||
|
||||
/**
|
||||
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
|
||||
*
|
||||
* @param string|null $apcuPrefix
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setApcuPrefix($apcuPrefix)
|
||||
{
|
||||
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The APCu prefix in use, or null if APCu caching is not enabled.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getApcuPrefix()
|
||||
{
|
||||
return $this->apcuPrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers this instance as an autoloader.
|
||||
*
|
||||
* @param bool $prepend Whether to prepend the autoloader or not
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register($prepend = false)
|
||||
{
|
||||
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
|
||||
|
||||
if (null === $this->vendorDir) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($prepend) {
|
||||
self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
|
||||
} else {
|
||||
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||
self::$registeredLoaders[$this->vendorDir] = $this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters this instance as an autoloader.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function unregister()
|
||||
{
|
||||
spl_autoload_unregister(array($this, 'loadClass'));
|
||||
|
||||
if (null !== $this->vendorDir) {
|
||||
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the given class or interface.
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
* @return true|null True if loaded, null otherwise
|
||||
*/
|
||||
public function loadClass($class)
|
||||
{
|
||||
if ($file = $this->findFile($class)) {
|
||||
$includeFile = self::$includeFile;
|
||||
$includeFile($file);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the path to the file where the class is defined.
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
*
|
||||
* @return string|false The path if found, false otherwise
|
||||
*/
|
||||
public function findFile($class)
|
||||
{
|
||||
// class map lookup
|
||||
if (isset($this->classMap[$class])) {
|
||||
return $this->classMap[$class];
|
||||
}
|
||||
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
|
||||
return false;
|
||||
}
|
||||
if (null !== $this->apcuPrefix) {
|
||||
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
|
||||
if ($hit) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
$file = $this->findFileWithExtension($class, '.php');
|
||||
|
||||
// Search for Hack files if we are running on HHVM
|
||||
if (false === $file && defined('HHVM_VERSION')) {
|
||||
$file = $this->findFileWithExtension($class, '.hh');
|
||||
}
|
||||
|
||||
if (null !== $this->apcuPrefix) {
|
||||
apcu_add($this->apcuPrefix.$class, $file);
|
||||
}
|
||||
|
||||
if (false === $file) {
|
||||
// Remember that this class does not exist.
|
||||
$this->missingClasses[$class] = true;
|
||||
}
|
||||
|
||||
return $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently registered loaders keyed by their corresponding vendor directories.
|
||||
*
|
||||
* @return array<string, self>
|
||||
*/
|
||||
public static function getRegisteredLoaders()
|
||||
{
|
||||
return self::$registeredLoaders;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $class
|
||||
* @param string $ext
|
||||
* @return string|false
|
||||
*/
|
||||
private function findFileWithExtension($class, $ext)
|
||||
{
|
||||
// PSR-4 lookup
|
||||
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
|
||||
|
||||
$first = $class[0];
|
||||
if (isset($this->prefixLengthsPsr4[$first])) {
|
||||
$subPath = $class;
|
||||
while (false !== $lastPos = strrpos($subPath, '\\')) {
|
||||
$subPath = substr($subPath, 0, $lastPos);
|
||||
$search = $subPath . '\\';
|
||||
if (isset($this->prefixDirsPsr4[$search])) {
|
||||
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
|
||||
foreach ($this->prefixDirsPsr4[$search] as $dir) {
|
||||
if (file_exists($file = $dir . $pathEnd)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-4 fallback dirs
|
||||
foreach ($this->fallbackDirsPsr4 as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 lookup
|
||||
if (false !== $pos = strrpos($class, '\\')) {
|
||||
// namespaced class name
|
||||
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
|
||||
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
|
||||
} else {
|
||||
// PEAR-like class name
|
||||
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
|
||||
}
|
||||
|
||||
if (isset($this->prefixesPsr0[$first])) {
|
||||
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
|
||||
if (0 === strpos($class, $prefix)) {
|
||||
foreach ($dirs as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 fallback dirs
|
||||
foreach ($this->fallbackDirsPsr0 as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 include paths.
|
||||
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
private static function initializeIncludeClosure()
|
||||
{
|
||||
if (self::$includeFile !== null) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope isolated include.
|
||||
*
|
||||
* Prevents access to $this/self from included files.
|
||||
*
|
||||
* @param string $file
|
||||
* @return void
|
||||
*/
|
||||
self::$includeFile = \Closure::bind(static function($file) {
|
||||
include $file;
|
||||
}, null, null);
|
||||
}
|
||||
}
|
||||
359
vendor/composer/InstalledVersions.php
vendored
Normal file
359
vendor/composer/InstalledVersions.php
vendored
Normal file
@ -0,0 +1,359 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer;
|
||||
|
||||
use Composer\Autoload\ClassLoader;
|
||||
use Composer\Semver\VersionParser;
|
||||
|
||||
/**
|
||||
* This class is copied in every Composer installed project and available to all
|
||||
*
|
||||
* See also https://getcomposer.org/doc/07-runtime.md#installed-versions
|
||||
*
|
||||
* To require its presence, you can require `composer-runtime-api ^2.0`
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class InstalledVersions
|
||||
{
|
||||
/**
|
||||
* @var mixed[]|null
|
||||
* @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
|
||||
*/
|
||||
private static $installed;
|
||||
|
||||
/**
|
||||
* @var bool|null
|
||||
*/
|
||||
private static $canGetVendors;
|
||||
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||
*/
|
||||
private static $installedByVendor = array();
|
||||
|
||||
/**
|
||||
* Returns a list of all package names which are present, either by being installed, replaced or provided
|
||||
*
|
||||
* @return string[]
|
||||
* @psalm-return list<string>
|
||||
*/
|
||||
public static function getInstalledPackages()
|
||||
{
|
||||
$packages = array();
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
$packages[] = array_keys($installed['versions']);
|
||||
}
|
||||
|
||||
if (1 === \count($packages)) {
|
||||
return $packages[0];
|
||||
}
|
||||
|
||||
return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all package names with a specific type e.g. 'library'
|
||||
*
|
||||
* @param string $type
|
||||
* @return string[]
|
||||
* @psalm-return list<string>
|
||||
*/
|
||||
public static function getInstalledPackagesByType($type)
|
||||
{
|
||||
$packagesByType = array();
|
||||
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
foreach ($installed['versions'] as $name => $package) {
|
||||
if (isset($package['type']) && $package['type'] === $type) {
|
||||
$packagesByType[] = $name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $packagesByType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given package is installed
|
||||
*
|
||||
* This also returns true if the package name is provided or replaced by another package
|
||||
*
|
||||
* @param string $packageName
|
||||
* @param bool $includeDevRequirements
|
||||
* @return bool
|
||||
*/
|
||||
public static function isInstalled($packageName, $includeDevRequirements = true)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (isset($installed['versions'][$packageName])) {
|
||||
return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given package satisfies a version constraint
|
||||
*
|
||||
* e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
|
||||
*
|
||||
* Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
|
||||
*
|
||||
* @param VersionParser $parser Install composer/semver to have access to this class and functionality
|
||||
* @param string $packageName
|
||||
* @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
|
||||
* @return bool
|
||||
*/
|
||||
public static function satisfies(VersionParser $parser, $packageName, $constraint)
|
||||
{
|
||||
$constraint = $parser->parseConstraints((string) $constraint);
|
||||
$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
|
||||
|
||||
return $provided->matches($constraint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a version constraint representing all the range(s) which are installed for a given package
|
||||
*
|
||||
* It is easier to use this via isInstalled() with the $constraint argument if you need to check
|
||||
* whether a given version of a package is installed, and not just whether it exists
|
||||
*
|
||||
* @param string $packageName
|
||||
* @return string Version constraint usable with composer/semver
|
||||
*/
|
||||
public static function getVersionRanges($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$ranges = array();
|
||||
if (isset($installed['versions'][$packageName]['pretty_version'])) {
|
||||
$ranges[] = $installed['versions'][$packageName]['pretty_version'];
|
||||
}
|
||||
if (array_key_exists('aliases', $installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
|
||||
}
|
||||
if (array_key_exists('replaced', $installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
|
||||
}
|
||||
if (array_key_exists('provided', $installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
|
||||
}
|
||||
|
||||
return implode(' || ', $ranges);
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
|
||||
*/
|
||||
public static function getVersion($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($installed['versions'][$packageName]['version'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $installed['versions'][$packageName]['version'];
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
|
||||
*/
|
||||
public static function getPrettyVersion($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($installed['versions'][$packageName]['pretty_version'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $installed['versions'][$packageName]['pretty_version'];
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
|
||||
*/
|
||||
public static function getReference($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($installed['versions'][$packageName]['reference'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $installed['versions'][$packageName]['reference'];
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
|
||||
*/
|
||||
public static function getInstallPath($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
|
||||
*/
|
||||
public static function getRootPackage()
|
||||
{
|
||||
$installed = self::getInstalled();
|
||||
|
||||
return $installed[0]['root'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw installed.php data for custom implementations
|
||||
*
|
||||
* @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
|
||||
* @return array[]
|
||||
* @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}
|
||||
*/
|
||||
public static function getRawData()
|
||||
{
|
||||
@trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
|
||||
|
||||
if (null === self::$installed) {
|
||||
// only require the installed.php file if this file is loaded from its dumped location,
|
||||
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
|
||||
if (substr(__DIR__, -8, 1) !== 'C') {
|
||||
self::$installed = include __DIR__ . '/installed.php';
|
||||
} else {
|
||||
self::$installed = array();
|
||||
}
|
||||
}
|
||||
|
||||
return self::$installed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw data of all installed.php which are currently loaded for custom implementations
|
||||
*
|
||||
* @return array[]
|
||||
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||
*/
|
||||
public static function getAllRawData()
|
||||
{
|
||||
return self::getInstalled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Lets you reload the static array from another file
|
||||
*
|
||||
* This is only useful for complex integrations in which a project needs to use
|
||||
* this class but then also needs to execute another project's autoloader in process,
|
||||
* and wants to ensure both projects have access to their version of installed.php.
|
||||
*
|
||||
* A typical case would be PHPUnit, where it would need to make sure it reads all
|
||||
* the data it needs from this class, then call reload() with
|
||||
* `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
|
||||
* the project in which it runs can then also use this class safely, without
|
||||
* interference between PHPUnit's dependencies and the project's dependencies.
|
||||
*
|
||||
* @param array[] $data A vendor/composer/installed.php data set
|
||||
* @return void
|
||||
*
|
||||
* @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $data
|
||||
*/
|
||||
public static function reload($data)
|
||||
{
|
||||
self::$installed = $data;
|
||||
self::$installedByVendor = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||
*/
|
||||
private static function getInstalled()
|
||||
{
|
||||
if (null === self::$canGetVendors) {
|
||||
self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
|
||||
}
|
||||
|
||||
$installed = array();
|
||||
|
||||
if (self::$canGetVendors) {
|
||||
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
|
||||
if (isset(self::$installedByVendor[$vendorDir])) {
|
||||
$installed[] = self::$installedByVendor[$vendorDir];
|
||||
} elseif (is_file($vendorDir.'/composer/installed.php')) {
|
||||
/** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
|
||||
$required = require $vendorDir.'/composer/installed.php';
|
||||
$installed[] = self::$installedByVendor[$vendorDir] = $required;
|
||||
if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
|
||||
self::$installed = $installed[count($installed) - 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (null === self::$installed) {
|
||||
// only require the installed.php file if this file is loaded from its dumped location,
|
||||
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
|
||||
if (substr(__DIR__, -8, 1) !== 'C') {
|
||||
/** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
|
||||
$required = require __DIR__ . '/installed.php';
|
||||
self::$installed = $required;
|
||||
} else {
|
||||
self::$installed = array();
|
||||
}
|
||||
}
|
||||
|
||||
if (self::$installed !== array()) {
|
||||
$installed[] = self::$installed;
|
||||
}
|
||||
|
||||
return $installed;
|
||||
}
|
||||
}
|
||||
21
vendor/composer/LICENSE
vendored
Normal file
21
vendor/composer/LICENSE
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
|
||||
Copyright (c) Nils Adermann, Jordi Boggiano
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
10
vendor/composer/autoload_classmap.php
vendored
Normal file
10
vendor/composer/autoload_classmap.php
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
// autoload_classmap.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
|
||||
);
|
||||
11
vendor/composer/autoload_files.php
vendored
Normal file
11
vendor/composer/autoload_files.php
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
// autoload_files.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'8653524d908cf23a56335c6d210d6627' => $vendorDir . '/abuyoyo/adminmenupage/wph_admin_page.php',
|
||||
'd8f9115e9a479bb7bf2fea8e74fb82f0' => $vendorDir . '/abuyoyo/screen-meta-links/screen-meta-links.php',
|
||||
);
|
||||
9
vendor/composer/autoload_namespaces.php
vendored
Normal file
9
vendor/composer/autoload_namespaces.php
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
// autoload_namespaces.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
);
|
||||
10
vendor/composer/autoload_psr4.php
vendored
Normal file
10
vendor/composer/autoload_psr4.php
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
// autoload_psr4.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'WPHelper\\' => array($vendorDir . '/abuyoyo/adminmenupage/src', $vendorDir . '/abuyoyo/metabox', $vendorDir . '/abuyoyo/plugincore'),
|
||||
);
|
||||
48
vendor/composer/autoload_real.php
vendored
Normal file
48
vendor/composer/autoload_real.php
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
// autoload_real.php @generated by Composer
|
||||
|
||||
class ComposerAutoloaderInita13a895834453aad32a897cc456c73ff
|
||||
{
|
||||
private static $loader;
|
||||
|
||||
public static function loadClassLoader($class)
|
||||
{
|
||||
if ('Composer\Autoload\ClassLoader' === $class) {
|
||||
require __DIR__ . '/ClassLoader.php';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Composer\Autoload\ClassLoader
|
||||
*/
|
||||
public static function getLoader()
|
||||
{
|
||||
if (null !== self::$loader) {
|
||||
return self::$loader;
|
||||
}
|
||||
|
||||
spl_autoload_register(array('ComposerAutoloaderInita13a895834453aad32a897cc456c73ff', 'loadClassLoader'), true, true);
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInita13a895834453aad32a897cc456c73ff', 'loadClassLoader'));
|
||||
|
||||
require __DIR__ . '/autoload_static.php';
|
||||
call_user_func(\Composer\Autoload\ComposerStaticInita13a895834453aad32a897cc456c73ff::getInitializer($loader));
|
||||
|
||||
$loader->register(true);
|
||||
|
||||
$filesToLoad = \Composer\Autoload\ComposerStaticInita13a895834453aad32a897cc456c73ff::$files;
|
||||
$requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
|
||||
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
||||
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
|
||||
|
||||
require $file;
|
||||
}
|
||||
}, null, null);
|
||||
foreach ($filesToLoad as $fileIdentifier => $file) {
|
||||
$requireFile($fileIdentifier, $file);
|
||||
}
|
||||
|
||||
return $loader;
|
||||
}
|
||||
}
|
||||
43
vendor/composer/autoload_static.php
vendored
Normal file
43
vendor/composer/autoload_static.php
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
// autoload_static.php @generated by Composer
|
||||
|
||||
namespace Composer\Autoload;
|
||||
|
||||
class ComposerStaticInita13a895834453aad32a897cc456c73ff
|
||||
{
|
||||
public static $files = array (
|
||||
'8653524d908cf23a56335c6d210d6627' => __DIR__ . '/..' . '/abuyoyo/adminmenupage/wph_admin_page.php',
|
||||
'd8f9115e9a479bb7bf2fea8e74fb82f0' => __DIR__ . '/..' . '/abuyoyo/screen-meta-links/screen-meta-links.php',
|
||||
);
|
||||
|
||||
public static $prefixLengthsPsr4 = array (
|
||||
'W' =>
|
||||
array (
|
||||
'WPHelper\\' => 9,
|
||||
),
|
||||
);
|
||||
|
||||
public static $prefixDirsPsr4 = array (
|
||||
'WPHelper\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/abuyoyo/adminmenupage/src',
|
||||
1 => __DIR__ . '/..' . '/abuyoyo/metabox',
|
||||
2 => __DIR__ . '/..' . '/abuyoyo/plugincore',
|
||||
),
|
||||
);
|
||||
|
||||
public static $classMap = array (
|
||||
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
|
||||
);
|
||||
|
||||
public static function getInitializer(ClassLoader $loader)
|
||||
{
|
||||
return \Closure::bind(function () use ($loader) {
|
||||
$loader->prefixLengthsPsr4 = ComposerStaticInita13a895834453aad32a897cc456c73ff::$prefixLengthsPsr4;
|
||||
$loader->prefixDirsPsr4 = ComposerStaticInita13a895834453aad32a897cc456c73ff::$prefixDirsPsr4;
|
||||
$loader->classMap = ComposerStaticInita13a895834453aad32a897cc456c73ff::$classMap;
|
||||
|
||||
}, null, ClassLoader::class);
|
||||
}
|
||||
}
|
||||
152
vendor/composer/installed.json
vendored
Normal file
152
vendor/composer/installed.json
vendored
Normal file
@ -0,0 +1,152 @@
|
||||
{
|
||||
"packages": [
|
||||
{
|
||||
"name": "abuyoyo/adminmenupage",
|
||||
"version": "0.29",
|
||||
"version_normalized": "0.29.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/abuyoyo/AdminMenuPage.git",
|
||||
"reference": "4cd47d5217ca25ed17af76f5fdbab3cab3b37ef8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/abuyoyo/AdminMenuPage/zipball/4cd47d5217ca25ed17af76f5fdbab3cab3b37ef8",
|
||||
"reference": "4cd47d5217ca25ed17af76f5fdbab3cab3b37ef8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"abuyoyo/metabox": "~0.8"
|
||||
},
|
||||
"suggest": {
|
||||
"abuyoyo/plugincore": "~0.26",
|
||||
"cmb2/cmb2": "~2.9"
|
||||
},
|
||||
"time": "2023-10-05T00:00:00+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"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.29"
|
||||
},
|
||||
"install-path": "../abuyoyo/adminmenupage"
|
||||
},
|
||||
{
|
||||
"name": "abuyoyo/metabox",
|
||||
"version": "0.8",
|
||||
"version_normalized": "0.8.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/abuyoyo/MetaBox.git",
|
||||
"reference": "98cb4c30db4c366c0d273985eb9c31ffa1cd78f9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/abuyoyo/MetaBox/zipball/98cb4c30db4c366c0d273985eb9c31ffa1cd78f9",
|
||||
"reference": "98cb4c30db4c366c0d273985eb9c31ffa1cd78f9",
|
||||
"shasum": ""
|
||||
},
|
||||
"time": "2023-07-18T19:14:03+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"WPHelper\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"description": "WordPress metabox helper class",
|
||||
"support": {
|
||||
"issues": "https://github.com/abuyoyo/MetaBox/issues",
|
||||
"source": "https://github.com/abuyoyo/MetaBox/tree/0.8"
|
||||
},
|
||||
"install-path": "../abuyoyo/metabox"
|
||||
},
|
||||
{
|
||||
"name": "abuyoyo/plugincore",
|
||||
"version": "0.27",
|
||||
"version_normalized": "0.27.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/abuyoyo/PluginCore.git",
|
||||
"reference": "d730a674cbe2dc92e60ace8e25a2e0e3fdeee3e6"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/abuyoyo/PluginCore/zipball/d730a674cbe2dc92e60ace8e25a2e0e3fdeee3e6",
|
||||
"reference": "d730a674cbe2dc92e60ace8e25a2e0e3fdeee3e6",
|
||||
"shasum": ""
|
||||
},
|
||||
"suggest": {
|
||||
"abuyoyo/adminmenupage": "~0.27",
|
||||
"yahnis-elsts/plugin-update-checker": "~5.2"
|
||||
},
|
||||
"time": "2022-10-03T00:00:00+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"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.27"
|
||||
},
|
||||
"install-path": "../abuyoyo/plugincore"
|
||||
},
|
||||
{
|
||||
"name": "abuyoyo/screen-meta-links",
|
||||
"version": "0.13",
|
||||
"version_normalized": "0.13.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/abuyoyo/screen-meta-links.git",
|
||||
"reference": "b324cef9eb5825d04ffa17f771237b7deca5cd01"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/abuyoyo/screen-meta-links/zipball/b324cef9eb5825d04ffa17f771237b7deca5cd01",
|
||||
"reference": "b324cef9eb5825d04ffa17f771237b7deca5cd01",
|
||||
"shasum": ""
|
||||
},
|
||||
"time": "2023-08-08T22:37:03+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"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.13",
|
||||
"issues": "https://github.com/abuyoyo/screen-meta-links/issues"
|
||||
},
|
||||
"install-path": "../abuyoyo/screen-meta-links"
|
||||
}
|
||||
],
|
||||
"dev": true,
|
||||
"dev-package-names": []
|
||||
}
|
||||
59
vendor/composer/installed.php
vendored
Normal file
59
vendor/composer/installed.php
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
<?php return array(
|
||||
'root' => array(
|
||||
'name' => 'abuyoyo/notice-manager',
|
||||
'pretty_version' => '0.25',
|
||||
'version' => '0.25.0.0',
|
||||
'reference' => NULL,
|
||||
'type' => 'wordpress-plugin',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
'dev' => true,
|
||||
),
|
||||
'versions' => array(
|
||||
'abuyoyo/adminmenupage' => array(
|
||||
'pretty_version' => '0.29',
|
||||
'version' => '0.29.0.0',
|
||||
'reference' => '4cd47d5217ca25ed17af76f5fdbab3cab3b37ef8',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../abuyoyo/adminmenupage',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'abuyoyo/metabox' => array(
|
||||
'pretty_version' => '0.8',
|
||||
'version' => '0.8.0.0',
|
||||
'reference' => '98cb4c30db4c366c0d273985eb9c31ffa1cd78f9',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../abuyoyo/metabox',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'abuyoyo/notice-manager' => array(
|
||||
'pretty_version' => '0.25',
|
||||
'version' => '0.25.0.0',
|
||||
'reference' => NULL,
|
||||
'type' => 'wordpress-plugin',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'abuyoyo/plugincore' => array(
|
||||
'pretty_version' => '0.27',
|
||||
'version' => '0.27.0.0',
|
||||
'reference' => 'd730a674cbe2dc92e60ace8e25a2e0e3fdeee3e6',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../abuyoyo/plugincore',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'abuyoyo/screen-meta-links' => array(
|
||||
'pretty_version' => '0.13',
|
||||
'version' => '0.13.0.0',
|
||||
'reference' => 'b324cef9eb5825d04ffa17f771237b7deca5cd01',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../abuyoyo/screen-meta-links',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
),
|
||||
);
|
||||
Loading…
Reference in New Issue
Block a user