Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: enqueue script and stylesheet with notice #10

Merged
merged 23 commits into from
Nov 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
43a1999
feature: improve custom notice support
JasonTheAdams Nov 15, 2024
2af852b
feature: improves custom clearing
JasonTheAdams Nov 15, 2024
9af13c2
feature: applies attributes to custom notice html
JasonTheAdams Nov 15, 2024
e49e265
fix: explicitly types parameter to pass static analysis
JasonTheAdams Nov 15, 2024
b76fde4
test: fixes failing tests
JasonTheAdams Nov 15, 2024
057fcf5
test: updates WithUopz trait to later version
JasonTheAdams Nov 18, 2024
5269820
test: add custom attribute tests
JasonTheAdams Nov 18, 2024
1392069
test: tests new AdminNotice methods
JasonTheAdams Nov 18, 2024
93461f9
chore: links elements object to code in readme
JasonTheAdams Nov 18, 2024
872af37
chore: improves inline comments
JasonTheAdams Nov 18, 2024
8cebd9c
test: adds test for NoticeLocation VO
JasonTheAdams Nov 18, 2024
3ccd34e
Merge branch 'main' into feature/custom-notice-closing
JasonTheAdams Nov 18, 2024
08add33
refactor: cleans up logic a bit
JasonTheAdams Nov 18, 2024
f3e6382
feature: adds support for notice script and stylesheet
JasonTheAdams Nov 19, 2024
51a5efc
refactor: renames enqueueStyle to enqueueStylesheet
JasonTheAdams Nov 19, 2024
e5976f2
refactor: adds inline comments and rename enqueue class
JasonTheAdams Nov 19, 2024
c8af4d5
chore: adds inline comments
JasonTheAdams Nov 19, 2024
20620de
refactor: adds NoticeLocation constants
JasonTheAdams Nov 19, 2024
8c8af8f
refactor: simplify close attributes DTO method
JasonTheAdams Nov 19, 2024
3885a22
refactor: cleans up element properties DTO and switch to mark-dismissed
JasonTheAdams Nov 19, 2024
fbe208c
Merge branch 'feature/custom-notice-closing' into feature/notice-scripts
JasonTheAdams Nov 19, 2024
1c2d728
Merge branch 'main' into feature/notice-scripts
JasonTheAdams Nov 19, 2024
b64ff31
test: resolves duplicate method from merge
JasonTheAdams Nov 19, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,36 @@ dismissible notices.
If you want the notice to be marked as dismissed, but not fade out, you can pass "clear" to the
`customerCloserAttributes` method: e.g. `$elements->customCloserAttributes('clear')`.

## Custom scripts & styles

Often times, especially for custom notices, you may want to enqueue custom scripts and styles,
however they should only be enqueued when the notice is displayed. This can be done by using the
`enqueueScript` and `enqueueStyle` methods on the notice.

### `enqueueScript($src, $deps = [], $ver = false, $args = [])`

Enqueues a script to be loaded when the notice is displayed, following the same parameters as
`wp_enqueue_script`. The only difference is that the loading strategy is "defer" by default.

```php
use StellarWP\AdminNotices\AdminNotices;

$notice = AdminNotices::show('my_notice', 'This is a notice')
->enqueueScript('https://example.com/my-script.js', ['jquery']);
```

### `enqueueStyle($src, $deps = [], $ver = false, $media = 'all')`

Enqueues a style to be loaded when the notice is displayed, following the same parameters as
`wp_enqueue_style`.

```php
use StellarWP\AdminNotices\AdminNotices;

$notice = AdminNotices::show('my_notice', 'This is a notice')
->enqueueStylesheet('https://example.com/my-style.css');
```

## Resetting dismissed notices

For dismissible notices, when the user dismisses the notice, it is permanently dismissed. If you
Expand Down
150 changes: 1 addition & 149 deletions src/Actions/DisplayNoticesInAdmin.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@

namespace StellarWP\AdminNotices\Actions;

use DateTimeImmutable;
use DateTimeZone;
use StellarWP\AdminNotices\AdminNotice;
use StellarWP\AdminNotices\Traits\HasNamespace;

Expand All @@ -31,156 +29,10 @@ public function __invoke(AdminNotice ...$notices)
}

foreach ($notices as $notice) {
if ($this->shouldDisplayNotice($notice)) {
if ((new NoticeShouldRender($this->namespace))($notice)) {
echo (new RenderAdminNotice($this->namespace))($notice);
}
}
}

/**
* Checks whether the notice should be displayed based on the provided conditions.
*
* @since 1.0.0
*/
private function shouldDisplayNotice(AdminNotice $notice): bool
{
return $this->passesDismissedConditions($notice)
&& $this->passesDateLimits($notice)
&& $this->passesWhenCallback($notice)
&& $this->passesUserCapabilities($notice)
&& $this->passesScreenConditions($notice);
}

/**
* Checks whether the notice should be displayed based on the provided date limits.
*
* @since 1.0.0
*/
private function passesDateLimits(AdminNotice $notice): bool
{
if (!$notice->getAfterDate() && !$notice->getUntilDate()) {
return true;
}

$now = new DateTimeImmutable('now', new DateTimeZone('UTC'));

if ($notice->getAfterDate() && $notice->getAfterDate() > $now) {
return false;
}

if ($notice->getUntilDate() && $notice->getUntilDate() < $now) {
return false;
}

return true;
}

/**
* Checks whether the notice should be displayed based on the provided callback.
*
* @since 1.0.0
*/
private function passesWhenCallback(AdminNotice $notice): bool
{
$callback = $notice->getWhenCallback();

if ($callback === null) {
return true;
}

return $callback();
}

/**
* Checks whether user limits were provided and they pass. Only one capability is required to pass, allowing for
* multiple users have visibility.
*
* @since 1.0.0
*/
private function passesUserCapabilities(AdminNotice $notice): bool
{
$capabilities = $notice->getUserCapabilities();

if (empty($capabilities)) {
return true;
}

foreach ($capabilities as $capability) {
if ($capability->currentUserCan()) {
return true;
}
}

return false;
}

/**
* Checks whether the notice is limited to specific screens and the current screen matches the conditions. Only one
* screen condition is required to pass, allowing for the notice to appear on multiple screens.
*
* @since 1.0.0
*/
private function passesScreenConditions(AdminNotice $notice): bool
{
$screenConditions = $notice->getOnConditions();

if (empty($screenConditions)) {
return true;
}

$screen = get_current_screen();
$currentUrl = get_admin_url(null, $_SERVER['REQUEST_URI']);

foreach ($screenConditions as $screenCondition) {
$condition = $screenCondition->getCondition();

if ($screenCondition->isRegex()) {
// do a regex comparison on the current url
if (preg_match($condition, $currentUrl) === 1) {
return true;
}
} elseif (is_string($condition)) {
// do a string comparison on the current url
if (strpos($currentUrl, $condition) !== false) {
return true;
}
} else {
// compare the condition array against the WP_Screen object
foreach ($condition as $property => $value) {
if ($screen->$property === $value) {
return true;
}
}
}
}

return false;
}

/**
* Checks whether the notice has been dismissed by the user.
*
* @since 1.1.0 added namespacing to the preferences key
* @since 1.0.0
*/
private function passesDismissedConditions(AdminNotice $notice): bool
{
global $wpdb;

$userPreferences = get_user_meta(get_current_user_id(), $wpdb->get_blog_prefix() . 'persisted_preferences', true);

$key = "stellarwp/admin-notices/$this->namespace";
if (!is_array($userPreferences) || empty($userPreferences[$key])) {
return true;
}

$dismissedNotices = $userPreferences[$key];

if (key_exists($notice->getId(), $dismissedNotices)) {
return false;
}

return true;
}
}

40 changes: 40 additions & 0 deletions src/Actions/EnqueueNoticesScriptsAndStyles.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

declare(strict_types=1);


namespace StellarWP\AdminNotices\Actions;

use StellarWP\AdminNotices\AdminNotice;
use StellarWP\AdminNotices\Traits\HasNamespace;

/**
* Checks the given admin notices and enqueues their scripts and styles if they exist and should be rendered.
*
* @unreleased
*/
class EnqueueNoticesScriptsAndStyles
{
use HasNamespace;

/**
* @unreleased
*/
public function __invoke(AdminNotice ...$notices)
{
foreach ($notices as $notice) {
$script = $notice->getScriptToEnqueue();
$style = $notice->getStyleToEnqueue();

if (($script || $style) && (new NoticeShouldRender($this->namespace))($notice)) {
if ($script) {
$script->enqueue("stellarwp-{$this->namespace}-{$notice->getId()}");
}

if ($style) {
$style->enqueue("stellarwp-{$this->namespace}-{$notice->getId()}");
}
}
}
}
}
Loading
Loading