Completed
Push — milestone/2_0/react-ui ( 5b168c...b737dc )
by
unknown
04:15
created

Carbon_Fields::on_boot()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 4
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 6
ccs 0
cts 5
cp 0
crap 6
rs 9.4285

1 Method

Rating   Name   Duplication   Size   Complexity  
A Carbon_Fields::is_booted() 0 3 1
1
<?php
2
3
namespace Carbon_Fields;
4
5
use Carbon_Fields\Pimple\Container as PimpleContainer;
6
use Carbon_Fields\Helper\Helper;
7
use Carbon_Fields\Loader\Loader;
8
use Carbon_Fields\Container\Repository as ContainerRepository;
9
use Carbon_Fields\Toolset\Key_Toolset;
10
use Carbon_Fields\Toolset\WP_Toolset;
11
use Carbon_Fields\Service\Meta_Query_Service;
12
use Carbon_Fields\Service\Legacy_Storage_Service_v_1_5;
13
use Carbon_Fields\Service\REST_API_Service;
14
use Carbon_Fields\Libraries\Sidebar_Manager\Sidebar_Manager;
15
16
use Carbon_Fields\REST_API\Router as REST_API_Router;
17
use Carbon_Fields\REST_API\Decorator as REST_API_Decorator;
18
19
use Carbon_Fields\Event\Emitter;
20
use Carbon_Fields\Event\PersistentListener;
21
use Carbon_Fields\Event\SingleEventListener;
22
23
use Carbon_Fields\Exception\Incorrect_Syntax_Exception;
24
25
/**
26
 * Holds a static reference to the ioc container
27
 */
28
class Carbon_Fields {
0 ignored issues
show
Coding Style introduced by
Since you have declared the constructor as private, maybe you should also declare the class as final.
Loading history...
29
30
	/**
31
	 * An event emitter to facilitate events before the WordPress environment is guaranteed to be loaded
32
	 * 
33
	 * @var Emitter
34
	 */
35
	protected $emitter;
36
37
	/**
38
	 * Flag if Carbon Fields has been booted
39
	 * 
40
	 * @var bool
41
	 */
42
	public $booted = false;
43
44
	/**
45
	 * Inversion of Control container instance
46
	 * 
47
	 * @var PimpleContainer
48
	 */
49
	public $ioc = null;
50
51
	/**
52
	 * Singleton implementation
53
	 *
54
	 * @return Carbon_Fields\Carbon_Fields
55
	 */
56
	public static function instance() {
57
		static $instance = null;
58
		if ( $instance === null ) {
59
			$instance = new static();
60
		}
61
		return $instance;
62
	}
63
64
	/**
65
	 * Constructor
66
	 */
67
	private function __construct() {
68
		$this->install( $this->get_default_ioc() );
69
	}
70
71
	/**
72
	 * Resolve a dependency through IoC
73
	 *
74
	 * @param  string $key
75
	 * @param  string $subcontainer Subcontainer to look into
76
	 * @return mixed
77
	 */
78 View Code Duplication
	public static function resolve( $key, $subcontainer = null ) {
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
79
		$ioc = static::instance()->ioc;
80
		if ( $subcontainer ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $subcontainer of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
81
			if ( ! isset( $ioc[ $subcontainer ] ) ) {
82
				return null;
83
			}
84
			$ioc = $ioc[ $subcontainer ];
85
		}
86
		return $ioc[ $key ];
87
	}
88
89
	/**
90
	 * Resolve a dependency through IoC with arguments
91
	 *
92
	 * @param  string $identifier   Key to resolve from the container
93
	 * @param  array  $arguments    Key-value array of arguments
94
	 * @param  string $subcontainer The container to resolve from
95
	 * @return mixed
96
	 */
97
	public static function resolve_with_arguments( $identifier, $arguments, $subcontainer = null ) {
98
		$supercontainer = $subcontainer ? static::resolve( $subcontainer ) : static::instance()->ioc;
99
		$container = new PimpleContainer();
100
		$container['container'] = $supercontainer;
101
		$container['arguments'] = $arguments;
102
		$container['object'] = $supercontainer->raw( $identifier );
103
		return $container['object'];
104
	}
105
106
	/**
107
	 * Resolve a service through IoC
108
	 *
109
	 * @param string $service_name
110
	 * @return mixed
111
	 */
112
	public static function service( $service_name ) {
113
		return static::resolve( $service_name, 'services' );
114
	}
115
116
	/**
117
	 * Check if a dependency is registered
118
	 *
119
	 * @param  string $key
120
	 * @param  string $subcontainer Subcontainer to look into
121
	 * @return bool
122
	 */
123 View Code Duplication
	public static function has( $key, $subcontainer = null ) {
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
124
		$ioc = static::instance()->ioc;
125
		if ( $subcontainer ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $subcontainer of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
126
			if ( ! isset( $ioc[ $subcontainer ] ) ) {
127
				return false;
128
			}
129
			$ioc = $ioc[ $subcontainer ];
130
		}
131
		return isset( $ioc[ $key ] );
132
	}
133
134
	/**
135
	 * Extend Carbon Fields by adding a new entity (container condition etc.)
136
	 *
137
	 * @param string $type     Type of extension - 'container_condition'
0 ignored issues
show
Bug introduced by
There is no parameter named $type. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
138
	 * @param string $class    Extension class name
139
	 * @param string $extender Extending callable
140
	 */
141
	public static function extend( $class, $extender ) {
142
		$type_dictionary = array(
143
			'_Field' => 'fields',
144
			'_Condition' => 'container_conditions',
145
		);
146
147
		$extension_suffix = '';
148
		$extension_subcontainer = '';
1 ignored issue
show
Comprehensibility Naming introduced by
The variable name $extension_subcontainer exceeds the maximum configured length of 20.

Very long variable names usually make code harder to read. It is therefore recommended not to make variable names too verbose.

Loading history...
149
		foreach ( $type_dictionary as $suffix => $subcontainer ) {
150
			if ( substr( $class, -strlen( $suffix ) ) === $suffix ) {
151
				$extension_suffix = $suffix;
152
				$extension_subcontainer = $subcontainer;
153
			}
154
		}
155
156
		if ( empty( $extension_suffix ) ) {
157
			Incorrect_Syntax_Exception::raise( 'Could not determine "' . $class . '" extension type. Extension classes must have one of the following suffixes: ' . implode( ', ', array_keys( $type_dictionary ) ) );
158
			return;
159
		}
160
161
		$identifier = Helper::class_to_type( $class, $extension_suffix );
162
		$ioc = static::instance()->ioc[ $extension_subcontainer ];
163
		$ioc[ $identifier ] = $ioc->factory( $extender );
164
	}
165
166
	/**
167
	 * Replace the ioc container for Carbon_Fields\Carbon_Fields
168
	 * 
169
	 * @param  PimpleContainer $ioc
170
	 */
171
	public function install( PimpleContainer $ioc ) {
172
		$this->ioc = $ioc;
173
	}
174
175
	/**
176
	 * Boot Carbon Fields with default IoC dependencies
177
	 */
178
	public static function boot() {
179
		if ( static::is_booted() ) {
180
			return;
181
		}
182
183
		if ( defined( __NAMESPACE__ . '\VERSION' ) ) {
184
			return; // Possibly attempting to load multiple versions of Carbon Fields; bail in favor of already loaded version
185
		}
186
187
		static::resolve( 'loader' )->boot();
188
		static::instance()->booted = true;
189
		static::instance()->get_emitter()->emit( 'loaded' );
190
		do_action( 'carbon_fields_loaded' );
191
	}
192
193
	/**
194
	 * Check if Carbon Fields has booted
195
	 */
196
	public static function is_booted() {
197
		return static::instance()->booted;
198
	}
199
200
	/**
201
	 * Throw exception if Carbon Fields has not been booted
202
	 */
203
	public static function verify_boot() {
204
		if ( ! static::is_booted() ) {
205
			throw new \Exception( 'You must call Carbon_Fields\Carbon_Fields::boot() in a suitable WordPress hook before using Carbon Fields.' );
206
		}
207
	}
208
209
	/**
210
	 * Get the event emitter
211
	 * 
212
	 * @return Emitter
213
	 */
214
	public function get_emitter() {
215
		if ( $this->emitter === null ) {
216
			$this->emitter = static::resolve( 'event_emitter' );
217
		}
218
		return $this->emitter;
219
	}
220
221
	/**
222
	 * Add a listener to an event
223
	 * 
224
	 * @param string   $event
225
	 * @return Listener $listener
226
	 */
227
	public static function add_listener( $event, $listener ) {
228
		return static::instance()->get_emitter()->add_listener( $event, $listener );
229
	}
230
231
	/**
232
	 * Remove a listener from any event
233
	 * 
234
	 * @param Listener $removed_listener
0 ignored issues
show
Documentation introduced by
There is no parameter named $removed_listener. Did you maybe mean $listener?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
235
	 */
236
	public static function remove_listener( $listener ) {
237
		static::instance()->get_emitter()->remove_listener( $listener );
238
	}
239
240
	/**
241
	 * Add a persistent listener to an event
242
	 * 
243
	 * @param  string   $event    The event to listen for
244
	 * @param  string   $callable The callable to call when the event is broadcasted
245
	 * @return Listener
246
	 */
247
	public static function on( $event, $callable ) {
1 ignored issue
show
Coding Style introduced by
This method's name is shorter than the configured minimum length of 3 characters.

Even though PHP does not care about the name of your methods, it is generally a good practice to choose method names which can be easily understood by other human readers.

Loading history...
248
		return static::instance()->get_emitter()->on( $event, $callable );
249
	}
250
251
	/**
252
	 * Add a one-time listener to an event
253
	 *
254
	 * @param  string   $event    The event to listen for
255
	 * @param  string   $callable The callable to call when the event is broadcasted
256
	 * @return Listener
257
	 */
258
	public static function once( $event, $callable ) {
259
		return static::instance()->get_emitter()->once( $event, $callable );
260
	}
261
262
	/**
263
	 * Get default IoC container dependencies
264
	 * 
265
	 * @return PimpleContainer
266
	 */
267
	protected static function get_default_ioc() {
268
		$ioc = new PimpleContainer();
269
270
		$ioc['loader'] = function( $ioc ) {
271
			return new Loader( $ioc['sidebar_manager'], $ioc['container_repository'] );
272
		};
273
274
		$ioc['container_repository'] = function() {
275
			return new ContainerRepository();
276
		};
277
278
		$ioc['fields'] = function() {
279
			return new PimpleContainer();
280
		};
281
282
		$ioc['key_toolset'] = function() {
283
			return new Key_Toolset();
284
		};
285
286
		$ioc['wp_toolset'] = function() {
287
			return new WP_Toolset();
288
		};
289
290
		$ioc['sidebar_manager'] = function() {
291
			return new Sidebar_Manager();
292
		};
293
294
		$ioc['rest_api_router'] = function( $ioc ) {
295
			return new REST_API_Router( $ioc['container_repository'] );
296
		};
297
298
		$ioc['rest_api_decorator'] = function( $ioc ) {
299
			return new REST_API_Decorator( $ioc['container_repository'] );
300
		};
301
302
		/* Services */
303
		$ioc['services'] = function( $ioc ) {
0 ignored issues
show
Unused Code introduced by
The parameter $ioc is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
304
			return new PimpleContainer();
305
		};
306
307
		$ioc['services']['meta_query'] = function( $services_ioc ) use ( $ioc ) {
1 ignored issue
show
Unused Code introduced by
The parameter $services_ioc is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
introduced by
Detected usage of meta_query, possible slow query.
Loading history...
308
			return new Meta_Query_Service( $ioc['container_repository'], $ioc['key_toolset'] );
309
		};
310
311
		$ioc['services']['legacy_storage'] = function( $services_ioc ) use ( $ioc ) {
0 ignored issues
show
Unused Code introduced by
The parameter $services_ioc is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
312
			return new Legacy_Storage_Service_v_1_5( $ioc['container_repository'], $ioc['key_toolset'] );
313
		};
314
315
		$ioc['services']['rest_api'] = function( $services_ioc ) use ( $ioc ) {
0 ignored issues
show
Unused Code introduced by
The parameter $services_ioc is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
316
			return new REST_API_Service( $ioc['rest_api_router'], $ioc['rest_api_decorator'] );
317
		};
318
319
		/* Events */
320
		$ioc['event_emitter'] = function() {
321
			return new Emitter();
322
		};
323
324
		$ioc['event_persistent_listener'] = function() {
325
			return new PersistentListener();
326
		};
327
328
		$ioc['event_single_event_listener'] = function() {
329
			return new SingleEventListener();
330
		};
331
332
		$ioc->register( new \Carbon_Fields\Provider\Container_Condition_Provider() );
333
334
		return $ioc;
335
	}
336
}