/
class-oik-update.php
434 lines (404 loc) · 13.7 KB
/
class-oik-update.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
<?php // (C) Copyright Bobbing Wide 2011-2021
if ( !defined( "CLASS_OIK_UPDATE_INCLUDED" ) ) {
define( "CLASS_OIK_UPDATE_INCLUDED", "3.4.2" );
/**
*
* Library: class-oik-update
* Provides: oik_update
* Depends: bobbfunc, bobbforms, class-bobbcomp, oik_plugins
* Deferred dependencies: class-oik-remote - could be cyclical!
*
* Functions that support the plugin and theme updates.
* Extracted from admin/oik-admin.inc
*
* These are the shared library functions.
*/
class oik_update {
/**
* Register this plugin as one that is served from a different server to WordPress.org
*
* @param string $file - fully qualified plugin file name
* @param string $server - server name initial value - only set when the server value in the options is blank
* @param string $apikey - hard coded apikey initial value
*
*
* Notes: Plugins registered using the API set the default value for the server ... which may be null
* i.e. they set the intention to be served from somewhere other than WordPress.org
* When required we determine the actual server location AND other fields as needed during oik_query_plugins_server()
*
* At least ONE plugin needs to call this API for the oik plugin server logic to be activated
*/
static function oik_register_plugin_server( $file, $server=null, $apikey=null ) {
global $bw_registered_plugins;
if ( !isset( $bw_registered_plugins ) ) {
self::oik_lazy_altapi_init();
}
$bw_registered_plugins[] = array( "file" => $file, "server" => $server, "apikey" => $apikey );
//bw_trace2( $bw_registered_plugins, "global bw_registered_plugins", true );
}
/**
* Register this theme as one that is served from a different server to WordPress.org
*/
static function oik_register_theme_server( $file, $server=null, $apikey=null ) {
global $bw_registered_themes;
if ( !isset( $bw_registered_themes ) ) {
self::oik_lazy_alttheme_init();
}
$bw_registered_themes[] = array( "file" => $file, "server" => $server, "apikey" => $apikey );
bw_trace2( $bw_registered_themes );
}
/**
* Only register our plugin server when needed.
*
*
*/
static function oik_lazy_altapi_init() {
add_action( "pre_set_site_transient_update_plugins", "oik_update::oik_altapi_check" );
add_action( "site_transient_update_plugins", "oik_update::oik_site_transient_update_plugins", 10, 1 );
add_filter( 'site_transient_update_plugins', 'oik_update::oik_site_transient_filter_symlinked_plugins' );
add_filter( 'site_transient_update_plugins', 'oik_update::oik_site_transient_filter_git_plugins' );
add_action( "plugins_api", "oik_update::oik_pluginsapi", 10, 3 );
}
/**
* Only register our theme server when needed
*/
static function oik_lazy_alttheme_init() {
add_action( "pre_set_site_transient_update_themes", "oik_update::oik_alttheme_check" );
add_action( "site_transient_update_themes", "oik_update::oik_site_transient_update_themes", 10, 1 );
add_filter( "themes_api", "oik_update::oik_themes_api", 10, 3 );
//add_filter( "themes_api_result", "oik_update::oik_themes_api_result", 10, 3 );
}
/**
* Checks for plugin updates.
*
* @param Object $transient
* @return Object the updated transient
*/
static function oik_altapi_check( $transient ) {
oik_require_lib( "class-oik-remote" );
return( oik_remote::oik_lazy_altapi_check( $transient ) );
}
/**
* Checks for theme updates.
*
* @param Object $transient
* @return Object the updated transient
*/
static function oik_alttheme_check( $transient ) {
oik_require_lib( "class-oik-remote" );
return( oik_remote::oik_lazy_alttheme_check( $transient ) );
}
/**
* If required, unset last_checked to force another "check for updates" for plugins
*
* Note: Only use this when testing the oik plugin update logic
*/
static function oik_site_transient_update_plugins( $transient ) {
if ( defined( "OIK_FORCE_CHECK" ) ) {
if ( OIK_FORCE_CHECK ) {
static $last_checked = null;
if ( !$last_checked ) {
$last_checked = $transient->last_checked;
unset( $transient->last_checked );
bw_trace2( $last_checked, "transient" );
}
} else {
//bw_backtrace();
}
}
return( $transient );
}
/**
* Removes symlinked plugins from the update list.
*
* Note: They are only removed on the update-core page.
*
* @param object $transient The 'transient' for plugin updates.
* @return mixed Updated transient.
*/
static function oik_site_transient_filter_symlinked_plugins( $transient ) {
if ( $transient && oik_update::is_update_core() ) {
foreach ( $transient->response as $plugin_file=>$plugin_object ) {
if ( oik_update::is_symlinked( $plugin_file ) ) {
unset( $transient->response[ $plugin_file ] );
}
}
}
return $transient;
}
/**
* Checks if it's the update-core page.
*
* Note: This can't be done early since global $current_screen may not be set.
* Worse than that, the get_current_screen() function may not be available.
*
* @return bool
*/
static function is_update_core() {
$is_update_core=false;
$current_screen = null;
if ( function_exists( "get_current_screen" )) {
$current_screen = get_current_screen();
bw_trace2($current_screen, "current_screen", false, BW_TRACE_VERBOSE);
}
if ( $current_screen && $current_screen->id === 'update-core' ) {
$is_update_core=true;
}
return $is_update_core;
}
/**
* Checks if a plugin is symlinked.
*
* @param string $plugin_file Plugin file e.g. oik/oik.php
* @return bool true if the plugin is symlinked
*/
static function is_symlinked( $plugin_file ) {
$normalized = wp_normalize_path( WP_PLUGIN_DIR );
$plugin_path = $normalized . '/' . $plugin_file;
$real_path = realpath( $plugin_path );
$real_path = wp_normalize_path( $real_path );
$symlinked = ( $real_path != $plugin_path ) ;
return $symlinked;
}
/**
* Removes git plugins from the update list.
*
* Plugins are only removed on the update-core page.
*
* @param object $transient The transient for plugin_updates.
* @return mixed
*/
static function oik_site_transient_filter_git_plugins( $transient ) {
if ( $transient && oik_update::is_update_core() ) {
foreach ( $transient->response as $plugin_file=>$plugin_object ) {
if ( oik_update::is_git( $plugin_file ) ) {
unset( $transient->response[ $plugin_file ] );
}
}
}
return $transient;
}
/**
* Determines if the plugin is a Git repository.
*
* @param string $plugin_file Plugin file name e.g. oik/oik.php.
* @return bool true if we consider this to be a Git repo.
*/
static function is_git( $plugin_file ) {
$is_git = false;
$dot_git = dirname( WP_PLUGIN_DIR . '/' . $plugin_file );
$dot_git .= '/.git';
$dot_git = str_replace( "/", DIRECTORY_SEPARATOR, $dot_git );
if ( file_exists( $dot_git ) && is_dir( $dot_git ) ) {
$is_git = true;
}
return $is_git;
}
/**
* Updates site transient for theme updates.
*
* If required, unset last_checked to force another "check for updates" for themes.
*
* Note: Only use this when testing the oik theme update logic
*/
static function oik_site_transient_update_themes( $transient ) {
if ( defined( "OIK_FORCE_CHECK_THEMES" ) && OIK_FORCE_CHECK_THEMES ) {
static $last_checked = null;
if ( !$last_checked ) {
$last_checked = $transient->last_checked;
unset( $transient->last_checked );
bw_trace2( $last_checked, "transient" );
}
}
//bw_backtrace();
return( $transient );
}
/**
* Return the plugins server if the requested plugin is one of ours
*
* Note: $bw_registered_plugins is an array of filenames
* we create $bw_slugs as an array of "slug" => array( 'basename' => "slug/plugin_name.php", 'file'=> 'server'=>, 'apikey'=> )
* $bw_plugins (stored in WordPress options) also contains 'server' and 'apikey'
*
* @param string $slug plugin slug
* @return array
*/
static function oik_query_plugins_server( $slug ) {
global $bw_registered_plugins, $bw_slugs;
if ( !isset( $bw_slugs ) ) {
$bw_slugs = array();
if ( isset( $bw_registered_plugins ) ) {
foreach ( $bw_registered_plugins as $key => $value ) {
$file = bw_array_get( $value, "file", null );
$plugin_basename = plugin_basename( $file );
$bw_slug = pathinfo( $plugin_basename, PATHINFO_DIRNAME );
$value['basename'] = $plugin_basename;
$bw_slugs[ $bw_slug ] = $value;
}
}
bw_trace2( $bw_slugs );
}
$plugin_settings = bobbcomp::bw_get_option( $slug, "bw_plugins" );
bw_trace2( $plugin_settings );
/* return the saved settings, with any registered defaults, otherwise just get the registered settings */
if ( $plugin_settings ) {
$server = bw_array_get( $plugin_settings, "server", null );
$apikey = bw_array_get( $plugin_settings, "apikey", null );
if ( !$server || !$apikey ) {
$value = bw_array_get( $bw_slugs, $slug, null );
}
if ( !$server ) {
$server = bobbcomp::bw_array_get_dcb( $value, "server", null, "oik_update::oik_get_plugins_server" );
}
if ( !$apikey ) {
$plugin_settings['apikey'] = bw_array_get( $value, "apikey", null );
}
} else {
$plugin_settings = bw_array_get( $bw_slugs, $slug, null );
if ( $plugin_settings ) {
$server = bobbcomp::bw_array_get_dcb( $plugin_settings, "server", null, "oik_update::oik_get_plugins_server" );
}
// apikey doesn't default here
}
if ( $plugin_settings ) {
$plugin_settings['server'] = $server;
bw_trace2( $server, "server" );
}
return( $plugin_settings );
}
/**
* Return the themes server if the requested theme is one of ours
*
* Note: $bw_registered_themes is an array of filenames
* we create $bw_theme_slugs as an array of "slug" => array( 'basename' => "theme name", 'file'=> 'server'=>, 'apikey'=> )
* $bw_themes (stored in WordPress options) also contains 'server' and 'apikey'
*
* @param string $slug theme name
* @return array
*/
static function oik_query_themes_server( $slug ) {
global $bw_registered_themes, $bw_theme_slugs;
if ( !isset( $bw_theme_slugs ) ) {
$bw_theme_slugs = array();
if ( is_array( $bw_registered_themes) && count( $bw_registered_themes ) ) {
foreach ( $bw_registered_themes as $key => $value ) {
$file = bw_array_get( $value, "file", null );
// The next 2 lines are equivalent to $bw_slug = bw_last_path( $file );
$pathinfo = pathinfo( $file, PATHINFO_DIRNAME );
$bw_slug = basename( $pathinfo );
$value['basename'] = $bw_slug;
$bw_theme_slugs[ $bw_slug ] = $value;
}
}
bw_trace2( $bw_theme_slugs );
}
$theme_settings = bobbcomp::bw_get_option( $slug, "bw_themes" );
bw_trace2( $theme_settings );
/* return the saved settings, with any registered defaults, otherwise just get the registered settings */
if ( $theme_settings ) {
$server = bw_array_get( $theme_settings, "server", null );
$apikey = bw_array_get( $theme_settings, "apikey", null );
if ( !$server || !$apikey ) {
$value = bw_array_get( $bw_theme_slugs, $slug, null );
}
if ( !$server ) {
$server = bobbcomp::bw_array_get_dcb( $value, "server", null, "oik_update::oik_get_themes_server" );
bw_trace2( $server, $slug, false );
}
if ( !$apikey ) {
$theme_settings['apikey'] = bw_array_get( $value, "apikey", null );
}
} else {
$theme_settings = bw_array_get( $bw_theme_slugs, $slug, null );
if ( $theme_settings ) {
$server = bobbcomp::bw_array_get_dcb( $theme_settings, "server", null, "oik_update::oik_get_themes_server" );
}
// apikey doesn't default here
}
if ( $theme_settings ) {
$theme_settings['server'] = $server;
bw_trace2( $server, "server", false, BW_TRACE_INFO );
}
return( $theme_settings );
}
/**
* Return the slug part of a plugin name
*
* This function should only be called when we know it's a plugin name with a directory.
*
* Sample results
* - "slug" for "slug/plugin_name.php" - when called for "update-check"
* - "slugonly" for "slugonly" - when called for "plugin_information"
* - "hello" for "hello.php" - does this ever happen?
* - null for null
*
* @param string $plugin - a plugin name
* @return string $slug - the slug used to identify the plugin
*
*/
static function bw_get_slug( $plugin ) {
if ( $plugin ) {
$pathinfo = pathinfo( $plugin );
$slug = $pathinfo['dirname'] ;
if ( $slug == '.' ) {
$slug = $pathinfo['filename'];
}
} else {
$slug = null;
}
return( $slug );
}
/**
* Return the last path for the given file
*
* @param string $file - a fully specified file name ( e.g. __FILE__ )
* @return string the last part of the file's path
* e.g.
*
* @link http://www.php.net/manual/en/function.basename.php#72254
* When using basename() on a path to a directory ('/bar/foo/'), the last path component ('foo') is returned
*/
static function bw_last_path( $file ) {
bw_trace2();
$pathinfo = pathinfo( $file, PATHINFO_DIRNAME );
$last_path = basename( $pathinfo );
return( $last_path );
}
static function oik_pluginsapi( $false, $action, $args ) {
oik_require_lib( "class-oik-remote" );
return( oik_remote::oik_lazy_pluginsapi( $false, $action, $args ) );
}
static function oik_themes_api( $false, $action, $args ) {
oik_require_lib( "class-oik-remote" );
return( oik_remote::oik_lazy_themes_api( $false, $action, $args ) );
}
/**
* Return the URL for the Premium (Pro) or Freemium version
*
* If BW_OIK_PLUGINS_SERVER is defined we'll use that.
* Else, we'll use the value of OIK_PLUGINS_COM
* which we'll define if it's not already defined
*
* @return string URL for an oik-plugins server
*/
static function oik_get_plugins_server() {
if ( defined( 'BW_OIK_PLUGINS_SERVER' )) {
$url = BW_OIK_PLUGINS_SERVER;
} else {
if ( !defined( "OIK_PLUGINS_COM" ) ) {
define( "OIK_PLUGINS_COM", "https://www.oik-plugins.com" );
}
$url = OIK_PLUGINS_COM;
}
return( $url );
}
/**
* Return the URL for the theme server
*
* @return string URL for an oik-plugins server
*/
static function oik_get_themes_server() {
return( self::oik_get_plugins_server() );
}
} /* end class */
} /* end !defined() */