Completed
Push — try/gutenberg-separate-jetpack... ( e8dd3e...f0efb9 )
by Bernhard
39:26 queued 23:22
created

Jetpack_Display_Posts_Widget::update()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 2
dl 0
loc 12
rs 9.8666
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * Display a list of recent posts from a WordPress.com or Jetpack-enabled blog.
5
 */
6
7
class Jetpack_Display_Posts_Widget extends Jetpack_Display_Posts_Widget__Base {
8
	/**
9
	 * @var string Widget options key prefix.
10
	 */
11
	public $widget_options_key_prefix = 'display_posts_site_data_';
12
13
	/**
14
	 * @var string The name of the cron that will update widget data.
15
	 */
16
	public static $cron_name = 'jetpack_display_posts_widget_cron_update';
17
18
19
	// DATA STORE
20
21
	/**
22
	 * Gets blog data from the cache.
23
	 *
24
	 * @param string $site
25
	 *
26
	 * @return array|WP_Error
27
	 */
28
	public function get_blog_data( $site ) {
29
		// load from cache, if nothing return an error
30
		$site_hash = $this->get_site_hash( $site );
31
32
		$cached_data = $this->wp_get_option( $this->widget_options_key_prefix . $site_hash );
33
34
		/**
35
		 * If the cache is empty, return an empty_cache error.
36
		 */
37
		if ( false === $cached_data ) {
38
			return new WP_Error(
39
				'empty_cache',
40
				__( 'Information about this blog is currently being retrieved.', 'jetpack' )
41
			);
42
		}
43
44
		return $cached_data;
45
46
	}
47
48
	/**
49
	 * Update a widget instance.
50
	 *
51
	 * @param string $site The site to fetch the latest data for.
52
	 *
53
	 * @return array - the new data
54
	 */
55
	public function update_instance( $site ) {
56
57
		/**
58
		 * Fetch current information for a site.
59
		 */
60
		$site_hash = $this->get_site_hash( $site );
61
62
		$option_key = $this->widget_options_key_prefix . $site_hash;
63
64
		$instance_data = $this->wp_get_option( $option_key );
65
66
		/**
67
		 * Fetch blog data and save it in $instance_data.
68
		 */
69
		$new_data = $this->fetch_blog_data( $site, $instance_data );
70
71
		/**
72
		 * If the option doesn't exist yet - create a new option
73
		 */
74
		if ( false === $instance_data ) {
75
			$this->wp_add_option( $option_key, $new_data );
76
		}
77
		else {
78
			$this->wp_update_option( $option_key, $new_data );
79
		}
80
81
		return $new_data;
82
	}
83
84
85
	// WIDGET API
86
87
	public function update( $new_instance, $old_instance ) {
88
		$instance = parent::update( $new_instance, $old_instance );
89
90
		/**
91
		 * Forcefully activate the update cron when saving widget instance.
92
		 *
93
		 * So we can be sure that it will be running later.
94
		 */
95
		$this->activate_cron();
96
97
		return $instance;
98
	}
99
100
101
	// CRON
102
103
	/**
104
	 * Activates widget update cron task.
105
	 */
106
	public static function activate_cron() {
107
		if ( ! wp_next_scheduled( self::$cron_name ) ) {
108
			wp_schedule_event( time(), 'minutes_10', self::$cron_name );
109
		}
110
	}
111
112
	/**
113
	 * Deactivates widget update cron task.
114
	 *
115
	 * This is a wrapper over the static method as it provides some syntactic sugar.
116
	 */
117
	public function deactivate_cron() {
118
		self::deactivate_cron_static();
119
	}
120
121
	/**
122
	 * Deactivates widget update cron task.
123
	 */
124
	public static function deactivate_cron_static() {
125
		$next_scheduled_time = wp_next_scheduled( self::$cron_name );
126
		wp_unschedule_event( $next_scheduled_time, self::$cron_name );
127
	}
128
129
	/**
130
	 * Checks if the update cron should be running and returns appropriate result.
131
	 *
132
	 * @return bool If the cron should be running or not.
133
	 */
134
	public function should_cron_be_running() {
135
		/**
136
		 * The cron doesn't need to run empty loops.
137
		 */
138
		$widget_instances = $this->get_instances_sites();
139
140
		if ( empty( $widget_instances ) || ! is_array( $widget_instances ) ) {
141
			return false;
142
		}
143
144
		if ( ! defined( 'IS_WPCOM' ) || ! IS_WPCOM ) {
145
			/**
146
			 * If Jetpack is not active or in development mode, we don't want to update widget data.
147
			 */
148
			if ( ! Jetpack::is_active() && ! Jetpack::is_development_mode() ) {
149
				return false;
150
			}
151
152
			/**
153
			 * If Extra Sidebar Widgets module is not active, we don't need to update widget data.
154
			 */
155
			if ( ! Jetpack::is_module_active( 'widgets' ) ) {
156
				return false;
157
			}
158
		}
159
160
		/**
161
		 * If none of the above checks failed, then we definitely want to update widget data.
162
		 */
163
		return true;
164
	}
165
166
	/**
167
	 * Main cron code. Updates all instances of the widget.
168
	 *
169
	 * @return bool
170
	 */
171
	public function cron_task() {
172
173
		/**
174
		 * If the cron should not be running, disable it.
175
		 */
176
		if ( false === $this->should_cron_be_running() ) {
177
			return true;
178
		}
179
180
		$instances_to_update = $this->get_instances_sites();
181
182
		/**
183
		 * If no instances are found to be updated - stop.
184
		 */
185
		if ( empty( $instances_to_update ) || ! is_array( $instances_to_update ) ) {
186
			return true;
187
		}
188
189
		foreach ( $instances_to_update as $site_url ) {
190
			$this->update_instance( $site_url );
191
		}
192
193
		return true;
194
	}
195
196
	/**
197
	 * Get a list of unique sites from all instances of the widget.
198
	 *
199
	 * @return array|bool
200
	 */
201
	public function get_instances_sites() {
202
203
		$widget_settings = $this->wp_get_option( 'widget_jetpack_display_posts_widget' );
204
205
		/**
206
		 * If the widget still hasn't been added anywhere, the config will not be present.
207
		 *
208
		 * In such case we don't want to continue execution.
209
		 */
210
		if ( false === $widget_settings || ! is_array( $widget_settings ) ) {
211
			return false;
212
		}
213
214
		$urls = array();
215
216
		foreach ( $widget_settings as $widget_instance_data ) {
217
			if ( isset( $widget_instance_data['url'] ) && ! empty( $widget_instance_data['url'] ) ) {
218
				$urls[] = $widget_instance_data['url'];
219
			}
220
		}
221
222
		/**
223
		 * Make sure only unique URLs are returned.
224
		 */
225
		$urls = array_unique( $urls );
226
227
		return $urls;
228
229
	}
230
231
232
	// MOCKABLES
233
234
	/**
235
	 * This is just to make method mocks in the unit tests easier.
236
	 *
237
	 * @param string $param Option key to get
238
	 *
239
	 * @return mixed
240
	 *
241
	 * @codeCoverageIgnore
242
	 */
243
	public function wp_get_option( $param ) {
244
		return get_option( $param );
245
	}
246
247
	/**
248
	 * This is just to make method mocks in the unit tests easier.
249
	 *
250
	 * @param string $option_name  Option name to be added
251
	 * @param mixed  $option_value Option value
252
	 *
253
	 * @return mixed
254
	 *
255
	 * @codeCoverageIgnore
256
	 */
257
	public function wp_add_option( $option_name, $option_value ) {
258
		return add_option( $option_name, $option_value );
259
	}
260
261
	/**
262
	 * This is just to make method mocks in the unit tests easier.
263
	 *
264
	 * @param string $option_name  Option name to be updated
265
	 * @param mixed  $option_value Option value
266
	 *
267
	 * @return mixed
268
	 *
269
	 * @codeCoverageIgnore
270
	 */
271
	public function wp_update_option( $option_name, $option_value ) {
272
		return update_option( $option_name, $option_value );
273
	}
274
}
275