Completed
Push — master ( b6760c...d0c54a )
by J.D.
03:04
created

WordPoints_App   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 240
Duplicated Lines 4.17 %

Coupling/Cohesion

Components 1
Dependencies 1
Metric Value
wmc 20
lcom 1
cbo 1
dl 10
loc 240
rs 10

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 17 3
A __isset() 0 3 1
C __get() 10 66 9
A __set() 0 12 2
A __unset() 0 12 2
A should_do_registry_init() 0 6 2
A init() 0 14 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
/**
4
 * Class for WordPoints apps.
5
 *
6
 * @package wordpoints-hooks-api
7
 * @since   1.0.0
8
 */
9
10
/**
11
 * An app for WordPoints.
12
 *
13
 * Apps are self-contained APIs that can include sub-apps.
14
 *
15
 * The sub-apps are not required to be instances of WordPoints_App themselves, they
16
 * can be any sort of object.
17
 *
18
 * @since 1.0.0
19
 *
20
 * @property-read WordPoints_Class_Registry_Persistent $sub_apps Child apps registry.
21
 * @property-read object                               $*        Child app objects.
22
 */
23
class WordPoints_App {
24
25
	/**
26
	 * The main app.
27
	 *
28
	 * @since 1.0.0
29
	 *
30
	 * @var WordPoints_App
31
	 */
32
	public static $main;
33
34
	/**
35
	 * The slug of this app.
36
	 *
37
	 * @since 1.0.0
38
	 *
39
	 * @var string
40
	 */
41
	protected $slug;
42
43
	/**
44
	 * The full slug of this app, prefixed with the slug of the parent app.
45
	 *
46
	 * @since 1.0.0
47
	 *
48
	 * @var string
49
	 */
50
	protected $full_slug;
51
52
	/**
53
	 * A registry for child apps.
54
	 *
55
	 * @since 1.0.0
56
	 *
57
	 * @var WordPoints_Class_Registry_Persistent
58
	 */
59
	protected $sub_apps;
60
61
	/**
62
	 * The parent of this app, if this is a sub-app.
63
	 *
64
	 * @since 1.0.0
65
	 *
66
	 * @var WordPoints_App
67
	 */
68
	protected $parent;
69
70
	/**
71
	 * Whether to skip calling an action when each registry is initialized.
72
	 *
73
	 * @since 1.0.0
74
	 *
75
	 * @var bool
76
	 */
77
	protected $silent = false;
78
79
	/**
80
	 * Keeps track of which registries have been initialized.
81
	 *
82
	 * @since 1.0.0
83
	 *
84
	 * @var bool[]
85
	 */
86
	protected $did_init = array();
87
88
	/**
89
	 * Whether properties are allowed to be set.
90
	 *
91
	 * @since 1.0.0
92
	 *
93
	 * @var bool
94
	 */
95
	protected $allow_set = false;
96
97
	/**
98
	 * @since 1.0.0
99
	 */
100
	public function __construct( $slug, $parent = null ) {
101
102
		$this->slug = $slug;
103
		$this->full_slug = $slug;
104
105
		if ( $parent instanceof WordPoints_App ) {
106
			$this->parent = $parent;
107
108
			if ( 'apps' !== $this->parent->full_slug ) {
109
				$this->full_slug = $this->parent->full_slug . '-' . $this->full_slug;
110
			}
111
		}
112
113
		$this->sub_apps = new WordPoints_Class_Registry_Persistent();
114
115
		$this->init();
116
	}
117
118
	/**
119
	 * @since 1.0.0
120
	 */
121
	public function __isset( $var ) {
122
		return $this->sub_apps->is_registered( $var );
123
	}
124
125
	/**
126
	 * @since 1.0.0
127
	 */
128
	public function __get( $var ) {
129
130
		if ( 'sub_apps' === $var ) {
131
			return $this->$var;
132
		}
133
134
		$sub = $this->sub_apps->get( $var, array( $this ) );
135
136
		if ( ! $sub ) {
137
			return null;
138
		}
139
140
		if (
141
			empty( $this->did_init[ $var ] )
142
			&& ! self::$main->silent
143
			&& $this->should_do_registry_init( $sub )
144
		) {
145
146
			$is_protected_property = array_key_exists( $var, get_object_vars( $this ) );
147
148
			// When the below action is called it is possible that some hooked code
149
			// may attempt to access the property that is being initialized. However,
150
			// the __get() function will not be called recursively, meaning that
151
			// instead of the true value the code will get null. To solve this, we
152
			// temporarily set this as a public property. However, we can't do this
153
			// for properties that the class has declared, because otherwise it would
154
			// be possible to modify and then unset protected class properties.
155 View Code Duplication
			if ( ! $is_protected_property ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
156
				$this->allow_set = true;
157
				$this->$var = $sub;
158
				$this->allow_set = false;
159
			}
160
161
			/**
162
			 * Initialization of an app registry.
163
			 *
164
			 * The $var is the slug of the registry.
165
			 *
166
			 * @since 1.0.0
167
			 *
168
			 * @param WordPoints_Class_RegistryI|WordPoints_Class_Registry_ChildrenI
169
			 *        $registry The registry object.
170
			 */
171
			do_action( "wordpoints_init_app_registry-{$this->full_slug}-{$var}", $sub );
172
173
			// Because this property was public, it's possible that it might have
174
			// been modified inadvertently. If this happens we give a warning.
175
			if ( $sub !== $this->$var ) {
176
				_doing_it_wrong(
177
					__METHOD__
178
					, esc_html( "Do not modify the {$var} property directly." )
179
					, '1.0.0'
180
				);
181
			}
182
183 View Code Duplication
			if ( ! $is_protected_property ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
184
				$this->allow_set = true;
185
				unset( $this->$var );
186
				$this->allow_set = false;
187
			}
188
189
			$this->did_init[ $var ] = true;
190
		}
191
192
		return $sub;
193
	}
194
195
	/**
196
	 * @since 1.0.0
197
	 */
198
	public function __set( $var, $value ) {
199
200
		if ( $this->allow_set ) {
201
			$this->$var = $value;
202
		} else {
203
			_doing_it_wrong(
204
				__METHOD__
205
				, 'Sub apps must be registered using $app->sub_apps->register().'
206
				, '1.0.0'
207
			);
208
		}
209
	}
210
211
	/**
212
	 * @since 1.0.0
213
	 */
214
	public function __unset( $var ) {
215
216
		if ( $this->allow_set ) {
217
			unset( $this->$var );
218
		} else {
219
			_doing_it_wrong(
220
				__METHOD__
221
				, 'Sub apps must be deregistered using $app->sub_apps->deregister().'
222
				, '1.0.0'
223
			);
224
		}
225
	}
226
227
	/**
228
	 * Check whether to call the init action for a registry sub-app.
229
	 *
230
	 * @since 1.0.0
231
	 *
232
	 * @param object $registry The sub-app object.
233
	 *
234
	 * @return bool Whether to call the init action or not.
235
	 */
236
	protected function should_do_registry_init( $registry ) {
237
		return (
238
		   $registry instanceof WordPoints_Class_RegistryI
239
		   || $registry instanceof WordPoints_Class_Registry_ChildrenI
240
		);
241
	}
242
243
	/**
244
	 * Initialize this app.
245
	 *
246
	 * @since 1.0.0
247
	 */
248
	protected function init() {
249
250
		/**
251
		 * WordPoints app initialized.
252
		 *
253
		 * The dynamic portion of the action is the slug of the app being
254
		 * initialized.
255
		 *
256
		 * @since 1.0.0
257
		 *
258
		 * @param WordPoints_App $app The app object.
259
		 */
260
		do_action( "wordpoints_init_app-{$this->full_slug}", $this );
261
	}
262
}
263
264
// EOF
265