Skip to content

Commit 936b0a9

Browse files
authored
wp-widget-control: base feature (#1)
* Sidebar storage * Widget storage * Require support * Wrapping up widget instance * WIP * WIP * WIP * Abstract widget instances to dto * Remove prepend from instances * Use generic * Wrapping up bulk * Adding the base features * Finishing up * Doc update * Formatting * README feedback * CR Feedback * Dont call save * PHPStan improve * CR feedback * Remove the storage namespace * Fixing phpstan
1 parent 2fdab04 commit 936b0a9

16 files changed

+1407
-41
lines changed

CHANGELOG.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Changelog
22

3-
All notable changes to `Create PHP Package` will be documented in this file.
3+
All notable changes to `WP Widget Control` will be documented in this file.
44

5-
## 0.1.0 - 202X-XX-XX
5+
## 0.1.0
66

77
- Initial release

README.md

Lines changed: 167 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,175 @@ composer require alleyinteractive/wp-widget-control
1414

1515
## Usage
1616

17-
Use this package like so:
17+
WP Widget Control lets you programmatically manage WordPress sidebars and
18+
widgets. This can be useful for setting up default widget configurations,
19+
managing widget curation with code for end to end testing, or simply
20+
maintaining widget state in a more structured way.
21+
22+
When you have to manage widgets with code, WordPress doesn't provide a great way
23+
to do that. WP Widget Control fills this gap by providing a simple API for
24+
managing widgets programmatically.
25+
26+
Here are some common usage patterns:
27+
28+
### Retrieve a Sidebar
29+
30+
```php
31+
use Alley\WP\Widget_Control\Sidebar;
32+
33+
$sidebar = Sidebar::from( 'sidebar-1' );
34+
```
35+
36+
### Append a Widget to a Sidebar
37+
38+
```php
39+
use Alley\WP\Widget_Control\Sidebar;
40+
use Alley\WP\Widget_Control\Widget;
41+
42+
$sidebar = Sidebar::from( 'sidebar-1' );
43+
44+
// Append a widget by its ID:
45+
$sidebar->append( 'example_widget-4' );
46+
47+
// You can create a new widget instance from the base ID and append it to the sidebar:
48+
$sidebar->append(
49+
Widget::from( 'example_widget' )->append( [ 'content' => 'Hello, World!' ] ),
50+
);
51+
52+
// Or by referencing the widget's class:
53+
$sidebar->append(
54+
Widget::from( \My\Custom\ExampleWidget::class )->append( [ 'content' => 'Hello, World!' ] ),
55+
);
56+
57+
// Save the sidebar to persist changes.
58+
$sidebar->save();
59+
```
60+
61+
### Insert Widgets Before or After Another Widget
62+
63+
```php
64+
use Alley\WP\Widget_Control\Sidebar;
65+
use Alley\WP\Widget_Control\Widget;
66+
67+
$sidebar = Sidebar::from( 'sidebar-1' );
68+
69+
// Insert a widget "block-99" before "block-2":
70+
$sidebar->insert_before( widget: 'block-99', before_widget_id: 'block-2' );
71+
72+
// Insert a widget "example_widget-6" after "example_widget-2":
73+
$sidebar->insert_after( widget: 'example_widget-6', after_widget_id: 'example_widget-2' );
74+
75+
// Also supports inserting a widget instance directly.
76+
// Inside a new widget instance before "example_widget-2":
77+
$sidebar->insert_before(
78+
widget: Widget::from( 'example_widget' )->append( [ 'content' => 'Hello, World!' ] ),
79+
before_widget_id: 'example_widget-2',
80+
);
81+
82+
// Save the sidebar to persist changes.
83+
$sidebar->save();
84+
```
85+
86+
### Remove a Widget by ID or Index
87+
88+
```php
89+
use Alley\WP\Widget_Control\Sidebar;
90+
use Alley\WP\Widget_Control\Widget_Instance;
91+
92+
$sidebar = Sidebar::from( 'sidebar-1' );
93+
94+
// Remove a widget by its ID:
95+
$sidebar->remove( 'block-2' );
96+
97+
// Remove a widget by its index:
98+
$sidebar->remove_index( 2 );
99+
100+
// Save the sidebar to persist changes.
101+
$sidebar->save();
102+
```
103+
104+
### Set All Widgets in a Sidebar
105+
106+
```php
107+
use Alley\WP\Widget_Control\Sidebar;
108+
use Alley\WP\Widget_Control\Widget;
109+
110+
$sidebar = Sidebar::from( 'sidebar-1' );
111+
112+
$sidebar->set( [
113+
// Use existing widget instances (they follow a widget_base-ID pattern).
114+
'nav_menu-1',
115+
'block-2',
116+
'example_widget-2',
117+
118+
// You can also create a new widget instance and append it to the sidebar.
119+
Widget::from( 'example_widget' )->append( [ 'content' => 'Hello, World!' ] ),
120+
Widget::from( \My\Custom\ExampleWidget::class )->append( [ 'content' => 'Hello, World!' ] ),
121+
] );
122+
123+
// Save the sidebar to persist changes.
124+
$sidebar->save();
125+
```
126+
127+
### Filter Widgets in a Sidebar
128+
129+
Remove a specific widget from a sidebar while keeping others:
18130

19131
```php
20-
$package = Create_PHP_Package\WP_Widget_Control\WP_Widget_Control();
21-
$package->perform_magic();
132+
use Alley\WP\Widget_Control\Sidebar;
133+
use Alley\WP\Widget_Control\Widget;
134+
use Alley\WP\Widget_Control\Widget_Instance;
135+
136+
$sidebar = Sidebar::from( 'sidebar-1' );
137+
138+
// Remove all widgets whose ID contains 'example_widget'.
139+
$sidebar->filter_by_id( function( string $widget_id ) {
140+
return ! str_contains( $widget_id, 'example_widget' );
141+
} );
142+
143+
// Keep only widgets of a certain type (using Widget_Instance).
144+
$sidebar->filter( function( Widget_Instance $widget ) {
145+
return $widget->id_base === 'example_widget';
146+
} );
147+
148+
// Save the sidebar to persist changes.
149+
$sidebar->save();
22150
```
23151

152+
### Clear All Widgets from a Sidebar
153+
154+
```php
155+
use Alley\WP\Widget_Control\Sidebar;
156+
157+
$sidebar = Sidebar::from( 'sidebar-1' );
158+
159+
$sidebar->clear();
160+
161+
// Save the sidebar to persist changes.
162+
$sidebar->save();
163+
```
164+
165+
### Full Sidebar Curation Example
166+
167+
In this example, we will set the sidebar to contain an instance of
168+
`ExampleWidget` and another instance of the `block` widget:
169+
170+
```php
171+
use Alley\WP\Widget_Control\Sidebar;
172+
use Alley\WP\Widget_Control\Widget;
173+
use Alley\WP\Widget_Control\Tests\ExampleWidget;
174+
175+
$sidebar->set( [
176+
Widget::from( ExampleWidget::class )->append( [ 'content' => 'Hello, World! 1' ] ),
177+
Widget::from( 'block' )->append( [ 'content' => 'Hello, World! 2' ] ),
178+
] );
179+
180+
// Save the sidebar to persist changes.
181+
$sidebar->save();
182+
```
183+
184+
These will be the only two widgets in the sidebar.
185+
24186
## Changelog
25187

26188
Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.
@@ -31,9 +193,9 @@ This project is actively maintained by [Alley
31193
Interactive](https://github.com/alleyinteractive). Like what you see? [Come work
32194
with us](https://alley.co/careers/).
33195

34-
- [Sean Fisher](https://github.com/Sean Fisher)
196+
- [Sean Fisher](https://github.com/srtfisher)
35197
- [All Contributors](../../contributors)
36198

37199
## License
38200

39-
The GNU General Public License (GPL) license. Please see [License File](LICENSE) for more information.
201+
The GNU General Public License (GPL) license. Please see [License File](LICENSE) for more information.

composer.json

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
],
1717
"require": {
1818
"php": "^8.2",
19-
"alleyinteractive/composer-wordpress-autoloader": "^1.0"
19+
"alleyinteractive/composer-wordpress-autoloader": "^1.0",
20+
"mantle-framework/support": "^1.5"
2021
},
2122
"require-dev": {
2223
"alleyinteractive/alley-coding-standards": "^2.0",
@@ -31,15 +32,20 @@
3132
},
3233
"sort-packages": true
3334
},
35+
"autoload": {
36+
"files": [
37+
"src/autoload.php"
38+
]
39+
},
3440
"autoload-dev": {
3541
"psr-4": {
36-
"Alley\\WP\\WP_Widget_Control\\Tests\\": "tests"
42+
"Alley\\WP\\Widget_Control\\Tests\\": "tests"
3743
}
3844
},
3945
"extra": {
4046
"wordpress-autoloader": {
4147
"autoload": {
42-
"Alley\\WP\\WP_Widget_Control\\": "src"
48+
"Alley\\WP\\Widget_Control\\": "src"
4349
}
4450
}
4551
},

src/autoload.php

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
/**
3+
* Helper functions for WP Widget Control.
4+
*
5+
* @package wp-widget-control
6+
*/
7+
8+
namespace Alley\WP\Widget_Control;
9+
10+
/**
11+
* Reload the widgets available to WordPress.
12+
*
13+
* This is a workaround to be able to set the widgets and then use them right
14+
* away in tests. This should not be used outside of tests.
15+
*/
16+
function reload_widgets(): void {
17+
if ( ! defined( 'MANTLE_IS_TESTING' ) || ! MANTLE_IS_TESTING ) {
18+
_doing_it_wrong(
19+
__FUNCTION__,
20+
'This function should only be used in tests.',
21+
'1.0.0',
22+
);
23+
}
24+
25+
$GLOBALS['wp_widget_factory'] = new \WP_Widget_Factory(); // phpcs:ignore WordPress.WP.GlobalVariablesOverride
26+
27+
$GLOBALS['wp_registered_widgets'] = []; // phpcs:ignore WordPress.WP.GlobalVariablesOverride
28+
29+
wp_widgets_init();
30+
}

0 commit comments

Comments
 (0)