Version Description
- Fixed #1351,#2716,#2833,#2736,#2718,#2953,#2888,#2855,#2906
Download this release
Release Info
Developer | Unyson |
Plugin | Unyson |
Version | 2.7.9 |
Comparing to | |
See all releases |
Code changes from version 2.7.8 to 2.7.9
- framework/core/components/backend.php +20 -36
- framework/core/components/theme.php +69 -71
- framework/extensions/update/class-fw-extension-update.php +337 -356
- framework/helpers/class-fw-form.php +1 -1
- framework/helpers/general.php +7 -0
- framework/includes/option-types/color-picker/static/js/scripts.js +4 -10
- framework/includes/option-types/multi-select/class-fw-option-type-multi-select.php +51 -50
- framework/includes/option-types/rgba-color-picker/class-fw-option-type-rgba-color-picker.php +1 -1
- framework/includes/option-types/rgba-color-picker/static/css/styles.css +15 -80
- framework/includes/option-types/rgba-color-picker/static/js/scripts.js +299 -257
- framework/includes/option-types/simple.php +12 -9
- framework/includes/option-types/wp-editor/class-fw-option-type-wp-editor.php +27 -29
- framework/manifest.php +1 -1
- framework/static/css/fw.css +29 -0
- framework/views/backend-settings-form.php +12 -3
- readme.txt +4 -1
- unyson.php +1 -1
framework/core/components/backend.php
CHANGED
@@ -624,7 +624,7 @@ final class _FW_Component_Backend {
|
|
624 |
* @param WP_Post $post
|
625 |
*/
|
626 |
public function _action_create_post_meta_boxes( $post_type, $post ) {
|
627 |
-
if ('comment' === $post_type) {
|
628 |
/**
|
629 |
* This is wrong, comment is not a post(type)
|
630 |
* it is stored in a separate db table and has a separate meta (wp_comments and wp_commentmeta)
|
@@ -641,50 +641,34 @@ final class _FW_Component_Backend {
|
|
641 |
$collected = array();
|
642 |
|
643 |
fw_collect_options( $collected, $options, array(
|
644 |
-
'limit_option_types'
|
645 |
'limit_container_types' => false,
|
646 |
-
'limit_level'
|
647 |
) );
|
648 |
|
649 |
-
if (empty($collected)) {
|
650 |
return;
|
651 |
}
|
652 |
|
653 |
$values = fw_get_db_post_option( $post->ID );
|
654 |
|
655 |
-
foreach ( $collected as $id =>
|
656 |
-
if (
|
657 |
-
|
658 |
-
&&
|
659 |
-
$option['type'] === 'box'
|
660 |
-
) { // this is a box, add it as a metabox
|
661 |
-
$context = isset( $option['context'] )
|
662 |
-
? $option['context']
|
663 |
-
: 'normal';
|
664 |
-
$priority = isset( $option['priority'] )
|
665 |
-
? $option['priority']
|
666 |
-
: 'default';
|
667 |
-
|
668 |
-
add_meta_box(
|
669 |
-
'fw-options-box-' . $id,
|
670 |
-
empty( $option['title'] ) ? ' ' : $option['title'],
|
671 |
-
$this->print_meta_box_content_callback,
|
672 |
-
$post_type,
|
673 |
-
$context,
|
674 |
-
$priority,
|
675 |
-
$this->render_options( $option['options'], $values )
|
676 |
-
);
|
677 |
-
} else { // this is not a box, wrap it in auto-generated box
|
678 |
-
add_meta_box(
|
679 |
-
'fw-options-box:auto-generated:'. time() .':'. fw_unique_increment(),
|
680 |
-
' ',
|
681 |
-
$this->print_meta_box_content_callback,
|
682 |
-
$post_type,
|
683 |
-
'normal',
|
684 |
-
'default',
|
685 |
-
$this->render_options( array($id => $option), $values )
|
686 |
-
);
|
687 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
688 |
}
|
689 |
}
|
690 |
|
624 |
* @param WP_Post $post
|
625 |
*/
|
626 |
public function _action_create_post_meta_boxes( $post_type, $post ) {
|
627 |
+
if ( 'comment' === $post_type ) {
|
628 |
/**
|
629 |
* This is wrong, comment is not a post(type)
|
630 |
* it is stored in a separate db table and has a separate meta (wp_comments and wp_commentmeta)
|
641 |
$collected = array();
|
642 |
|
643 |
fw_collect_options( $collected, $options, array(
|
644 |
+
'limit_option_types' => false,
|
645 |
'limit_container_types' => false,
|
646 |
+
'limit_level' => 1,
|
647 |
) );
|
648 |
|
649 |
+
if ( empty( $collected ) ) {
|
650 |
return;
|
651 |
}
|
652 |
|
653 |
$values = fw_get_db_post_option( $post->ID );
|
654 |
|
655 |
+
foreach ( $collected as $id => $option ) {
|
656 |
+
if ( ! isset( $option['options'] ) || ! in_array( $option['type'], array( 'box', 'group' ) ) ) {
|
657 |
+
continue;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
658 |
}
|
659 |
+
|
660 |
+
$context = isset( $option['context'] ) ? $option['context'] : 'normal';
|
661 |
+
$priority = isset( $option['priority'] ) ? $option['priority'] : 'default';
|
662 |
+
|
663 |
+
add_meta_box(
|
664 |
+
"fw-options-{$option['type']}-{$id}",
|
665 |
+
empty( $option['title'] ) ? ' ' : $option['title'],
|
666 |
+
$this->print_meta_box_content_callback,
|
667 |
+
$post_type,
|
668 |
+
$context,
|
669 |
+
$priority,
|
670 |
+
$this->render_options( $option['options'], $values )
|
671 |
+
);
|
672 |
}
|
673 |
}
|
674 |
|
framework/core/components/theme.php
CHANGED
@@ -1,11 +1,10 @@
|
|
1 |
-
<?php
|
2 |
|
3 |
/**
|
4 |
* Theme Component
|
5 |
* Works with framework customizations / theme directory
|
6 |
*/
|
7 |
-
final class _FW_Component_Theme
|
8 |
-
{
|
9 |
private static $cache_key = 'fw_theme';
|
10 |
|
11 |
/**
|
@@ -26,29 +25,28 @@ final class _FW_Component_Theme
|
|
26 |
/**
|
27 |
* @internal
|
28 |
*/
|
29 |
-
public function _init()
|
30 |
-
|
31 |
-
add_action('admin_notices', array($this, '_action_admin_notices'));
|
32 |
}
|
33 |
|
34 |
/**
|
35 |
* @internal
|
36 |
*/
|
37 |
-
public function _after_components_init()
|
38 |
-
{
|
39 |
}
|
40 |
|
41 |
/**
|
42 |
* Search relative path in: child theme -> parent "theme" directory and return full path
|
|
|
43 |
* @param string $rel_path
|
|
|
44 |
* @return false|string
|
45 |
*/
|
46 |
-
public function locate_path($rel_path)
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
return fw_get_template_customizations_directory('/theme'. $rel_path);
|
52 |
} else {
|
53 |
return false;
|
54 |
}
|
@@ -56,86 +54,83 @@ final class _FW_Component_Theme
|
|
56 |
|
57 |
/**
|
58 |
* Return array with options from specified name/path
|
|
|
59 |
* @param string $name '{theme}/framework-customizations/theme/options/{$name}.php'
|
60 |
* @param array $variables These will be available in options file (like variables for view)
|
|
|
61 |
* @return array
|
62 |
*/
|
63 |
-
public function get_options($name, array $variables = array())
|
64 |
-
|
65 |
-
$path = $this->locate_path('/options/'. $name .'.php');
|
66 |
|
67 |
-
if (
|
68 |
return array();
|
69 |
}
|
70 |
|
71 |
-
$variables = fw_get_variables_from_file($path, array('options' => array()), $variables);
|
72 |
|
73 |
return $variables['options'];
|
74 |
}
|
75 |
|
76 |
-
public function get_settings_options()
|
77 |
-
|
78 |
-
$cache_key = self::$cache_key .'/options/settings';
|
79 |
|
80 |
try {
|
81 |
-
return FW_Cache::get($cache_key);
|
82 |
-
} catch (FW_Cache_Not_Found_Exception $e) {
|
83 |
-
$options = apply_filters('fw_settings_options', $this->get_options('settings'));
|
84 |
|
85 |
-
FW_Cache::set($cache_key, $options);
|
86 |
|
87 |
return $options;
|
88 |
}
|
89 |
}
|
90 |
|
91 |
-
public function get_customizer_options()
|
92 |
-
|
93 |
-
$cache_key = self::$cache_key .'/options/customizer';
|
94 |
|
95 |
try {
|
96 |
-
return FW_Cache::get($cache_key);
|
97 |
-
} catch (FW_Cache_Not_Found_Exception $e) {
|
98 |
-
$options = apply_filters('fw_customizer_options', $this->get_options('customizer'));
|
99 |
|
100 |
-
FW_Cache::set($cache_key, $options);
|
101 |
|
102 |
return $options;
|
103 |
}
|
104 |
}
|
105 |
|
106 |
-
public function get_post_options($post_type)
|
107 |
-
|
108 |
-
$cache_key = self::$cache_key .'/options/posts/'. $post_type;
|
109 |
|
110 |
try {
|
111 |
-
return FW_Cache::get($cache_key);
|
112 |
-
} catch (FW_Cache_Not_Found_Exception $e) {
|
113 |
$options = apply_filters(
|
114 |
'fw_post_options',
|
115 |
apply_filters( "fw_post_options:$post_type", $this->get_options( 'posts/' . $post_type ) ),
|
116 |
$post_type
|
117 |
);
|
118 |
|
119 |
-
FW_Cache::set($cache_key, $options);
|
120 |
|
121 |
return $options;
|
122 |
}
|
123 |
}
|
124 |
|
125 |
-
public function get_taxonomy_options($taxonomy)
|
126 |
-
|
127 |
-
$cache_key = self::$cache_key .'/options/taxonomies/'. $taxonomy;
|
128 |
|
129 |
try {
|
130 |
-
return FW_Cache::get($cache_key);
|
131 |
-
} catch (FW_Cache_Not_Found_Exception $e) {
|
132 |
$options = apply_filters(
|
133 |
'fw_taxonomy_options',
|
134 |
apply_filters( "fw_taxonomy_options:$taxonomy", $this->get_options( 'taxonomies/' . $taxonomy ) ),
|
135 |
$taxonomy
|
136 |
);
|
137 |
|
138 |
-
FW_Cache::set($cache_key, $options);
|
139 |
|
140 |
return $options;
|
141 |
}
|
@@ -144,62 +139,65 @@ final class _FW_Component_Theme
|
|
144 |
/**
|
145 |
* Return config key value, or entire config array
|
146 |
* Config array is merged from child configs
|
|
|
147 |
* @param string|null $key Multi key format accepted: 'a/b/c'
|
148 |
* @param mixed $default_value
|
|
|
149 |
* @return mixed|null
|
150 |
*/
|
151 |
-
final public function get_config($key = null, $default_value = null)
|
152 |
-
|
153 |
-
$cache_key = self::$cache_key .'/config';
|
154 |
|
155 |
try {
|
156 |
-
$config = FW_Cache::get($cache_key);
|
157 |
-
} catch (FW_Cache_Not_Found_Exception $e) {
|
158 |
// default values
|
159 |
$config = array(
|
160 |
/** Toggle Theme Settings form ajax submit */
|
161 |
'settings_form_ajax_submit' => true,
|
162 |
/** Toggle Theme Settings side tabs */
|
163 |
-
'settings_form_side_tabs'
|
164 |
/** Toggle Tabs rendered all at once, or initialized only on open/display */
|
165 |
-
'lazy_tabs'
|
166 |
);
|
167 |
|
168 |
-
if (file_exists(fw_get_template_customizations_directory('/theme/config.php'))) {
|
169 |
-
$variables = fw_get_variables_from_file(fw_get_template_customizations_directory('/theme/config.php'), array('cfg' => null));
|
170 |
|
171 |
-
if (!empty($variables['cfg'])) {
|
172 |
-
$config = array_merge($config, $variables['cfg']);
|
173 |
-
unset($variables);
|
174 |
}
|
175 |
}
|
176 |
|
177 |
-
if (is_child_theme() && file_exists(fw_get_stylesheet_customizations_directory('/theme/config.php'))) {
|
178 |
-
$variables = fw_get_variables_from_file(fw_get_stylesheet_customizations_directory('/theme/config.php'), array('cfg' => null));
|
179 |
|
180 |
-
if (!empty($variables['cfg'])) {
|
181 |
-
$config = array_merge($config, $variables['cfg']);
|
182 |
-
unset($variables);
|
183 |
}
|
184 |
}
|
185 |
|
186 |
-
unset($path);
|
187 |
|
188 |
-
FW_Cache::set($cache_key, $config);
|
189 |
}
|
190 |
|
191 |
-
return $key === null ? $config : fw_akg($key, $config, $default_value);
|
192 |
}
|
193 |
|
194 |
/**
|
195 |
* @internal
|
196 |
*/
|
197 |
-
public function _action_admin_notices()
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
|
|
|
|
203 |
}
|
204 |
}
|
205 |
}
|
1 |
+
<?php defined( 'FW' ) or die();
|
2 |
|
3 |
/**
|
4 |
* Theme Component
|
5 |
* Works with framework customizations / theme directory
|
6 |
*/
|
7 |
+
final class _FW_Component_Theme {
|
|
|
8 |
private static $cache_key = 'fw_theme';
|
9 |
|
10 |
/**
|
25 |
/**
|
26 |
* @internal
|
27 |
*/
|
28 |
+
public function _init() {
|
29 |
+
add_action( 'admin_notices', array( $this, '_action_admin_notices' ) );
|
|
|
30 |
}
|
31 |
|
32 |
/**
|
33 |
* @internal
|
34 |
*/
|
35 |
+
public function _after_components_init() {
|
|
|
36 |
}
|
37 |
|
38 |
/**
|
39 |
* Search relative path in: child theme -> parent "theme" directory and return full path
|
40 |
+
*
|
41 |
* @param string $rel_path
|
42 |
+
*
|
43 |
* @return false|string
|
44 |
*/
|
45 |
+
public function locate_path( $rel_path ) {
|
46 |
+
if ( is_child_theme() && file_exists( fw_get_stylesheet_customizations_directory( '/theme' . $rel_path ) ) ) {
|
47 |
+
return fw_get_stylesheet_customizations_directory( '/theme' . $rel_path );
|
48 |
+
} elseif ( file_exists( fw_get_template_customizations_directory( '/theme' . $rel_path ) ) ) {
|
49 |
+
return fw_get_template_customizations_directory( '/theme' . $rel_path );
|
|
|
50 |
} else {
|
51 |
return false;
|
52 |
}
|
54 |
|
55 |
/**
|
56 |
* Return array with options from specified name/path
|
57 |
+
*
|
58 |
* @param string $name '{theme}/framework-customizations/theme/options/{$name}.php'
|
59 |
* @param array $variables These will be available in options file (like variables for view)
|
60 |
+
*
|
61 |
* @return array
|
62 |
*/
|
63 |
+
public function get_options( $name, array $variables = array() ) {
|
64 |
+
$path = $this->locate_path( '/options/' . $name . '.php' );
|
|
|
65 |
|
66 |
+
if ( ! $path ) {
|
67 |
return array();
|
68 |
}
|
69 |
|
70 |
+
$variables = fw_get_variables_from_file( $path, array( 'options' => array() ), $variables );
|
71 |
|
72 |
return $variables['options'];
|
73 |
}
|
74 |
|
75 |
+
public function get_settings_options() {
|
76 |
+
$cache_key = self::$cache_key . '/options/settings';
|
|
|
77 |
|
78 |
try {
|
79 |
+
return FW_Cache::get( $cache_key );
|
80 |
+
} catch ( FW_Cache_Not_Found_Exception $e ) {
|
81 |
+
$options = apply_filters( 'fw_settings_options', $this->get_options( 'settings' ) );
|
82 |
|
83 |
+
FW_Cache::set( $cache_key, $options );
|
84 |
|
85 |
return $options;
|
86 |
}
|
87 |
}
|
88 |
|
89 |
+
public function get_customizer_options() {
|
90 |
+
$cache_key = self::$cache_key . '/options/customizer';
|
|
|
91 |
|
92 |
try {
|
93 |
+
return FW_Cache::get( $cache_key );
|
94 |
+
} catch ( FW_Cache_Not_Found_Exception $e ) {
|
95 |
+
$options = apply_filters( 'fw_customizer_options', $this->get_options( 'customizer' ) );
|
96 |
|
97 |
+
FW_Cache::set( $cache_key, $options );
|
98 |
|
99 |
return $options;
|
100 |
}
|
101 |
}
|
102 |
|
103 |
+
public function get_post_options( $post_type ) {
|
104 |
+
$cache_key = self::$cache_key . '/options/posts/' . $post_type;
|
|
|
105 |
|
106 |
try {
|
107 |
+
return FW_Cache::get( $cache_key );
|
108 |
+
} catch ( FW_Cache_Not_Found_Exception $e ) {
|
109 |
$options = apply_filters(
|
110 |
'fw_post_options',
|
111 |
apply_filters( "fw_post_options:$post_type", $this->get_options( 'posts/' . $post_type ) ),
|
112 |
$post_type
|
113 |
);
|
114 |
|
115 |
+
FW_Cache::set( $cache_key, $options );
|
116 |
|
117 |
return $options;
|
118 |
}
|
119 |
}
|
120 |
|
121 |
+
public function get_taxonomy_options( $taxonomy ) {
|
122 |
+
$cache_key = self::$cache_key . '/options/taxonomies/' . $taxonomy;
|
|
|
123 |
|
124 |
try {
|
125 |
+
return FW_Cache::get( $cache_key );
|
126 |
+
} catch ( FW_Cache_Not_Found_Exception $e ) {
|
127 |
$options = apply_filters(
|
128 |
'fw_taxonomy_options',
|
129 |
apply_filters( "fw_taxonomy_options:$taxonomy", $this->get_options( 'taxonomies/' . $taxonomy ) ),
|
130 |
$taxonomy
|
131 |
);
|
132 |
|
133 |
+
FW_Cache::set( $cache_key, $options );
|
134 |
|
135 |
return $options;
|
136 |
}
|
139 |
/**
|
140 |
* Return config key value, or entire config array
|
141 |
* Config array is merged from child configs
|
142 |
+
*
|
143 |
* @param string|null $key Multi key format accepted: 'a/b/c'
|
144 |
* @param mixed $default_value
|
145 |
+
*
|
146 |
* @return mixed|null
|
147 |
*/
|
148 |
+
final public function get_config( $key = null, $default_value = null ) {
|
149 |
+
$cache_key = self::$cache_key . '/config';
|
|
|
150 |
|
151 |
try {
|
152 |
+
$config = FW_Cache::get( $cache_key );
|
153 |
+
} catch ( FW_Cache_Not_Found_Exception $e ) {
|
154 |
// default values
|
155 |
$config = array(
|
156 |
/** Toggle Theme Settings form ajax submit */
|
157 |
'settings_form_ajax_submit' => true,
|
158 |
/** Toggle Theme Settings side tabs */
|
159 |
+
'settings_form_side_tabs' => false,
|
160 |
/** Toggle Tabs rendered all at once, or initialized only on open/display */
|
161 |
+
'lazy_tabs' => true,
|
162 |
);
|
163 |
|
164 |
+
if ( file_exists( fw_get_template_customizations_directory( '/theme/config.php' ) ) ) {
|
165 |
+
$variables = fw_get_variables_from_file( fw_get_template_customizations_directory( '/theme/config.php' ), array( 'cfg' => null ) );
|
166 |
|
167 |
+
if ( ! empty( $variables['cfg'] ) ) {
|
168 |
+
$config = array_merge( $config, $variables['cfg'] );
|
169 |
+
unset( $variables );
|
170 |
}
|
171 |
}
|
172 |
|
173 |
+
if ( is_child_theme() && file_exists( fw_get_stylesheet_customizations_directory( '/theme/config.php' ) ) ) {
|
174 |
+
$variables = fw_get_variables_from_file( fw_get_stylesheet_customizations_directory( '/theme/config.php' ), array( 'cfg' => null ) );
|
175 |
|
176 |
+
if ( ! empty( $variables['cfg'] ) ) {
|
177 |
+
$config = array_merge( $config, $variables['cfg'] );
|
178 |
+
unset( $variables );
|
179 |
}
|
180 |
}
|
181 |
|
182 |
+
unset( $path );
|
183 |
|
184 |
+
FW_Cache::set( $cache_key, $config );
|
185 |
}
|
186 |
|
187 |
+
return $key === null ? $config : fw_akg( $key, $config, $default_value );
|
188 |
}
|
189 |
|
190 |
/**
|
191 |
* @internal
|
192 |
*/
|
193 |
+
public function _action_admin_notices() {
|
194 |
+
if ( is_admin() && ! fw()->theme->manifest->check_requirements() && current_user_can( 'manage_options' ) ) {
|
195 |
+
echo
|
196 |
+
'<div class="notice notice-warning">
|
197 |
+
<p>' .
|
198 |
+
__( 'Theme requirements not met:', 'fw' ) . ' ' . fw()->theme->manifest->get_not_met_requirement_text() .
|
199 |
+
'</p>
|
200 |
+
</div>';
|
201 |
}
|
202 |
}
|
203 |
}
|
framework/extensions/update/class-fw-extension-update.php
CHANGED
@@ -1,135 +1,121 @@
|
|
1 |
-
<?php
|
2 |
|
3 |
-
require dirname(__FILE__) .'/includes/extends/class-fw-ext-update-service.php';
|
4 |
|
5 |
-
class FW_Extension_Update extends FW_Extension
|
6 |
-
{
|
7 |
/**
|
8 |
* {@inheritdoc}
|
9 |
*/
|
10 |
-
public function _child_extension_is_valid($child_extension_instance)
|
11 |
-
|
12 |
-
return is_subclass_of($child_extension_instance, 'FW_Ext_Update_Service');
|
13 |
}
|
14 |
|
15 |
/**
|
16 |
* File names to skip (do not delete or change) during the update process
|
17 |
* @var array
|
18 |
*/
|
19 |
-
private $skip_file_names = array('.git');
|
20 |
|
21 |
/**
|
22 |
* @internal
|
23 |
*/
|
24 |
-
protected function _init()
|
25 |
-
{
|
26 |
-
{
|
27 |
-
$has_access = (current_user_can('update_themes') || current_user_can('update_plugins'));
|
28 |
-
|
29 |
-
if ($has_access) {
|
30 |
-
if (is_multisite() && !is_network_admin()) {
|
31 |
-
// only network admin can change files that affects the entire network
|
32 |
-
$has_access = false;
|
33 |
-
}
|
34 |
-
}
|
35 |
|
36 |
-
|
37 |
-
|
38 |
-
}
|
39 |
}
|
40 |
|
41 |
$this->add_actions();
|
42 |
$this->add_filters();
|
|
|
|
|
43 |
}
|
44 |
|
45 |
-
private function add_actions()
|
46 |
-
{
|
47 |
-
add_action('core_upgrade_preamble', array($this, '_action_updates_page_footer'));
|
48 |
|
49 |
-
add_action(
|
50 |
-
add_action(
|
51 |
-
add_action('update-core-custom_'. 'fw-update-extensions', array($this, '_action_update_extensions'));
|
52 |
|
53 |
-
add_action('
|
|
|
|
|
|
|
54 |
}
|
55 |
|
56 |
-
private function add_filters()
|
57 |
-
|
58 |
-
add_filter('wp_get_update_data', array($this, '_filter_update_data'), 10, 2);
|
59 |
}
|
60 |
|
61 |
-
private function get_fixed_version($version)
|
62 |
-
{
|
63 |
// remove from the beginning everything that is not a number: 'v1.2.3' -> '1.2.3', 'ver1.0.0' -> '1.0.0'
|
64 |
-
return preg_replace('/^[^0-9]+/i', '', $version);;
|
65 |
}
|
66 |
|
67 |
-
private function get_wp_fs_tmp_dir()
|
68 |
-
{
|
69 |
return FW_WP_Filesystem::real_path_to_filesystem_path(
|
70 |
-
apply_filters('fw_tmp_dir', fw_fix_path(WP_CONTENT_DIR) .'/tmp')
|
71 |
);
|
72 |
}
|
73 |
|
74 |
/**
|
75 |
* @internal
|
76 |
*/
|
77 |
-
public function _action_updates_page_footer()
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
));
|
82 |
}
|
83 |
|
84 |
/**
|
85 |
* @internal
|
86 |
*/
|
87 |
-
public function _filter_update_data($data, $titles)
|
88 |
-
|
89 |
-
$updates = $this->get_updates(!empty($_GET['force-check']));
|
90 |
|
91 |
-
if ($updates['framework'] && !is_wp_error($updates['framework'])) {
|
92 |
-
|
93 |
}
|
94 |
|
95 |
-
if ($updates['theme'] && !is_wp_error($updates['theme'])) {
|
96 |
-
|
97 |
}
|
98 |
|
99 |
-
if (!empty($updates['extensions'])) {
|
100 |
foreach ( $updates['extensions'] as $ext_name => $ext_update ) {
|
101 |
if ( is_wp_error( $ext_update ) ) {
|
102 |
continue;
|
103 |
}
|
104 |
|
105 |
-
|
106 |
|
107 |
-
if ($this->get_config('extensions_as_one_update')) {
|
108 |
// no matter how many extensions, display as one update
|
109 |
break;
|
110 |
}
|
111 |
}
|
|
|
|
|
|
|
|
|
112 |
}
|
113 |
|
114 |
return $data;
|
115 |
}
|
116 |
|
117 |
-
private function get_updates($force_check = false)
|
118 |
-
{
|
119 |
$cache_key = 'fw_ext_update/updates';
|
120 |
|
121 |
// use cache because this method may be called multiple times (to prevent useless requests to update servers)
|
122 |
-
|
123 |
try {
|
124 |
-
return FW_Cache::get($cache_key);
|
125 |
-
} catch (FW_Cache_Not_Found_Exception $e) {
|
126 |
$updates = array(
|
127 |
-
'framework' => $this->get_framework_update($force_check),
|
128 |
-
'theme' => $this->get_theme_update($force_check),
|
129 |
-
'extensions' => $this->get_extensions_with_updates($force_check)
|
130 |
);
|
131 |
|
132 |
-
FW_Cache::set($cache_key, $updates);
|
133 |
|
134 |
return $updates;
|
135 |
}
|
@@ -137,56 +123,57 @@ class FW_Extension_Update extends FW_Extension
|
|
137 |
|
138 |
/**
|
139 |
* Collect extensions that has new versions available
|
|
|
140 |
* @param bool $force_check
|
|
|
141 |
* @return array {ext_name => update_data}
|
142 |
*/
|
143 |
-
private function get_extensions_with_updates($force_check = false)
|
144 |
-
|
145 |
-
$
|
146 |
-
$
|
147 |
-
$theme_ext_requirements = fw()->theme->manifest->get('requirements/extensions');
|
148 |
|
149 |
-
foreach (fw()->extensions->get_all() as $ext_name => $extension) {
|
150 |
/** @var FW_Extension $extension */
|
151 |
|
152 |
/**
|
153 |
* Ask each service if it knows how to update the extension
|
154 |
*/
|
155 |
-
foreach ($services as $service_name => $service) {
|
156 |
/** @var $service FW_Ext_Update_Service */
|
157 |
|
158 |
-
$latest_version = $service->_get_extension_latest_version($extension, $force_check);
|
159 |
|
160 |
-
if ($latest_version === false) {
|
161 |
// It said that it doesn't know how to update it
|
162 |
continue;
|
163 |
}
|
164 |
|
165 |
-
if (is_wp_error($latest_version)) {
|
166 |
-
$updates[$ext_name] = $latest_version;
|
167 |
break;
|
168 |
}
|
169 |
|
170 |
-
$fixed_latest_version = $this->get_fixed_version($latest_version);
|
171 |
|
172 |
-
if (!version_compare($fixed_latest_version, $extension->manifest->get_version(), '>')) {
|
173 |
// we already have latest version
|
174 |
continue;
|
175 |
}
|
176 |
|
177 |
if (
|
178 |
-
isset($theme_ext_requirements[$ext_name])
|
179 |
&&
|
180 |
-
isset($theme_ext_requirements[$ext_name]['max_version'])
|
181 |
&&
|
182 |
-
version_compare($fixed_latest_version, $theme_ext_requirements[$ext_name]['max_version'], '>')
|
183 |
) {
|
184 |
continue; // do not allow update if it exceeds max_version
|
185 |
}
|
186 |
|
187 |
-
$updates[$ext_name] = array(
|
188 |
-
'service'
|
189 |
-
'latest_version'
|
190 |
'fixed_latest_version' => $fixed_latest_version
|
191 |
);
|
192 |
|
@@ -199,37 +186,37 @@ class FW_Extension_Update extends FW_Extension
|
|
199 |
|
200 |
/**
|
201 |
* @param bool $force_check
|
|
|
202 |
* @return array|false|WP_Error
|
203 |
*/
|
204 |
-
private function get_framework_update($force_check = false)
|
205 |
-
{
|
206 |
/**
|
207 |
* Ask each service if it knows how to update the framework
|
208 |
*/
|
209 |
-
foreach ($this->get_children() as $service_name => $service) {
|
210 |
/** @var $service FW_Ext_Update_Service */
|
211 |
|
212 |
-
$latest_version = $service->_get_framework_latest_version($force_check);
|
213 |
|
214 |
-
if ($latest_version === false) {
|
215 |
// It said that it doesn't know how to update it
|
216 |
continue;
|
217 |
}
|
218 |
|
219 |
-
if (is_wp_error($latest_version)) {
|
220 |
return $latest_version;
|
221 |
}
|
222 |
|
223 |
-
$fixed_latest_version = $this->get_fixed_version($latest_version);
|
224 |
|
225 |
-
if (!version_compare($fixed_latest_version, fw()->manifest->get_version(), '>')) {
|
226 |
// we already have latest version
|
227 |
continue;
|
228 |
}
|
229 |
|
230 |
return array(
|
231 |
-
'service'
|
232 |
-
'latest_version'
|
233 |
'fixed_latest_version' => $fixed_latest_version
|
234 |
);
|
235 |
}
|
@@ -239,37 +226,37 @@ class FW_Extension_Update extends FW_Extension
|
|
239 |
|
240 |
/**
|
241 |
* @param bool $force_check
|
|
|
242 |
* @return array|false|WP_Error
|
243 |
*/
|
244 |
-
private function get_theme_update($force_check = false)
|
245 |
-
{
|
246 |
/**
|
247 |
* Ask each service if it knows how to update the theme
|
248 |
*/
|
249 |
-
foreach ($this->get_children() as $service_name => $service) {
|
250 |
/** @var $service FW_Ext_Update_Service */
|
251 |
|
252 |
-
$latest_version = $service->_get_theme_latest_version($force_check);
|
253 |
|
254 |
-
if ($latest_version === false) {
|
255 |
// It said that it doesn't know how to update it
|
256 |
continue;
|
257 |
}
|
258 |
|
259 |
-
if (is_wp_error($latest_version)) {
|
260 |
return $latest_version;
|
261 |
}
|
262 |
|
263 |
-
$fixed_latest_version = $this->get_fixed_version($latest_version);
|
264 |
|
265 |
-
if (!version_compare($fixed_latest_version, fw()->theme->manifest->get_version(), '>')) {
|
266 |
// we already have latest version
|
267 |
continue;
|
268 |
}
|
269 |
|
270 |
return array(
|
271 |
-
'service'
|
272 |
-
'latest_version'
|
273 |
'fixed_latest_version' => $fixed_latest_version
|
274 |
);
|
275 |
}
|
@@ -279,29 +266,29 @@ class FW_Extension_Update extends FW_Extension
|
|
279 |
|
280 |
/**
|
281 |
* Turn on/off the maintenance mode
|
|
|
282 |
* @param bool $enable
|
283 |
*/
|
284 |
-
private function maintenance_mode($enable = false)
|
285 |
-
{
|
286 |
/** @var WP_Filesystem_Base $wp_filesystem */
|
287 |
global $wp_filesystem;
|
288 |
|
289 |
-
if (
|
290 |
return;
|
291 |
}
|
292 |
|
293 |
$file_path = $wp_filesystem->abspath() . '.maintenance';
|
294 |
|
295 |
-
if ($wp_filesystem->exists($file_path)) {
|
296 |
-
if (
|
297 |
-
trigger_error(__('Cannot delete: ', 'fw') . $file_path, E_USER_WARNING);
|
298 |
}
|
299 |
}
|
300 |
|
301 |
-
if ($enable) {
|
302 |
// Create maintenance file to signal that we are upgrading
|
303 |
-
if (
|
304 |
-
trigger_error(__('Cannot create: ', 'fw') . $file_path, E_USER_WARNING);
|
305 |
}
|
306 |
}
|
307 |
}
|
@@ -314,10 +301,10 @@ class FW_Extension_Update extends FW_Extension
|
|
314 |
* @param array $data
|
315 |
* @param bool $merge_extensions The extensions/ directory will not be replaced entirely,
|
316 |
* only extensions that comes with the update will be replaced
|
|
|
317 |
* @return null|WP_Error
|
318 |
*/
|
319 |
-
private function update($data, $merge_extensions = false)
|
320 |
-
{
|
321 |
$required_data_keys = array(
|
322 |
'wp_fs_destination_dir' => true,
|
323 |
'download_callback' => true,
|
@@ -326,8 +313,8 @@ class FW_Extension_Update extends FW_Extension
|
|
326 |
'title' => true,
|
327 |
);
|
328 |
|
329 |
-
if (count($required_data_keys) > count(array_intersect_key($required_data_keys, $data))) {
|
330 |
-
trigger_error('Some required keys are not present', E_USER_ERROR);
|
331 |
}
|
332 |
|
333 |
// move manually every key to variable, so IDE will understand better them
|
@@ -360,7 +347,7 @@ class FW_Extension_Update extends FW_Extension
|
|
360 |
*/
|
361 |
$title = $data['title'];
|
362 |
|
363 |
-
unset($data);
|
364 |
}
|
365 |
|
366 |
/**
|
@@ -376,61 +363,61 @@ class FW_Extension_Update extends FW_Extension
|
|
376 |
|
377 |
// create temporary directory
|
378 |
{
|
379 |
-
if ($wp_filesystem->exists($tmp_download_dir)) {
|
380 |
// just in case it already exists, clear everything, it may contain old files
|
381 |
-
if (
|
382 |
-
$error = __('Cannot remove old temporary directory: ', 'fw') . $tmp_download_dir;
|
383 |
break;
|
384 |
}
|
385 |
}
|
386 |
|
387 |
-
if (!FW_WP_Filesystem::mkdir_recursive($tmp_download_dir)) {
|
388 |
-
$error = __('Cannot create directory: ', 'fw') . $tmp_download_dir;
|
389 |
break;
|
390 |
}
|
391 |
}
|
392 |
|
393 |
-
$skin->feedback(sprintf(__('Downloading the %s...', 'fw'), $title));
|
394 |
{
|
395 |
-
$downloaded_dir = call_user_func_array($download_callback, $download_callback_args);
|
396 |
|
397 |
-
if (
|
398 |
-
$error = sprintf(__('Cannot download the %s.', 'fw'), $title);
|
399 |
break;
|
400 |
-
} elseif (is_wp_error($downloaded_dir)) {
|
401 |
$error = $downloaded_dir;
|
402 |
break;
|
403 |
}
|
404 |
}
|
405 |
|
406 |
-
$this->maintenance_mode(true);
|
407 |
|
408 |
-
$skin->feedback(sprintf(__('Installing the %s...', 'fw'), $title));
|
409 |
{
|
410 |
// remove all files from destination directory
|
411 |
{
|
412 |
-
$dir_files = $wp_filesystem->dirlist($wp_fs_destination_dir, true);
|
413 |
-
if ($dir_files === false) {
|
414 |
-
$error =__('Cannot access directory: ', 'fw') . $wp_fs_destination_dir;
|
415 |
break;
|
416 |
}
|
417 |
|
418 |
-
foreach ($dir_files as $file) {
|
419 |
-
if (in_array($file['name'], $this->skip_file_names)) {
|
420 |
continue;
|
421 |
}
|
422 |
|
423 |
-
if ($merge_extensions) {
|
424 |
-
if ($file['name'] === 'extensions' && $file['type'] === 'd') {
|
425 |
// do not remove extensions, will be merged later
|
426 |
continue;
|
427 |
}
|
428 |
}
|
429 |
|
430 |
-
$file_path = $wp_fs_destination_dir .'/'. $file['name'];
|
431 |
|
432 |
-
if (
|
433 |
-
$error = __('Cannot remove: ', 'fw') . $file_path;
|
434 |
break 2;
|
435 |
}
|
436 |
}
|
@@ -438,54 +425,54 @@ class FW_Extension_Update extends FW_Extension
|
|
438 |
|
439 |
// move all files from the temporary directory to the destination directory
|
440 |
{
|
441 |
-
$dir_files = $wp_filesystem->dirlist($downloaded_dir, true);
|
442 |
-
if ($dir_files === false) {
|
443 |
-
$error = __('Cannot access directory: ', 'fw') . $downloaded_dir;
|
444 |
break;
|
445 |
}
|
446 |
|
447 |
-
foreach ($dir_files as $file) {
|
448 |
-
if (in_array($file['name'], $this->skip_file_names)) {
|
449 |
continue;
|
450 |
}
|
451 |
|
452 |
-
$downloaded_file_path = $downloaded_dir .'/'. $file['name'];
|
453 |
-
$destination_file_path = $wp_fs_destination_dir .'/'. $file['name'];
|
454 |
|
455 |
-
if ($merge_extensions) {
|
456 |
-
if ($file['name'] === 'extensions' && $file['type'] === 'd') {
|
457 |
// merge extensions/ after all other files was moved
|
458 |
$merge_extensions_data = array(
|
459 |
-
'source'
|
460 |
'destination' => $destination_file_path,
|
461 |
);
|
462 |
continue;
|
463 |
}
|
464 |
}
|
465 |
|
466 |
-
if (
|
467 |
$error = sprintf(
|
468 |
-
__('Cannot move "%s" to "%s"', 'fw'),
|
469 |
$downloaded_file_path, $destination_file_path
|
470 |
);
|
471 |
break 2;
|
472 |
}
|
473 |
}
|
474 |
|
475 |
-
if ($merge_extensions) {
|
476 |
-
if (!empty($merge_extensions_data)) {
|
477 |
$merge_result = $this->merge_extensions(
|
478 |
$merge_extensions_data['source'],
|
479 |
$merge_extensions_data['destination']
|
480 |
);
|
481 |
|
482 |
-
if ($merge_result === false) {
|
483 |
$error = sprintf(
|
484 |
-
__('Cannot merge "%s" with "%s"', 'fw'),
|
485 |
$downloaded_file_path, $destination_file_path
|
486 |
);
|
487 |
break;
|
488 |
-
} elseif (is_wp_error($merge_result)) {
|
489 |
$error = $merge_result;
|
490 |
break;
|
491 |
}
|
@@ -494,20 +481,20 @@ class FW_Extension_Update extends FW_Extension
|
|
494 |
}
|
495 |
}
|
496 |
|
497 |
-
$skin->feedback(sprintf(__('The %s has been successfully updated.', 'fw'), $title));
|
498 |
-
} while(false);
|
499 |
|
500 |
-
$this->maintenance_mode(false);
|
501 |
|
502 |
-
if ($wp_filesystem->exists($tmp_download_dir)) {
|
503 |
if ( ! $wp_filesystem->delete( $tmp_download_dir, true, 'd' ) ) {
|
504 |
$error = sprintf( __( 'Cannot remove temporary directory "%s".', 'fw' ), $tmp_download_dir );
|
505 |
}
|
506 |
}
|
507 |
|
508 |
-
if ($error) {
|
509 |
-
if (!is_wp_error($error)) {
|
510 |
-
$error = new WP_Error( 'fw_ext_update_failed', (string)$error );
|
511 |
}
|
512 |
|
513 |
return $error;
|
@@ -516,56 +503,58 @@ class FW_Extension_Update extends FW_Extension
|
|
516 |
|
517 |
/**
|
518 |
* Merge two extensions/ directories
|
|
|
519 |
* @param string $source_dir WP_Filesystem dir '/a/b/c/extensions'
|
520 |
* @param string $destination_dir WP_Filesystem dir '/a/b/d/extensions'
|
|
|
521 |
* @return bool|WP_Error
|
522 |
*/
|
523 |
-
private function merge_extensions($source_dir, $destination_dir)
|
524 |
-
{
|
525 |
/** @var WP_Filesystem_Base $wp_filesystem */
|
526 |
global $wp_filesystem;
|
527 |
|
528 |
$wp_error_id = 'fw_ext_update_merge_extensions';
|
529 |
|
530 |
-
if (
|
531 |
// do a simple move if destination does not exist
|
532 |
-
if (
|
533 |
-
return new WP_Error($wp_error_id,
|
534 |
-
sprintf(__('Cannot move "%s" to "%s"', 'fw'), $source_dir, $destination_dir)
|
535 |
);
|
536 |
}
|
|
|
537 |
return true;
|
538 |
}
|
539 |
|
540 |
-
$source_ext_dirs = $wp_filesystem->dirlist($source_dir, true);
|
541 |
-
if ($source_ext_dirs === false) {
|
542 |
-
return new WP_Error($wp_error_id,
|
543 |
-
__('Cannot access directory: ', 'fw') . $source_dir
|
544 |
);
|
545 |
}
|
546 |
|
547 |
-
foreach ($source_ext_dirs as $ext_dir) {
|
548 |
-
if (in_array($ext_dir['name'], $this->skip_file_names)) {
|
549 |
continue;
|
550 |
}
|
551 |
|
552 |
-
if ($ext_dir['type'] !== 'd') {
|
553 |
// process only directories from the extensions/ directory
|
554 |
continue;
|
555 |
}
|
556 |
|
557 |
-
$source_extension_dir
|
558 |
-
$destination_extension_dir = $destination_dir .'/'. $ext_dir['name'];
|
559 |
|
560 |
{
|
561 |
-
$source_ext_files = $wp_filesystem->dirlist($source_extension_dir, true);
|
562 |
-
if ($source_ext_files === false) {
|
563 |
-
return new WP_Error($wp_error_id,
|
564 |
-
__('Cannot access directory: ', 'fw') . $source_extension_dir
|
565 |
);
|
566 |
}
|
567 |
|
568 |
-
if (empty($source_ext_files)) {
|
569 |
/**
|
570 |
* Source extension directory is empty, do nothing.
|
571 |
* This happens when the extension is a git submodule in repository
|
@@ -578,40 +567,40 @@ class FW_Extension_Update extends FW_Extension
|
|
578 |
// prepare destination
|
579 |
{
|
580 |
// create if not exists
|
581 |
-
if (
|
582 |
-
if (!FW_WP_Filesystem::mkdir_recursive($destination_extension_dir)) {
|
583 |
-
return new WP_Error($wp_error_id,
|
584 |
-
__('Cannot create directory: ', 'fw') . $destination_extension_dir
|
585 |
);
|
586 |
}
|
587 |
}
|
588 |
|
589 |
// remove everything except the extensions/ dir
|
590 |
{
|
591 |
-
$dest_ext_files = $wp_filesystem->dirlist($destination_extension_dir, true);
|
592 |
-
if ($dest_ext_files === false) {
|
593 |
-
return new WP_Error($wp_error_id,
|
594 |
-
__('Cannot access directory: ', 'fw') . $destination_extension_dir
|
595 |
);
|
596 |
}
|
597 |
|
598 |
$destination_has_extensions_dir = false;
|
599 |
|
600 |
-
foreach ($dest_ext_files as $dest_ext_file) {
|
601 |
-
if (in_array($dest_ext_file['name'], $this->skip_file_names)) {
|
602 |
continue;
|
603 |
}
|
604 |
|
605 |
-
if ($dest_ext_file['name'] === 'extensions' && $dest_ext_file['type'] === 'd') {
|
606 |
$destination_has_extensions_dir = true;
|
607 |
continue;
|
608 |
}
|
609 |
|
610 |
-
$dest_ext_file_path = $destination_extension_dir .'/'. $dest_ext_file['name'];
|
611 |
|
612 |
-
if (
|
613 |
-
return new WP_Error($wp_error_id,
|
614 |
-
__('Cannot delete: ', 'fw') . $dest_ext_file_path
|
615 |
);
|
616 |
}
|
617 |
}
|
@@ -622,22 +611,22 @@ class FW_Extension_Update extends FW_Extension
|
|
622 |
{
|
623 |
$source_has_extensions_dir = false;
|
624 |
|
625 |
-
foreach ($source_ext_files as $source_ext_file) {
|
626 |
-
if (in_array($source_ext_file['name'], $this->skip_file_names)) {
|
627 |
continue;
|
628 |
}
|
629 |
|
630 |
-
if ($source_ext_file['name'] === 'extensions' && $source_ext_file['type'] === 'd') {
|
631 |
$source_has_extensions_dir = true;
|
632 |
continue;
|
633 |
}
|
634 |
|
635 |
-
$source_ext_file_path = $source_extension_dir .'/'. $source_ext_file['name'];
|
636 |
-
$dest_ext_file_path
|
637 |
|
638 |
-
if (
|
639 |
-
return new WP_Error($wp_error_id,
|
640 |
-
sprintf(__('Cannot move "%s" to "%s"', 'fw'),
|
641 |
$source_ext_file_path, $dest_ext_file_path
|
642 |
)
|
643 |
);
|
@@ -645,25 +634,25 @@ class FW_Extension_Update extends FW_Extension
|
|
645 |
}
|
646 |
}
|
647 |
|
648 |
-
if ($source_has_extensions_dir) {
|
649 |
-
if ($destination_has_extensions_dir) {
|
650 |
$merge_result = $this->merge_extensions(
|
651 |
-
$source_extension_dir .'/extensions',
|
652 |
-
$destination_extension_dir .'/extensions'
|
653 |
);
|
654 |
|
655 |
-
if ($merge_result !== true) {
|
656 |
return $merge_result;
|
657 |
}
|
658 |
} else {
|
659 |
-
if (
|
660 |
-
$source_extension_dir .'/extensions',
|
661 |
-
$destination_extension_dir .'/extensions'
|
662 |
-
)) {
|
663 |
-
return new WP_Error($wp_error_id,
|
664 |
-
sprintf(__('Cannot move "%s" to "%s"', 'fw'),
|
665 |
-
$source_extension_dir .'/extensions',
|
666 |
-
$destination_extension_dir .'/extensions'
|
667 |
)
|
668 |
);
|
669 |
}
|
@@ -677,184 +666,181 @@ class FW_Extension_Update extends FW_Extension
|
|
677 |
/**
|
678 |
* @internal
|
679 |
*/
|
680 |
-
public function _action_update_framework()
|
681 |
-
{
|
682 |
$nonce_name = '_nonce_fw_ext_update_framework';
|
683 |
-
if (!isset($_POST[$nonce_name]) || !wp_verify_nonce($_POST[$nonce_name])) {
|
684 |
-
wp_die(__('Invalid nonce.', 'fw'));
|
685 |
}
|
686 |
|
687 |
{
|
688 |
-
if (!class_exists('_FW_Ext_Update_Framework_Upgrader_Skin')) {
|
689 |
fw_include_file_isolated(
|
690 |
-
$this->get_declared_path('/includes/classes/class--fw-ext-update-framework-upgrader-skin.php')
|
691 |
);
|
692 |
}
|
693 |
|
694 |
-
$skin = new _FW_Ext_Update_Framework_Upgrader_Skin(array(
|
695 |
-
'title' => __('Framework Update', 'fw'),
|
696 |
-
));
|
697 |
}
|
698 |
|
699 |
-
require_once ABSPATH .'wp-admin/admin-header.php';
|
700 |
|
701 |
$skin->header();
|
702 |
|
703 |
do {
|
704 |
-
if (!FW_WP_Filesystem::request_access(fw_get_framework_directory(), fw_current_url(), array($nonce_name))) {
|
705 |
break;
|
706 |
}
|
707 |
|
708 |
$update = $this->get_framework_update();
|
709 |
|
710 |
-
if ($update === false) {
|
711 |
-
$skin->error(__('Failed to get framework latest version.', 'fw'));
|
712 |
break;
|
713 |
-
} elseif (is_wp_error($update)) {
|
714 |
-
$skin->error($update);
|
715 |
break;
|
716 |
}
|
717 |
|
718 |
/** @var FW_Ext_Update_Service $service */
|
719 |
-
$service = $this->get_child($update['service']);
|
720 |
|
721 |
-
$update_result = $this->update(array(
|
722 |
-
'wp_fs_destination_dir'
|
723 |
fw_get_framework_directory()
|
724 |
),
|
725 |
-
'download_callback'
|
726 |
-
'download_callback_args' => array($update['latest_version'], $this->get_wp_fs_tmp_dir()),
|
727 |
-
'skin'
|
728 |
-
'title'
|
729 |
-
));
|
730 |
-
|
731 |
-
if (is_wp_error($update_result)) {
|
732 |
-
$skin->error($update_result);
|
733 |
break;
|
734 |
}
|
735 |
|
736 |
-
$skin->set_result(true);
|
737 |
$skin->after();
|
738 |
-
} while(false);
|
739 |
|
740 |
$skin->footer();
|
741 |
|
742 |
-
require_once(ABSPATH . 'wp-admin/admin-footer.php');
|
743 |
}
|
744 |
|
745 |
/**
|
746 |
* @internal
|
747 |
*/
|
748 |
-
public function _action_update_theme()
|
749 |
-
{
|
750 |
$nonce_name = '_nonce_fw_ext_update_theme';
|
751 |
-
if (!isset($_POST[$nonce_name]) || !wp_verify_nonce($_POST[$nonce_name])) {
|
752 |
-
wp_die(__('Invalid nonce.', 'fw'));
|
753 |
}
|
754 |
|
755 |
{
|
756 |
-
if (!class_exists('_FW_Ext_Update_Theme_Upgrader_Skin')) {
|
757 |
fw_include_file_isolated(
|
758 |
-
$this->get_declared_path('/includes/classes/class--fw-ext-update-theme-upgrader-skin.php')
|
759 |
);
|
760 |
}
|
761 |
|
762 |
-
$skin = new _FW_Ext_Update_Theme_Upgrader_Skin(array(
|
763 |
-
'title' => __('Theme Update', 'fw'),
|
764 |
-
));
|
765 |
}
|
766 |
|
767 |
-
require_once(ABSPATH . 'wp-admin/admin-header.php');
|
768 |
|
769 |
$skin->header();
|
770 |
|
771 |
do {
|
772 |
-
if (!FW_WP_Filesystem::request_access(get_template_directory(), fw_current_url(), array($nonce_name))) {
|
773 |
break;
|
774 |
}
|
775 |
|
776 |
$update = $this->get_theme_update();
|
777 |
|
778 |
-
if ($update === false) {
|
779 |
-
$skin->error(__('Failed to get theme latest version.', 'fw'));
|
780 |
break;
|
781 |
-
} elseif (is_wp_error($update)) {
|
782 |
-
$skin->error($update);
|
783 |
break;
|
784 |
}
|
785 |
|
786 |
/** @var FW_Ext_Update_Service $service */
|
787 |
-
$service = $this->get_child($update['service']);
|
788 |
|
789 |
-
$update_result = $this->update(array(
|
790 |
-
'wp_fs_destination_dir'
|
791 |
get_template_directory()
|
792 |
),
|
793 |
-
'download_callback'
|
794 |
-
'download_callback_args' => array($update['latest_version'], $this->get_wp_fs_tmp_dir()),
|
795 |
-
'skin'
|
796 |
-
'title'
|
797 |
-
));
|
798 |
-
|
799 |
-
if (is_wp_error($update_result)) {
|
800 |
-
$skin->error($update_result);
|
801 |
break;
|
802 |
}
|
803 |
|
804 |
-
$skin->set_result(true);
|
805 |
$skin->after();
|
806 |
-
} while(false);
|
807 |
|
808 |
$skin->footer();
|
809 |
|
810 |
-
require_once(ABSPATH . 'wp-admin/admin-footer.php');
|
811 |
}
|
812 |
|
813 |
/**
|
814 |
* @internal
|
815 |
*/
|
816 |
-
public function _action_update_extensions()
|
817 |
-
{
|
818 |
$nonce_name = '_nonce_fw_ext_update_extensions';
|
819 |
-
if (!isset($_POST[$nonce_name]) || !wp_verify_nonce($_POST[$nonce_name])) {
|
820 |
-
wp_die(__('Invalid nonce.', 'fw'));
|
821 |
}
|
822 |
|
823 |
$form_input_name = 'extensions';
|
824 |
-
$extensions_list = FW_Request::POST($form_input_name);
|
825 |
|
826 |
-
if (empty($extensions_list)) {
|
827 |
FW_Flash_Messages::add(
|
828 |
'fw_ext_update',
|
829 |
-
__('Please check the extensions you want to update.', 'fw'),
|
830 |
'warning'
|
831 |
);
|
832 |
-
wp_redirect(self_admin_url('update-core.php'));
|
833 |
exit;
|
834 |
}
|
835 |
|
836 |
// handle changes by the hack below
|
837 |
{
|
838 |
-
if (is_string($extensions_list)) {
|
839 |
-
$extensions_list = json_decode($extensions_list);
|
840 |
} else {
|
841 |
-
$extensions_list = array_keys($extensions_list);
|
842 |
}
|
843 |
}
|
844 |
|
845 |
{
|
846 |
-
if (!class_exists('_FW_Ext_Update_Extensions_Upgrader_Skin')) {
|
847 |
fw_include_file_isolated(
|
848 |
-
$this->get_declared_path('/includes/classes/class--fw-ext-update-extensions-upgrader-skin.php')
|
849 |
);
|
850 |
}
|
851 |
|
852 |
-
$skin = new _FW_Ext_Update_Extensions_Upgrader_Skin(array(
|
853 |
-
'title' => __('Extensions Update', 'fw'),
|
854 |
-
));
|
855 |
}
|
856 |
|
857 |
-
require_once(ABSPATH . 'wp-admin/admin-header.php');
|
858 |
|
859 |
$skin->header();
|
860 |
|
@@ -863,106 +849,96 @@ class FW_Extension_Update extends FW_Extension
|
|
863 |
* Hack for the ftp credentials template that does not support array post values
|
864 |
* https://github.com/WordPress/WordPress/blob/3949a8b6cc50a021ed93798287b4ef9ea8a560d9/wp-admin/includes/file.php#L1144
|
865 |
*/
|
866 |
-
|
867 |
-
|
868 |
-
|
869 |
-
|
870 |
-
|
871 |
-
|
872 |
-
|
873 |
-
|
874 |
-
array($nonce_name, $form_input_name))
|
875 |
-
) {
|
876 |
-
{ // revert hack changes
|
877 |
-
$_POST[$form_input_name] = $original_post_value;
|
878 |
-
unset($original_post_value);
|
879 |
-
}
|
880 |
break;
|
881 |
}
|
882 |
|
883 |
-
|
884 |
-
|
885 |
-
|
886 |
-
}
|
887 |
|
888 |
$updates = $this->get_extensions_with_updates();
|
889 |
|
890 |
-
if (empty($updates)) {
|
891 |
-
$skin->error(__('No extensions updates found.', 'fw'));
|
892 |
break;
|
893 |
}
|
894 |
|
895 |
-
foreach ($extensions_list as $extension_name) {
|
896 |
-
if (!($extension = fw()->extensions->get($extension_name))) {
|
897 |
-
$skin->error(
|
898 |
-
sprintf(__('Extension "%s" does not exist or is disabled.', 'fw'), $extension_name)
|
899 |
-
);
|
900 |
continue;
|
901 |
}
|
902 |
|
903 |
-
if (!isset($updates[$extension_name])) {
|
904 |
-
$skin->error(
|
905 |
-
sprintf(__('No update found for the "%s" extension.', 'fw'), $extension->manifest->get_name())
|
906 |
-
);
|
907 |
continue;
|
908 |
}
|
909 |
|
910 |
-
$update = $updates[$extension_name];
|
911 |
|
912 |
-
if (is_wp_error($update)) {
|
913 |
-
$skin->error($update);
|
914 |
continue;
|
915 |
}
|
916 |
|
917 |
/** @var FW_Ext_Update_Service $service */
|
918 |
-
$service = $this->get_child($update['service']);
|
919 |
|
920 |
-
$update_result = $this->update(array(
|
921 |
-
'wp_fs_destination_dir'
|
922 |
$extension->get_declared_path()
|
923 |
),
|
924 |
-
'download_callback'
|
925 |
-
'download_callback_args' => array(
|
926 |
-
|
927 |
-
|
928 |
-
|
929 |
-
|
930 |
-
|
931 |
-
$
|
|
|
|
|
|
|
|
|
932 |
continue;
|
933 |
}
|
934 |
|
935 |
-
$skin->set_result(true);
|
936 |
|
937 |
-
if (
|
938 |
$skin->decrement_extension_update_count( $extension_name );
|
939 |
}
|
940 |
}
|
941 |
|
942 |
-
if ($this->get_config('extensions_as_one_update')) {
|
943 |
$skin->decrement_extension_update_count( $extension_name );
|
944 |
}
|
945 |
|
946 |
$skin->after();
|
947 |
-
} while(false);
|
948 |
|
949 |
$skin->footer();
|
950 |
|
951 |
-
require_once(ABSPATH . 'wp-admin/admin-footer.php');
|
952 |
}
|
953 |
|
954 |
public function _action_admin_notices() {
|
955 |
-
|
956 |
-
|
957 |
-
|
958 |
-
|
959 |
-
&&
|
960 |
-
!empty($updates['extensions'])
|
961 |
-
) { /* ok */ } else {
|
962 |
return;
|
963 |
}
|
964 |
|
965 |
-
foreach ($updates['extensions'] as $ext_name => $ext_update) {
|
966 |
if ( is_wp_error( $ext_update ) ) {
|
967 |
return;
|
968 |
}
|
@@ -970,13 +946,18 @@ class FW_Extension_Update extends FW_Extension
|
|
970 |
break;
|
971 |
}
|
972 |
|
973 |
-
echo
|
974 |
-
|
975 |
-
|
976 |
-
|
977 |
-
|
978 |
-
|
979 |
-
|
980 |
-
|
|
|
|
|
|
|
|
|
|
|
981 |
}
|
982 |
}
|
1 |
+
<?php defined( 'FW' ) or die( 'Forbidden' );
|
2 |
|
3 |
+
require dirname( __FILE__ ) . '/includes/extends/class-fw-ext-update-service.php';
|
4 |
|
5 |
+
class FW_Extension_Update extends FW_Extension {
|
|
|
6 |
/**
|
7 |
* {@inheritdoc}
|
8 |
*/
|
9 |
+
public function _child_extension_is_valid( $child_extension_instance ) {
|
10 |
+
return is_subclass_of( $child_extension_instance, 'FW_Ext_Update_Service' );
|
|
|
11 |
}
|
12 |
|
13 |
/**
|
14 |
* File names to skip (do not delete or change) during the update process
|
15 |
* @var array
|
16 |
*/
|
17 |
+
private $skip_file_names = array( '.git' );
|
18 |
|
19 |
/**
|
20 |
* @internal
|
21 |
*/
|
22 |
+
protected function _init() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
|
24 |
+
if ( ! current_user_can( 'update_plugins' ) ) {
|
25 |
+
return false;
|
|
|
26 |
}
|
27 |
|
28 |
$this->add_actions();
|
29 |
$this->add_filters();
|
30 |
+
|
31 |
+
return true;
|
32 |
}
|
33 |
|
34 |
+
private function add_actions() {
|
|
|
|
|
35 |
|
36 |
+
add_action( 'admin_notices', array( $this, '_action_admin_notices' ) );
|
37 |
+
add_action( 'network_admin_notices', array( $this, '_action_admin_notices' ) );
|
|
|
38 |
|
39 |
+
add_action( 'core_upgrade_preamble', array( $this, '_action_updates_page_footer' ) );
|
40 |
+
add_action( 'update-core-custom_' . 'fw-update-framework', array( $this, '_action_update_framework' ) );
|
41 |
+
add_action( 'update-core-custom_' . 'fw-update-theme', array( $this, '_action_update_theme' ) );
|
42 |
+
add_action( 'update-core-custom_' . 'fw-update-extensions', array( $this, '_action_update_extensions' ) );
|
43 |
}
|
44 |
|
45 |
+
private function add_filters() {
|
46 |
+
add_filter( 'wp_get_update_data', array( $this, '_filter_update_data' ), 10, 2 );
|
|
|
47 |
}
|
48 |
|
49 |
+
private function get_fixed_version( $version ) {
|
|
|
50 |
// remove from the beginning everything that is not a number: 'v1.2.3' -> '1.2.3', 'ver1.0.0' -> '1.0.0'
|
51 |
+
return preg_replace( '/^[^0-9]+/i', '', $version );;
|
52 |
}
|
53 |
|
54 |
+
private function get_wp_fs_tmp_dir() {
|
|
|
55 |
return FW_WP_Filesystem::real_path_to_filesystem_path(
|
56 |
+
apply_filters( 'fw_tmp_dir', fw_fix_path( WP_CONTENT_DIR ) . '/tmp' )
|
57 |
);
|
58 |
}
|
59 |
|
60 |
/**
|
61 |
* @internal
|
62 |
*/
|
63 |
+
public function _action_updates_page_footer() {
|
64 |
+
echo $this->render_view( 'updates-list', array(
|
65 |
+
'updates' => $this->get_updates( ! empty( $_GET['force-check'] ) )
|
66 |
+
) );
|
|
|
67 |
}
|
68 |
|
69 |
/**
|
70 |
* @internal
|
71 |
*/
|
72 |
+
public function _filter_update_data( $data, $titles ) {
|
73 |
+
$updates = $this->get_updates( ! empty( $_GET['force-check'] ) );
|
|
|
74 |
|
75 |
+
if ( $updates['framework'] && ! is_wp_error( $updates['framework'] ) ) {
|
76 |
+
++ $data['counts']['total'];
|
77 |
}
|
78 |
|
79 |
+
if ( $updates['theme'] && ! is_wp_error( $updates['theme'] ) ) {
|
80 |
+
++ $data['counts']['total'];
|
81 |
}
|
82 |
|
83 |
+
if ( ! empty( $updates['extensions'] ) ) {
|
84 |
foreach ( $updates['extensions'] as $ext_name => $ext_update ) {
|
85 |
if ( is_wp_error( $ext_update ) ) {
|
86 |
continue;
|
87 |
}
|
88 |
|
89 |
+
++ $data['counts']['total'];
|
90 |
|
91 |
+
if ( $this->get_config( 'extensions_as_one_update' ) ) {
|
92 |
// no matter how many extensions, display as one update
|
93 |
break;
|
94 |
}
|
95 |
}
|
96 |
+
|
97 |
+
$title = esc_html__( 'Available extensions updates.', 'fw' );
|
98 |
+
|
99 |
+
$data['title'] = empty( $data['title'] ) ? $title : $data['title'] . ', ' . $title;
|
100 |
}
|
101 |
|
102 |
return $data;
|
103 |
}
|
104 |
|
105 |
+
private function get_updates( $force_check = false ) {
|
|
|
106 |
$cache_key = 'fw_ext_update/updates';
|
107 |
|
108 |
// use cache because this method may be called multiple times (to prevent useless requests to update servers)
|
|
|
109 |
try {
|
110 |
+
return FW_Cache::get( $cache_key );
|
111 |
+
} catch ( FW_Cache_Not_Found_Exception $e ) {
|
112 |
$updates = array(
|
113 |
+
'framework' => $this->get_framework_update( $force_check ),
|
114 |
+
'theme' => $this->get_theme_update( $force_check ),
|
115 |
+
'extensions' => $this->get_extensions_with_updates( $force_check )
|
116 |
);
|
117 |
|
118 |
+
FW_Cache::set( $cache_key, $updates );
|
119 |
|
120 |
return $updates;
|
121 |
}
|
123 |
|
124 |
/**
|
125 |
* Collect extensions that has new versions available
|
126 |
+
*
|
127 |
* @param bool $force_check
|
128 |
+
*
|
129 |
* @return array {ext_name => update_data}
|
130 |
*/
|
131 |
+
private function get_extensions_with_updates( $force_check = false ) {
|
132 |
+
$updates = array();
|
133 |
+
$services = $this->get_children();
|
134 |
+
$theme_ext_requirements = fw()->theme->manifest->get( 'requirements/extensions' );
|
|
|
135 |
|
136 |
+
foreach ( fw()->extensions->get_all() as $ext_name => $extension ) {
|
137 |
/** @var FW_Extension $extension */
|
138 |
|
139 |
/**
|
140 |
* Ask each service if it knows how to update the extension
|
141 |
*/
|
142 |
+
foreach ( $services as $service_name => $service ) {
|
143 |
/** @var $service FW_Ext_Update_Service */
|
144 |
|
145 |
+
$latest_version = $service->_get_extension_latest_version( $extension, $force_check );
|
146 |
|
147 |
+
if ( $latest_version === false ) {
|
148 |
// It said that it doesn't know how to update it
|
149 |
continue;
|
150 |
}
|
151 |
|
152 |
+
if ( is_wp_error( $latest_version ) ) {
|
153 |
+
$updates[ $ext_name ] = $latest_version;
|
154 |
break;
|
155 |
}
|
156 |
|
157 |
+
$fixed_latest_version = $this->get_fixed_version( $latest_version );
|
158 |
|
159 |
+
if ( ! version_compare( $fixed_latest_version, $extension->manifest->get_version(), '>' ) ) {
|
160 |
// we already have latest version
|
161 |
continue;
|
162 |
}
|
163 |
|
164 |
if (
|
165 |
+
isset( $theme_ext_requirements[ $ext_name ] )
|
166 |
&&
|
167 |
+
isset( $theme_ext_requirements[ $ext_name ]['max_version'] )
|
168 |
&&
|
169 |
+
version_compare( $fixed_latest_version, $theme_ext_requirements[ $ext_name ]['max_version'], '>' )
|
170 |
) {
|
171 |
continue; // do not allow update if it exceeds max_version
|
172 |
}
|
173 |
|
174 |
+
$updates[ $ext_name ] = array(
|
175 |
+
'service' => $service_name,
|
176 |
+
'latest_version' => $latest_version,
|
177 |
'fixed_latest_version' => $fixed_latest_version
|
178 |
);
|
179 |
|
186 |
|
187 |
/**
|
188 |
* @param bool $force_check
|
189 |
+
*
|
190 |
* @return array|false|WP_Error
|
191 |
*/
|
192 |
+
private function get_framework_update( $force_check = false ) {
|
|
|
193 |
/**
|
194 |
* Ask each service if it knows how to update the framework
|
195 |
*/
|
196 |
+
foreach ( $this->get_children() as $service_name => $service ) {
|
197 |
/** @var $service FW_Ext_Update_Service */
|
198 |
|
199 |
+
$latest_version = $service->_get_framework_latest_version( $force_check );
|
200 |
|
201 |
+
if ( $latest_version === false ) {
|
202 |
// It said that it doesn't know how to update it
|
203 |
continue;
|
204 |
}
|
205 |
|
206 |
+
if ( is_wp_error( $latest_version ) ) {
|
207 |
return $latest_version;
|
208 |
}
|
209 |
|
210 |
+
$fixed_latest_version = $this->get_fixed_version( $latest_version );
|
211 |
|
212 |
+
if ( ! version_compare( $fixed_latest_version, fw()->manifest->get_version(), '>' ) ) {
|
213 |
// we already have latest version
|
214 |
continue;
|
215 |
}
|
216 |
|
217 |
return array(
|
218 |
+
'service' => $service_name,
|
219 |
+
'latest_version' => $latest_version,
|
220 |
'fixed_latest_version' => $fixed_latest_version
|
221 |
);
|
222 |
}
|
226 |
|
227 |
/**
|
228 |
* @param bool $force_check
|
229 |
+
*
|
230 |
* @return array|false|WP_Error
|
231 |
*/
|
232 |
+
private function get_theme_update( $force_check = false ) {
|
|
|
233 |
/**
|
234 |
* Ask each service if it knows how to update the theme
|
235 |
*/
|
236 |
+
foreach ( $this->get_children() as $service_name => $service ) {
|
237 |
/** @var $service FW_Ext_Update_Service */
|
238 |
|
239 |
+
$latest_version = $service->_get_theme_latest_version( $force_check );
|
240 |
|
241 |
+
if ( $latest_version === false ) {
|
242 |
// It said that it doesn't know how to update it
|
243 |
continue;
|
244 |
}
|
245 |
|
246 |
+
if ( is_wp_error( $latest_version ) ) {
|
247 |
return $latest_version;
|
248 |
}
|
249 |
|
250 |
+
$fixed_latest_version = $this->get_fixed_version( $latest_version );
|
251 |
|
252 |
+
if ( ! version_compare( $fixed_latest_version, fw()->theme->manifest->get_version(), '>' ) ) {
|
253 |
// we already have latest version
|
254 |
continue;
|
255 |
}
|
256 |
|
257 |
return array(
|
258 |
+
'service' => $service_name,
|
259 |
+
'latest_version' => $latest_version,
|
260 |
'fixed_latest_version' => $fixed_latest_version
|
261 |
);
|
262 |
}
|
266 |
|
267 |
/**
|
268 |
* Turn on/off the maintenance mode
|
269 |
+
*
|
270 |
* @param bool $enable
|
271 |
*/
|
272 |
+
private function maintenance_mode( $enable = false ) {
|
|
|
273 |
/** @var WP_Filesystem_Base $wp_filesystem */
|
274 |
global $wp_filesystem;
|
275 |
|
276 |
+
if ( ! $wp_filesystem || ( is_wp_error( $wp_filesystem->errors ) && $wp_filesystem->errors->get_error_code() ) ) {
|
277 |
return;
|
278 |
}
|
279 |
|
280 |
$file_path = $wp_filesystem->abspath() . '.maintenance';
|
281 |
|
282 |
+
if ( $wp_filesystem->exists( $file_path ) ) {
|
283 |
+
if ( ! $wp_filesystem->delete( $file_path ) ) {
|
284 |
+
trigger_error( __( 'Cannot delete: ', 'fw' ) . $file_path, E_USER_WARNING );
|
285 |
}
|
286 |
}
|
287 |
|
288 |
+
if ( $enable ) {
|
289 |
// Create maintenance file to signal that we are upgrading
|
290 |
+
if ( ! $wp_filesystem->put_contents( $file_path, '<?php $upgrading = ' . time() . '; ?>', FS_CHMOD_FILE ) ) {
|
291 |
+
trigger_error( __( 'Cannot create: ', 'fw' ) . $file_path, E_USER_WARNING );
|
292 |
}
|
293 |
}
|
294 |
}
|
301 |
* @param array $data
|
302 |
* @param bool $merge_extensions The extensions/ directory will not be replaced entirely,
|
303 |
* only extensions that comes with the update will be replaced
|
304 |
+
*
|
305 |
* @return null|WP_Error
|
306 |
*/
|
307 |
+
private function update( $data, $merge_extensions = false ) {
|
|
|
308 |
$required_data_keys = array(
|
309 |
'wp_fs_destination_dir' => true,
|
310 |
'download_callback' => true,
|
313 |
'title' => true,
|
314 |
);
|
315 |
|
316 |
+
if ( count( $required_data_keys ) > count( array_intersect_key( $required_data_keys, $data ) ) ) {
|
317 |
+
trigger_error( 'Some required keys are not present', E_USER_ERROR );
|
318 |
}
|
319 |
|
320 |
// move manually every key to variable, so IDE will understand better them
|
347 |
*/
|
348 |
$title = $data['title'];
|
349 |
|
350 |
+
unset( $data );
|
351 |
}
|
352 |
|
353 |
/**
|
363 |
|
364 |
// create temporary directory
|
365 |
{
|
366 |
+
if ( $wp_filesystem->exists( $tmp_download_dir ) ) {
|
367 |
// just in case it already exists, clear everything, it may contain old files
|
368 |
+
if ( ! $wp_filesystem->rmdir( $tmp_download_dir, true ) ) {
|
369 |
+
$error = __( 'Cannot remove old temporary directory: ', 'fw' ) . $tmp_download_dir;
|
370 |
break;
|
371 |
}
|
372 |
}
|
373 |
|
374 |
+
if ( ! FW_WP_Filesystem::mkdir_recursive( $tmp_download_dir ) ) {
|
375 |
+
$error = __( 'Cannot create directory: ', 'fw' ) . $tmp_download_dir;
|
376 |
break;
|
377 |
}
|
378 |
}
|
379 |
|
380 |
+
$skin->feedback( sprintf( __( 'Downloading the %s...', 'fw' ), $title ) );
|
381 |
{
|
382 |
+
$downloaded_dir = call_user_func_array( $download_callback, $download_callback_args );
|
383 |
|
384 |
+
if ( ! $downloaded_dir ) {
|
385 |
+
$error = sprintf( __( 'Cannot download the %s.', 'fw' ), $title );
|
386 |
break;
|
387 |
+
} elseif ( is_wp_error( $downloaded_dir ) ) {
|
388 |
$error = $downloaded_dir;
|
389 |
break;
|
390 |
}
|
391 |
}
|
392 |
|
393 |
+
$this->maintenance_mode( true );
|
394 |
|
395 |
+
$skin->feedback( sprintf( __( 'Installing the %s...', 'fw' ), $title ) );
|
396 |
{
|
397 |
// remove all files from destination directory
|
398 |
{
|
399 |
+
$dir_files = $wp_filesystem->dirlist( $wp_fs_destination_dir, true );
|
400 |
+
if ( $dir_files === false ) {
|
401 |
+
$error = __( 'Cannot access directory: ', 'fw' ) . $wp_fs_destination_dir;
|
402 |
break;
|
403 |
}
|
404 |
|
405 |
+
foreach ( $dir_files as $file ) {
|
406 |
+
if ( in_array( $file['name'], $this->skip_file_names ) ) {
|
407 |
continue;
|
408 |
}
|
409 |
|
410 |
+
if ( $merge_extensions ) {
|
411 |
+
if ( $file['name'] === 'extensions' && $file['type'] === 'd' ) {
|
412 |
// do not remove extensions, will be merged later
|
413 |
continue;
|
414 |
}
|
415 |
}
|
416 |
|
417 |
+
$file_path = $wp_fs_destination_dir . '/' . $file['name'];
|
418 |
|
419 |
+
if ( ! $wp_filesystem->delete( $file_path, true, $file['type'] ) ) {
|
420 |
+
$error = __( 'Cannot remove: ', 'fw' ) . $file_path;
|
421 |
break 2;
|
422 |
}
|
423 |
}
|
425 |
|
426 |
// move all files from the temporary directory to the destination directory
|
427 |
{
|
428 |
+
$dir_files = $wp_filesystem->dirlist( $downloaded_dir, true );
|
429 |
+
if ( $dir_files === false ) {
|
430 |
+
$error = __( 'Cannot access directory: ', 'fw' ) . $downloaded_dir;
|
431 |
break;
|
432 |
}
|
433 |
|
434 |
+
foreach ( $dir_files as $file ) {
|
435 |
+
if ( in_array( $file['name'], $this->skip_file_names ) ) {
|
436 |
continue;
|
437 |
}
|
438 |
|
439 |
+
$downloaded_file_path = $downloaded_dir . '/' . $file['name'];
|
440 |
+
$destination_file_path = $wp_fs_destination_dir . '/' . $file['name'];
|
441 |
|
442 |
+
if ( $merge_extensions ) {
|
443 |
+
if ( $file['name'] === 'extensions' && $file['type'] === 'd' ) {
|
444 |
// merge extensions/ after all other files was moved
|
445 |
$merge_extensions_data = array(
|
446 |
+
'source' => $downloaded_file_path,
|
447 |
'destination' => $destination_file_path,
|
448 |
);
|
449 |
continue;
|
450 |
}
|
451 |
}
|
452 |
|
453 |
+
if ( ! $wp_filesystem->move( $downloaded_file_path, $destination_file_path ) ) {
|
454 |
$error = sprintf(
|
455 |
+
__( 'Cannot move "%s" to "%s"', 'fw' ),
|
456 |
$downloaded_file_path, $destination_file_path
|
457 |
);
|
458 |
break 2;
|
459 |
}
|
460 |
}
|
461 |
|
462 |
+
if ( $merge_extensions ) {
|
463 |
+
if ( ! empty( $merge_extensions_data ) ) {
|
464 |
$merge_result = $this->merge_extensions(
|
465 |
$merge_extensions_data['source'],
|
466 |
$merge_extensions_data['destination']
|
467 |
);
|
468 |
|
469 |
+
if ( $merge_result === false ) {
|
470 |
$error = sprintf(
|
471 |
+
__( 'Cannot merge "%s" with "%s"', 'fw' ),
|
472 |
$downloaded_file_path, $destination_file_path
|
473 |
);
|
474 |
break;
|
475 |
+
} elseif ( is_wp_error( $merge_result ) ) {
|
476 |
$error = $merge_result;
|
477 |
break;
|
478 |
}
|
481 |
}
|
482 |
}
|
483 |
|
484 |
+
$skin->feedback( sprintf( __( 'The %s has been successfully updated.', 'fw' ), $title ) );
|
485 |
+
} while ( false );
|
486 |
|
487 |
+
$this->maintenance_mode( false );
|
488 |
|
489 |
+
if ( $wp_filesystem->exists( $tmp_download_dir ) ) {
|
490 |
if ( ! $wp_filesystem->delete( $tmp_download_dir, true, 'd' ) ) {
|
491 |
$error = sprintf( __( 'Cannot remove temporary directory "%s".', 'fw' ), $tmp_download_dir );
|
492 |
}
|
493 |
}
|
494 |
|
495 |
+
if ( $error ) {
|
496 |
+
if ( ! is_wp_error( $error ) ) {
|
497 |
+
$error = new WP_Error( 'fw_ext_update_failed', (string) $error );
|
498 |
}
|
499 |
|
500 |
return $error;
|
503 |
|
504 |
/**
|
505 |
* Merge two extensions/ directories
|
506 |
+
*
|
507 |
* @param string $source_dir WP_Filesystem dir '/a/b/c/extensions'
|
508 |
* @param string $destination_dir WP_Filesystem dir '/a/b/d/extensions'
|
509 |
+
*
|
510 |
* @return bool|WP_Error
|
511 |
*/
|
512 |
+
private function merge_extensions( $source_dir, $destination_dir ) {
|
|
|
513 |
/** @var WP_Filesystem_Base $wp_filesystem */
|
514 |
global $wp_filesystem;
|
515 |
|
516 |
$wp_error_id = 'fw_ext_update_merge_extensions';
|
517 |
|
518 |
+
if ( ! $wp_filesystem->exists( $destination_dir ) ) {
|
519 |
// do a simple move if destination does not exist
|
520 |
+
if ( ! $wp_filesystem->move( $source_dir, $destination_dir ) ) {
|
521 |
+
return new WP_Error( $wp_error_id,
|
522 |
+
sprintf( __( 'Cannot move "%s" to "%s"', 'fw' ), $source_dir, $destination_dir )
|
523 |
);
|
524 |
}
|
525 |
+
|
526 |
return true;
|
527 |
}
|
528 |
|
529 |
+
$source_ext_dirs = $wp_filesystem->dirlist( $source_dir, true );
|
530 |
+
if ( $source_ext_dirs === false ) {
|
531 |
+
return new WP_Error( $wp_error_id,
|
532 |
+
__( 'Cannot access directory: ', 'fw' ) . $source_dir
|
533 |
);
|
534 |
}
|
535 |
|
536 |
+
foreach ( $source_ext_dirs as $ext_dir ) {
|
537 |
+
if ( in_array( $ext_dir['name'], $this->skip_file_names ) ) {
|
538 |
continue;
|
539 |
}
|
540 |
|
541 |
+
if ( $ext_dir['type'] !== 'd' ) {
|
542 |
// process only directories from the extensions/ directory
|
543 |
continue;
|
544 |
}
|
545 |
|
546 |
+
$source_extension_dir = $source_dir . '/' . $ext_dir['name'];
|
547 |
+
$destination_extension_dir = $destination_dir . '/' . $ext_dir['name'];
|
548 |
|
549 |
{
|
550 |
+
$source_ext_files = $wp_filesystem->dirlist( $source_extension_dir, true );
|
551 |
+
if ( $source_ext_files === false ) {
|
552 |
+
return new WP_Error( $wp_error_id,
|
553 |
+
__( 'Cannot access directory: ', 'fw' ) . $source_extension_dir
|
554 |
);
|
555 |
}
|
556 |
|
557 |
+
if ( empty( $source_ext_files ) ) {
|
558 |
/**
|
559 |
* Source extension directory is empty, do nothing.
|
560 |
* This happens when the extension is a git submodule in repository
|
567 |
// prepare destination
|
568 |
{
|
569 |
// create if not exists
|
570 |
+
if ( ! $wp_filesystem->exists( $destination_extension_dir ) ) {
|
571 |
+
if ( ! FW_WP_Filesystem::mkdir_recursive( $destination_extension_dir ) ) {
|
572 |
+
return new WP_Error( $wp_error_id,
|
573 |
+
__( 'Cannot create directory: ', 'fw' ) . $destination_extension_dir
|
574 |
);
|
575 |
}
|
576 |
}
|
577 |
|
578 |
// remove everything except the extensions/ dir
|
579 |
{
|
580 |
+
$dest_ext_files = $wp_filesystem->dirlist( $destination_extension_dir, true );
|
581 |
+
if ( $dest_ext_files === false ) {
|
582 |
+
return new WP_Error( $wp_error_id,
|
583 |
+
__( 'Cannot access directory: ', 'fw' ) . $destination_extension_dir
|
584 |
);
|
585 |
}
|
586 |
|
587 |
$destination_has_extensions_dir = false;
|
588 |
|
589 |
+
foreach ( $dest_ext_files as $dest_ext_file ) {
|
590 |
+
if ( in_array( $dest_ext_file['name'], $this->skip_file_names ) ) {
|
591 |
continue;
|
592 |
}
|
593 |
|
594 |
+
if ( $dest_ext_file['name'] === 'extensions' && $dest_ext_file['type'] === 'd' ) {
|
595 |
$destination_has_extensions_dir = true;
|
596 |
continue;
|
597 |
}
|
598 |
|
599 |
+
$dest_ext_file_path = $destination_extension_dir . '/' . $dest_ext_file['name'];
|
600 |
|
601 |
+
if ( ! $wp_filesystem->delete( $dest_ext_file_path, true, $dest_ext_file['type'] ) ) {
|
602 |
+
return new WP_Error( $wp_error_id,
|
603 |
+
__( 'Cannot delete: ', 'fw' ) . $dest_ext_file_path
|
604 |
);
|
605 |
}
|
606 |
}
|
611 |
{
|
612 |
$source_has_extensions_dir = false;
|
613 |
|
614 |
+
foreach ( $source_ext_files as $source_ext_file ) {
|
615 |
+
if ( in_array( $source_ext_file['name'], $this->skip_file_names ) ) {
|
616 |
continue;
|
617 |
}
|
618 |
|
619 |
+
if ( $source_ext_file['name'] === 'extensions' && $source_ext_file['type'] === 'd' ) {
|
620 |
$source_has_extensions_dir = true;
|
621 |
continue;
|
622 |
}
|
623 |
|
624 |
+
$source_ext_file_path = $source_extension_dir . '/' . $source_ext_file['name'];
|
625 |
+
$dest_ext_file_path = $destination_extension_dir . '/' . $source_ext_file['name'];
|
626 |
|
627 |
+
if ( ! $wp_filesystem->move( $source_ext_file_path, $dest_ext_file_path ) ) {
|
628 |
+
return new WP_Error( $wp_error_id,
|
629 |
+
sprintf( __( 'Cannot move "%s" to "%s"', 'fw' ),
|
630 |
$source_ext_file_path, $dest_ext_file_path
|
631 |
)
|
632 |
);
|
634 |
}
|
635 |
}
|
636 |
|
637 |
+
if ( $source_has_extensions_dir ) {
|
638 |
+
if ( $destination_has_extensions_dir ) {
|
639 |
$merge_result = $this->merge_extensions(
|
640 |
+
$source_extension_dir . '/extensions',
|
641 |
+
$destination_extension_dir . '/extensions'
|
642 |
);
|
643 |
|
644 |
+
if ( $merge_result !== true ) {
|
645 |
return $merge_result;
|
646 |
}
|
647 |
} else {
|
648 |
+
if ( ! $wp_filesystem->move(
|
649 |
+
$source_extension_dir . '/extensions',
|
650 |
+
$destination_extension_dir . '/extensions'
|
651 |
+
) ) {
|
652 |
+
return new WP_Error( $wp_error_id,
|
653 |
+
sprintf( __( 'Cannot move "%s" to "%s"', 'fw' ),
|
654 |
+
$source_extension_dir . '/extensions',
|
655 |
+
$destination_extension_dir . '/extensions'
|
656 |
)
|
657 |
);
|
658 |
}
|
666 |
/**
|
667 |
* @internal
|
668 |
*/
|
669 |
+
public function _action_update_framework() {
|
|
|
670 |
$nonce_name = '_nonce_fw_ext_update_framework';
|
671 |
+
if ( ! isset( $_POST[ $nonce_name ] ) || ! wp_verify_nonce( $_POST[ $nonce_name ] ) ) {
|
672 |
+
wp_die( __( 'Invalid nonce.', 'fw' ) );
|
673 |
}
|
674 |
|
675 |
{
|
676 |
+
if ( ! class_exists( '_FW_Ext_Update_Framework_Upgrader_Skin' ) ) {
|
677 |
fw_include_file_isolated(
|
678 |
+
$this->get_declared_path( '/includes/classes/class--fw-ext-update-framework-upgrader-skin.php' )
|
679 |
);
|
680 |
}
|
681 |
|
682 |
+
$skin = new _FW_Ext_Update_Framework_Upgrader_Skin( array(
|
683 |
+
'title' => __( 'Framework Update', 'fw' ),
|
684 |
+
) );
|
685 |
}
|
686 |
|
687 |
+
require_once ABSPATH . 'wp-admin/admin-header.php';
|
688 |
|
689 |
$skin->header();
|
690 |
|
691 |
do {
|
692 |
+
if ( ! FW_WP_Filesystem::request_access( fw_get_framework_directory(), fw_current_url(), array( $nonce_name ) ) ) {
|
693 |
break;
|
694 |
}
|
695 |
|
696 |
$update = $this->get_framework_update();
|
697 |
|
698 |
+
if ( $update === false ) {
|
699 |
+
$skin->error( __( 'Failed to get framework latest version.', 'fw' ) );
|
700 |
break;
|
701 |
+
} elseif ( is_wp_error( $update ) ) {
|
702 |
+
$skin->error( $update );
|
703 |
break;
|
704 |
}
|
705 |
|
706 |
/** @var FW_Ext_Update_Service $service */
|
707 |
+
$service = $this->get_child( $update['service'] );
|
708 |
|
709 |
+
$update_result = $this->update( array(
|
710 |
+
'wp_fs_destination_dir' => FW_WP_Filesystem::real_path_to_filesystem_path(
|
711 |
fw_get_framework_directory()
|
712 |
),
|
713 |
+
'download_callback' => array( $service, '_download_framework' ),
|
714 |
+
'download_callback_args' => array( $update['latest_version'], $this->get_wp_fs_tmp_dir() ),
|
715 |
+
'skin' => $skin,
|
716 |
+
'title' => __( 'Framework', 'fw' ),
|
717 |
+
) );
|
718 |
+
|
719 |
+
if ( is_wp_error( $update_result ) ) {
|
720 |
+
$skin->error( $update_result );
|
721 |
break;
|
722 |
}
|
723 |
|
724 |
+
$skin->set_result( true );
|
725 |
$skin->after();
|
726 |
+
} while ( false );
|
727 |
|
728 |
$skin->footer();
|
729 |
|
730 |
+
require_once( ABSPATH . 'wp-admin/admin-footer.php' );
|
731 |
}
|
732 |
|
733 |
/**
|
734 |
* @internal
|
735 |
*/
|
736 |
+
public function _action_update_theme() {
|
|
|
737 |
$nonce_name = '_nonce_fw_ext_update_theme';
|
738 |
+
if ( ! isset( $_POST[ $nonce_name ] ) || ! wp_verify_nonce( $_POST[ $nonce_name ] ) ) {
|
739 |
+
wp_die( __( 'Invalid nonce.', 'fw' ) );
|
740 |
}
|
741 |
|
742 |
{
|
743 |
+
if ( ! class_exists( '_FW_Ext_Update_Theme_Upgrader_Skin' ) ) {
|
744 |
fw_include_file_isolated(
|
745 |
+
$this->get_declared_path( '/includes/classes/class--fw-ext-update-theme-upgrader-skin.php' )
|
746 |
);
|
747 |
}
|
748 |
|
749 |
+
$skin = new _FW_Ext_Update_Theme_Upgrader_Skin( array(
|
750 |
+
'title' => __( 'Theme Update', 'fw' ),
|
751 |
+
) );
|
752 |
}
|
753 |
|
754 |
+
require_once( ABSPATH . 'wp-admin/admin-header.php' );
|
755 |
|
756 |
$skin->header();
|
757 |
|
758 |
do {
|
759 |
+
if ( ! FW_WP_Filesystem::request_access( get_template_directory(), fw_current_url(), array( $nonce_name ) ) ) {
|
760 |
break;
|
761 |
}
|
762 |
|
763 |
$update = $this->get_theme_update();
|
764 |
|
765 |
+
if ( $update === false ) {
|
766 |
+
$skin->error( __( 'Failed to get theme latest version.', 'fw' ) );
|
767 |
break;
|
768 |
+
} elseif ( is_wp_error( $update ) ) {
|
769 |
+
$skin->error( $update );
|
770 |
break;
|
771 |
}
|
772 |
|
773 |
/** @var FW_Ext_Update_Service $service */
|
774 |
+
$service = $this->get_child( $update['service'] );
|
775 |
|
776 |
+
$update_result = $this->update( array(
|
777 |
+
'wp_fs_destination_dir' => FW_WP_Filesystem::real_path_to_filesystem_path(
|
778 |
get_template_directory()
|
779 |
),
|
780 |
+
'download_callback' => array( $service, '_download_theme' ),
|
781 |
+
'download_callback_args' => array( $update['latest_version'], $this->get_wp_fs_tmp_dir() ),
|
782 |
+
'skin' => $skin,
|
783 |
+
'title' => __( 'Theme', 'fw' ),
|
784 |
+
) );
|
785 |
+
|
786 |
+
if ( is_wp_error( $update_result ) ) {
|
787 |
+
$skin->error( $update_result );
|
788 |
break;
|
789 |
}
|
790 |
|
791 |
+
$skin->set_result( true );
|
792 |
$skin->after();
|
793 |
+
} while ( false );
|
794 |
|
795 |
$skin->footer();
|
796 |
|
797 |
+
require_once( ABSPATH . 'wp-admin/admin-footer.php' );
|
798 |
}
|
799 |
|
800 |
/**
|
801 |
* @internal
|
802 |
*/
|
803 |
+
public function _action_update_extensions() {
|
|
|
804 |
$nonce_name = '_nonce_fw_ext_update_extensions';
|
805 |
+
if ( ! isset( $_POST[ $nonce_name ] ) || ! wp_verify_nonce( $_POST[ $nonce_name ] ) ) {
|
806 |
+
wp_die( __( 'Invalid nonce.', 'fw' ) );
|
807 |
}
|
808 |
|
809 |
$form_input_name = 'extensions';
|
810 |
+
$extensions_list = FW_Request::POST( $form_input_name );
|
811 |
|
812 |
+
if ( empty( $extensions_list ) ) {
|
813 |
FW_Flash_Messages::add(
|
814 |
'fw_ext_update',
|
815 |
+
__( 'Please check the extensions you want to update.', 'fw' ),
|
816 |
'warning'
|
817 |
);
|
818 |
+
wp_redirect( self_admin_url( 'update-core.php' ) );
|
819 |
exit;
|
820 |
}
|
821 |
|
822 |
// handle changes by the hack below
|
823 |
{
|
824 |
+
if ( is_string( $extensions_list ) ) {
|
825 |
+
$extensions_list = json_decode( $extensions_list );
|
826 |
} else {
|
827 |
+
$extensions_list = array_keys( $extensions_list );
|
828 |
}
|
829 |
}
|
830 |
|
831 |
{
|
832 |
+
if ( ! class_exists( '_FW_Ext_Update_Extensions_Upgrader_Skin' ) ) {
|
833 |
fw_include_file_isolated(
|
834 |
+
$this->get_declared_path( '/includes/classes/class--fw-ext-update-extensions-upgrader-skin.php' )
|
835 |
);
|
836 |
}
|
837 |
|
838 |
+
$skin = new _FW_Ext_Update_Extensions_Upgrader_Skin( array(
|
839 |
+
'title' => __( 'Extensions Update', 'fw' ),
|
840 |
+
) );
|
841 |
}
|
842 |
|
843 |
+
require_once( ABSPATH . 'wp-admin/admin-header.php' );
|
844 |
|
845 |
$skin->header();
|
846 |
|
849 |
* Hack for the ftp credentials template that does not support array post values
|
850 |
* https://github.com/WordPress/WordPress/blob/3949a8b6cc50a021ed93798287b4ef9ea8a560d9/wp-admin/includes/file.php#L1144
|
851 |
*/
|
852 |
+
$original_post_value = $_POST[ $form_input_name ];
|
853 |
+
$_POST[ $form_input_name ] = wp_slash( json_encode( $extensions_list ) );
|
854 |
+
|
855 |
+
if ( ! FW_WP_Filesystem::request_access( fw_get_framework_directory( '/extensions' ), fw_current_url(), array( $nonce_name, $form_input_name ) ) ) {
|
856 |
+
// revert hack changes
|
857 |
+
$_POST[ $form_input_name ] = $original_post_value;
|
858 |
+
unset( $original_post_value );
|
859 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
860 |
break;
|
861 |
}
|
862 |
|
863 |
+
// revert hack changes
|
864 |
+
$_POST[ $form_input_name ] = $original_post_value;
|
865 |
+
unset( $original_post_value );
|
|
|
866 |
|
867 |
$updates = $this->get_extensions_with_updates();
|
868 |
|
869 |
+
if ( empty( $updates ) ) {
|
870 |
+
$skin->error( __( 'No extensions updates found.', 'fw' ) );
|
871 |
break;
|
872 |
}
|
873 |
|
874 |
+
foreach ( $extensions_list as $extension_name ) {
|
875 |
+
if ( ! ( $extension = fw()->extensions->get( $extension_name ) ) ) {
|
876 |
+
$skin->error( sprintf( __( 'Extension "%s" does not exist or is disabled.', 'fw' ), $extension_name ) );
|
|
|
|
|
877 |
continue;
|
878 |
}
|
879 |
|
880 |
+
if ( ! isset( $updates[ $extension_name ] ) ) {
|
881 |
+
$skin->error( sprintf( __( 'No update found for the "%s" extension.', 'fw' ), $extension->manifest->get_name() ) );
|
|
|
|
|
882 |
continue;
|
883 |
}
|
884 |
|
885 |
+
$update = $updates[ $extension_name ];
|
886 |
|
887 |
+
if ( is_wp_error( $update ) ) {
|
888 |
+
$skin->error( $update );
|
889 |
continue;
|
890 |
}
|
891 |
|
892 |
/** @var FW_Ext_Update_Service $service */
|
893 |
+
$service = $this->get_child( $update['service'] );
|
894 |
|
895 |
+
$update_result = $this->update( array(
|
896 |
+
'wp_fs_destination_dir' => FW_WP_Filesystem::real_path_to_filesystem_path(
|
897 |
$extension->get_declared_path()
|
898 |
),
|
899 |
+
'download_callback' => array( $service, '_download_extension' ),
|
900 |
+
'download_callback_args' => array(
|
901 |
+
$extension,
|
902 |
+
$update['latest_version'],
|
903 |
+
$this->get_wp_fs_tmp_dir()
|
904 |
+
),
|
905 |
+
'skin' => $skin,
|
906 |
+
'title' => sprintf( __( '%s extension', 'fw' ), $extension->manifest->get_name() ),
|
907 |
+
), true );
|
908 |
+
|
909 |
+
if ( is_wp_error( $update_result ) ) {
|
910 |
+
$skin->error( $update_result );
|
911 |
continue;
|
912 |
}
|
913 |
|
914 |
+
$skin->set_result( true );
|
915 |
|
916 |
+
if ( ! $this->get_config( 'extensions_as_one_update' ) ) {
|
917 |
$skin->decrement_extension_update_count( $extension_name );
|
918 |
}
|
919 |
}
|
920 |
|
921 |
+
if ( $this->get_config( 'extensions_as_one_update' ) ) {
|
922 |
$skin->decrement_extension_update_count( $extension_name );
|
923 |
}
|
924 |
|
925 |
$skin->after();
|
926 |
+
} while ( false );
|
927 |
|
928 |
$skin->footer();
|
929 |
|
930 |
+
require_once( ABSPATH . 'wp-admin/admin-footer.php' );
|
931 |
}
|
932 |
|
933 |
public function _action_admin_notices() {
|
934 |
+
|
935 |
+
$updates = $this->get_updates();
|
936 |
+
|
937 |
+
if ( empty( $updates['extensions'] ) || strpos( get_current_screen()->id, 'update-core' ) !== false ) {
|
|
|
|
|
|
|
938 |
return;
|
939 |
}
|
940 |
|
941 |
+
foreach ( $updates['extensions'] as $ext_name => $ext_update ) {
|
942 |
if ( is_wp_error( $ext_update ) ) {
|
943 |
return;
|
944 |
}
|
946 |
break;
|
947 |
}
|
948 |
|
949 |
+
echo
|
950 |
+
'<div class="notice notice-warning">
|
951 |
+
<p>' .
|
952 |
+
sprintf(
|
953 |
+
esc_html__( 'New extensions updates available. %s', 'fw' ),
|
954 |
+
fw_html_tag(
|
955 |
+
'a',
|
956 |
+
array( 'href' => self_admin_url( 'update-core.php' ) . '#fw-ext-update-extensions' ),
|
957 |
+
esc_html__( 'Go to Updates page', 'fw' )
|
958 |
+
)
|
959 |
+
) .
|
960 |
+
'</p>
|
961 |
+
</div>';
|
962 |
}
|
963 |
}
|
framework/helpers/class-fw-form.php
CHANGED
@@ -462,7 +462,7 @@ class FW_Form {
|
|
462 |
$errors = array();
|
463 |
|
464 |
if ( ! $this->check_nonce( $this->get_nonce() ) ) {
|
465 |
-
$errors[ $this->get_nonce_name() ] =
|
466 |
}
|
467 |
|
468 |
/**
|
462 |
$errors = array();
|
463 |
|
464 |
if ( ! $this->check_nonce( $this->get_nonce() ) ) {
|
465 |
+
$errors[ $this->get_nonce_name() ] = esc_html__( 'Your session expired. Please refresh page and try again.', 'fw' );
|
466 |
}
|
467 |
|
468 |
/**
|
framework/helpers/general.php
CHANGED
@@ -732,6 +732,11 @@ if ( ! function_exists( 'fw_render_view' ) ):
|
|
732 |
* @return string HTML
|
733 |
*/
|
734 |
function fw_render_view( $file_path, $view_variables = array(), $return = true ) {
|
|
|
|
|
|
|
|
|
|
|
735 |
extract( $view_variables, EXTR_REFS );
|
736 |
unset( $view_variables );
|
737 |
|
@@ -743,6 +748,8 @@ if ( ! function_exists( 'fw_render_view' ) ):
|
|
743 |
} else {
|
744 |
require $file_path;
|
745 |
}
|
|
|
|
|
746 |
}
|
747 |
endif;
|
748 |
|
732 |
* @return string HTML
|
733 |
*/
|
734 |
function fw_render_view( $file_path, $view_variables = array(), $return = true ) {
|
735 |
+
|
736 |
+
if ( ! is_file( $file_path ) ) {
|
737 |
+
return '';
|
738 |
+
}
|
739 |
+
|
740 |
extract( $view_variables, EXTR_REFS );
|
741 |
unset( $view_variables );
|
742 |
|
748 |
} else {
|
749 |
require $file_path;
|
750 |
}
|
751 |
+
|
752 |
+
return '';
|
753 |
}
|
754 |
endif;
|
755 |
|
framework/includes/option-types/color-picker/static/js/scripts.js
CHANGED
@@ -27,17 +27,11 @@ jQuery(document).ready(function($){
|
|
27 |
getInstance: function ($iris) {
|
28 |
return $iris.data('a8cIris');
|
29 |
},
|
30 |
-
updatePreview: function ($input, color) {
|
31 |
-
if (this.isColorValid(color)) {
|
32 |
-
$input.
|
33 |
-
'background-color': color,
|
34 |
-
'color': this.isColorDark(color) ? '#FFFFFF' : '#000000'
|
35 |
-
});
|
36 |
} else {
|
37 |
-
$input.css({
|
38 |
-
'background-color': '',
|
39 |
-
'color': ''
|
40 |
-
});
|
41 |
}
|
42 |
},
|
43 |
increment: 0
|
27 |
getInstance: function ($iris) {
|
28 |
return $iris.data('a8cIris');
|
29 |
},
|
30 |
+
updatePreview: function ( $input, color ) {
|
31 |
+
if ( this.isColorValid( color ) ) {
|
32 |
+
$input.attr( 'style', 'background-color:' + color + ' !important; color:' + ( this.isColorDark( color ) ? '#FFFFFF' : '#000000' ) + ' !important;' );
|
|
|
|
|
|
|
33 |
} else {
|
34 |
+
$input.css( {'background-color': '', 'color': ''} );
|
|
|
|
|
|
|
35 |
}
|
36 |
},
|
37 |
increment: 0
|
framework/includes/option-types/multi-select/class-fw-option-type-multi-select.php
CHANGED
@@ -342,9 +342,9 @@ if ( ! class_exists( 'FW_Option_Type_Multi_Select' ) ):
|
|
342 |
switch ( $option['population'] ) {
|
343 |
case 'array' :
|
344 |
if ( isset( $option['choices'] ) && is_array( $option['choices'] ) ) {
|
345 |
-
foreach ($option['choices'] as $c_key => $c_val) {
|
346 |
$items[] = array(
|
347 |
-
'val'
|
348 |
'title' => $c_val,
|
349 |
);
|
350 |
}
|
@@ -352,27 +352,20 @@ if ( ! class_exists( 'FW_Option_Type_Multi_Select' ) ):
|
|
352 |
break;
|
353 |
case 'posts' :
|
354 |
if ( isset( $option['source'] ) ) {
|
355 |
-
$source = is_array( $option['source'] ) ? $option['source'] : array( $option['source'] );
|
356 |
|
357 |
-
$items = self::get_posts( $data['value'] );
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
}
|
369 |
-
|
370 |
-
if ( count( $items ) == $option['prepopulate'] ) {
|
371 |
-
break;
|
372 |
-
}
|
373 |
-
}
|
374 |
-
}
|
375 |
}
|
|
|
376 |
$items = array_map(
|
377 |
array( $this, 'build_post' ),
|
378 |
$items,
|
@@ -385,22 +378,18 @@ if ( ! class_exists( 'FW_Option_Type_Multi_Select' ) ):
|
|
385 |
|
386 |
$items = self::get_terms( $data['value'], $source );
|
387 |
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
if ( count( $items ) == $option['prepopulate'] ) {
|
400 |
-
break;
|
401 |
-
}
|
402 |
-
}
|
403 |
}
|
|
|
404 |
}
|
405 |
|
406 |
$items = array_map(
|
@@ -410,27 +399,39 @@ if ( ! class_exists( 'FW_Option_Type_Multi_Select' ) ):
|
|
410 |
);
|
411 |
break;
|
412 |
case 'users' :
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
417 |
}
|
418 |
|
419 |
-
$items = self::query_users(array(
|
420 |
-
'role' => array_fill_keys($source, true),
|
421 |
-
'id' => $data['value'],
|
422 |
-
'limit' => $option['prepopulate'],
|
423 |
-
));
|
424 |
break;
|
425 |
default :
|
426 |
return '(Invalid <code>population</code> parameter)';
|
427 |
}
|
428 |
|
429 |
-
$option['attr']['data-options']
|
430 |
-
$option['attr']['data-population']
|
431 |
-
$option['attr']['data-show-type']
|
432 |
-
$option['attr']['data-source']
|
433 |
-
$option['attr']['data-limit']
|
|
|
434 |
} else {
|
435 |
return '(The <code>population</code> parameter is required)';
|
436 |
}
|
342 |
switch ( $option['population'] ) {
|
343 |
case 'array' :
|
344 |
if ( isset( $option['choices'] ) && is_array( $option['choices'] ) ) {
|
345 |
+
foreach ( $option['choices'] as $c_key => $c_val ) {
|
346 |
$items[] = array(
|
347 |
+
'val' => $c_key,
|
348 |
'title' => $c_val,
|
349 |
);
|
350 |
}
|
352 |
break;
|
353 |
case 'posts' :
|
354 |
if ( isset( $option['source'] ) ) {
|
|
|
355 |
|
356 |
+
$items = self::get_posts( (array) $data['value'] );
|
357 |
+
|
358 |
+
$query = new WP_Query( array(
|
359 |
+
'post_type' => $option['source'],
|
360 |
+
'post__not_in' => $data['value'],
|
361 |
+
'posts_per_page' => $option['prepopulate'],
|
362 |
+
'fields' => 'ids',
|
363 |
+
'ignore_sticky_posts' => 1
|
364 |
+
) );
|
365 |
+
|
366 |
+
$items = array_merge( $items, $query->get_posts() );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
367 |
}
|
368 |
+
|
369 |
$items = array_map(
|
370 |
array( $this, 'build_post' ),
|
371 |
$items,
|
378 |
|
379 |
$items = self::get_terms( $data['value'], $source );
|
380 |
|
381 |
+
$terms = get_terms( array(
|
382 |
+
'taxonomy' => $option['source'],
|
383 |
+
'hide_empty' => false,
|
384 |
+
'exclude' => $data['value'],
|
385 |
+
'number' => $option['prepopulate'],
|
386 |
+
'fields' => 'ids'
|
387 |
+
) );
|
388 |
+
|
389 |
+
if ( ! is_wp_error( $terms ) ) {
|
390 |
+
$items = array_merge( $items, (array) $terms );
|
|
|
|
|
|
|
|
|
|
|
391 |
}
|
392 |
+
|
393 |
}
|
394 |
|
395 |
$items = array_map(
|
399 |
);
|
400 |
break;
|
401 |
case 'users' :
|
402 |
+
|
403 |
+
$source = ! empty( $option['source'] ) ? (array) $option['source'] : array();
|
404 |
+
|
405 |
+
$items = self::query_users( array(
|
406 |
+
'role' => array_fill_keys( $source, true ),
|
407 |
+
'id' => $data['value'],
|
408 |
+
'limit' => $option['prepopulate']
|
409 |
+
) );
|
410 |
+
|
411 |
+
$users = get_users(
|
412 |
+
array(
|
413 |
+
'role__in' => $source,
|
414 |
+
'exclude' => (array) $data['value'],
|
415 |
+
'number' => (int) $option['prepopulate'],
|
416 |
+
'fields' => array( 'ID', 'display_name' )
|
417 |
+
)
|
418 |
+
);
|
419 |
+
|
420 |
+
foreach ( $users as $user ) {
|
421 |
+
$items[] = array( 'val' => $user->ID, 'title' => $user->display_name );
|
422 |
}
|
423 |
|
|
|
|
|
|
|
|
|
|
|
424 |
break;
|
425 |
default :
|
426 |
return '(Invalid <code>population</code> parameter)';
|
427 |
}
|
428 |
|
429 |
+
$option['attr']['data-options'] = json_encode( $items );
|
430 |
+
$option['attr']['data-population'] = $population;
|
431 |
+
$option['attr']['data-show-type'] = (int) fw_akg( 'show-type', $option, false );
|
432 |
+
$option['attr']['data-source'] = json_encode( $source );
|
433 |
+
$option['attr']['data-limit'] = ( intval( $option['limit'] ) > 0 ) ? $option['limit'] : 0;
|
434 |
+
|
435 |
} else {
|
436 |
return '(The <code>population</code> parameter is required)';
|
437 |
}
|
framework/includes/option-types/rgba-color-picker/class-fw-option-type-rgba-color-picker.php
CHANGED
@@ -63,7 +63,7 @@ class FW_Option_Type_Rgba_Color_Picker extends FW_Option_Type {
|
|
63 |
|
64 |
$option['attr']['data-palettes'] = json_encode( $palettes );
|
65 |
|
66 |
-
return '<input type="text" ' . fw_attr_to_html( $option['attr'] ) . '>';
|
67 |
}
|
68 |
|
69 |
/**
|
63 |
|
64 |
$option['attr']['data-palettes'] = json_encode( $palettes );
|
65 |
|
66 |
+
return '<input type="text" ' . fw_attr_to_html( $option['attr'] ) . ' data-alpha="true">';
|
67 |
}
|
68 |
|
69 |
/**
|
framework/includes/option-types/rgba-color-picker/static/css/styles.css
CHANGED
@@ -1,86 +1,21 @@
|
|
1 |
-
|
2 |
-
|
3 |
-
|
4 |
-
color: #000;
|
5 |
}
|
6 |
-
|
7 |
-
|
8 |
-
height: 24px;
|
9 |
-
width: 100%;
|
10 |
-
background-color: #FFF;
|
11 |
-
background-image: url(../images/transparency-grid.png);
|
12 |
-
box-shadow: 0 0 5px rgba(0, 0, 0, 0.4) inset;
|
13 |
-
-webkit-border-radius: 3px;
|
14 |
-
-moz-border-radius: 3px;
|
15 |
-
border-radius: 3px;
|
16 |
-
padding: 0;
|
17 |
}
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
background-color: #FFF;
|
22 |
-
text-shadow: 0 1px 0 #FFF;
|
23 |
-
text-decoration: none;
|
24 |
-
position: absolute;
|
25 |
-
z-index: 2;
|
26 |
-
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
|
27 |
-
border: 1px solid #aaa;
|
28 |
-
-webkit-border-radius: 4px;
|
29 |
-
-moz-border-radius: 4px;
|
30 |
-
border-radius: 4px;
|
31 |
-
opacity: 0.9;
|
32 |
-
margin-top: -2px;
|
33 |
-
height: 20px;
|
34 |
-
cursor: ew-resize;
|
35 |
-
font-size: 12px;
|
36 |
-
padding: 3px;
|
37 |
}
|
38 |
-
|
39 |
-
|
40 |
-
position: relative;
|
41 |
-
text-align: center;
|
42 |
-
width: 88%;
|
43 |
}
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
display: block;
|
48 |
-
border-right: 1px solid #aaa;
|
49 |
-
border-left: 1px solid #aaa;
|
50 |
-
border-top: none;
|
51 |
-
border-bottom: 1px solid #aaa;
|
52 |
-
background: #FFF;
|
53 |
-
padding: 0 11px 6px;
|
54 |
-
position: relative;
|
55 |
-
top: 176px;
|
56 |
-
width: 89%;
|
57 |
-
left: -1px;
|
58 |
}
|
59 |
-
|
60 |
-
|
61 |
-
.fw-option-type-rgba-color-picker-iris,
|
62 |
-
.fw-option-type-rgba-color-picker-iris.iris-picker {
|
63 |
-
z-index: 999;
|
64 |
-
position: absolute;
|
65 |
-
}
|
66 |
-
|
67 |
-
.fw-option-type-rgba-color-picker-iris .fw-option-type-rgba-color-picker-reset-default {
|
68 |
-
width: 139px;
|
69 |
-
margin-top: 2px;
|
70 |
-
cursor: pointer;
|
71 |
-
}
|
72 |
-
|
73 |
-
.fw-option-type-rgba-color-picker-iris .fw-option-type-rgba-color-picker-reset-default span {
|
74 |
-
line-height: 16px;
|
75 |
-
padding-left: 2px;
|
76 |
-
float: left;
|
77 |
-
}
|
78 |
-
|
79 |
-
|
80 |
-
.fw-option-type-rgba-color-picker-with-reset-default > .iris-palette-container {
|
81 |
-
bottom: 27px !important;
|
82 |
-
}
|
83 |
-
|
84 |
-
.fw-option-type-rgba-color-picker-with-reset-default .fw-alpha-container {
|
85 |
-
top: 192px;
|
86 |
}
|
1 |
+
.fw-backend-option-input-type-rgba-color-picker .iris-palette {
|
2 |
+
height: 33px !important;
|
3 |
+
width: 33px !important;
|
|
|
4 |
}
|
5 |
+
.fw-backend-option-input-type-rgba-color-picker .fw-option-help-in-input {
|
6 |
+
top: 2px !important;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
}
|
8 |
+
.fw-backend-option-input-type-rgba-color-picker .wp-picker-holder {
|
9 |
+
position:absolute;
|
10 |
+
z-index:99999;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
}
|
12 |
+
.fw-backend-option-input-type-rgba-color-picker .wp-picker-clear {
|
13 |
+
height: 23px !important;
|
|
|
|
|
|
|
14 |
}
|
15 |
+
.fw-backend-option-input-type-rgba-color-picker .wp-color-result {
|
16 |
+
height: auto;
|
17 |
+
box-shadow:none;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
}
|
19 |
+
.fw-backend-option-input-type-rgba-color-picker input {
|
20 |
+
max-width: 140px !important;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
}
|
framework/includes/option-types/rgba-color-picker/static/js/scripts.js
CHANGED
@@ -1,288 +1,330 @@
|
|
1 |
-
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8 |
};
|
9 |
-
Color.prototype.toRgba = function ( a ) {
|
10 |
-
var rgb = this.toRgb();
|
11 |
-
rgb['a'] = ( typeof a === 'undefined' ) ? 1 : a;
|
12 |
-
|
13 |
-
return rgb;
|
14 |
-
}
|
15 |
-
Color.prototype.toRgbaCSS = function ( a ) {
|
16 |
-
var rgba = this.toRgba( a );
|
17 |
-
|
18 |
-
return 'rgba(' + rgba.r + ',' + rgba.g + ',' + rgba.b + ',' + rgba.a + ')';
|
19 |
-
}
|
20 |
-
|
21 |
-
var helpers = {
|
22 |
-
optionClass: 'fw-option-type-rgba-color-picker',
|
23 |
-
eventNamespace: '.fwOptionTypeRgbaColorPicker',
|
24 |
-
hexColorRegex: /^#([a-f0-9]{3}){1,2}$/i,
|
25 |
-
localized: window._fw_option_type_rgba_color_picker_localized,
|
26 |
-
increment: 0,
|
27 |
-
isColorDark: function ( rgbaColor ) {
|
28 |
-
var r, g, b, o = 1;
|
29 |
-
|
30 |
-
if ( this.hexColorRegex.test( rgbaColor ) ) {
|
31 |
-
var color = rgbaColor.substring( 1 ); // remove #
|
32 |
-
|
33 |
-
r = parseInt( color.substr( 0, 2 ), 16 );
|
34 |
-
g = parseInt( color.substr( 2, 2 ), 16 );
|
35 |
-
b = parseInt( color.substr( 4, 2 ), 16 );
|
36 |
-
} else {
|
37 |
-
var rgba = rgbaColor
|
38 |
-
.replace( /^(rgb|rgba)\(/, '' )
|
39 |
-
.replace( /\)$/, '' )
|
40 |
-
.replace( /\s/g, '' )
|
41 |
-
.split( ',' );
|
42 |
-
|
43 |
-
r = rgba[0];
|
44 |
-
g = rgba[1];
|
45 |
-
b = rgba[2];
|
46 |
-
o = rgba[3] || 1;
|
47 |
-
}
|
48 |
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
) / 1000;
|
58 |
-
|
59 |
-
return yiq < 128 && o > 0.4;
|
60 |
-
},
|
61 |
-
isColorValid: function ( rgbaColor ) {
|
62 |
-
return ! Color( rgbaColor ).error;
|
63 |
-
},
|
64 |
-
getInstance: function ( $iris ) {
|
65 |
-
return $iris.data( 'a8cIris' );
|
66 |
-
},
|
67 |
-
updatePreview: function ( $input, color ) {
|
68 |
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
74 |
} else {
|
75 |
-
|
76 |
-
'background-color': '',
|
77 |
-
'color': ''
|
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 |
-
defaultColor: false,
|
106 |
-
create: function () {
|
107 |
-
$( this ).val( Color( savedVal ).toStr() )
|
108 |
-
},
|
109 |
-
change: function ( event, ui ) {
|
110 |
-
var $transparency = $input.next( '.iris-picker' ).find( '.transparency' );
|
111 |
-
$transparency.css( 'backgroundColor', ui.color.toStr( 'no-alpha' ) );
|
112 |
-
|
113 |
-
$alphaSlider.slider( "option", "value", ui.color._alpha * 100 );
|
114 |
-
|
115 |
-
clearTimeout( changeTimeoutId );
|
116 |
-
changeTimeoutId = setTimeout( function () {
|
117 |
-
$input.trigger( 'fw:option-type:rgba-color-picker:change', {
|
118 |
-
$element: $input,
|
119 |
-
iris: $input.data( 'a8cIris' ),
|
120 |
-
alphaSlider: $alphaSlider.data( 'uiSlider' )
|
121 |
-
} );
|
122 |
-
$input.val( ui.color.toStr() )
|
123 |
-
$input.trigger( 'change' );
|
124 |
-
|
125 |
-
}, 12 );
|
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 |
-
* Show it manually
|
160 |
-
*/
|
161 |
-
$input.on( 'focus', function () {
|
162 |
-
if ( ! $picker.is( ':visible' ) ) {
|
163 |
-
$input.iris( 'show' );
|
164 |
-
}
|
165 |
-
} );
|
166 |
|
167 |
-
|
168 |
-
|
|
|
169 |
|
170 |
-
|
171 |
-
|
|
|
172 |
} );
|
173 |
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
$alphaSlider.slider( {
|
184 |
-
value: Color( $input.val() )._alpha * 100,
|
185 |
-
range: "max",
|
186 |
-
step: 1,
|
187 |
-
min: 0,
|
188 |
-
max: 100,
|
189 |
-
slide: function ( event, ui ) {
|
190 |
-
$( this ).find( '.ui-slider-handle' ).text( ui.value );
|
191 |
-
|
192 |
-
$input.data( 'a8cIris' )._color._alpha = parseFloat( ui.value ) / 100.0;
|
193 |
-
|
194 |
-
var color = $input.iris( 'color', true )
|
195 |
-
var cssColor = color.toCSS( 'rgba', ui.value / 100 )
|
196 |
-
|
197 |
-
$input.val( cssColor );
|
198 |
-
|
199 |
-
clearTimeout( changeTimeoutId );
|
200 |
-
changeTimeoutId = setTimeout( function () {
|
201 |
-
$input.trigger( 'fw:option-type:rgba-color-picker:change', {
|
202 |
-
$element: $input,
|
203 |
-
iris: $input.data( 'a8cIris' ),
|
204 |
-
alphaSlider: $alphaSlider.data( 'uiSlider' )
|
205 |
-
} );
|
206 |
-
$input.trigger( 'change' );
|
207 |
-
}, 12 );
|
208 |
-
},
|
209 |
-
create: function ( event, ui ) {
|
210 |
-
var v = $( this ).slider( 'value' ),
|
211 |
-
$transparency = $input.next( '.iris-picker:first' ).find( '.transparency' );
|
212 |
-
|
213 |
-
$( this ).find( '.ui-slider-handle' ).text( v );
|
214 |
-
|
215 |
-
$transparency.css( 'backgroundColor', Color( $input.val() ).toRgbaCSS( 1 ) );
|
216 |
-
},
|
217 |
-
change: function ( event, ui ) {
|
218 |
-
$( this ).find( '.ui-slider-handle' ).text( ui.value );
|
219 |
-
|
220 |
-
$input.data( 'a8cIris' )._color._alpha = parseFloat( ui.value ) / 100.0;
|
221 |
-
$input.val( $input.iris( 'color', true ).toRgbaCSS( ui.value / 100 ) )
|
222 |
-
|
223 |
-
clearTimeout( changeTimeoutId );
|
224 |
-
changeTimeoutId = setTimeout( function () {
|
225 |
-
$input.trigger( 'fw:option-type:rgba-color-picker:change', {
|
226 |
-
$element: $input,
|
227 |
-
iris: $input.data( 'a8cIris' ),
|
228 |
-
alphaSlider: $alphaSlider.data( 'uiSlider' )
|
229 |
-
} );
|
230 |
-
$input.trigger( 'change' );
|
231 |
-
}, 12 );
|
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 |
} );
|
1 |
+
( function( $ ) {
|
2 |
+
// Variable for some backgrounds ( grid )
|
3 |
+
var image = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAAHnlligAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAHJJREFUeNpi+P///4EDBxiAGMgCCCAGFB5AADGCRBgYDh48CCRZIJS9vT2QBAggFBkmBiSAogxFBiCAoHogAKIKAlBUYTELAiAmEtABEECk20G6BOmuIl0CIMBQ/IEMkO0myiSSraaaBhZcbkUOs0HuBwDplz5uFJ3Z4gAAAABJRU5ErkJggg==',
|
4 |
+
// html stuff for wpColorPicker copy of the original color-picker.js
|
5 |
+
_before = '<a tabindex="0" class="wp-color-result" />',
|
6 |
+
_after = '<div class="wp-picker-holder" />',
|
7 |
+
_wrap = '<div class="wp-picker-container" />',
|
8 |
+
_button = '<input type="button" class="button button-small hidden" />';
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Overwrite Color
|
12 |
+
* for enable support rbga
|
13 |
+
*/
|
14 |
+
Color.fn.toString = function() {
|
15 |
+
if ( this._alpha < 1 )
|
16 |
+
return this.toCSS( 'rgba', this._alpha ).replace( /\s+/g, '' );
|
17 |
+
|
18 |
+
var hex = parseInt( this._color, 10 ).toString( 16 );
|
19 |
+
|
20 |
+
if ( this.error )
|
21 |
+
return '';
|
22 |
+
|
23 |
+
if ( hex.length < 6 )
|
24 |
+
hex = ( '00000' + hex ).substr( -6 );
|
25 |
+
|
26 |
+
return '#' + hex;
|
27 |
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
|
29 |
+
/**
|
30 |
+
* Overwrite wpColorPicker
|
31 |
+
*/
|
32 |
+
$.widget( 'wp.wpColorPicker', $.wp.wpColorPicker, {
|
33 |
+
_create: function() {
|
34 |
+
// bail early for unsupported Iris.
|
35 |
+
if ( ! $.support.iris )
|
36 |
+
return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
37 |
|
38 |
+
var self = this,
|
39 |
+
el = self.element;
|
40 |
+
|
41 |
+
$.extend( self.options, el.data() );
|
42 |
+
|
43 |
+
// keep close bound so it can be attached to a body listener
|
44 |
+
self.close = $.proxy( self.close, self );
|
45 |
+
|
46 |
+
self.initialValue = el.val();
|
47 |
+
|
48 |
+
// Set up HTML structure, hide things
|
49 |
+
el.addClass( 'wp-color-picker' ).hide().wrap( _wrap );
|
50 |
+
self.wrap = el.parent();
|
51 |
+
self.toggler = $( _before ).insertBefore( el ).css( { backgroundColor : self.initialValue } ).attr( 'title', wpColorPickerL10n.pick ).attr( 'data-current', wpColorPickerL10n.current );
|
52 |
+
self.pickerContainer = $( _after ).insertAfter( el );
|
53 |
+
self.button = $( _button );
|
54 |
+
|
55 |
+
if ( self.options.defaultColor ) {
|
56 |
+
self.button.addClass( 'wp-picker-default' ).val( wpColorPickerL10n.defaultString );
|
57 |
} else {
|
58 |
+
self.button.addClass( 'wp-picker-clear' ).val( wpColorPickerL10n.clear );
|
|
|
|
|
|
|
59 |
}
|
|
|
|
|
60 |
|
61 |
+
el.wrap( '<span class="wp-picker-input-wrap" />' ).after( self.button );
|
62 |
+
|
63 |
+
el.iris( {
|
64 |
+
target : self.pickerContainer,
|
65 |
+
hide : self.options.hide,
|
66 |
+
width : self.options.width,
|
67 |
+
mode : self.options.mode,
|
68 |
+
palettes : self.options.palettes,
|
69 |
+
change : function( event, ui ) {
|
70 |
+
|
71 |
+
if ( self.options.alpha ) {
|
72 |
+
self.toggler.css( { 'background-image' : 'url(' + image + ')' } ).html( '<span />' );
|
73 |
+
self.toggler.find( 'span' ).css( {
|
74 |
+
'width' : '100%',
|
75 |
+
'height' : '100%',
|
76 |
+
'position' : 'absolute',
|
77 |
+
'top' : 0,
|
78 |
+
'left' : 0,
|
79 |
+
'border-top-left-radius' : '3px',
|
80 |
+
'border-bottom-left-radius' : '3px',
|
81 |
+
'background' : ui.color.toString()
|
82 |
+
} );
|
83 |
+
} else {
|
84 |
+
self.toggler.css( { backgroundColor : ui.color.toString() } );
|
85 |
+
}
|
86 |
+
|
87 |
+
// Check for a custom cb
|
88 |
+
if ( $.isFunction( self.options.change ) )
|
89 |
+
self.options.change.call( this, event, ui );
|
90 |
}
|
91 |
+
} );
|
92 |
|
93 |
+
el.val( self.initialValue );
|
94 |
+
self._addListeners();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
95 |
|
96 |
+
if ( ! self.options.hide ) {
|
97 |
+
self.toggler.click();
|
98 |
+
}
|
99 |
+
},
|
100 |
+
_addListeners: function() {
|
101 |
+
var self = this;
|
102 |
|
103 |
+
// prevent any clicks inside this widget from leaking to the top and closing it
|
104 |
+
self.wrap.on( 'click.wpcolorpicker', function( event ) {
|
105 |
+
event.stopPropagation();
|
106 |
+
} );
|
107 |
|
108 |
+
self.toggler.on( 'click', function() {
|
109 |
+
if ( self.toggler.hasClass( 'wp-picker-open' ) ) {
|
110 |
+
self.close();
|
111 |
+
} else {
|
112 |
+
self.open();
|
113 |
+
}
|
114 |
+
});
|
115 |
+
|
116 |
+
self.element.on( 'change', function( event ) {
|
117 |
+
// Empty or Error = clear
|
118 |
+
if ( $( this ).val() === '' || self.element.hasClass( 'iris-error' ) ) {
|
119 |
+
if ( self.options.alpha ) {
|
120 |
+
self.toggler.removeAttr( 'style' );
|
121 |
+
self.toggler.find( 'span' ).css( 'backgroundColor', '' );
|
122 |
+
} else {
|
123 |
+
self.toggler.css( 'backgroundColor', '' );
|
124 |
+
}
|
125 |
|
126 |
+
// fire clear callback if we have one
|
127 |
+
if ( $.isFunction( self.options.clear ) )
|
128 |
+
self.options.clear.call( this, event );
|
129 |
+
}
|
130 |
+
} );
|
131 |
|
132 |
+
// open a keyboard-focused closed picker with space or enter
|
133 |
+
self.toggler.on( 'keyup', function( event ) {
|
134 |
+
if ( event.keyCode === 13 || event.keyCode === 32 ) {
|
135 |
+
event.preventDefault();
|
136 |
+
self.toggler.trigger( 'click' ).next().focus();
|
137 |
+
}
|
138 |
+
});
|
139 |
+
|
140 |
+
self.button.on( 'click', function( event ) {
|
141 |
+
if ( $( this ).hasClass( 'wp-picker-clear' ) ) {
|
142 |
+
self.element.val( '' );
|
143 |
+
if ( self.options.alpha ) {
|
144 |
+
self.toggler.removeAttr( 'style' );
|
145 |
+
self.toggler.find( 'span' ).css( 'backgroundColor', '' );
|
146 |
+
} else {
|
147 |
+
self.toggler.css( 'backgroundColor', '' );
|
148 |
+
}
|
149 |
|
150 |
+
if ( $.isFunction( self.options.clear ) )
|
151 |
+
self.options.clear.call( this, event );
|
152 |
+
|
153 |
+
} else if ( $( this ).hasClass( 'wp-picker-default' ) ) {
|
154 |
+
self.element.val( self.options.defaultColor ).change();
|
155 |
+
}
|
156 |
+
});
|
157 |
+
}
|
158 |
+
});
|
159 |
+
|
160 |
+
/**
|
161 |
+
* Overwrite iris
|
162 |
+
*/
|
163 |
+
$.widget( 'a8c.iris', $.a8c.iris, {
|
164 |
+
_create: function() {
|
165 |
+
this._super();
|
166 |
+
|
167 |
+
// Global option for check is mode rbga is enabled
|
168 |
+
this.options.alpha = this.element.data( 'alpha' ) || false;
|
169 |
+
|
170 |
+
// Is not input disabled
|
171 |
+
if ( ! this.element.is( ':input' ) )
|
172 |
+
this.options.alpha = false;
|
173 |
+
|
174 |
+
if ( typeof this.options.alpha !== 'undefined' && this.options.alpha ) {
|
175 |
+
var self = this,
|
176 |
+
el = self.element,
|
177 |
+
_html = '<div class="iris-strip iris-slider iris-alpha-slider"><div class="iris-slider-offset iris-slider-offset-alpha"></div></div>',
|
178 |
+
aContainer = $( _html ).appendTo( self.picker.find( '.iris-picker-inner' ) ),
|
179 |
+
aSlider = aContainer.find( '.iris-slider-offset-alpha' ),
|
180 |
+
controls = {
|
181 |
+
aContainer : aContainer,
|
182 |
+
aSlider : aSlider
|
183 |
};
|
184 |
+
|
185 |
+
if ( typeof el.data( 'custom-width' ) !== 'undefined' ) {
|
186 |
+
self.options.customWidth = parseInt( el.data( 'custom-width' ) ) || 0;
|
187 |
+
} else {
|
188 |
+
self.options.customWidth = 100;
|
189 |
}
|
190 |
|
191 |
+
// Set default width for input reset
|
192 |
+
self.options.defaultWidth = el.width();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
193 |
|
194 |
+
// Update width for input
|
195 |
+
if ( self._color._alpha < 1 || self._color.toString().indexOf('rgb') != -1 )
|
196 |
+
el.width( parseInt( self.options.defaultWidth + self.options.customWidth ) );
|
197 |
|
198 |
+
// Push new controls
|
199 |
+
$.each( controls, function( k, v ) {
|
200 |
+
self.controls[k] = v;
|
201 |
} );
|
202 |
|
203 |
+
// Change size strip and add margin for sliders
|
204 |
+
self.controls.square.css( { 'margin-right': '0' } );
|
205 |
+
var emptyWidth = ( self.picker.width() - self.controls.square.width() - 20 ),
|
206 |
+
stripsMargin = ( emptyWidth / 6 ),
|
207 |
+
stripsWidth = ( ( emptyWidth / 2 ) - stripsMargin );
|
208 |
+
|
209 |
+
$.each( [ 'aContainer', 'strip' ], function( k, v ) {
|
210 |
+
self.controls[v].width( stripsWidth ).css( { 'margin-left' : stripsMargin + 'px' } );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
211 |
} );
|
212 |
|
213 |
+
// Add new slider
|
214 |
+
self._initControls();
|
215 |
+
|
216 |
+
// For updated widget
|
217 |
+
self._change();
|
218 |
+
}
|
219 |
+
},
|
220 |
+
_initControls: function() {
|
221 |
+
this._super();
|
222 |
+
|
223 |
+
if ( this.options.alpha ) {
|
224 |
+
var self = this,
|
225 |
+
controls = self.controls;
|
226 |
+
|
227 |
+
controls.aSlider.slider({
|
228 |
+
orientation : 'vertical',
|
229 |
+
min : 0,
|
230 |
+
max : 100,
|
231 |
+
step : 1,
|
232 |
+
value : parseInt( self._color._alpha * 100 ),
|
233 |
+
slide : function( event, ui ) {
|
234 |
+
// Update alpha value
|
235 |
+
self._color._alpha = parseFloat( ui.value / 100 );
|
236 |
+
self._change.apply( self, arguments );
|
237 |
}
|
238 |
+
});
|
239 |
+
}
|
240 |
+
},
|
241 |
+
_change: function() {
|
242 |
+
this._super();
|
243 |
+
|
244 |
+
var self = this,
|
245 |
+
el = self.element;
|
246 |
+
|
247 |
+
if ( this.options.alpha ) {
|
248 |
+
var controls = self.controls,
|
249 |
+
alpha = parseInt( self._color._alpha * 100 ),
|
250 |
+
color = self._color.toRgb(),
|
251 |
+
gradient = [
|
252 |
+
'rgb(' + color.r + ',' + color.g + ',' + color.b + ') 0%',
|
253 |
+
'rgba(' + color.r + ',' + color.g + ',' + color.b + ', 0) 100%'
|
254 |
+
],
|
255 |
+
defaultWidth = self.options.defaultWidth,
|
256 |
+
customWidth = self.options.customWidth,
|
257 |
+
target = self.picker.closest( '.wp-picker-container' ).find( '.wp-color-result' );
|
258 |
+
|
259 |
+
// Generate background slider alpha, only for CSS3 old browser fuck!! :)
|
260 |
+
controls.aContainer.css( { 'background' : 'linear-gradient(to bottom, ' + gradient.join( ', ' ) + '), url(' + image + ')' } );
|
261 |
+
|
262 |
+
if ( target.hasClass( 'wp-picker-open' ) ) {
|
263 |
+
// Update alpha value
|
264 |
+
controls.aSlider.slider( 'value', alpha );
|
265 |
+
|
266 |
+
/**
|
267 |
+
* Disabled change opacity in default slider Saturation ( only is alpha enabled )
|
268 |
+
* and change input width for view all value
|
269 |
+
*/
|
270 |
+
if ( self._color._alpha < 1 ) {
|
271 |
+
controls.strip.attr( 'style', controls.strip.attr( 'style' ).replace( /rgba\(([0-9]+,)(\s+)?([0-9]+,)(\s+)?([0-9]+)(,(\s+)?[0-9\.]+)\)/g, 'rgb($1$3$5)' ) );
|
272 |
+
el.width( parseInt( defaultWidth + customWidth ) );
|
273 |
+
} else {
|
274 |
+
el.width( defaultWidth );
|
275 |
}
|
276 |
+
}
|
277 |
+
}
|
278 |
|
279 |
+
var reset = el.data( 'reset-alpha' ) || false;
|
280 |
+
|
281 |
+
if ( reset ) {
|
282 |
+
self.picker.find( '.iris-palette-container' ).on( 'click.palette', '.iris-palette', function() {
|
283 |
+
self._color._alpha = 1;
|
284 |
+
self.active = 'external';
|
285 |
+
self._change();
|
286 |
+
} );
|
287 |
+
}
|
288 |
+
},
|
289 |
+
_addInputListeners: function( input ) {
|
290 |
+
var self = this,
|
291 |
+
debounceTimeout = 100,
|
292 |
+
callback = function( event ) {
|
293 |
+
var color = new Color( input.val() ),
|
294 |
+
val = input.val();
|
295 |
+
|
296 |
+
input.removeClass( 'iris-error' );
|
297 |
+
// we gave a bad color
|
298 |
+
if ( color.error ) {
|
299 |
+
// don't error on an empty input
|
300 |
+
if ( val !== '' )
|
301 |
+
input.addClass( 'iris-error' );
|
302 |
+
} else {
|
303 |
+
if ( color.toString() !== self._color.toString() ) {
|
304 |
+
// let's not do this on keyup for hex shortcodes
|
305 |
+
if ( ! ( event.type === 'keyup' && val.match( /^[0-9a-fA-F]{3}$/ ) ) )
|
306 |
+
self._setOption( 'color', color.toString() );
|
307 |
+
}
|
308 |
+
}
|
309 |
+
};
|
310 |
|
311 |
+
input.on( 'change', callback ).on( 'keyup', self._debounce( callback, debounceTimeout ) );
|
312 |
|
313 |
+
// If we initialized hidden, show on first focus. The rest is up to you.
|
314 |
+
if ( self.options.hide ) {
|
315 |
+
input.on( 'focus', function() {
|
316 |
+
self.show();
|
317 |
+
} );
|
318 |
+
}
|
319 |
+
}
|
320 |
} );
|
321 |
+
}( jQuery ) );
|
322 |
|
323 |
+
// Auto Call plugin is class is color-picker
|
324 |
+
jQuery( document ).ready( function( $ ) {
|
325 |
+
fwEvents.on( 'fw:options:init', function ( data ) {
|
326 |
+
data.$elements.find( 'input.fw-option-type-rgba-color-picker' ).each( function () {
|
327 |
+
$( this ).wpColorPicker();
|
328 |
+
});
|
329 |
+
});
|
330 |
} );
|
framework/includes/option-types/simple.php
CHANGED
@@ -560,16 +560,19 @@ class FW_Option_Type_Checkboxes extends FW_Option_Type {
|
|
560 |
if ( is_array( $input_value ) ) {
|
561 |
$value = array();
|
562 |
|
563 |
-
foreach (
|
564 |
-
if (
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
|
|
|
|
|
|
|
|
|
|
|
570 |
}
|
571 |
-
|
572 |
-
$value[ $choice ] = true;
|
573 |
}
|
574 |
} else {
|
575 |
$value = $option['value'];
|
560 |
if ( is_array( $input_value ) ) {
|
561 |
$value = array();
|
562 |
|
563 |
+
foreach ($option['choices'] as $choice => $choice_value){
|
564 |
+
if (isset($input_value[$choice]) && $input_value[$choice] ) {
|
565 |
+
// Handle boolean values that got lost into the universe
|
566 |
+
// and somehow become strings by the miracle of
|
567 |
+
// PHP's $_POST parsing
|
568 |
+
$value[$choice] = is_string(
|
569 |
+
$input_value[$choice]
|
570 |
+
) ? $input_value[$choice] === 'true' : true;
|
571 |
+
} else {
|
572 |
+
// If the value's missing from the input it is falsy,
|
573 |
+
// for sure
|
574 |
+
$value[$choice] = false;
|
575 |
}
|
|
|
|
|
576 |
}
|
577 |
} else {
|
578 |
$value = $option['value'];
|
framework/includes/option-types/wp-editor/class-fw-option-type-wp-editor.php
CHANGED
@@ -92,39 +92,37 @@ class FW_Option_Type_Wp_Editor extends FW_Option_Type {
|
|
92 |
* {@inheritdoc}
|
93 |
*/
|
94 |
protected function _enqueue_static( $id, $option, $data ) {
|
95 |
-
if (! wp_script_is('editor')) {
|
96 |
-
|
97 |
-
wp_editor('', fw_rand_md5());
|
98 |
-
ob_end_clean();
|
99 |
}
|
|
|
100 |
/**
|
101 |
* The below styles usually are included directly in html when wp_editor() is called
|
102 |
* but since we call it (below) wrapped in ob_start()...ob_end_clean() the html is not printed.
|
103 |
* So included the styles manually.
|
104 |
*/
|
105 |
-
{
|
106 |
-
wp_enqueue_style(
|
107 |
-
/**
|
108 |
-
* https://github.com/WordPress/WordPress/blob/4.4.2/wp-includes/script-loader.php#L731
|
109 |
-
* without prefix it won't enqueue
|
110 |
-
*/
|
111 |
-
'fw-option-type-' . $this->get_type() .'-dashicons',
|
112 |
-
includes_url('css/dashicons.min.css'),
|
113 |
-
array(),
|
114 |
-
fw()->manifest->get_version()
|
115 |
-
);
|
116 |
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
128 |
|
129 |
$uri = fw_get_framework_directory_uri(
|
130 |
'/includes/option-types/' . $this->get_type() . '/static'
|
@@ -133,7 +131,7 @@ class FW_Option_Type_Wp_Editor extends FW_Option_Type {
|
|
133 |
wp_enqueue_script(
|
134 |
'fw-option-type-' . $this->get_type(),
|
135 |
$uri . '/scripts.js',
|
136 |
-
array('jquery', 'fw-events', 'editor', 'fw'),
|
137 |
fw()->manifest->get_version(),
|
138 |
true
|
139 |
);
|
@@ -141,11 +139,11 @@ class FW_Option_Type_Wp_Editor extends FW_Option_Type {
|
|
141 |
wp_enqueue_style(
|
142 |
'fw-option-type-' . $this->get_type(),
|
143 |
$uri . '/styles.css',
|
144 |
-
array('dashicons', 'editor-buttons'),
|
145 |
fw()->manifest->get_version()
|
146 |
);
|
147 |
|
148 |
-
do_action('fw:option-type:wp-editor:enqueue-scripts');
|
149 |
}
|
150 |
|
151 |
/**
|
92 |
* {@inheritdoc}
|
93 |
*/
|
94 |
protected function _enqueue_static( $id, $option, $data ) {
|
95 |
+
if ( ! wp_script_is( 'editor' ) ) {
|
96 |
+
wp_enqueue_script( 'editor' );
|
|
|
|
|
97 |
}
|
98 |
+
|
99 |
/**
|
100 |
* The below styles usually are included directly in html when wp_editor() is called
|
101 |
* but since we call it (below) wrapped in ob_start()...ob_end_clean() the html is not printed.
|
102 |
* So included the styles manually.
|
103 |
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
|
105 |
+
wp_enqueue_style(
|
106 |
+
/**
|
107 |
+
* https://github.com/WordPress/WordPress/blob/4.4.2/wp-includes/script-loader.php#L731
|
108 |
+
* without prefix it won't enqueue
|
109 |
+
*/
|
110 |
+
'fw-option-type-' . $this->get_type() . '-dashicons',
|
111 |
+
includes_url( 'css/dashicons.min.css' ),
|
112 |
+
array(),
|
113 |
+
fw()->manifest->get_version()
|
114 |
+
);
|
115 |
+
|
116 |
+
wp_enqueue_style(
|
117 |
+
/**
|
118 |
+
* https://github.com/WordPress/WordPress/blob/4.4.2/wp-includes/script-loader.php#L737
|
119 |
+
* without prefix it won't enqueue
|
120 |
+
*/
|
121 |
+
'fw-option-type-' . $this->get_type() . '-editor-buttons',
|
122 |
+
includes_url( '/css/editor.min.css' ),
|
123 |
+
array( 'dashicons', 'fw-unycon' ),
|
124 |
+
fw()->manifest->get_version()
|
125 |
+
);
|
126 |
|
127 |
$uri = fw_get_framework_directory_uri(
|
128 |
'/includes/option-types/' . $this->get_type() . '/static'
|
131 |
wp_enqueue_script(
|
132 |
'fw-option-type-' . $this->get_type(),
|
133 |
$uri . '/scripts.js',
|
134 |
+
array( 'jquery', 'fw-events', 'editor', 'fw' ),
|
135 |
fw()->manifest->get_version(),
|
136 |
true
|
137 |
);
|
139 |
wp_enqueue_style(
|
140 |
'fw-option-type-' . $this->get_type(),
|
141 |
$uri . '/styles.css',
|
142 |
+
array( 'dashicons', 'editor-buttons' ),
|
143 |
fw()->manifest->get_version()
|
144 |
);
|
145 |
|
146 |
+
do_action( 'fw:option-type:wp-editor:enqueue-scripts' );
|
147 |
}
|
148 |
|
149 |
/**
|
framework/manifest.php
CHANGED
@@ -4,4 +4,4 @@ $manifest = array();
|
|
4 |
|
5 |
$manifest['name'] = __('Unyson', 'fw');
|
6 |
|
7 |
-
$manifest['version'] = '2.7.
|
4 |
|
5 |
$manifest['name'] = __('Unyson', 'fw');
|
6 |
|
7 |
+
$manifest['version'] = '2.7.9';
|
framework/static/css/fw.css
CHANGED
@@ -3235,6 +3235,35 @@ body > .fw-sole-modal .fw-sole-modal-content p {
|
|
3235 |
|
3236 |
/* end: SoleModal */
|
3237 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3238 |
|
3239 |
/* qtip custom style */
|
3240 |
|
3235 |
|
3236 |
/* end: SoleModal */
|
3237 |
|
3238 |
+
/* Fixed: https://github.com/ThemeFuse/Unyson/issues/2888 */
|
3239 |
+
.appearance_page_fw-settings .fw-sole-modal-content .wp-spinner{
|
3240 |
+
-webkit-animation: fw-spin 1.2s linear infinite;
|
3241 |
+
-moz-animation: fw-spin 1.2s linear infinite;
|
3242 |
+
-ms-animation: fw-spin 1.2s linear infinite;
|
3243 |
+
-o-animation: fw-spin 1.2s linear infinite;
|
3244 |
+
animation: fw-spin 1.2s linear infinite;
|
3245 |
+
}
|
3246 |
+
@-ms-keyframes fw-spin {
|
3247 |
+
from { -ms-transform: rotate(0deg); }
|
3248 |
+
to { -ms-transform: rotate(360deg); }
|
3249 |
+
}
|
3250 |
+
@-moz-keyframes fw-spin {
|
3251 |
+
from { -moz-transform: rotate(0deg); }
|
3252 |
+
to { -moz-transform: rotate(360deg); }
|
3253 |
+
}
|
3254 |
+
@-webkit-keyframes fw-spin {
|
3255 |
+
from { -webkit-transform: rotate(0deg); }
|
3256 |
+
to { -webkit-transform: rotate(360deg); }
|
3257 |
+
}
|
3258 |
+
@keyframes fw-spin {
|
3259 |
+
from {
|
3260 |
+
transform:rotate(0deg);
|
3261 |
+
}
|
3262 |
+
to {
|
3263 |
+
transform:rotate(360deg);
|
3264 |
+
}
|
3265 |
+
}
|
3266 |
+
/* End Fixed: https://github.com/ThemeFuse/Unyson/issues/2888 */
|
3267 |
|
3268 |
/* qtip custom style */
|
3269 |
|
framework/views/backend-settings-form.php
CHANGED
@@ -188,7 +188,7 @@
|
|
188 |
fw.soleModal.show(
|
189 |
loadingModalId,
|
190 |
'<h2 class="fw-text-muted">'+
|
191 |
-
'<img src="
|
192 |
title +
|
193 |
'</h2>'+
|
194 |
'<p class="fw-text-muted"><em>'+ description +'</em></p>'+ loadingExtraMessage,
|
@@ -206,8 +206,16 @@
|
|
206 |
afterSubmitDelay: function (elements) {
|
207 |
fwEvents.trigger('fw:options:init:tabs', {$elements: elements.$form});
|
208 |
},
|
209 |
-
onErrors: function() {
|
210 |
-
fw.soleModal.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
211 |
},
|
212 |
onAjaxError: function(elements, data) {
|
213 |
{
|
@@ -228,6 +236,7 @@
|
|
228 |
/**
|
229 |
* Display messages
|
230 |
*/
|
|
|
231 |
do {
|
232 |
/**
|
233 |
* Don't display the "Settings successfully saved" message
|
188 |
fw.soleModal.show(
|
189 |
loadingModalId,
|
190 |
'<h2 class="fw-text-muted">'+
|
191 |
+
'<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAAAAACo4kLRAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAnRSTlMA/1uRIrUAAAACYktHRADdUu+NWwAAAAd0SU1FB+EKCgYABDchIukAAACZelRYdFJhdyBwcm9maWxlIHR5cGUgZ2lmOnhtcCBkYXRheG1wAAAImU2NMQ5CMQxD957iHyGNnaTlNkVtEQMSAwPHJx8WHMleXuxyu+/L+/E85niNzHJ85b1gRwvx6vCrWxCGBkdNF1WVaD5DODkx2H0Fgkmv5I2dxFQ9mRKiy3seMdBZCZ4lnUqjQYj/GRW3LPm95w42VvkACzYml9QYNjwAAACjSURBVBjTfZChDoNAEETfbZpgVqJPXHIO0w+hCZYPxJKUD6mpIzmBPrmmigoQcCSM2eRlszM7buWqxzbSd8Y0NgEAtwJ5WvYd39Y7TKOB7xkW0C6AQB4N6KuqB2zMIDDZ0cQmENJ2b8i/AYAl4db3pwj0fAlzmXJGsBIagl4/kitShFjCiNCUsEEI/sx8QKA9WWkLAnV3oNrVN9VtJZtyKrnUH9vgMmhlXVedAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE3LTEwLTEwVDA2OjAwOjA0LTA3OjAw4kWx4AAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNy0xMC0xMFQwNjowMDowNC0wNzowMJMYCVwAAAAASUVORK5CYII=" alt="Loading" class="wp-spinner" /> '+
|
192 |
title +
|
193 |
'</h2>'+
|
194 |
'<p class="fw-text-muted"><em>'+ description +'</em></p>'+ loadingExtraMessage,
|
206 |
afterSubmitDelay: function (elements) {
|
207 |
fwEvents.trigger('fw:options:init:tabs', {$elements: elements.$form});
|
208 |
},
|
209 |
+
onErrors: function( elements, data ) {
|
210 |
+
var message = $.map( data.errors, function( mssg ) { return '<p class="fw-text-danger">' + mssg + '</p>' } ) + fw.soleModal.renderFlashMessages( data.flash_messages );
|
211 |
+
|
212 |
+
fw.soleModal.hide( loadingModalId );
|
213 |
+
|
214 |
+
fw.soleModal.show(
|
215 |
+
'fw-options-ajax-save-error',
|
216 |
+
'<p class="fw-text-danger">' + message + '</p>'
|
217 |
+
);
|
218 |
+
|
219 |
},
|
220 |
onAjaxError: function(elements, data) {
|
221 |
{
|
236 |
/**
|
237 |
* Display messages
|
238 |
*/
|
239 |
+
|
240 |
do {
|
241 |
/**
|
242 |
* Don't display the "Settings successfully saved" message
|
readme.txt
CHANGED
@@ -3,7 +3,7 @@ Contributors: unyson
|
|
3 |
Tags: page builder, shortcodes, backup, seo, breadcrumbs, portfolio, framework
|
4 |
Requires at least: 4.4
|
5 |
Tested up to: 4.8
|
6 |
-
Stable tag: 2.7.
|
7 |
License: GPLv2 or later
|
8 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
9 |
|
@@ -85,6 +85,9 @@ Yes; Unyson will work with any theme.
|
|
85 |
|
86 |
== Changelog ==
|
87 |
|
|
|
|
|
|
|
88 |
= 2.7.8 =
|
89 |
* Fixed [#2905](https://github.com/ThemeFuse/Unyson/issues/2905),[#2862](https://github.com/ThemeFuse/Unyson/issues/2862),[#2909](https://github.com/ThemeFuse/Unyson/issues/2909),[#2924](https://github.com/ThemeFuse/Unyson/issues/2924),[#2925](https://github.com/ThemeFuse/Unyson/issues/2925),[#2921](https://github.com/ThemeFuse/Unyson/issues/2921),[#2844](https://github.com/ThemeFuse/Unyson/issues/2844)
|
90 |
|
3 |
Tags: page builder, shortcodes, backup, seo, breadcrumbs, portfolio, framework
|
4 |
Requires at least: 4.4
|
5 |
Tested up to: 4.8
|
6 |
+
Stable tag: 2.7.9
|
7 |
License: GPLv2 or later
|
8 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
9 |
|
85 |
|
86 |
== Changelog ==
|
87 |
|
88 |
+
= 2.7.9 =
|
89 |
+
* Fixed [#1351](https://github.com/ThemeFuse/Unyson/issues/1351),[#2716](https://github.com/ThemeFuse/Unyson/issues/2716),[#2833](https://github.com/ThemeFuse/Unyson/issues/2833),[#2736](https://github.com/ThemeFuse/Unyson/issues/2736),[#2718](https://github.com/ThemeFuse/Unyson/issues/2718),[#2953](https://github.com/ThemeFuse/Unyson/issues/2953),[#2888](https://github.com/ThemeFuse/Unyson/issues/2888),[#2855](https://github.com/ThemeFuse/Unyson/issues/2855),[#2906](https://github.com/ThemeFuse/Unyson/issues/2906)
|
90 |
+
|
91 |
= 2.7.8 =
|
92 |
* Fixed [#2905](https://github.com/ThemeFuse/Unyson/issues/2905),[#2862](https://github.com/ThemeFuse/Unyson/issues/2862),[#2909](https://github.com/ThemeFuse/Unyson/issues/2909),[#2924](https://github.com/ThemeFuse/Unyson/issues/2924),[#2925](https://github.com/ThemeFuse/Unyson/issues/2925),[#2921](https://github.com/ThemeFuse/Unyson/issues/2921),[#2844](https://github.com/ThemeFuse/Unyson/issues/2844)
|
93 |
|
unyson.php
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
* Plugin Name: Unyson
|
4 |
* Plugin URI: http://unyson.io/
|
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.7.
|
7 |
* Author: ThemeFuse
|
8 |
* Author URI: http://themefuse.com
|
9 |
* License: GPL2+
|
3 |
* Plugin Name: Unyson
|
4 |
* Plugin URI: http://unyson.io/
|
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.7.9
|
7 |
* Author: ThemeFuse
|
8 |
* Author URI: http://themefuse.com
|
9 |
* License: GPL2+
|