Passed
Push — master ( 83bd91...24b191 )
by Glynn
03:34 queued 54s
created

set_view_callback_from_renderable()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 20
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 9
c 2
b 0
f 0
dl 0
loc 20
rs 9.9666
cc 3
nc 2
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * Registration Registrar for all post types.
7
 *
8
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
9
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
10
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
11
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
12
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
13
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
14
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
15
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
16
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
17
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
18
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
19
 *
20
 * @author Glynn Quelch <[email protected]>
21
 * @license http://www.opensource.org/licenses/mit-license.html  MIT License
22
 * @package PinkCrab\Registerables
23
 */
24
25
namespace PinkCrab\Registerables\Registrar;
26
27
use Exception;
28
use PinkCrab\Loader\Hook_Loader;
29
use PinkCrab\Registerables\Meta_Box;
30
use PinkCrab\Perique\Services\View\View;
31
use PinkCrab\Perique\Interfaces\DI_Container;
32
use PinkCrab\Registerables\Validator\Meta_Box_Validator;
33
34
class Meta_Box_Registrar {
35
36
	/**
37
	 * @var Meta_Box_Validator
38
	 */
39
	protected $validator;
40
41
	/**
42
	 * @var DI_Container
43
	 */
44
	protected $container;
45
46
	/**
47
	 * @var Hook_Loader
48
	 */
49
	protected $loader;
50
51
	public function __construct(
52
		Meta_Box_Validator $validator,
53
		DI_Container $container,
54
		Hook_Loader $loader
55
	) {
56
		$this->validator = $validator;
57
		$this->container = $container;
58
		$this->loader    = $loader;
59
	}
60
61
	/**
62
	 * Register a meta box.
63
	 *
64
	 * @param Meta_Box $meta_box
65
	 * @return void
66
	 */
67
	public function register( Meta_Box $meta_box ): void {
68
69
		if ( ! $this->validator->verify_meta_box( $meta_box ) ) {
70
			throw new Exception(
71
				sprintf(
72
					'Failed validating meta box model(%s) with errors: %s',
73
					get_class( $meta_box ),
74
					join( ', ', $this->validator->get_errors() )
75
				)
76
			);
77
		}
78
79
		// Set the view using View, if not traditional callback supplied and a defined template.
80
		if ( ! \is_callable( $meta_box->view ) && is_string( $meta_box->view_template ) ) {
81
			$meta_box = $this->set_view_callback_from_renderable( $meta_box );
82
		}
83
		if ( \is_callable( $meta_box->view ) ) {
84
			$meta_box = $this->set_view_callback_from_callable( $meta_box );
85
		}
86
87
		// Add meta_box to loader.
88
		$this->loader->action(
89
			'add_meta_boxes',
90
			function() use ( $meta_box ) : void {
91
				\add_meta_box(
92
					$meta_box->key,
93
					$meta_box->label,
94
					$meta_box->view, /** @phpstan-ignore-line, is validated above*/
95
					$meta_box->screen,
96
					$meta_box->context,
97
					$meta_box->priority,
98
					$meta_box->view_vars
99
				);
100
			}
101
		);
102
		// If we have any hook calls, add them to the loader.
103
		if ( $this->is_active( $meta_box ) && ! empty( $meta_box->actions ) ) {
104
			foreach ( $meta_box->actions as $handle => $hook ) {
105
				$this->loader->action( (string) $handle, $hook['callback'], $hook['priority'], $hook['params'] );
106
			}
107
		}
108
109
	}
110
111
	/**
112
	 * Sets the view callback for a view which is defined as a callback.
113
	 *
114
	 * @param \PinkCrab\Registerables\Meta_Box $meta_box
115
	 * @return \PinkCrab\Registerables\Meta_Box
116
	 */
117
	protected function set_view_callback_from_callable( Meta_Box $meta_box ): Meta_Box {
118
119
		// Get the current view callback.
120
		$current_callback = $meta_box->view;
121
122
		$meta_box->view(
123
			function ( \WP_Post $post, array $args ) use ( $meta_box, $current_callback ) {
124
125
				// Set the view args
126
				$args['args']['post'] = $post;
127
				$args['args']         = $this->filter_view_args( $meta_box, $post, $args['args'] );
128
129
				// Render the callback.
130
				if ( \is_callable( $current_callback ) ) {
131
					call_user_func( $current_callback, $post, $args );
0 ignored issues
show
Bug introduced by
It seems like $current_callback can also be of type null; however, parameter $callback of call_user_func() does only seem to accept callable, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

131
					call_user_func( /** @scrutinizer ignore-type */ $current_callback, $post, $args );
Loading history...
132
				}
133
			}
134
		);
135
136
		return $meta_box;
137
	}
138
139
	/**
140
	 * Apply rendering the view using View to a meta_box
141
	 *
142
	 * @param \PinkCrab\Registerables\Meta_Box $meta_box
143
	 * @return \PinkCrab\Registerables\Meta_Box
144
	 */
145
	protected function set_view_callback_from_renderable( Meta_Box $meta_box ): Meta_Box {
146
147
		// Create View(View)
148
		$view = $this->container->create( View::class );
149
		if ( is_null( $view ) || ! is_a( $view, View::class ) ) {
150
			throw new Exception( 'View not defined' );
151
		}
152
153
		$meta_box->view(
154
			function ( \WP_Post $post, array $args ) use ( $meta_box, $view ) {
155
156
				$args['args']['post'] = $post;
157
				$args['args']         = $this->filter_view_args( $meta_box, $post, $args['args'] );
158
159
				// @phpstan-ignore-next-line, template should already be checked for valid template path in register() method (which calls this)
160
				$view->render( $meta_box->view_template, $args['args'] );
0 ignored issues
show
Bug introduced by
It seems like $meta_box->view_template can also be of type null; however, parameter $view of PinkCrab\Perique\Services\View\View::render() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

160
				$view->render( /** @scrutinizer ignore-type */ $meta_box->view_template, $args['args'] );
Loading history...
161
			}
162
		);
163
164
		return $meta_box;
165
	}
166
167
	/**
168
	 * Checks if the checkbox should be active.
169
	 *
170
	 * @return boolean
171
	 */
172
	protected function is_active( Meta_Box $meta_box ): bool {
173
		global $current_screen;
174
175
		return ! is_null( $current_screen )
176
		&& ! empty( $current_screen->post_type )
177
		&& in_array( $current_screen->post_type, $meta_box->screen, true );
178
	}
179
180
	/**
181
	 * Filters the render time args through the optional
182
	 * callback definition in model class.
183
	 *
184
	 * @param \PinkCrab\Registerables\Meta_Box $meta_box
185
	 * @param array<string, mixed> $view_args
186
	 * @return array<string, mixed>
187
	 */
188
	public function filter_view_args( Meta_Box $meta_box, \WP_Post $post, array $view_args ): array {
189
		if ( is_callable( $meta_box->view_data_filter ) ) {
190
			$view_args = ( $meta_box->view_data_filter )( $post, $view_args );
191
		}
192
		return $view_args;
193
	}
194
}
195