1 <?php
2
3 /**
4 * Vanilla widgets enhanced with ACF.
5 *
6 * @author Nevma, http://www.nevma.gr, info@nevma.gr
7 *
8 * @license http://www.gnu.org/licenses/gpl-3.0.en.html GPLv3
9 */
10
11
12
13 /**
14 * Vanilla Widget class. Implements a general-purpose widget, mainly but not
15 * necessarily, intended to be used in combination with ACF.
16 *
17 * @extends WP_Widget
18 */
19
20 abstract class Vanilla_Widget extends WP_Widget {
21
22 /**
23 * Class constructor.
24 */
25
26 function __construct () {
27
28 // The name of the class that the user ended up creating by dynamically extending this class
29
30 $child_class = get_called_class();
31
32 $widget_id = strtolower( $child_class );
33 $widget_name = $child_class;
34
35 parent::__construct(
36 $widget_id,
37 str_ireplace( '_', ' ', $widget_name ),
38 array( 'description' => __( 'A general purpose widget customisable via ACF.', 'nevma-theme' ), )
39 );
40
41 }
42
43
44
45 /**
46 * Displays the widget's output on the front-end.
47 *
48 * @param array $args The widget args, passed by WordPress.
49 * @param array $instance The widget instance, passed by WordPress.
50 */
51
52 public function widget ( $args, $instance ) {
53
54 // Before and after widget arguments are defined by themes
55
56 echo $args['before_widget'];
57
58 $title = apply_filters( 'widget_title', $instance['title'] );
59
60 if ( ! empty( $title ) ) {
61
62 // Before and after title arguments are defined by themes
63
64 echo $args['before_title'] . $title . $args['after_title'];
65
66 }
67
68 $user_callback = static::$vanilla_callback;
69
70 $widget_id = $args['widget_id'];
71
72 if ( function_exists( $user_callback) ) {
73 call_user_func( $user_callback, $widget_id );
74 } else {
75 echo '<p>' . __( 'Callback function does not exist.', 'nevma-theme' ) . '</p>';
76 }
77
78 // Before and after widget arguments are defined by themes
79
80 echo $args['after_widget'];
81
82 }
83
84
85
86 /**
87 * Displays the markup for the widget back-end.
88 *
89 * @param array $instance The widget instance.
90 */
91
92 public function form ( $instance ) {
93
94 // Display the title if set, or a default one otherwise.
95
96 $title = isset( $instance['title'] ) ? $instance['title'] : ''; ?>
97
98 <p>
99 <label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php _e( 'Title:' ); ?></label>
100
101 <input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>" />
102 </p> <?php
103
104 }
105
106
107
108 /**
109 * Sanitizes the new widget settings during update.
110 *
111 * @param array $new_instance The new widget instance.
112 * @param array $old_instance The old widget instance, prior to
113 * updating.
114 *
115 * @return array|boolean The new instance, sanitized.
116 */
117
118 public function update ( $new_instance, $old_instance ) {
119
120 $instance = array();
121
122 $instance['title'] = ! empty( $new_instance['title'] ) ? strip_tags( $new_instance['title'] ) : '';
123
124 return $instance;
125
126 }
127
128
129
130 /**
131 * Registers the widget in WordPress.
132 */
133
134 public static function register () {
135
136 // Invoke the child class at registration!
137
138 register_widget( get_called_class() );
139
140 }
141
142 }
143
144
145
146 /**
147 * Registers a new Vanilla Widget
148 *
149 * @param string $widget_name A unique widget name, containing only
150 * alphanumeric characters and underscores.
151 * @param string $callback A valid PHP callback to display the widget
152 * output. The widget id will be passed to it.
153 *
154 * @return boolean True on success, or false if the class already exists, or
155 * the widget name is invalid.
156 */
157
158 function vanilla_widgets_register ( $widget_name, $callback ) {
159
160 $class_name = 'Vanilla_Widget_' . $widget_name;
161
162 if ( class_exists( $class_name ) ) {
163 return false;
164 }
165
166 /**
167 * @todo Make sure you've done some really damn good validation on the
168 * widget name at this point!
169 */
170
171 // Get the actual Vanilla_Widget child-class declaration by customizing the boilerplate.
172
173 $class_declaration = vanilla_widgets_get_class_declaration( $class_name, $callback );
174
175 // Create the class by evaluating the declaration.
176
177 eval( $class_declaration );
178
179 // Schedule the registration of the widget.
180
181 add_action( 'widgets_init', array( $class_name, 'register' ) );
182 }
183
184
185
186 /**
187 * Creates and returns the proper declaration of a widget class that extends
188 * Vanilla_Widget.
189 *
190 * @param string $class_name The class name.
191 * @param string $callback A valid PHP callback.
192 *
193 * @return string The class declaration.
194 */
195
196 function vanilla_widgets_get_class_declaration ( $class_name, $callback ) {
197
198 ob_start(); ?>
199
200 class <?php echo $class_name; ?> extends Vanilla_Widget {
201
202 protected static $vanilla_callback = '<?php echo $callback; ?>';
203
204 function __construct() {
205 parent::__construct();
206 }
207
208 } <?php
209
210 return ob_get_clean();
211
212 }
213
214 ?>