Unyson - Version 2.1.3

Version Description

  • Multi-site: Only network administrator can install/remove/update extensions
Download this release

Release Info

Developer Unyson
Plugin Icon 128x128 Unyson
Version 2.1.3
Comparing to
See all releases

Code changes from version 2.1.2 to 2.1.3

README.md CHANGED
@@ -1,10 +1,10 @@
1
  # Unyson Framework
2
 
3
- [Unyson](http://unyson.themefuse.com/) is a framework for [WordPress](http://wordpress.org/) that facilitates development of a theme.
4
 
5
  This framework was created from the ground up by the team behind [ThemeFuse](http://themefuse.com/) from the desire to empower developers to build outstanding WordPress themes fast and easy.
6
 
7
- To get started, check out http://unyson.themefuse.com/!
8
 
9
  If you are not a developer, please use the [Unyson plugin page](https://wordpress.org/plugins/unyson/) on WordPress.org.
10
 
@@ -43,7 +43,7 @@ A good bug report includes full details to easily understand the issue you are h
43
 
44
  ## Documentation
45
 
46
- Unyson's documentation is available on http://unyson-docs.themefuse.com/.
47
 
48
  ## Copyright and license
49
 
1
  # Unyson Framework
2
 
3
+ [Unyson](http://unyson.themefuse.com/) is a framework for [WordPress](http://wordpress.org/) that facilitates the development of a theme.
4
 
5
  This framework was created from the ground up by the team behind [ThemeFuse](http://themefuse.com/) from the desire to empower developers to build outstanding WordPress themes fast and easy.
6
 
7
+ To get started, check out the [Scratch Theme](https://github.com/ThemeFuse/Scratch-Theme).
8
 
9
  If you are not a developer, please use the [Unyson plugin page](https://wordpress.org/plugins/unyson/) on WordPress.org.
10
 
43
 
44
  ## Documentation
45
 
46
+ Unyson's documentation is available on http://unyson-docs.themefuse.com/
47
 
48
  ## Copyright and license
49
 
framework/bootstrap.php CHANGED
@@ -1,24 +1,11 @@
1
  <?php if (!defined('ABSPATH')) die('Forbidden');
2
 
3
- /**
4
- * Loads the framework
5
- * Include this file in theme/functions.php
6
- */
7
-
8
  if (defined('FW')) {
9
  /**
10
  * The framework is already loaded.
11
  */
12
- return;
13
  } else {
14
- /**
15
- * Tells that the framework is loaded.
16
- * You can check if this constant is defined to be sure the file is not accessed directly from browser.
17
- */
18
  define('FW', true);
19
- }
20
-
21
- if (!function_exists('_action_init_framework')):
22
 
23
  /**
24
  * Load the framework on 'after_setup_theme' action when the theme information is available
@@ -106,5 +93,4 @@ if (!function_exists('_action_init_framework')):
106
  */
107
  do_action('fw_init');
108
  }
109
-
110
- endif;
1
  <?php if (!defined('ABSPATH')) die('Forbidden');
2
 
 
 
 
 
 
3
  if (defined('FW')) {
4
  /**
5
  * The framework is already loaded.
6
  */
 
7
  } else {
 
 
 
 
8
  define('FW', true);
 
 
 
9
 
10
  /**
11
  * Load the framework on 'after_setup_theme' action when the theme information is available
93
  */
94
  do_action('fw_init');
95
  }
96
+ }
 
framework/core/components/extensions/manager/class--fw-extensions-manager.php CHANGED
@@ -31,37 +31,91 @@ final class _FW_Extensions_Manager
31
  return;
32
  }
33
 
34
- if (!current_user_can($this->get_capability())) {
 
 
 
 
 
 
35
  return;
36
  }
37
 
 
38
  {
39
  add_action('fw_init', array($this, '_action_fw_init'));
40
  add_action('admin_menu', array($this, '_action_admin_menu'));
 
41
  add_action('admin_footer', array($this, '_action_admin_footer'));
42
- add_action('fw_plugin_pre_update', array($this, '_action_plugin_pre_update'));
43
- add_action('fw_plugin_post_update', array($this, '_action_plugin_post_update'));
44
- add_action('wp_ajax_fw_extensions_check_direct_fs_access', array($this, '_action_ajax_check_direct_fs_access'));
45
  add_action('admin_enqueue_scripts', array($this, '_action_enqueue_menu_icon_style'));
46
 
47
- /**
48
- * as late as possible, but to be able to make redirects (content not started)
49
- */
50
- add_action('current_screen', array($this, '_action_check_if_plugin_was_activated'), 100);
 
 
51
  }
52
 
 
53
  {
54
  add_filter('fw_plugin_action_list', array($this, '_filter_plugin_action_list'));
55
  }
56
  }
57
 
58
  /**
59
- * Capability that has access to the extensions page and all its functionality
60
- * @return string
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
  */
62
- private function get_capability()
63
  {
64
- return 'update_plugins';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
  }
66
 
67
  private function get_page_slug()
@@ -148,7 +202,8 @@ final class _FW_Extensions_Manager
148
  */
149
  public function _action_ajax_check_direct_fs_access()
150
  {
151
- if (!current_user_can($this->get_capability())) {
 
152
  wp_send_json_error();
153
  }
154
 
@@ -164,14 +219,6 @@ final class _FW_Extensions_Manager
164
  */
165
  public function _action_check_if_plugin_was_activated()
166
  {
167
- if (!is_admin()) {
168
- return;
169
- }
170
-
171
- if (!current_user_can($this->get_capability())) {
172
- return;
173
- }
174
-
175
  {
176
  $option_name = '_fw_plugin_activated';
177
 
@@ -414,7 +461,7 @@ final class _FW_Extensions_Manager
414
  return;
415
  }
416
 
417
- if (!current_user_can($this->get_capability())) {
418
  return;
419
  }
420
 
@@ -475,54 +522,55 @@ final class _FW_Extensions_Manager
475
  */
476
  public function _action_admin_menu()
477
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
478
  /**
479
- * Extensions page
 
480
  */
481
- {
482
- $data = array(
483
- 'title' => fw()->manifest->get_name(),
484
- 'capability' => $this->get_capability(),
485
- 'slug' => $this->get_page_slug(),
486
- 'content_callback' => array($this, '_display_page'),
487
- );
488
-
489
- /**
490
- * Use this action if you what to add the extensions page in a custom place in menu
491
- * Usage example http://pastebin.com/2iWVRPAU
492
- */
493
- do_action('fw_backend_add_custom_extensions_menu', $data);
494
 
495
- /**
496
- * check if menu was added in the action above
497
- */
498
- {
499
- global $_registered_pages;
500
 
501
- $menu_exists = false;
502
 
503
- if (!empty($_registered_pages)) {
504
- foreach ( $_registered_pages as $hookname => $b ) {
505
- if ( strpos( $hookname, $data['slug'] ) !== false ) {
506
- $menu_exists = true;
507
- break;
508
- }
509
  }
510
  }
511
  }
 
512
 
513
- if ($menu_exists) {
514
- //
515
- } else {
516
- add_menu_page(
517
- $data['title'],
518
- $data['title'],
519
- $data['capability'],
520
- $data['slug'],
521
- $data['content_callback'],
522
- 'none',
523
- 3
524
- );
525
- }
526
  }
527
  }
528
 
@@ -656,6 +704,7 @@ final class _FW_Extensions_Manager
656
  'activate' => $this->get_nonce('activate'),
657
  'deactivate' => $this->get_nonce('deactivate'),
658
  ),
 
659
  ), false);
660
 
661
  echo '</div>';
@@ -665,6 +714,18 @@ final class _FW_Extensions_Manager
665
 
666
  private function display_install_page()
667
  {
 
 
 
 
 
 
 
 
 
 
 
 
668
  if (array_key_exists('supported', $_GET)) {
669
  $supported = true;
670
 
@@ -681,8 +742,6 @@ final class _FW_Extensions_Manager
681
 
682
  unset($extension_names);
683
 
684
- $flash_id = 'fw_extensions_install';
685
-
686
  if (is_wp_error($install_data)) {
687
  FW_Flash_Messages::add($flash_id, $install_data->get_error_message(), 'error');
688
  $this->js_redirect();
@@ -936,6 +995,18 @@ final class _FW_Extensions_Manager
936
 
937
  private function display_delete_page()
938
  {
 
 
 
 
 
 
 
 
 
 
 
 
939
  $installed_extensions = $this->get_installed_extensions();
940
 
941
  $extensions = array_fill_keys(array_map('trim', explode(',', FW_Request::GET('extension', ''))), array());
@@ -963,7 +1034,7 @@ final class _FW_Extensions_Manager
963
  } while(false);
964
 
965
  if ($error) {
966
- FW_Flash_Messages::add('fw_extensions_delete', $error, 'error');
967
  $this->js_redirect();
968
  return;
969
  }
@@ -1103,6 +1174,8 @@ final class _FW_Extensions_Manager
1103
 
1104
  $installed_extensions = $this->get_installed_extensions();
1105
 
 
 
1106
  {
1107
  $error = '';
1108
 
@@ -1119,7 +1192,7 @@ final class _FW_Extensions_Manager
1119
  } while(false);
1120
 
1121
  if ($error) {
1122
- FW_Flash_Messages::add('fw_extension_page', $error, 'error');
1123
  $this->js_redirect();
1124
  return;
1125
  }
@@ -1183,7 +1256,7 @@ final class _FW_Extensions_Manager
1183
  echo '</div>';
1184
 
1185
  if ($error) {
1186
- FW_Flash_Messages::add('fw_extension_page', $error, 'error');
1187
  $this->js_redirect();
1188
  return;
1189
  }
@@ -1518,7 +1591,7 @@ final class _FW_Extensions_Manager
1518
  public function _extension_settings_form_validate($errors)
1519
  {
1520
  do {
1521
- if (!current_user_can($this->get_capability())) {
1522
  $errors[] = __('You are not allowed to save extensions settings.', 'fw');
1523
  break;
1524
  }
@@ -2036,7 +2109,15 @@ final class _FW_Extensions_Manager
2036
  static $cache_link = null;
2037
 
2038
  if ($cache_link === null) {
2039
- $cache_link = menu_page_url($this->get_page_slug(), false);
 
 
 
 
 
 
 
 
2040
  }
2041
 
2042
  return $cache_link;
31
  return;
32
  }
33
 
34
+ // In any case/permission, make sure to not miss the plugin update actions to prevent extensions delete
35
+ {
36
+ add_action('fw_plugin_pre_update', array($this, '_action_plugin_pre_update'));
37
+ add_action('fw_plugin_post_update', array($this, '_action_plugin_post_update'));
38
+ }
39
+
40
+ if (!$this->can_activate() && !$this->can_install()) {
41
  return;
42
  }
43
 
44
+ /** Actions */
45
  {
46
  add_action('fw_init', array($this, '_action_fw_init'));
47
  add_action('admin_menu', array($this, '_action_admin_menu'));
48
+ add_action('network_admin_menu', array($this, '_action_admin_menu'));
49
  add_action('admin_footer', array($this, '_action_admin_footer'));
 
 
 
50
  add_action('admin_enqueue_scripts', array($this, '_action_enqueue_menu_icon_style'));
51
 
52
+ if ($this->can_install()) {
53
+ add_action('wp_ajax_fw_extensions_check_direct_fs_access', array($this, '_action_ajax_check_direct_fs_access'));
54
+
55
+ // as late as possible, but to be able to make redirects (content not started)
56
+ add_action('current_screen', array($this, '_action_check_if_plugin_was_activated'), 100);
57
+ }
58
  }
59
 
60
+ /** Filters */
61
  {
62
  add_filter('fw_plugin_action_list', array($this, '_filter_plugin_action_list'));
63
  }
64
  }
65
 
66
  /**
67
+ * If current user can:
68
+ * - activate extension
69
+ * - disable extensions
70
+ * - save extension settings options
71
+ * @return bool
72
+ */
73
+ private function can_activate()
74
+ {
75
+ static $can_activate = null;
76
+
77
+ if ($can_activate === null) {
78
+ $can_activate = current_user_can('manage_options');
79
+
80
+ if ($can_activate) {
81
+ // also you can use this method to get the capability
82
+ $can_activate = 'manage_options';
83
+ }
84
+
85
+ if (!$can_activate) {
86
+ // make sure if can install, then also can activate. (can install) > (can activate)
87
+ $can_activate = $this->can_install();
88
+ }
89
+ }
90
+
91
+ return $can_activate;
92
+ }
93
+
94
+ /**
95
+ * If current user can:
96
+ * - install extensions
97
+ * - delete extensions
98
+ * @return bool
99
  */
100
+ private function can_install()
101
  {
102
+ static $can_install = null;
103
+
104
+ if ($can_install === null) {
105
+ $can_install = current_user_can('install_plugins');
106
+
107
+ if (is_multisite() && !is_network_admin()) {
108
+ // only network admin can change files that affects the entire network
109
+ $can_install = false;
110
+ }
111
+
112
+ if ($can_install) {
113
+ // also you can use this method to get the capability
114
+ $can_install = 'install_plugins';
115
+ }
116
+ }
117
+
118
+ return $can_install;
119
  }
120
 
121
  private function get_page_slug()
202
  */
203
  public function _action_ajax_check_direct_fs_access()
204
  {
205
+ if (!$this->can_install()) {
206
+ // if can't install, no need to know if has access or not
207
  wp_send_json_error();
208
  }
209
 
219
  */
220
  public function _action_check_if_plugin_was_activated()
221
  {
 
 
 
 
 
 
 
 
222
  {
223
  $option_name = '_fw_plugin_activated';
224
 
461
  return;
462
  }
463
 
464
+ if (!$this->can_activate()) {
465
  return;
466
  }
467
 
522
  */
523
  public function _action_admin_menu()
524
  {
525
+ $capability = $this->can_activate();
526
+
527
+ if (!$capability) {
528
+ return;
529
+ }
530
+
531
+ $data = array(
532
+ 'title' => fw()->manifest->get_name(),
533
+ 'capability' => $capability,
534
+ 'slug' => $this->get_page_slug(),
535
+ 'content_callback' => array($this, '_display_page'),
536
+ );
537
+
538
  /**
539
+ * Use this action if you what to add the extensions page in a custom place in menu
540
+ * Usage example http://pastebin.com/2iWVRPAU
541
  */
542
+ do_action('fw_backend_add_custom_extensions_menu', $data);
 
 
 
 
 
 
 
 
 
 
 
 
543
 
544
+ /**
545
+ * check if menu was added in the action above
546
+ */
547
+ {
548
+ global $_registered_pages;
549
 
550
+ $menu_exists = false;
551
 
552
+ if (!empty($_registered_pages)) {
553
+ foreach ( $_registered_pages as $hookname => $b ) {
554
+ if ( strpos( $hookname, $data['slug'] ) !== false ) {
555
+ $menu_exists = true;
556
+ break;
 
557
  }
558
  }
559
  }
560
+ }
561
 
562
+ if ($menu_exists) {
563
+ //
564
+ } else {
565
+ add_menu_page(
566
+ $data['title'],
567
+ $data['title'],
568
+ $data['capability'],
569
+ $data['slug'],
570
+ $data['content_callback'],
571
+ 'none',
572
+ 3
573
+ );
 
574
  }
575
  }
576
 
704
  'activate' => $this->get_nonce('activate'),
705
  'deactivate' => $this->get_nonce('deactivate'),
706
  ),
707
+ 'can_install' => $this->can_install(),
708
  ), false);
709
 
710
  echo '</div>';
714
 
715
  private function display_install_page()
716
  {
717
+ $flash_id = 'fw_extensions_install';
718
+
719
+ if (!$this->can_install()) {
720
+ FW_Flash_Messages::add(
721
+ $flash_id,
722
+ __('You are not allowed to install extensions.', 'fw'),
723
+ 'error'
724
+ );
725
+ $this->js_redirect();
726
+ return;
727
+ }
728
+
729
  if (array_key_exists('supported', $_GET)) {
730
  $supported = true;
731
 
742
 
743
  unset($extension_names);
744
 
 
 
745
  if (is_wp_error($install_data)) {
746
  FW_Flash_Messages::add($flash_id, $install_data->get_error_message(), 'error');
747
  $this->js_redirect();
995
 
996
  private function display_delete_page()
997
  {
998
+ $flash_id = 'fw_extensions_delete';
999
+
1000
+ if (!$this->can_install()) {
1001
+ FW_Flash_Messages::add(
1002
+ $flash_id,
1003
+ __('You are not allowed to delete extensions.', 'fw'),
1004
+ 'error'
1005
+ );
1006
+ $this->js_redirect();
1007
+ return;
1008
+ }
1009
+
1010
  $installed_extensions = $this->get_installed_extensions();
1011
 
1012
  $extensions = array_fill_keys(array_map('trim', explode(',', FW_Request::GET('extension', ''))), array());
1034
  } while(false);
1035
 
1036
  if ($error) {
1037
+ FW_Flash_Messages::add($flash_id, $error, 'error');
1038
  $this->js_redirect();
1039
  return;
1040
  }
1174
 
1175
  $installed_extensions = $this->get_installed_extensions();
1176
 
1177
+ $flash_id = 'fw_extension_page';
1178
+
1179
  {
1180
  $error = '';
1181
 
1192
  } while(false);
1193
 
1194
  if ($error) {
1195
+ FW_Flash_Messages::add($flash_id, $error, 'error');
1196
  $this->js_redirect();
1197
  return;
1198
  }
1256
  echo '</div>';
1257
 
1258
  if ($error) {
1259
+ FW_Flash_Messages::add($flash_id, $error, 'error');
1260
  $this->js_redirect();
1261
  return;
1262
  }
1591
  public function _extension_settings_form_validate($errors)
1592
  {
1593
  do {
1594
+ if (!current_user_can($this->can_activate())) {
1595
  $errors[] = __('You are not allowed to save extensions settings.', 'fw');
1596
  break;
1597
  }
2109
  static $cache_link = null;
2110
 
2111
  if ($cache_link === null) {
2112
+ $cache_link = menu_page_url( $this->get_page_slug(), false );
2113
+
2114
+ // https://core.trac.wordpress.org/ticket/28226
2115
+ if (is_multisite() && is_network_admin()) {
2116
+ $cache_link = self_admin_url(
2117
+ // extract relative link
2118
+ preg_replace('/^'. preg_quote(admin_url(), '/') .'/', '', $cache_link)
2119
+ );
2120
+ }
2121
  }
2122
 
2123
  return $cache_link;
framework/core/components/extensions/manager/views/extension.php CHANGED
@@ -8,6 +8,7 @@
8
  * @var array $lists
9
  * @var array $nonces
10
  * @var string $default_thumbnail
 
11
  */
12
 
13
  $is_active = (bool)fw()->extensions->get($name);
@@ -108,7 +109,7 @@ if (isset($lists['available'][$name])) {
108
  * If you delete such extension you will not be able to install it back.
109
  * Most often these will be extensions located in the theme.
110
  */
111
- if ($available_data):
112
  ?>
113
  <form action="<?php echo esc_attr($link) ?>&sub-page=delete&extension=<?php echo esc_attr($name) ?>"
114
  method="post"
@@ -121,7 +122,7 @@ if (isset($lists['available'][$name])) {
121
  </form>
122
  <?php endif; ?>
123
  </div>
124
- <?php elseif ($available_data): ?>
125
  <form action="<?php echo esc_attr($link) ?>&sub-page=install&extension=<?php echo esc_attr($name) ?>" method="post" class="fw-extension-ajax-form">
126
  <?php wp_nonce_field($nonces['install']['action'], $nonces['install']['name']); ?>
127
  <input type="submit" class="button" value="<?php esc_attr_e('Download', 'fw') ?>">
@@ -169,11 +170,18 @@ if (isset($lists['available'][$name])) {
169
 
170
  if ( ! empty( $req_data['min_version'] ) ) {
171
  if (!version_compare($req_data['min_version'], $wp_version, '<=')) {
172
- $requirements[] = sprintf(
173
- __('You need to update WordPress to %s: %s', 'fw'),
174
- $req_data['min_version'],
175
- fw_html_tag('a', array('href' => self_admin_url('update-core.php')), __('Update WordPress', 'fw'))
176
- );
 
 
 
 
 
 
 
177
  }
178
  }
179
 
@@ -193,14 +201,22 @@ if (isset($lists['available'][$name])) {
193
 
194
  if ( ! empty( $req_data['min_version'] ) ) {
195
  if (!version_compare($req_data['min_version'], fw()->manifest->get_version(), '<=')) {
196
- $requirements[] = sprintf(
197
- __('You need to update %s to %s: %s', 'fw'),
198
- fw()->manifest->get_name(),
199
- $req_data['min_version'],
200
- fw_html_tag('a', array('href' => self_admin_url('update-core.php')),
201
- sprintf(__('Update %s', 'fw'), fw()->manifest->get_name())
202
- )
203
- );
 
 
 
 
 
 
 
 
204
  }
205
  }
206
 
@@ -223,14 +239,22 @@ if (isset($lists['available'][$name])) {
223
 
224
  if ( ! empty( $req_ext_data['min_version'] ) ) {
225
  if (!version_compare($req_ext_data['min_version'], $ext->manifest->get_version(), '<=')) {
226
- $requirements[] = sprintf(
227
- __('You need to update the %s extension to %s: %s', 'fw'),
228
- $ext->manifest->get_name(),
229
- $req_ext_data['min_version'],
230
- fw_html_tag('a', array('href' => self_admin_url('update-core.php')),
231
- sprintf(__('Update %s', 'fw'), $ext->manifest->get_name())
232
- )
233
- );
 
 
 
 
 
 
 
 
234
  }
235
  }
236
 
@@ -258,14 +282,14 @@ if (isset($lists['available'][$name])) {
258
  <?php
259
  $requirements[] = ob_get_clean();
260
  } else {
261
- if (isset($lists['available'][$req_ext])) {
262
  $ext_title = $lists['available'][ $req_ext ]['name'];
263
 
264
  $requirements[] = sprintf(
265
  __( 'The %s extension is not installed: %s', 'fw' ),
266
  $ext_title,
267
- fw_html_tag('a', array('href' => $link .'&sub-page=install&extension='. $req_ext),
268
- sprintf(__('Install %s', 'fw'), $ext_title)
269
  )
270
  );
271
  } else {
@@ -292,7 +316,11 @@ if (isset($lists['available'][$name])) {
292
  );
293
  unset($requirements);
294
  ?>"><?php _e('View Requirements', 'fw') ?></a>
295
- &nbsp; <p class="fw-visible-xs-block"></p><a href="<?php echo esc_attr($link) ?>&sub-page=delete&extension=<?php echo esc_attr($name) ?>" class="button" ><?php _e('Remove', 'fw'); ?></a>
 
 
 
 
296
  </div>
297
  </div>
298
  </div>
8
  * @var array $lists
9
  * @var array $nonces
10
  * @var string $default_thumbnail
11
+ * @var bool $can_install
12
  */
13
 
14
  $is_active = (bool)fw()->extensions->get($name);
109
  * If you delete such extension you will not be able to install it back.
110
  * Most often these will be extensions located in the theme.
111
  */
112
+ if ($can_install && $available_data):
113
  ?>
114
  <form action="<?php echo esc_attr($link) ?>&sub-page=delete&extension=<?php echo esc_attr($name) ?>"
115
  method="post"
122
  </form>
123
  <?php endif; ?>
124
  </div>
125
+ <?php elseif ($can_install && $available_data): ?>
126
  <form action="<?php echo esc_attr($link) ?>&sub-page=install&extension=<?php echo esc_attr($name) ?>" method="post" class="fw-extension-ajax-form">
127
  <?php wp_nonce_field($nonces['install']['action'], $nonces['install']['name']); ?>
128
  <input type="submit" class="button" value="<?php esc_attr_e('Download', 'fw') ?>">
170
 
171
  if ( ! empty( $req_data['min_version'] ) ) {
172
  if (!version_compare($req_data['min_version'], $wp_version, '<=')) {
173
+ if ($can_install) {
174
+ $requirements[] = sprintf(
175
+ __( 'You need to update WordPress to %s: %s', 'fw' ),
176
+ $req_data['min_version'],
177
+ fw_html_tag( 'a', array( 'href' => self_admin_url( 'update-core.php' ) ), __( 'Update WordPress', 'fw' ) )
178
+ );
179
+ } else {
180
+ $requirements[] = sprintf(
181
+ __( 'WordPress needs to be updated to %s', 'fw' ),
182
+ $req_data['min_version']
183
+ );
184
+ }
185
  }
186
  }
187
 
201
 
202
  if ( ! empty( $req_data['min_version'] ) ) {
203
  if (!version_compare($req_data['min_version'], fw()->manifest->get_version(), '<=')) {
204
+ if ($can_install) {
205
+ $requirements[] = sprintf(
206
+ __( 'You need to update %s to %s: %s', 'fw' ),
207
+ fw()->manifest->get_name(),
208
+ $req_data['min_version'],
209
+ fw_html_tag( 'a', array( 'href' => self_admin_url( 'update-core.php' ) ),
210
+ sprintf( __( 'Update %s', 'fw' ), fw()->manifest->get_name() )
211
+ )
212
+ );
213
+ } else {
214
+ $requirements[] = sprintf(
215
+ __( '%s needs to be updated to %s', 'fw' ),
216
+ fw()->manifest->get_name(),
217
+ $req_data['min_version']
218
+ );
219
+ }
220
  }
221
  }
222
 
239
 
240
  if ( ! empty( $req_ext_data['min_version'] ) ) {
241
  if (!version_compare($req_ext_data['min_version'], $ext->manifest->get_version(), '<=')) {
242
+ if ($can_install) {
243
+ $requirements[] = sprintf(
244
+ __('You need to update the %s extension to %s: %s', 'fw'),
245
+ $ext->manifest->get_name(),
246
+ $req_ext_data['min_version'],
247
+ fw_html_tag('a', array('href' => self_admin_url('update-core.php')),
248
+ sprintf(__('Update %s', 'fw'), $ext->manifest->get_name())
249
+ )
250
+ );
251
+ } else {
252
+ $requirements[] = sprintf(
253
+ __('The %s extension needs to be updated to %s', 'fw'),
254
+ $ext->manifest->get_name(),
255
+ $req_ext_data['min_version']
256
+ );
257
+ }
258
  }
259
  }
260
 
282
  <?php
283
  $requirements[] = ob_get_clean();
284
  } else {
285
+ if ($can_install && isset($lists['available'][$req_ext])) {
286
  $ext_title = $lists['available'][ $req_ext ]['name'];
287
 
288
  $requirements[] = sprintf(
289
  __( 'The %s extension is not installed: %s', 'fw' ),
290
  $ext_title,
291
+ fw_html_tag( 'a', array( 'href' => $link . '&sub-page=install&extension=' . $req_ext ),
292
+ sprintf( __( 'Install %s', 'fw' ), $ext_title )
293
  )
294
  );
295
  } else {
316
  );
317
  unset($requirements);
318
  ?>"><?php _e('View Requirements', 'fw') ?></a>
319
+ &nbsp; <p class="fw-visible-xs-block"></p><?php
320
+ if ($can_install):
321
+ ?><a href="<?php echo esc_attr($link) ?>&sub-page=delete&extension=<?php echo esc_attr($name) ?>" class="button" ><?php _e('Remove', 'fw'); ?></a><?php
322
+ endif;
323
+ ?>
324
  </div>
325
  </div>
326
  </div>
framework/core/components/extensions/manager/views/extensions-page.php CHANGED
@@ -5,6 +5,7 @@
5
  * @var array $nonces
6
  * @var mixed $display_default_value
7
  * @var string $default_thumbnail
 
8
  */
9
 
10
  $dir = dirname(__FILE__);
@@ -42,6 +43,7 @@ foreach ($lists['active'] as $name => &$data) {
42
  'lists' => &$lists,
43
  'nonces' => $nonces,
44
  'default_thumbnail' => $default_thumbnail,
 
45
  ), false);
46
 
47
  $displayed[$name] = true;
@@ -77,11 +79,15 @@ foreach ($lists['active'] as $name => &$data) {
77
  if (true !== fw_akg('display', $lists['installed'][$name]['manifest'], $display_default_value)) {
78
  continue;
79
  }
80
- } elseif (!isset($lists['available'][$name])) {
81
- /*trigger_error(
82
- sprintf(__('Supported extension "%s" is not available.', 'fw'), $name)
83
- );*/
84
- continue;
 
 
 
 
85
  }
86
 
87
  fw_render_view($extension_view_path, array(
@@ -92,6 +98,7 @@ foreach ($lists['active'] as $name => &$data) {
92
  'lists' => &$lists,
93
  'nonces' => $nonces,
94
  'default_thumbnail' => $default_thumbnail,
 
95
  ), false);
96
 
97
  $displayed[$name] = $something_displayed = true;
@@ -115,40 +122,45 @@ foreach ($lists['active'] as $name => &$data) {
115
  'lists' => &$lists,
116
  'nonces' => $nonces,
117
  'default_thumbnail' => $default_thumbnail,
 
118
  ), false);
119
 
120
  $displayed[$name] = $something_displayed = true;
121
  }
122
 
123
- foreach ($lists['available'] as $name => &$data) {
124
- if (isset($displayed[$name])) {
125
- continue;
126
- } elseif (isset($lists['installed'][$name])) {
127
- continue;
128
- } elseif ($data['display'] !== true) {
129
- continue;
130
- }
131
-
132
- /**
133
- * fixme: remove this in the future when this extensions will look good on any theme
134
- */
135
- if (in_array($name, array('styling', 'megamenu'))) {
136
- if (isset($lists['supported'][$name]) || (defined('WP_DEBUG') && WP_DEBUG)) { } else {
137
  continue;
138
  }
139
- }
140
 
141
- fw_render_view($extension_view_path, array(
142
- 'name' => $name,
143
- 'title' => $data['name'],
144
- 'description' => $data['description'],
145
- 'link' => $link,
146
- 'lists' => &$lists,
147
- 'nonces' => $nonces,
148
- 'default_thumbnail' => $default_thumbnail,
149
- ), false);
150
 
151
- $something_displayed = true;
 
 
 
 
 
 
 
 
 
 
 
 
152
  }
153
  ?>
154
  </div>
5
  * @var array $nonces
6
  * @var mixed $display_default_value
7
  * @var string $default_thumbnail
8
+ * @var bool $can_install
9
  */
10
 
11
  $dir = dirname(__FILE__);
43
  'lists' => &$lists,
44
  'nonces' => $nonces,
45
  'default_thumbnail' => $default_thumbnail,
46
+ 'can_install' => $can_install,
47
  ), false);
48
 
49
  $displayed[$name] = true;
79
  if (true !== fw_akg('display', $lists['installed'][$name]['manifest'], $display_default_value)) {
80
  continue;
81
  }
82
+ } else {
83
+ if (isset($lists['available'][$name])) {
84
+ if (!$can_install) {
85
+ continue;
86
+ }
87
+ } else {
88
+ //trigger_error(sprintf(__('Supported extension "%s" is not available.', 'fw'), $name));
89
+ continue;
90
+ }
91
  }
92
 
93
  fw_render_view($extension_view_path, array(
98
  'lists' => &$lists,
99
  'nonces' => $nonces,
100
  'default_thumbnail' => $default_thumbnail,
101
+ 'can_install' => $can_install,
102
  ), false);
103
 
104
  $displayed[$name] = $something_displayed = true;
122
  'lists' => &$lists,
123
  'nonces' => $nonces,
124
  'default_thumbnail' => $default_thumbnail,
125
+ 'can_install' => $can_install,
126
  ), false);
127
 
128
  $displayed[$name] = $something_displayed = true;
129
  }
130
 
131
+ if ($can_install) {
132
+ foreach ( $lists['available'] as $name => &$data ) {
133
+ if ( isset( $displayed[ $name ] ) ) {
134
+ continue;
135
+ } elseif ( isset( $lists['installed'][ $name ] ) ) {
136
+ continue;
137
+ } elseif ( $data['display'] !== true ) {
 
 
 
 
 
 
 
138
  continue;
139
  }
 
140
 
141
+ /**
142
+ * fixme: remove this in the future when this extensions will look good on any theme
143
+ */
144
+ if ( in_array( $name, array( 'styling', 'megamenu' ) ) ) {
145
+ if ( isset( $lists['supported'][ $name ] ) || ( defined( 'WP_DEBUG' ) && WP_DEBUG ) ) {
146
+ } else {
147
+ continue;
148
+ }
149
+ }
150
 
151
+ fw_render_view( $extension_view_path, array(
152
+ 'name' => $name,
153
+ 'title' => $data['name'],
154
+ 'description' => $data['description'],
155
+ 'link' => $link,
156
+ 'lists' => &$lists,
157
+ 'nonces' => $nonces,
158
+ 'default_thumbnail' => $default_thumbnail,
159
+ 'can_install' => $can_install,
160
+ ), false );
161
+
162
+ $something_displayed = true;
163
+ }
164
  }
165
  ?>
166
  </div>
framework/extensions/update/class-fw-extension-update.php CHANGED
@@ -29,14 +29,25 @@ class FW_Extension_Update extends FW_Extension
29
  */
30
  protected function _init()
31
  {
32
- if (current_user_can('update_themes') || current_user_can('update_plugins')) {
33
- $this->context = get_template_directory();
 
 
 
 
 
 
 
34
 
35
- $this->add_actions();
36
- $this->add_filters();
37
- } else {
38
- return false; // prevent child extensions activation
39
  }
 
 
 
 
 
40
  }
41
 
42
  private function add_actions()
29
  */
30
  protected function _init()
31
  {
32
+ {
33
+ $has_access = (current_user_can('update_themes') || current_user_can('update_plugins'));
34
+
35
+ if ($has_access) {
36
+ if (is_multisite() && !is_network_admin()) {
37
+ // only network admin can change files that affects the entire network
38
+ $has_access = false;
39
+ }
40
+ }
41
 
42
+ if (!$has_access) {
43
+ return false; // prevent child extensions activation
44
+ }
 
45
  }
46
+
47
+ $this->context = get_template_directory();
48
+
49
+ $this->add_actions();
50
+ $this->add_filters();
51
  }
52
 
53
  private function add_actions()
framework/extensions/update/manifest.php CHANGED
@@ -5,5 +5,5 @@ $manifest = array();
5
  $manifest['name'] = __('Update', 'fw');
6
  $manifest['description'] = __('Keep you framework, extensions and theme up to date.', 'fw');
7
  $manifest['standalone'] = true;
8
- $manifest['version'] = '1.0.0';
9
  $manifest['github_update'] = 'ThemeFuse/Unyson-Update-Extension';
5
  $manifest['name'] = __('Update', 'fw');
6
  $manifest['description'] = __('Keep you framework, extensions and theme up to date.', 'fw');
7
  $manifest['standalone'] = true;
8
+ $manifest['version'] = '1.0.1';
9
  $manifest['github_update'] = 'ThemeFuse/Unyson-Update-Extension';
framework/manifest.php CHANGED
@@ -4,4 +4,4 @@ $manifest = array();
4
 
5
  $manifest['name'] = __('Unyson', 'fw');
6
 
7
- $manifest['version'] = '2.1.2';
4
 
5
  $manifest['name'] = __('Unyson', 'fw');
6
 
7
+ $manifest['version'] = '2.1.3';
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: unyson, themefusecom
3
  Tags: page builder, cms, grid, layout, responsive, back up, backup, db backup, dump, migrate, schedule, search engine optimization, seo, media, slideshow, shortcode, slide, slideshare, slideshow, google sitemaps, sitemaps, analytics, google analytics, calendar, event, events, google maps, learning, lessons, sidebars, breadcrumbs, review, portfolio
4
  Requires at least: 4.0.0
5
  Tested up to: 4.0.1
6
- Stable tag: 2.1.2
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
@@ -28,6 +28,8 @@ A simple and easy way to build a powerful website.
28
  * **Feedback.** We've added a way for users to submit reviews and ratings for events, projects, etc.
29
  * **Learning.** Create courses, lessons and quizzes for your online training site.
30
 
 
 
31
  **Get involved**
32
 
33
  Developers can contribute to the source code on the [Unyson GitHub Repository](https://github.com/ThemeFuse/Unyson/blob/master/CONTRIBUTING.md).
@@ -82,6 +84,9 @@ Yes; Unyson will work with any theme.
82
 
83
  == Changelog ==
84
 
 
 
 
85
  = 2.1.2 =
86
  * Minor fixes and improvements in the extensions installation process
87
 
3
  Tags: page builder, cms, grid, layout, responsive, back up, backup, db backup, dump, migrate, schedule, search engine optimization, seo, media, slideshow, shortcode, slide, slideshare, slideshow, google sitemaps, sitemaps, analytics, google analytics, calendar, event, events, google maps, learning, lessons, sidebars, breadcrumbs, review, portfolio
4
  Requires at least: 4.0.0
5
  Tested up to: 4.0.1
6
+ Stable tag: 2.1.3
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
28
  * **Feedback.** We've added a way for users to submit reviews and ratings for events, projects, etc.
29
  * **Learning.** Create courses, lessons and quizzes for your online training site.
30
 
31
+ To get started, check out the [Scratch Theme](https://github.com/ThemeFuse/Scratch-Theme).
32
+
33
  **Get involved**
34
 
35
  Developers can contribute to the source code on the [Unyson GitHub Repository](https://github.com/ThemeFuse/Unyson/blob/master/CONTRIBUTING.md).
84
 
85
  == Changelog ==
86
 
87
+ = 2.1.3 =
88
+ * Multi-site: Only network administrator can install/remove/update extensions
89
+
90
  = 2.1.2 =
91
  * Minor fixes and improvements in the extensions installation process
92
 
unyson.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: Unyson
4
  * Plugin URI: http://unyson.themefuse.com/
5
  * Description: A free drag & drop framework that comes with a bunch of built in extensions that will help you develop premium themes fast & easy.
6
- * Version: 2.1.2
7
  * Author: ThemeFuse
8
  * Author URI: http://themefuse.com
9
  * License: GPL2+
@@ -11,87 +11,94 @@
11
  * Domain Path: /languages/
12
  */
13
 
14
- {
15
- /** @internal */
16
- function _filter_fw_framework_plugin_directory_uri() {
17
- return plugin_dir_url( __FILE__ ) . 'framework';
18
- }
19
- add_filter( 'fw_framework_directory_uri', '_filter_fw_framework_plugin_directory_uri' );
20
- }
21
-
22
- require dirname( __FILE__ ) . '/framework/bootstrap.php';
23
 
24
- /**
25
- * Plugin related functionality
26
- *
27
- * Note:
28
- * The framework doesn't know that it's used as a plugin.
29
- * It can be localed in the theme directory or any other directory.
30
- * Only its path and uri is known (specified above)
31
- */
32
- {
33
- /** @internal */
34
- function _action_fw_plugin_activate() {
35
- foreach ( glob( dirname( __FILE__ ) . '/framework/includes/on-plugin-activation/*.php' ) as $file ) {
36
- require_once $file;
37
  }
 
38
  }
39
- register_activation_hook( __FILE__, '_action_fw_plugin_activate' );
40
 
41
- /** @internal */
42
- function _action_term_meta_new_blog( $blog_id, $user_id, $domain, $path, $site_id, $meta ) {
43
- if ( is_plugin_active_for_network( plugin_basename( __FILE__ ) ) ) {
44
- _fw_term_meta_setup_blog( $blog_id );
 
 
 
 
 
 
 
 
 
 
 
 
45
  }
46
- }
47
- add_action( 'wpmu_new_blog', '_action_term_meta_new_blog', 10, 6 );
48
 
49
- /** @internal */
50
- function _filter_check_if_plugin_pre_update($result, $data) {
51
- if (isset($data['plugin']) && $data['plugin'] === plugin_basename( __FILE__ )) {
52
- /**
53
- * Before plugin update
54
- */
55
- do_action('fw_plugin_pre_update');
56
  }
 
57
 
58
- return $result;
59
- }
60
- add_filter('upgrader_pre_install', '_filter_check_if_plugin_pre_update', 10, 2);
 
 
 
 
 
61
 
62
- /** @internal */
63
- function _filter_check_if_plugin_post_update($result, $data) {
64
- if (isset($data['plugin']) && $data['plugin'] === plugin_basename( __FILE__ )) {
65
- /**
66
- * After plugin update
67
- */
68
- do_action('fw_plugin_post_update');
69
  }
 
70
 
71
- return $result;
72
- }
73
- add_filter('upgrader_post_install', '_filter_check_if_plugin_post_update', 10, 2);
 
 
 
 
 
74
 
75
- /** @internal */
76
- function _filter_plugin_action_list( $actions ) {
77
- return apply_filters('fw_plugin_action_list', $actions);
78
- }
79
- add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), '_filter_plugin_action_list' );
80
 
81
- /** @internal */
82
- function _action_fw_textdomain() {
83
- load_plugin_textdomain( 'fw', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
84
- }
85
- add_action( 'plugins_loaded', '_action_fw_textdomain' );
86
 
87
- /** @internal */
88
- function _filter_fw_tmp_dir($dir) {
89
- /**
90
- * Some users force WP_Filesystem to use the 'direct' method <?php define( 'FS_METHOD', 'direct' ); ?> and set chmod 777 to the unyson/ plugin.
91
- * By default tmp dir is WP_CONTENT_DIR.'/tmp' and WP_Filesystem can't create it with 'direct' method, then users can't download and install extensions.
92
- * In order to prevent this situation, create the temporary directory inside the plugin folder.
93
- */
94
- return dirname(__FILE__) . '/tmp';
 
 
 
 
 
 
 
 
95
  }
96
- add_filter('fw_tmp_dir', '_filter_fw_tmp_dir');
97
  }
3
  * Plugin Name: Unyson
4
  * Plugin URI: http://unyson.themefuse.com/
5
  * Description: A free drag & drop framework that comes with a bunch of built in extensions that will help you develop premium themes fast & easy.
6
+ * Version: 2.1.3
7
  * Author: ThemeFuse
8
  * Author URI: http://themefuse.com
9
  * License: GPL2+
11
  * Domain Path: /languages/
12
  */
13
 
14
+ if (defined('FW')) {
15
+ /**
16
+ * The plugin was already loaded (maybe as another plugin with different directory name)
17
+ */
18
+ } else {
 
 
 
 
19
 
20
+ {
21
+ /** @internal */
22
+ function _filter_fw_framework_plugin_directory_uri() {
23
+ return plugin_dir_url( __FILE__ ) . 'framework';
 
 
 
 
 
 
 
 
 
24
  }
25
+ add_filter( 'fw_framework_directory_uri', '_filter_fw_framework_plugin_directory_uri' );
26
  }
 
27
 
28
+ require dirname( __FILE__ ) . '/framework/bootstrap.php';
29
+
30
+ /**
31
+ * Plugin related functionality
32
+ *
33
+ * Note:
34
+ * The framework doesn't know that it's used as a plugin.
35
+ * It can be localed in the theme directory or any other directory.
36
+ * Only its path and uri is known (specified above)
37
+ */
38
+ {
39
+ /** @internal */
40
+ function _action_fw_plugin_activate() {
41
+ foreach ( glob( dirname( __FILE__ ) . '/framework/includes/on-plugin-activation/*.php' ) as $file ) {
42
+ require_once $file;
43
+ }
44
  }
45
+ register_activation_hook( __FILE__, '_action_fw_plugin_activate' );
 
46
 
47
+ /** @internal */
48
+ function _action_term_meta_new_blog( $blog_id, $user_id, $domain, $path, $site_id, $meta ) {
49
+ if ( is_plugin_active_for_network( plugin_basename( __FILE__ ) ) ) {
50
+ _fw_term_meta_setup_blog( $blog_id );
51
+ }
 
 
52
  }
53
+ add_action( 'wpmu_new_blog', '_action_term_meta_new_blog', 10, 6 );
54
 
55
+ /** @internal */
56
+ function _filter_check_if_plugin_pre_update( $result, $data ) {
57
+ if ( isset( $data['plugin'] ) && $data['plugin'] === plugin_basename( __FILE__ ) ) {
58
+ /**
59
+ * Before plugin update
60
+ */
61
+ do_action( 'fw_plugin_pre_update' );
62
+ }
63
 
64
+ return $result;
 
 
 
 
 
 
65
  }
66
+ add_filter( 'upgrader_pre_install', '_filter_check_if_plugin_pre_update', 10, 2 );
67
 
68
+ /** @internal */
69
+ function _filter_check_if_plugin_post_update( $result, $data ) {
70
+ if ( isset( $data['plugin'] ) && $data['plugin'] === plugin_basename( __FILE__ ) ) {
71
+ /**
72
+ * After plugin update
73
+ */
74
+ do_action( 'fw_plugin_post_update' );
75
+ }
76
 
77
+ return $result;
78
+ }
79
+ add_filter( 'upgrader_post_install', '_filter_check_if_plugin_post_update', 10, 2 );
 
 
80
 
81
+ /** @internal */
82
+ function _filter_plugin_action_list( $actions ) {
83
+ return apply_filters( 'fw_plugin_action_list', $actions );
84
+ }
85
+ add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), '_filter_plugin_action_list' );
86
 
87
+ /** @internal */
88
+ function _action_fw_textdomain() {
89
+ load_plugin_textdomain( 'fw', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
90
+ }
91
+ add_action( 'plugins_loaded', '_action_fw_textdomain' );
92
+
93
+ /** @internal */
94
+ function _filter_fw_tmp_dir( $dir ) {
95
+ /**
96
+ * Some users force WP_Filesystem to use the 'direct' method <?php define( 'FS_METHOD', 'direct' ); ?> and set chmod 777 to the unyson/ plugin.
97
+ * By default tmp dir is WP_CONTENT_DIR.'/tmp' and WP_Filesystem can't create it with 'direct' method, then users can't download and install extensions.
98
+ * In order to prevent this situation, create the temporary directory inside the plugin folder.
99
+ */
100
+ return dirname( __FILE__ ) . '/tmp';
101
+ }
102
+ add_filter( 'fw_tmp_dir', '_filter_fw_tmp_dir' );
103
  }
 
104
  }