Version Description
- Added File Cache #1828
- Migration to native term meta #1745
- The possibility to register Available Extensions from theme
- Fixed #1860, #1877, #1897, #1810
Download this release
Release Info
Developer | Unyson |
Plugin | Unyson |
Version | 2.6.0 |
Comparing to | |
See all releases |
Code changes from version 2.5.12 to 2.6.0
- framework/bootstrap-helpers.php +40 -25
- framework/bootstrap.php +9 -2
- framework/core/components/backend.php +17 -11
- framework/core/components/extensions.php +16 -2
- framework/core/components/extensions/manager/available-extensions.php +72 -26
- framework/core/components/extensions/manager/class--fw-extensions-manager.php +482 -247
- framework/core/components/extensions/manager/includes/available-ext/class--fw-available-extensions-register.php +7 -0
- framework/core/components/extensions/manager/includes/available-ext/class-fw-available-extension.php +131 -0
- framework/core/components/extensions/manager/includes/download-source/class--fw-ext-download-source-register.php +9 -0
- framework/core/components/extensions/manager/includes/download-source/class--fw-ext-download-source.php +20 -0
- framework/core/components/extensions/manager/includes/download-source/types/class-fw-download-source-github.php +187 -0
- framework/core/components/extensions/manager/includes/download-source/types/init.php +15 -0
- framework/core/components/extensions/manager/static/extensions-page.css +12 -1
- framework/core/components/theme.php +13 -7
- framework/core/extends/class-fw-extension.php +31 -12
- framework/extensions/update/manifest.php +1 -1
- framework/extensions/update/views/updates-list.php +1 -1
- framework/helpers/class-fw-cache.php +6 -4
- framework/helpers/class-fw-file-cache.php +237 -0
- framework/helpers/class-fw-wp-filesystem.php +1 -1
- framework/helpers/database.php +182 -17
- framework/helpers/general.php +60 -27
- framework/helpers/type/class-fw-type-register.php +22 -2
- framework/includes/hooks.php +24 -57
- framework/includes/option-types/addable-box/static/js/scripts.js +10 -13
- framework/includes/option-types/addable-option/static/js/scripts.js +13 -3
- framework/includes/option-types/addable-popup/class-fw-option-type-addable-popup.php +15 -7
- framework/includes/option-types/addable-popup/static/css/styles.css +6 -9
- framework/includes/option-types/addable-popup/static/js/addable-popup.js +10 -8
- framework/includes/option-types/addable-popup/{views/view.php → view.php} +17 -18
- framework/includes/option-types/color-picker/static/js/scripts.js +1 -1
- framework/includes/option-types/icon-v2/static/js/icon-picker.js +25 -2
- framework/includes/option-types/image-picker/class-fw-option-type-image-picker.php +7 -6
- framework/includes/option-types/oembed/static/js/oembed.js +24 -13
- framework/includes/option-types/rgba-color-picker/static/js/scripts.js +2 -2
- framework/includes/option-types/wp-editor/includes/class-fw-wp-editor-settings.php +13 -11
- framework/includes/option-types/wp-editor/static/scripts.js +4 -3
- framework/includes/term-meta/function_fw_term_meta_setup_blog.php +0 -38
- framework/manifest.php +1 -1
- readme.txt +10 -73
- unyson.php +11 -41
framework/bootstrap-helpers.php
CHANGED
@@ -23,13 +23,16 @@ function fw_fix_path($path) {
|
|
23 |
* @return string
|
24 |
*/
|
25 |
function fw_get_framework_customizations_dir_rel_path($append = '') {
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
|
|
|
|
|
|
30 |
}
|
31 |
|
32 |
-
return $
|
33 |
}
|
34 |
|
35 |
/** Child theme related functions */
|
@@ -71,13 +74,16 @@ function fw_get_framework_customizations_dir_rel_path($append = '') {
|
|
71 |
* @return string
|
72 |
*/
|
73 |
function fw_get_template_customizations_directory($rel_path = '') {
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
|
|
|
|
|
|
78 |
}
|
79 |
|
80 |
-
return $
|
81 |
}
|
82 |
|
83 |
/**
|
@@ -86,13 +92,16 @@ function fw_get_framework_customizations_dir_rel_path($append = '') {
|
|
86 |
* @return string
|
87 |
*/
|
88 |
function fw_get_template_customizations_directory_uri($rel_path = '') {
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
|
|
|
|
|
|
93 |
}
|
94 |
|
95 |
-
return $
|
96 |
}
|
97 |
}
|
98 |
|
@@ -104,13 +113,16 @@ function fw_get_framework_customizations_dir_rel_path($append = '') {
|
|
104 |
* @return string
|
105 |
*/
|
106 |
function fw_get_framework_directory($rel_path = '') {
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
|
|
|
|
|
|
111 |
}
|
112 |
|
113 |
-
return $
|
114 |
}
|
115 |
|
116 |
/**
|
@@ -119,12 +131,15 @@ function fw_get_framework_customizations_dir_rel_path($append = '') {
|
|
119 |
* @return string
|
120 |
*/
|
121 |
function fw_get_framework_directory_uri($rel_path = '') {
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
|
|
|
|
|
|
126 |
}
|
127 |
|
128 |
-
return $
|
129 |
}
|
130 |
}
|
23 |
* @return string
|
24 |
*/
|
25 |
function fw_get_framework_customizations_dir_rel_path($append = '') {
|
26 |
+
try {
|
27 |
+
$dir = FW_Cache::get($cache_key = 'fw_customizations_dir_rel_path');
|
28 |
+
} catch (FW_Cache_Not_Found_Exception $e) {
|
29 |
+
FW_Cache::set(
|
30 |
+
$cache_key,
|
31 |
+
$dir = apply_filters('fw_framework_customizations_dir_rel_path', '/framework-customizations')
|
32 |
+
);
|
33 |
}
|
34 |
|
35 |
+
return $dir . $append;
|
36 |
}
|
37 |
|
38 |
/** Child theme related functions */
|
74 |
* @return string
|
75 |
*/
|
76 |
function fw_get_template_customizations_directory($rel_path = '') {
|
77 |
+
try {
|
78 |
+
$dir = FW_Cache::get($cache_key = 'fw_template_customizations_dir');
|
79 |
+
} catch (FW_Cache_Not_Found_Exception $e) {
|
80 |
+
FW_Cache::set(
|
81 |
+
$cache_key,
|
82 |
+
$dir = get_template_directory() . fw_get_framework_customizations_dir_rel_path()
|
83 |
+
);
|
84 |
}
|
85 |
|
86 |
+
return $dir . $rel_path;
|
87 |
}
|
88 |
|
89 |
/**
|
92 |
* @return string
|
93 |
*/
|
94 |
function fw_get_template_customizations_directory_uri($rel_path = '') {
|
95 |
+
try {
|
96 |
+
$dir = FW_Cache::get($cache_key = 'fw_template_customizations_dir_uri');
|
97 |
+
} catch (FW_Cache_Not_Found_Exception $e) {
|
98 |
+
FW_Cache::set(
|
99 |
+
$cache_key,
|
100 |
+
$dir = get_template_directory_uri() . fw_get_framework_customizations_dir_rel_path()
|
101 |
+
);
|
102 |
}
|
103 |
|
104 |
+
return $dir . $rel_path;
|
105 |
}
|
106 |
}
|
107 |
|
113 |
* @return string
|
114 |
*/
|
115 |
function fw_get_framework_directory($rel_path = '') {
|
116 |
+
try {
|
117 |
+
$dir = FW_Cache::get($cache_key = 'fw_framework_dir');
|
118 |
+
} catch (FW_Cache_Not_Found_Exception $e) {
|
119 |
+
FW_Cache::set(
|
120 |
+
$cache_key,
|
121 |
+
$dir = apply_filters('fw_framework_directory', dirname(__FILE__))
|
122 |
+
);
|
123 |
}
|
124 |
|
125 |
+
return $dir . $rel_path;
|
126 |
}
|
127 |
|
128 |
/**
|
131 |
* @return string
|
132 |
*/
|
133 |
function fw_get_framework_directory_uri($rel_path = '') {
|
134 |
+
try {
|
135 |
+
$dir = FW_Cache::get($cache_key = 'fw_framework_dir_uri');
|
136 |
+
} catch (FW_Cache_Not_Found_Exception $e) {
|
137 |
+
FW_Cache::set(
|
138 |
+
$cache_key,
|
139 |
+
$dir = apply_filters('fw_framework_directory_uri', get_template_directory_uri() . '/framework')
|
140 |
+
);
|
141 |
}
|
142 |
|
143 |
+
return $dir . $rel_path;
|
144 |
}
|
145 |
}
|
framework/bootstrap.php
CHANGED
@@ -24,6 +24,12 @@ if (defined('FW')) {
|
|
24 |
|
25 |
include $fw_dir .'/bootstrap-helpers.php';
|
26 |
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
/**
|
28 |
* Load core
|
29 |
*/
|
@@ -41,9 +47,10 @@ if (defined('FW')) {
|
|
41 |
'meta',
|
42 |
'class-fw-access-key',
|
43 |
'class-fw-dumper',
|
44 |
-
'general',
|
45 |
'class-fw-wp-filesystem',
|
46 |
-
'class-fw-cache',
|
|
|
47 |
'class-fw-form',
|
48 |
'class-fw-request',
|
49 |
'class-fw-session',
|
24 |
|
25 |
include $fw_dir .'/bootstrap-helpers.php';
|
26 |
|
27 |
+
// these are required when fw() is executed below
|
28 |
+
{
|
29 |
+
require $fw_dir .'/helpers/general.php';
|
30 |
+
require $fw_dir .'/helpers/class-fw-cache.php';
|
31 |
+
}
|
32 |
+
|
33 |
/**
|
34 |
* Load core
|
35 |
*/
|
47 |
'meta',
|
48 |
'class-fw-access-key',
|
49 |
'class-fw-dumper',
|
50 |
+
// 'general', // included below
|
51 |
'class-fw-wp-filesystem',
|
52 |
+
// 'class-fw-cache', // included below
|
53 |
+
'class-fw-file-cache',
|
54 |
'class-fw-form',
|
55 |
'class-fw-request',
|
56 |
'class-fw-session',
|
framework/core/components/backend.php
CHANGED
@@ -1587,15 +1587,21 @@ final class _FW_Component_Backend {
|
|
1587 |
'limit_option_types' => false,
|
1588 |
'limit_container_types' => false,
|
1589 |
'limit_level' => 0,
|
1590 |
-
'
|
1591 |
) );
|
1592 |
|
1593 |
-
|
1594 |
-
|
1595 |
-
|
1596 |
-
|
1597 |
-
|
1598 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
1599 |
}
|
1600 |
}
|
1601 |
|
@@ -1963,9 +1969,9 @@ final class _FW_Component_Backend {
|
|
1963 |
* not existing container types will throw notices.
|
1964 |
* To prevent that, extract and send it only options (without containers)
|
1965 |
*/
|
1966 |
-
fw_collect_options($options_for_enqueue, $customizer_options
|
1967 |
-
|
1968 |
-
|
1969 |
|
1970 |
unset($options_for_enqueue, $customizer_options);
|
1971 |
}
|
@@ -1973,7 +1979,7 @@ final class _FW_Component_Backend {
|
|
1973 |
wp_enqueue_script(
|
1974 |
'fw-backend-customizer',
|
1975 |
fw_get_framework_directory_uri( '/static/js/backend-customizer.js' ),
|
1976 |
-
array( 'jquery', 'fw-events', 'backbone' ),
|
1977 |
fw()->manifest->get_version(),
|
1978 |
true
|
1979 |
);
|
1587 |
'limit_option_types' => false,
|
1588 |
'limit_container_types' => false,
|
1589 |
'limit_level' => 0,
|
1590 |
+
'callback' => array(__CLASS__, '_callback_fw_collect_options_enqueue_static'),
|
1591 |
) );
|
1592 |
|
1593 |
+
unset($collected);
|
1594 |
+
}
|
1595 |
+
|
1596 |
+
/**
|
1597 |
+
* @internal
|
1598 |
+
* @param array $data
|
1599 |
+
*/
|
1600 |
+
public static function _callback_fw_collect_options_enqueue_static($data) {
|
1601 |
+
if ($data['group'] === 'option') {
|
1602 |
+
fw()->backend->option_type($data['option']['type'])->enqueue_static($data['id'], $data['option']);
|
1603 |
+
} elseif ($data['group'] === 'container') {
|
1604 |
+
fw()->backend->container_type($data['option']['type'])->enqueue_static($data['id'], $data['option']);
|
1605 |
}
|
1606 |
}
|
1607 |
|
1969 |
* not existing container types will throw notices.
|
1970 |
* To prevent that, extract and send it only options (without containers)
|
1971 |
*/
|
1972 |
+
fw_collect_options($options_for_enqueue, $customizer_options, array(
|
1973 |
+
'callback' => array(__CLASS__, '_callback_fw_collect_options_enqueue_static'),
|
1974 |
+
));
|
1975 |
|
1976 |
unset($options_for_enqueue, $customizer_options);
|
1977 |
}
|
1979 |
wp_enqueue_script(
|
1980 |
'fw-backend-customizer',
|
1981 |
fw_get_framework_directory_uri( '/static/js/backend-customizer.js' ),
|
1982 |
+
array( 'jquery', 'fw-events', 'backbone', 'fw-backend-options' ),
|
1983 |
fw()->manifest->get_version(),
|
1984 |
true
|
1985 |
);
|
framework/core/components/extensions.php
CHANGED
@@ -147,7 +147,13 @@ final class _FW_Component_Extensions
|
|
147 |
$data['parent'] = null;
|
148 |
}
|
149 |
|
150 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
151 |
|
152 |
if (empty($dirs)) {
|
153 |
return;
|
@@ -306,7 +312,15 @@ final class _FW_Component_Extensions
|
|
306 |
}
|
307 |
|
308 |
foreach ($paths as $path => $uri) {
|
309 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
310 |
foreach ($files as $dir_file_path) {
|
311 |
fw_include_file_isolated($dir_file_path);
|
312 |
}
|
147 |
$data['parent'] = null;
|
148 |
}
|
149 |
|
150 |
+
try {
|
151 |
+
$dirs = FW_File_Cache::get($cache_key = 'core:ext:load:glob:'. $data['path']);
|
152 |
+
} catch (FW_File_Cache_Not_Found_Exception $e) {
|
153 |
+
$dirs = glob($data['path'] .'/*', GLOB_ONLYDIR);
|
154 |
+
|
155 |
+
FW_File_Cache::set($cache_key, $dirs);
|
156 |
+
}
|
157 |
|
158 |
if (empty($dirs)) {
|
159 |
return;
|
312 |
}
|
313 |
|
314 |
foreach ($paths as $path => $uri) {
|
315 |
+
try {
|
316 |
+
$files = FW_File_Cache::get($cache_key = 'core:ext:glob:inc-all-php:'. $extension->get_name() .':'. $path);
|
317 |
+
} catch (FW_File_Cache_Not_Found_Exception $e) {
|
318 |
+
$files = glob($path . $dir_rel_path .'/*.php');
|
319 |
+
|
320 |
+
FW_File_Cache::set($cache_key, $files);
|
321 |
+
}
|
322 |
+
|
323 |
+
if ($files) {
|
324 |
foreach ($files as $dir_file_path) {
|
325 |
fw_include_file_isolated($dir_file_path);
|
326 |
}
|
framework/core/components/extensions/manager/available-extensions.php
CHANGED
@@ -13,11 +13,13 @@ $extensions = array(
|
|
13 |
'description' => __( "Let's you easily build countless pages with the help of the drag and drop visual page builder that comes with a lot of already created shortcodes.", 'fw' ),
|
14 |
'thumbnail' => $thumbnails_uri . '/page-builder.jpg',
|
15 |
'download' => array(
|
16 |
-
'
|
17 |
-
|
18 |
-
|
|
|
19 |
),
|
20 |
),
|
|
|
21 |
'wp-shortcodes' => array(
|
22 |
'display' => true,
|
23 |
'parent' => 'shortcodes',
|
@@ -28,11 +30,13 @@ $extensions = array(
|
|
28 |
),
|
29 |
'thumbnail' => $thumbnails_uri . '/wp-shortcodes.jpg',
|
30 |
'download' => array(
|
31 |
-
'
|
|
|
32 |
'user_repo' => 'ThemeFuse/Unyson-WP-Shortcodes-Extension',
|
33 |
),
|
34 |
),
|
35 |
),
|
|
|
36 |
'backups' => array(
|
37 |
'display' => true,
|
38 |
'parent' => null,
|
@@ -40,11 +44,13 @@ $extensions = array(
|
|
40 |
'description' => __( 'This extension lets you create an automated backup schedule, import demo content or even create a demo content archive for migration purposes.', 'fw' ),
|
41 |
'thumbnail' => $thumbnails_uri . '/backups.jpg',
|
42 |
'download' => array(
|
43 |
-
'
|
|
|
44 |
'user_repo' => $github_account . '/Unyson-Backups-Extension',
|
45 |
),
|
46 |
),
|
47 |
),
|
|
|
48 |
'sidebars' => array(
|
49 |
'display' => true,
|
50 |
'parent' => null,
|
@@ -52,11 +58,13 @@ $extensions = array(
|
|
52 |
'description' => __( 'Brings a new layer of customization freedom to your website by letting you add more than one sidebar to a page, or different sidebars on different pages.', 'fw' ),
|
53 |
'thumbnail' => $thumbnails_uri . '/sidebars.jpg',
|
54 |
'download' => array(
|
55 |
-
'
|
|
|
56 |
'user_repo' => $github_account . '/Unyson-Sidebars-Extension',
|
57 |
),
|
58 |
),
|
59 |
),
|
|
|
60 |
'slider' => array(
|
61 |
'display' => true,
|
62 |
'parent' => 'media',
|
@@ -64,11 +72,13 @@ $extensions = array(
|
|
64 |
'description' => __( 'Adds a sliders module to your website from where you\'ll be able to create different built in jQuery sliders for your homepage and rest of the pages.', 'fw' ),
|
65 |
'thumbnail' => $thumbnails_uri . '/sliders.jpg',
|
66 |
'download' => array(
|
67 |
-
'
|
|
|
68 |
'user_repo' => $github_account . '/Unyson-Sliders-Extension',
|
69 |
),
|
70 |
),
|
71 |
),
|
|
|
72 |
'portfolio' => array(
|
73 |
'display' => true,
|
74 |
'parent' => null,
|
@@ -76,11 +86,13 @@ $extensions = array(
|
|
76 |
'description' => __( 'This extension will add a fully fledged portfolio module that will let you display your projects using the built in portfolio pages.', 'fw' ),
|
77 |
'thumbnail' => $thumbnails_uri . '/portfolio.jpg',
|
78 |
'download' => array(
|
79 |
-
'
|
|
|
80 |
'user_repo' => $github_account . '/Unyson-Portfolio-Extension',
|
81 |
),
|
82 |
),
|
83 |
),
|
|
|
84 |
'megamenu' => array(
|
85 |
'display' => true,
|
86 |
'parent' => null,
|
@@ -88,11 +100,13 @@ $extensions = array(
|
|
88 |
'description' => __( 'The Mega Menu extension adds a user-friendly drop down menu that will let you easily create highly customized menu configurations.', 'fw' ),
|
89 |
'thumbnail' => $thumbnails_uri . '/mega-menu.jpg',
|
90 |
'download' => array(
|
91 |
-
'
|
|
|
92 |
'user_repo' => $github_account . '/Unyson-MegaMenu-Extension',
|
93 |
),
|
94 |
),
|
95 |
),
|
|
|
96 |
'breadcrumbs' => array(
|
97 |
'display' => true,
|
98 |
'parent' => null,
|
@@ -100,11 +114,13 @@ $extensions = array(
|
|
100 |
'description' => __( 'Creates a simplified navigation menu for the pages that can be placed anywhere in the theme. This will make navigating the website much easier.', 'fw' ),
|
101 |
'thumbnail' => $thumbnails_uri . '/breadcrumbs.jpg',
|
102 |
'download' => array(
|
103 |
-
'
|
|
|
104 |
'user_repo' => $github_account . '/Unyson-Breadcrumbs-Extension',
|
105 |
),
|
106 |
),
|
107 |
),
|
|
|
108 |
'seo' => array(
|
109 |
'display' => true,
|
110 |
'parent' => null,
|
@@ -112,11 +128,13 @@ $extensions = array(
|
|
112 |
'description' => __( 'This extension will enable you to have a fully optimized WordPress website by adding optimized meta titles, keywords and descriptions.', 'fw' ),
|
113 |
'thumbnail' => $thumbnails_uri . '/seo.jpg',
|
114 |
'download' => array(
|
115 |
-
'
|
|
|
116 |
'user_repo' => $github_account . '/Unyson-SEO-Extension',
|
117 |
),
|
118 |
),
|
119 |
),
|
|
|
120 |
'events' => array(
|
121 |
'display' => true,
|
122 |
'parent' => null,
|
@@ -124,11 +142,13 @@ $extensions = array(
|
|
124 |
'description' => __( 'This extension adds a fully fledged Events module to your theme. It comes with built in pages that contain a calendar where events can be added.', 'fw' ),
|
125 |
'thumbnail' => $thumbnails_uri . '/events.jpg',
|
126 |
'download' => array(
|
127 |
-
'
|
|
|
128 |
'user_repo' => $github_account . '/Unyson-Events-Extension',
|
129 |
),
|
130 |
),
|
131 |
),
|
|
|
132 |
'analytics' => array(
|
133 |
'display' => true,
|
134 |
'parent' => null,
|
@@ -136,11 +156,13 @@ $extensions = array(
|
|
136 |
'description' => __( 'Enables the possibility to add the Google Analytics tracking code that will let you get all the analytics about visitors, page views and more.', 'fw' ),
|
137 |
'thumbnail' => $thumbnails_uri . '/analytics.jpg',
|
138 |
'download' => array(
|
139 |
-
'
|
|
|
140 |
'user_repo' => $github_account . '/Unyson-Analytics-Extension',
|
141 |
),
|
142 |
),
|
143 |
),
|
|
|
144 |
'feedback' => array(
|
145 |
'display' => true,
|
146 |
'parent' => null,
|
@@ -148,11 +170,13 @@ $extensions = array(
|
|
148 |
'description' => __( 'Adds the possibility to leave feedback (comments, reviews and rating) about your products, articles, etc. This replaces the default comments system.', 'fw' ),
|
149 |
'thumbnail' => $thumbnails_uri . '/feedback.jpg',
|
150 |
'download' => array(
|
151 |
-
'
|
|
|
152 |
'user_repo' => $github_account . '/Unyson-Feedback-Extension',
|
153 |
),
|
154 |
),
|
155 |
),
|
|
|
156 |
'learning' => array(
|
157 |
'display' => true,
|
158 |
'parent' => null,
|
@@ -160,11 +184,13 @@ $extensions = array(
|
|
160 |
'description' => __( 'This extension adds a Learning module to your theme. Using this extension you can add courses, lessons and tests for your users to take.', 'fw' ),
|
161 |
'thumbnail' => $thumbnails_uri . '/learning.jpg',
|
162 |
'download' => array(
|
163 |
-
'
|
|
|
164 |
'user_repo' => $github_account . '/Unyson-Learning-Extension',
|
165 |
),
|
166 |
),
|
167 |
),
|
|
|
168 |
'shortcodes' => array(
|
169 |
'display' => false,
|
170 |
'parent' => null,
|
@@ -172,11 +198,13 @@ $extensions = array(
|
|
172 |
'description' => '',
|
173 |
'thumbnail' => 'about:blank',
|
174 |
'download' => array(
|
175 |
-
'
|
|
|
176 |
'user_repo' => $github_account . '/Unyson-Shortcodes-Extension',
|
177 |
),
|
178 |
),
|
179 |
),
|
|
|
180 |
'builder' => array(
|
181 |
'display' => false,
|
182 |
'parent' => null,
|
@@ -184,11 +212,13 @@ $extensions = array(
|
|
184 |
'description' => '',
|
185 |
'thumbnail' => 'about:blank',
|
186 |
'download' => array(
|
187 |
-
'
|
|
|
188 |
'user_repo' => $github_account . '/Unyson-Builder-Extension',
|
189 |
),
|
190 |
),
|
191 |
),
|
|
|
192 |
'forms' => array(
|
193 |
'display' => false,
|
194 |
'parent' => null,
|
@@ -196,11 +226,13 @@ $extensions = array(
|
|
196 |
'description' => __( 'This extension adds the possibility to create a contact form. Use the drag & drop form builder to create any contact form you\'ll ever want or need.', 'fw' ),
|
197 |
'thumbnail' => $thumbnails_uri . '/forms.jpg',
|
198 |
'download' => array(
|
199 |
-
'
|
|
|
200 |
'user_repo' => $github_account . '/Unyson-Forms-Extension',
|
201 |
),
|
202 |
),
|
203 |
),
|
|
|
204 |
'mailer' => array(
|
205 |
'display' => false,
|
206 |
'parent' => null,
|
@@ -208,11 +240,13 @@ $extensions = array(
|
|
208 |
'description' => __( 'This extension will let you set some global email options and it is used by other extensions (like Forms) to send emails.', 'fw' ),
|
209 |
'thumbnail' => $thumbnails_uri . '/mailer.jpg',
|
210 |
'download' => array(
|
211 |
-
'
|
|
|
212 |
'user_repo' => $github_account . '/Unyson-Mailer-Extension',
|
213 |
),
|
214 |
),
|
215 |
),
|
|
|
216 |
'social' => array(
|
217 |
'display' => true,
|
218 |
'parent' => null,
|
@@ -220,11 +254,13 @@ $extensions = array(
|
|
220 |
'description' => __( 'Use this extension to configure all your social related APIs. Other extensions will use the Social extension to connect to your social accounts.', 'fw' ),
|
221 |
'thumbnail' => $thumbnails_uri . '/social.jpg',
|
222 |
'download' => array(
|
223 |
-
'
|
|
|
224 |
'user_repo' => $github_account . '/Unyson-Social-Extension',
|
225 |
),
|
226 |
),
|
227 |
),
|
|
|
228 |
'backup' => array(
|
229 |
'display' => true,
|
230 |
'parent' => null,
|
@@ -232,11 +268,13 @@ $extensions = array(
|
|
232 |
'description' => __( 'This extension lets you set up daily, weekly or monthly backup schedule. You can choose between a full backup or a data base only backup.', 'fw' ),
|
233 |
'thumbnail' => $thumbnails_uri . '/backup.jpg',
|
234 |
'download' => array(
|
235 |
-
'
|
|
|
236 |
'user_repo' => $github_account . '/Unyson-Backup-Extension',
|
237 |
),
|
238 |
),
|
239 |
),
|
|
|
240 |
'media' => array(
|
241 |
'display' => false,
|
242 |
'parent' => null,
|
@@ -244,11 +282,13 @@ $extensions = array(
|
|
244 |
'description' => '',
|
245 |
'thumbnail' => 'about:blank',
|
246 |
'download' => array(
|
247 |
-
'
|
|
|
248 |
'user_repo' => $github_account . '/Unyson-Empty-Extension',
|
249 |
),
|
250 |
),
|
251 |
),
|
|
|
252 |
'population-method' => array(
|
253 |
'display' => false,
|
254 |
'parent' => 'media',
|
@@ -256,11 +296,13 @@ $extensions = array(
|
|
256 |
'description' => '',
|
257 |
'thumbnail' => 'about:blank',
|
258 |
'download' => array(
|
259 |
-
'
|
|
|
260 |
'user_repo' => $github_account . '/Unyson-PopulationMethods-Extension',
|
261 |
),
|
262 |
),
|
263 |
),
|
|
|
264 |
'styling' => array(
|
265 |
'display' => true,
|
266 |
'parent' => null,
|
@@ -268,11 +310,13 @@ $extensions = array(
|
|
268 |
'description' => __( 'This extension lets you control the website visual style. Starting from predefined styles to changing specific fonts and colors across the website.', 'fw' ),
|
269 |
'thumbnail' => $thumbnails_uri . '/styling.jpg',
|
270 |
'download' => array(
|
271 |
-
'
|
|
|
272 |
'user_repo' => $github_account . '/Unyson-Styling-Extension',
|
273 |
),
|
274 |
),
|
275 |
),
|
|
|
276 |
'translation' => array(
|
277 |
'display' => true,
|
278 |
'parent' => null,
|
@@ -280,9 +324,11 @@ $extensions = array(
|
|
280 |
'description' => __( 'This extension lets you translate your website in any language or even add multiple languages for your users to change at their will from the front-end.', 'fw' ),
|
281 |
'thumbnail' => $thumbnails_uri . '/translation.jpg',
|
282 |
'download' => array(
|
283 |
-
'
|
|
|
284 |
'user_repo' => $github_account . '/Unyson-Translation-Extension',
|
285 |
-
)
|
286 |
),
|
287 |
),
|
288 |
);
|
|
13 |
'description' => __( "Let's you easily build countless pages with the help of the drag and drop visual page builder that comes with a lot of already created shortcodes.", 'fw' ),
|
14 |
'thumbnail' => $thumbnails_uri . '/page-builder.jpg',
|
15 |
'download' => array(
|
16 |
+
'source' => 'github',
|
17 |
+
'opts' => array(
|
18 |
+
'user_repo' => $github_account . '/Unyson-PageBuilder-Extension'
|
19 |
+
)
|
20 |
),
|
21 |
),
|
22 |
+
|
23 |
'wp-shortcodes' => array(
|
24 |
'display' => true,
|
25 |
'parent' => 'shortcodes',
|
30 |
),
|
31 |
'thumbnail' => $thumbnails_uri . '/wp-shortcodes.jpg',
|
32 |
'download' => array(
|
33 |
+
'source' => 'github',
|
34 |
+
'opts' => array(
|
35 |
'user_repo' => 'ThemeFuse/Unyson-WP-Shortcodes-Extension',
|
36 |
),
|
37 |
),
|
38 |
),
|
39 |
+
|
40 |
'backups' => array(
|
41 |
'display' => true,
|
42 |
'parent' => null,
|
44 |
'description' => __( 'This extension lets you create an automated backup schedule, import demo content or even create a demo content archive for migration purposes.', 'fw' ),
|
45 |
'thumbnail' => $thumbnails_uri . '/backups.jpg',
|
46 |
'download' => array(
|
47 |
+
'source' => 'github',
|
48 |
+
'opts' => array(
|
49 |
'user_repo' => $github_account . '/Unyson-Backups-Extension',
|
50 |
),
|
51 |
),
|
52 |
),
|
53 |
+
|
54 |
'sidebars' => array(
|
55 |
'display' => true,
|
56 |
'parent' => null,
|
58 |
'description' => __( 'Brings a new layer of customization freedom to your website by letting you add more than one sidebar to a page, or different sidebars on different pages.', 'fw' ),
|
59 |
'thumbnail' => $thumbnails_uri . '/sidebars.jpg',
|
60 |
'download' => array(
|
61 |
+
'source' => 'github',
|
62 |
+
'opts' => array(
|
63 |
'user_repo' => $github_account . '/Unyson-Sidebars-Extension',
|
64 |
),
|
65 |
),
|
66 |
),
|
67 |
+
|
68 |
'slider' => array(
|
69 |
'display' => true,
|
70 |
'parent' => 'media',
|
72 |
'description' => __( 'Adds a sliders module to your website from where you\'ll be able to create different built in jQuery sliders for your homepage and rest of the pages.', 'fw' ),
|
73 |
'thumbnail' => $thumbnails_uri . '/sliders.jpg',
|
74 |
'download' => array(
|
75 |
+
'source' => 'github',
|
76 |
+
'opts' => array(
|
77 |
'user_repo' => $github_account . '/Unyson-Sliders-Extension',
|
78 |
),
|
79 |
),
|
80 |
),
|
81 |
+
|
82 |
'portfolio' => array(
|
83 |
'display' => true,
|
84 |
'parent' => null,
|
86 |
'description' => __( 'This extension will add a fully fledged portfolio module that will let you display your projects using the built in portfolio pages.', 'fw' ),
|
87 |
'thumbnail' => $thumbnails_uri . '/portfolio.jpg',
|
88 |
'download' => array(
|
89 |
+
'source' => 'github',
|
90 |
+
'opts' => array(
|
91 |
'user_repo' => $github_account . '/Unyson-Portfolio-Extension',
|
92 |
),
|
93 |
),
|
94 |
),
|
95 |
+
|
96 |
'megamenu' => array(
|
97 |
'display' => true,
|
98 |
'parent' => null,
|
100 |
'description' => __( 'The Mega Menu extension adds a user-friendly drop down menu that will let you easily create highly customized menu configurations.', 'fw' ),
|
101 |
'thumbnail' => $thumbnails_uri . '/mega-menu.jpg',
|
102 |
'download' => array(
|
103 |
+
'source' => 'github',
|
104 |
+
'opts' => array(
|
105 |
'user_repo' => $github_account . '/Unyson-MegaMenu-Extension',
|
106 |
),
|
107 |
),
|
108 |
),
|
109 |
+
|
110 |
'breadcrumbs' => array(
|
111 |
'display' => true,
|
112 |
'parent' => null,
|
114 |
'description' => __( 'Creates a simplified navigation menu for the pages that can be placed anywhere in the theme. This will make navigating the website much easier.', 'fw' ),
|
115 |
'thumbnail' => $thumbnails_uri . '/breadcrumbs.jpg',
|
116 |
'download' => array(
|
117 |
+
'source' => 'github',
|
118 |
+
'opts' => array(
|
119 |
'user_repo' => $github_account . '/Unyson-Breadcrumbs-Extension',
|
120 |
),
|
121 |
),
|
122 |
),
|
123 |
+
|
124 |
'seo' => array(
|
125 |
'display' => true,
|
126 |
'parent' => null,
|
128 |
'description' => __( 'This extension will enable you to have a fully optimized WordPress website by adding optimized meta titles, keywords and descriptions.', 'fw' ),
|
129 |
'thumbnail' => $thumbnails_uri . '/seo.jpg',
|
130 |
'download' => array(
|
131 |
+
'source' => 'github',
|
132 |
+
'opts' => array(
|
133 |
'user_repo' => $github_account . '/Unyson-SEO-Extension',
|
134 |
),
|
135 |
),
|
136 |
),
|
137 |
+
|
138 |
'events' => array(
|
139 |
'display' => true,
|
140 |
'parent' => null,
|
142 |
'description' => __( 'This extension adds a fully fledged Events module to your theme. It comes with built in pages that contain a calendar where events can be added.', 'fw' ),
|
143 |
'thumbnail' => $thumbnails_uri . '/events.jpg',
|
144 |
'download' => array(
|
145 |
+
'source' => 'github',
|
146 |
+
'opts' => array(
|
147 |
'user_repo' => $github_account . '/Unyson-Events-Extension',
|
148 |
),
|
149 |
),
|
150 |
),
|
151 |
+
|
152 |
'analytics' => array(
|
153 |
'display' => true,
|
154 |
'parent' => null,
|
156 |
'description' => __( 'Enables the possibility to add the Google Analytics tracking code that will let you get all the analytics about visitors, page views and more.', 'fw' ),
|
157 |
'thumbnail' => $thumbnails_uri . '/analytics.jpg',
|
158 |
'download' => array(
|
159 |
+
'source' => 'github',
|
160 |
+
'opts' => array(
|
161 |
'user_repo' => $github_account . '/Unyson-Analytics-Extension',
|
162 |
),
|
163 |
),
|
164 |
),
|
165 |
+
|
166 |
'feedback' => array(
|
167 |
'display' => true,
|
168 |
'parent' => null,
|
170 |
'description' => __( 'Adds the possibility to leave feedback (comments, reviews and rating) about your products, articles, etc. This replaces the default comments system.', 'fw' ),
|
171 |
'thumbnail' => $thumbnails_uri . '/feedback.jpg',
|
172 |
'download' => array(
|
173 |
+
'source' => 'github',
|
174 |
+
'opts' => array(
|
175 |
'user_repo' => $github_account . '/Unyson-Feedback-Extension',
|
176 |
),
|
177 |
),
|
178 |
),
|
179 |
+
|
180 |
'learning' => array(
|
181 |
'display' => true,
|
182 |
'parent' => null,
|
184 |
'description' => __( 'This extension adds a Learning module to your theme. Using this extension you can add courses, lessons and tests for your users to take.', 'fw' ),
|
185 |
'thumbnail' => $thumbnails_uri . '/learning.jpg',
|
186 |
'download' => array(
|
187 |
+
'source' => 'github',
|
188 |
+
'opts' => array(
|
189 |
'user_repo' => $github_account . '/Unyson-Learning-Extension',
|
190 |
),
|
191 |
),
|
192 |
),
|
193 |
+
|
194 |
'shortcodes' => array(
|
195 |
'display' => false,
|
196 |
'parent' => null,
|
198 |
'description' => '',
|
199 |
'thumbnail' => 'about:blank',
|
200 |
'download' => array(
|
201 |
+
'source' => 'github',
|
202 |
+
'opts' => array(
|
203 |
'user_repo' => $github_account . '/Unyson-Shortcodes-Extension',
|
204 |
),
|
205 |
),
|
206 |
),
|
207 |
+
|
208 |
'builder' => array(
|
209 |
'display' => false,
|
210 |
'parent' => null,
|
212 |
'description' => '',
|
213 |
'thumbnail' => 'about:blank',
|
214 |
'download' => array(
|
215 |
+
'source' => 'github',
|
216 |
+
'opts' => array(
|
217 |
'user_repo' => $github_account . '/Unyson-Builder-Extension',
|
218 |
),
|
219 |
),
|
220 |
),
|
221 |
+
|
222 |
'forms' => array(
|
223 |
'display' => false,
|
224 |
'parent' => null,
|
226 |
'description' => __( 'This extension adds the possibility to create a contact form. Use the drag & drop form builder to create any contact form you\'ll ever want or need.', 'fw' ),
|
227 |
'thumbnail' => $thumbnails_uri . '/forms.jpg',
|
228 |
'download' => array(
|
229 |
+
'source' => 'github',
|
230 |
+
'opts' => array(
|
231 |
'user_repo' => $github_account . '/Unyson-Forms-Extension',
|
232 |
),
|
233 |
),
|
234 |
),
|
235 |
+
|
236 |
'mailer' => array(
|
237 |
'display' => false,
|
238 |
'parent' => null,
|
240 |
'description' => __( 'This extension will let you set some global email options and it is used by other extensions (like Forms) to send emails.', 'fw' ),
|
241 |
'thumbnail' => $thumbnails_uri . '/mailer.jpg',
|
242 |
'download' => array(
|
243 |
+
'source' => 'github',
|
244 |
+
'opts' => array(
|
245 |
'user_repo' => $github_account . '/Unyson-Mailer-Extension',
|
246 |
),
|
247 |
),
|
248 |
),
|
249 |
+
|
250 |
'social' => array(
|
251 |
'display' => true,
|
252 |
'parent' => null,
|
254 |
'description' => __( 'Use this extension to configure all your social related APIs. Other extensions will use the Social extension to connect to your social accounts.', 'fw' ),
|
255 |
'thumbnail' => $thumbnails_uri . '/social.jpg',
|
256 |
'download' => array(
|
257 |
+
'source' => 'github',
|
258 |
+
'opts' => array(
|
259 |
'user_repo' => $github_account . '/Unyson-Social-Extension',
|
260 |
),
|
261 |
),
|
262 |
),
|
263 |
+
|
264 |
'backup' => array(
|
265 |
'display' => true,
|
266 |
'parent' => null,
|
268 |
'description' => __( 'This extension lets you set up daily, weekly or monthly backup schedule. You can choose between a full backup or a data base only backup.', 'fw' ),
|
269 |
'thumbnail' => $thumbnails_uri . '/backup.jpg',
|
270 |
'download' => array(
|
271 |
+
'source' => 'github',
|
272 |
+
'opts' => array(
|
273 |
'user_repo' => $github_account . '/Unyson-Backup-Extension',
|
274 |
),
|
275 |
),
|
276 |
),
|
277 |
+
|
278 |
'media' => array(
|
279 |
'display' => false,
|
280 |
'parent' => null,
|
282 |
'description' => '',
|
283 |
'thumbnail' => 'about:blank',
|
284 |
'download' => array(
|
285 |
+
'source' => 'github',
|
286 |
+
'opts' => array(
|
287 |
'user_repo' => $github_account . '/Unyson-Empty-Extension',
|
288 |
),
|
289 |
),
|
290 |
),
|
291 |
+
|
292 |
'population-method' => array(
|
293 |
'display' => false,
|
294 |
'parent' => 'media',
|
296 |
'description' => '',
|
297 |
'thumbnail' => 'about:blank',
|
298 |
'download' => array(
|
299 |
+
'source' => 'github',
|
300 |
+
'opts' => array(
|
301 |
'user_repo' => $github_account . '/Unyson-PopulationMethods-Extension',
|
302 |
),
|
303 |
),
|
304 |
),
|
305 |
+
|
306 |
'styling' => array(
|
307 |
'display' => true,
|
308 |
'parent' => null,
|
310 |
'description' => __( 'This extension lets you control the website visual style. Starting from predefined styles to changing specific fonts and colors across the website.', 'fw' ),
|
311 |
'thumbnail' => $thumbnails_uri . '/styling.jpg',
|
312 |
'download' => array(
|
313 |
+
'source' => 'github',
|
314 |
+
'opts' => array(
|
315 |
'user_repo' => $github_account . '/Unyson-Styling-Extension',
|
316 |
),
|
317 |
),
|
318 |
),
|
319 |
+
|
320 |
'translation' => array(
|
321 |
'display' => true,
|
322 |
'parent' => null,
|
324 |
'description' => __( 'This extension lets you translate your website in any language or even add multiple languages for your users to change at their will from the front-end.', 'fw' ),
|
325 |
'thumbnail' => $thumbnails_uri . '/translation.jpg',
|
326 |
'download' => array(
|
327 |
+
'source' => 'github',
|
328 |
+
'opts' => array(
|
329 |
'user_repo' => $github_account . '/Unyson-Translation-Extension',
|
330 |
+
)
|
331 |
),
|
332 |
),
|
333 |
);
|
334 |
+
|
framework/core/components/extensions/manager/class--fw-extensions-manager.php
CHANGED
@@ -21,10 +21,21 @@ final class _FW_Extensions_Manager
|
|
21 |
'standalone' => false,
|
22 |
);
|
23 |
|
24 |
-
private $download_timeout = 300;
|
25 |
-
|
26 |
private $default_thumbnail = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2PUsHf9DwAC8AGtfm5YCAAAAABJRU5ErkJgggAA';
|
27 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
public function __construct()
|
29 |
{
|
30 |
// In any case/permission, make sure to not miss the plugin update actions to prevent extensions delete
|
@@ -33,6 +44,17 @@ final class _FW_Extensions_Manager
|
|
33 |
add_action('fw_plugin_post_update', array($this, '_action_plugin_post_update'));
|
34 |
}
|
35 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
36 |
if (!is_admin()) {
|
37 |
return;
|
38 |
}
|
@@ -191,9 +213,58 @@ final class _FW_Extensions_Manager
|
|
191 |
|
192 |
return FW_Cache::get($cache_key);
|
193 |
} catch (FW_Cache_Not_Found_Exception $e) {
|
194 |
-
$
|
195 |
-
'extensions'
|
196 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
197 |
|
198 |
{
|
199 |
$installed_extensions = $this->get_installed_extensions();
|
@@ -201,7 +272,7 @@ final class _FW_Extensions_Manager
|
|
201 |
|
202 |
if (isset($installed_extensions['backup'])) {
|
203 |
// make sure only Backup or Backups can be installed
|
204 |
-
unset($
|
205 |
}
|
206 |
|
207 |
foreach (
|
@@ -213,14 +284,14 @@ final class _FW_Extensions_Manager
|
|
213 |
&&
|
214 |
!isset($installed_extensions[$obsolete_extension])
|
215 |
) {
|
216 |
-
unset($
|
217 |
}
|
218 |
}
|
219 |
}
|
220 |
|
221 |
-
FW_Cache::set($cache_key, $
|
222 |
|
223 |
-
return $
|
224 |
}
|
225 |
}
|
226 |
|
@@ -816,7 +887,15 @@ final class _FW_Extensions_Manager
|
|
816 |
'display' => isset($ext_data['display'])
|
817 |
? $ext_data['display']
|
818 |
: $this->manifest_default_values['display'],
|
|
|
819 |
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
820 |
}
|
821 |
|
822 |
foreach (fw()->theme->manifest->get('supported_extensions', array()) as $required_ext_name => $required_ext_data) {
|
@@ -928,6 +1007,7 @@ final class _FW_Extensions_Manager
|
|
928 |
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
929 |
if (!isset($_POST[$nonce['name']]) || !wp_verify_nonce($_POST[$nonce['name']], $nonce['action'])) {
|
930 |
$skin->error(__('Invalid nonce.', 'fw'));
|
|
|
931 |
}
|
932 |
|
933 |
if (!FW_WP_Filesystem::request_access(
|
@@ -1142,14 +1222,22 @@ final class _FW_Extensions_Manager
|
|
1142 |
* Install parent extensions and the extension
|
1143 |
*/
|
1144 |
{
|
1145 |
-
$
|
|
|
|
|
|
|
|
|
1146 |
|
1147 |
foreach ($parents as $parent_extension_name) {
|
1148 |
$current_extension_path .= '/extensions/'. $parent_extension_name;
|
|
|
|
|
|
|
|
|
|
|
1149 |
|
1150 |
if (isset($installed_extensions[$parent_extension_name])) {
|
1151 |
-
// skip already installed extensions
|
1152 |
-
continue;
|
1153 |
}
|
1154 |
|
1155 |
if ($verbose) {
|
@@ -1210,7 +1298,9 @@ final class _FW_Extensions_Manager
|
|
1210 |
|
1211 |
$merge_result = $this->merge_extension(
|
1212 |
$wp_fw_downloaded_dir,
|
1213 |
-
FW_WP_Filesystem::real_path_to_filesystem_path(
|
|
|
|
|
1214 |
);
|
1215 |
|
1216 |
if (is_wp_error($merge_result)) {
|
@@ -1425,6 +1515,7 @@ final class _FW_Extensions_Manager
|
|
1425 |
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
1426 |
if (!isset($_POST[$nonce['name']]) || !wp_verify_nonce($_POST[$nonce['name']], $nonce['action'])) {
|
1427 |
$skin->error(__('Invalid nonce.', 'fw'));
|
|
|
1428 |
}
|
1429 |
|
1430 |
if (!FW_WP_Filesystem::request_access(
|
@@ -2352,7 +2443,7 @@ final class _FW_Extensions_Manager
|
|
2352 |
/**
|
2353 |
* Download an extension
|
2354 |
*
|
2355 |
-
* global $wp_filesystem; must
|
2356 |
*
|
2357 |
* @param string $extension_name
|
2358 |
* @param array $data Extension data from the "available extensions" array
|
@@ -2362,6 +2453,7 @@ final class _FW_Extensions_Manager
|
|
2362 |
{
|
2363 |
$wp_error_id = 'fw_extension_download';
|
2364 |
|
|
|
2365 |
if (empty($data['download'])) {
|
2366 |
return new WP_Error(
|
2367 |
$wp_error_id,
|
@@ -2394,220 +2486,103 @@ final class _FW_Extensions_Manager
|
|
2394 |
}
|
2395 |
}
|
2396 |
|
2397 |
-
|
2398 |
-
|
2399 |
-
foreach ($data['download'] as $source => $source_data) {
|
2400 |
-
switch ($source) {
|
2401 |
-
case 'github':
|
2402 |
-
if (empty($source_data['user_repo'])) {
|
2403 |
-
return new WP_Error(
|
2404 |
-
$wp_error_id,
|
2405 |
-
sprintf(__('"%s" extension github source "user_repo" parameter is required', 'fw'), $this->get_extension_title($extension_name))
|
2406 |
-
);
|
2407 |
-
}
|
2408 |
-
|
2409 |
-
{
|
2410 |
-
$transient_name = 'fw_ext_mngr_gh_dl';
|
2411 |
-
$transient_ttl = HOUR_IN_SECONDS;
|
2412 |
|
2413 |
-
|
2414 |
|
2415 |
-
|
2416 |
-
$cache = array();
|
2417 |
-
}
|
2418 |
-
}
|
2419 |
|
2420 |
-
|
2421 |
-
|
2422 |
-
|
2423 |
-
|
2424 |
-
|
2425 |
-
|
2426 |
-
|
2427 |
-
|
2428 |
-
isset($theme_ext_requirements[$extension_name]['max_version'])
|
2429 |
-
) {
|
2430 |
-
$tag = 'tags/v'. $theme_ext_requirements[$extension_name]['max_version'];
|
2431 |
-
} else {
|
2432 |
-
$tag = 'latest';
|
2433 |
-
}
|
2434 |
-
|
2435 |
-
$response = $http->get(
|
2436 |
-
apply_filters('fw_github_api_url', 'https://api.github.com')
|
2437 |
-
. '/repos/'. $source_data['user_repo'] .'/releases/'. $tag
|
2438 |
-
);
|
2439 |
-
|
2440 |
-
unset($http);
|
2441 |
-
|
2442 |
-
$response_code = intval(wp_remote_retrieve_response_code($response));
|
2443 |
-
|
2444 |
-
if ($response_code !== 200) {
|
2445 |
-
if ($response_code === 403) {
|
2446 |
-
if ($json_response = json_decode($response['body'], true)) {
|
2447 |
-
return new WP_Error(
|
2448 |
-
$wp_error_id,
|
2449 |
-
__('Github error:', 'fw') .' '. $json_response['message']
|
2450 |
-
);
|
2451 |
-
} else {
|
2452 |
-
return new WP_Error(
|
2453 |
-
$wp_error_id,
|
2454 |
-
sprintf(
|
2455 |
-
__( 'Failed to access Github repository "%s" releases. (Response code: %d)', 'fw' ),
|
2456 |
-
$source_data['user_repo'], $response_code
|
2457 |
-
)
|
2458 |
-
);
|
2459 |
-
}
|
2460 |
-
} elseif ($response_code) {
|
2461 |
-
return new WP_Error(
|
2462 |
-
$wp_error_id,
|
2463 |
-
sprintf(
|
2464 |
-
__( 'Failed to access Github repository "%s" releases. (Response code: %d)', 'fw' ),
|
2465 |
-
$source_data['user_repo'], $response_code
|
2466 |
-
)
|
2467 |
-
);
|
2468 |
-
} elseif (is_wp_error($response)) {
|
2469 |
-
return new WP_Error(
|
2470 |
-
$wp_error_id,
|
2471 |
-
sprintf(
|
2472 |
-
__( 'Failed to access Github repository "%s" releases. (%s)', 'fw' ),
|
2473 |
-
$source_data['user_repo'], $response->get_error_message()
|
2474 |
-
)
|
2475 |
-
);
|
2476 |
-
} else {
|
2477 |
-
return new WP_Error(
|
2478 |
-
$wp_error_id,
|
2479 |
-
sprintf(
|
2480 |
-
__( 'Failed to access Github repository "%s" releases.', 'fw' ),
|
2481 |
-
$source_data['user_repo']
|
2482 |
-
)
|
2483 |
-
);
|
2484 |
-
}
|
2485 |
-
}
|
2486 |
-
|
2487 |
-
$release = json_decode($response['body'], true);
|
2488 |
-
|
2489 |
-
unset($response);
|
2490 |
-
|
2491 |
-
if (empty($release)) {
|
2492 |
-
return new WP_Error(
|
2493 |
-
$wp_error_id,
|
2494 |
-
sprintf(
|
2495 |
-
__('"%s" extension github repository "%s" has no releases.', 'fw'),
|
2496 |
-
$this->get_extension_title($extension_name), $source_data['user_repo']
|
2497 |
-
)
|
2498 |
-
);
|
2499 |
-
}
|
2500 |
|
2501 |
-
|
2502 |
-
|
2503 |
-
|
2504 |
-
'tag_name' => $release['tag_name']
|
2505 |
-
);
|
2506 |
|
2507 |
-
|
2508 |
-
|
|
|
|
|
|
|
|
|
2509 |
|
2510 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2511 |
|
2512 |
-
|
2513 |
-
|
|
|
2514 |
|
2515 |
-
|
2516 |
-
|
2517 |
-
|
2518 |
-
$response = $http->request($download_link, array(
|
2519 |
-
'timeout' => $this->download_timeout,
|
2520 |
-
));
|
2521 |
-
|
2522 |
-
unset($http);
|
2523 |
-
|
2524 |
-
if (($response_code = intval(wp_remote_retrieve_response_code($response))) !== 200) {
|
2525 |
-
if ($response_code) {
|
2526 |
-
return new WP_Error(
|
2527 |
-
$wp_error_id,
|
2528 |
-
sprintf( __( 'Cannot download the "%s" extension zip. (Response code: %d)', 'fw' ),
|
2529 |
-
$this->get_extension_title( $extension_name ), $response_code
|
2530 |
-
)
|
2531 |
-
);
|
2532 |
-
} elseif (is_wp_error($response)) {
|
2533 |
-
return new WP_Error(
|
2534 |
-
$wp_error_id,
|
2535 |
-
sprintf( __( 'Cannot download the "%s" extension zip. %s', 'fw' ),
|
2536 |
-
$this->get_extension_title( $extension_name ),
|
2537 |
-
$response->get_error_message()
|
2538 |
-
)
|
2539 |
-
);
|
2540 |
-
} else {
|
2541 |
-
return new WP_Error(
|
2542 |
-
$wp_error_id,
|
2543 |
-
sprintf( __( 'Cannot download the "%s" extension zip.', 'fw' ),
|
2544 |
-
$this->get_extension_title( $extension_name )
|
2545 |
-
)
|
2546 |
-
);
|
2547 |
-
}
|
2548 |
-
}
|
2549 |
|
2550 |
-
|
2551 |
|
2552 |
-
|
2553 |
-
if (!$wp_filesystem->put_contents($zip_path, $response['body'])) {
|
2554 |
-
return new WP_Error(
|
2555 |
-
$wp_error_id,
|
2556 |
-
sprintf(__('Cannot save the "%s" extension zip.', 'fw'), $this->get_extension_title($extension_name))
|
2557 |
-
);
|
2558 |
-
}
|
2559 |
|
2560 |
-
|
|
|
|
|
|
|
|
|
|
|
2561 |
|
2562 |
-
|
2563 |
-
FW_WP_Filesystem::filesystem_path_to_real_path($zip_path),
|
2564 |
-
$wp_fs_tmp_dir
|
2565 |
-
);
|
2566 |
|
2567 |
-
|
2568 |
-
|
2569 |
-
|
|
|
2570 |
|
2571 |
-
|
2572 |
-
|
2573 |
-
|
2574 |
-
$wp_error_id,
|
2575 |
-
sprintf(__('Cannot remove the "%s" extension downloaded zip.', 'fw'), $this->get_extension_title($extension_name))
|
2576 |
-
);
|
2577 |
-
}
|
2578 |
|
2579 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
2580 |
|
2581 |
-
|
2582 |
-
return new WP_Error(
|
2583 |
-
$wp_error_id,
|
2584 |
-
__('Cannot access the unzipped directory files.', 'fw')
|
2585 |
-
);
|
2586 |
-
}
|
2587 |
|
2588 |
-
|
2589 |
-
|
2590 |
-
|
2591 |
-
|
2592 |
-
|
2593 |
-
|
2594 |
-
return $wp_fs_tmp_dir .'/'. $file['name'];
|
2595 |
-
}
|
2596 |
-
}
|
2597 |
|
2598 |
-
|
2599 |
-
|
2600 |
-
|
2601 |
-
|
2602 |
-
|
2603 |
-
|
2604 |
-
|
2605 |
-
return new WP_Error(
|
2606 |
-
$wp_error_id,
|
2607 |
-
sprintf(__('Unknown "%s" extension download source "%s"', 'fw'), $this->get_extension_title($extension_name), $source)
|
2608 |
-
);
|
2609 |
}
|
2610 |
}
|
|
|
|
|
|
|
|
|
|
|
2611 |
}
|
2612 |
|
2613 |
/**
|
@@ -2625,18 +2600,20 @@ final class _FW_Extensions_Manager
|
|
2625 |
|
2626 |
$wp_error_id = 'fw_extensions_merge';
|
2627 |
|
2628 |
-
|
|
|
|
|
2629 |
|
2630 |
-
|
2631 |
-
|
2632 |
-
|
2633 |
-
|
2634 |
-
|
2635 |
-
|
2636 |
|
2637 |
-
|
2638 |
-
|
2639 |
-
|
2640 |
}
|
2641 |
|
2642 |
/**
|
@@ -2654,18 +2631,42 @@ final class _FW_Extensions_Manager
|
|
2654 |
}
|
2655 |
|
2656 |
if (!empty($destination_files)) {
|
2657 |
-
|
2658 |
-
|
2659 |
-
|
2660 |
-
|
2661 |
-
|
2662 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2663 |
|
2664 |
-
|
2665 |
-
|
2666 |
-
|
2667 |
-
|
2668 |
-
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2669 |
}
|
2670 |
}
|
2671 |
|
@@ -2680,28 +2681,30 @@ final class _FW_Extensions_Manager
|
|
2680 |
}
|
2681 |
}
|
2682 |
|
2683 |
-
|
|
|
|
|
2684 |
|
2685 |
-
|
2686 |
-
|
2687 |
-
|
2688 |
-
|
2689 |
-
|
2690 |
-
}
|
2691 |
|
2692 |
-
|
2693 |
-
|
2694 |
-
|
2695 |
-
|
2696 |
-
|
2697 |
-
|
2698 |
-
|
2699 |
-
|
2700 |
-
|
|
|
2701 |
}
|
2702 |
-
}
|
2703 |
|
2704 |
-
|
|
|
2705 |
|
2706 |
if (!$has_sub_extensions) {
|
2707 |
return;
|
@@ -2742,6 +2745,13 @@ final class _FW_Extensions_Manager
|
|
2742 |
{
|
2743 |
$supported_extensions = fw()->theme->manifest->get('supported_extensions', array());
|
2744 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2745 |
if (empty($supported_extensions)) {
|
2746 |
return array();
|
2747 |
}
|
@@ -3194,6 +3204,9 @@ final class _FW_Extensions_Manager
|
|
3194 |
return $extensions;
|
3195 |
}
|
3196 |
|
|
|
|
|
|
|
3197 |
public function _action_admin_notices() {
|
3198 |
/**
|
3199 |
* In v2.4.12 was done a terrible mistake https://github.com/ThemeFuse/Unyson-Extensions-Approval/issues/160
|
@@ -3216,4 +3229,226 @@ final class _FW_Extensions_Manager
|
|
3216 |
, '</p></div>';
|
3217 |
}
|
3218 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3219 |
}
|
21 |
'standalone' => false,
|
22 |
);
|
23 |
|
|
|
|
|
24 |
private $default_thumbnail = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2PUsHf9DwAC8AGtfm5YCAAAAABJRU5ErkJgggAA';
|
25 |
|
26 |
+
/**
|
27 |
+
* @var FW_Access_Key
|
28 |
+
*/
|
29 |
+
private static $access_key;
|
30 |
+
|
31 |
+
private static function get_access_key() {
|
32 |
+
if (!self::$access_key) {
|
33 |
+
self::$access_key = new FW_Access_Key('fw_ext_manager');
|
34 |
+
}
|
35 |
+
|
36 |
+
return self::$access_key;
|
37 |
+
}
|
38 |
+
|
39 |
public function __construct()
|
40 |
{
|
41 |
// In any case/permission, make sure to not miss the plugin update actions to prevent extensions delete
|
44 |
add_action('fw_plugin_post_update', array($this, '_action_plugin_post_update'));
|
45 |
}
|
46 |
|
47 |
+
// Preserve {theme}/framework-customizations/theme/available-extensions.php
|
48 |
+
{
|
49 |
+
add_filter('upgrader_pre_install', array($this, '_filter_theme_available_extensions_copy'), 999, 2);
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Must be executed after
|
53 |
+
* https://github.com/WordPress/WordPress/blob/4.6/wp-admin/includes/class-theme-upgrader.php#L204-L205
|
54 |
+
*/
|
55 |
+
add_action('upgrader_process_complete', array($this, '_action_theme_available_extensions_restore'), 999, 2);
|
56 |
+
}
|
57 |
+
|
58 |
if (!is_admin()) {
|
59 |
return;
|
60 |
}
|
213 |
|
214 |
return FW_Cache::get($cache_key);
|
215 |
} catch (FW_Cache_Not_Found_Exception $e) {
|
216 |
+
$extensions = fw_get_variables_from_file(
|
217 |
+
dirname( __FILE__ ) . '/available-extensions.php',
|
218 |
+
array( 'extensions' => array() )
|
219 |
+
);
|
220 |
+
$extensions = $extensions['extensions'];
|
221 |
+
|
222 |
+
// Allow theme to register available extensions
|
223 |
+
if (file_exists(
|
224 |
+
$theme_available_ext_file = fw_fix_path(get_template_directory())
|
225 |
+
. fw_get_framework_customizations_dir_rel_path( '/theme/available-extensions.php' )
|
226 |
+
)) {
|
227 |
+
require_once dirname( __FILE__ ) . '/includes/available-ext/class--fw-available-extensions-register.php';
|
228 |
+
require_once dirname( __FILE__ ) . '/includes/available-ext/class-fw-available-extension.php';
|
229 |
+
|
230 |
+
$register = new _FW_Available_Extensions_Register(self::get_access_key()->get_key());
|
231 |
+
|
232 |
+
/**
|
233 |
+
* Usage:
|
234 |
+
* Create {theme}/framework-customizations/theme/available-extensions.php with the following contents:
|
235 |
+
* $extension = new FW_Available_Extension();
|
236 |
+
* $extension->set_...();
|
237 |
+
* $register->register($extension);
|
238 |
+
*/
|
239 |
+
fw_get_variables_from_file($theme_available_ext_file, array(), array('register' => $register));
|
240 |
+
|
241 |
+
foreach ($register->_get_types(self::$access_key) as $extension) {
|
242 |
+
/** @var FW_Available_Extension $extension */
|
243 |
+
if (isset($extensions[ $extension->get_name() ])) {
|
244 |
+
trigger_error(
|
245 |
+
'Overwriting default extension "'. $extension->get_name() .'" is not allowed',
|
246 |
+
E_USER_WARNING
|
247 |
+
);
|
248 |
+
continue;
|
249 |
+
} elseif (!$extension->is_valid()) {
|
250 |
+
trigger_error(
|
251 |
+
'Theme extension "'. $extension->get_name() .'" is not valid',
|
252 |
+
E_USER_WARNING
|
253 |
+
);
|
254 |
+
continue;
|
255 |
+
} else {
|
256 |
+
$extensions[ $extension->get_name() ] = array(
|
257 |
+
'theme' => true, // Registered by theme
|
258 |
+
'display' => $extension->get_display(),
|
259 |
+
'parent' => $extension->get_parent(),
|
260 |
+
'name' => $extension->get_title(),
|
261 |
+
'description' => $extension->get_description(),
|
262 |
+
'thumbnail' => $extension->get_thumbnail(),
|
263 |
+
'download' => $extension->get_download_source(),
|
264 |
+
);
|
265 |
+
}
|
266 |
+
}
|
267 |
+
}
|
268 |
|
269 |
{
|
270 |
$installed_extensions = $this->get_installed_extensions();
|
272 |
|
273 |
if (isset($installed_extensions['backup'])) {
|
274 |
// make sure only Backup or Backups can be installed
|
275 |
+
unset($extensions['backups']);
|
276 |
}
|
277 |
|
278 |
foreach (
|
284 |
&&
|
285 |
!isset($installed_extensions[$obsolete_extension])
|
286 |
) {
|
287 |
+
unset($extensions[$obsolete_extension]);
|
288 |
}
|
289 |
}
|
290 |
}
|
291 |
|
292 |
+
FW_Cache::set($cache_key, $extensions);
|
293 |
|
294 |
+
return $extensions;
|
295 |
}
|
296 |
}
|
297 |
|
887 |
'display' => isset($ext_data['display'])
|
888 |
? $ext_data['display']
|
889 |
: $this->manifest_default_values['display'],
|
890 |
+
'theme' => isset($ext_data['theme']) && $ext_data['theme'],
|
891 |
);
|
892 |
+
|
893 |
+
if ($lists['available'][$ext_name]['theme']) {
|
894 |
+
$lists['supported'][$ext_name] = array(
|
895 |
+
'name' => $lists['available'][$ext_name]['name'],
|
896 |
+
'description' => $lists['available'][$ext_name]['description'],
|
897 |
+
);
|
898 |
+
}
|
899 |
}
|
900 |
|
901 |
foreach (fw()->theme->manifest->get('supported_extensions', array()) as $required_ext_name => $required_ext_data) {
|
1007 |
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
1008 |
if (!isset($_POST[$nonce['name']]) || !wp_verify_nonce($_POST[$nonce['name']], $nonce['action'])) {
|
1009 |
$skin->error(__('Invalid nonce.', 'fw'));
|
1010 |
+
break;
|
1011 |
}
|
1012 |
|
1013 |
if (!FW_WP_Filesystem::request_access(
|
1222 |
* Install parent extensions and the extension
|
1223 |
*/
|
1224 |
{
|
1225 |
+
$destination_path = array(
|
1226 |
+
'framework' => fw_get_framework_directory(),
|
1227 |
+
'theme' => fw_fix_path(get_template_directory()) . fw_get_framework_customizations_dir_rel_path()
|
1228 |
+
);
|
1229 |
+
$current_extension_path = '';
|
1230 |
|
1231 |
foreach ($parents as $parent_extension_name) {
|
1232 |
$current_extension_path .= '/extensions/'. $parent_extension_name;
|
1233 |
+
$destination = (
|
1234 |
+
isset($available_extensions[$parent_extension_name]['theme'])
|
1235 |
+
&&
|
1236 |
+
$available_extensions[$parent_extension_name]['theme']
|
1237 |
+
) ? 'theme' : 'framework';
|
1238 |
|
1239 |
if (isset($installed_extensions[$parent_extension_name])) {
|
1240 |
+
continue; // skip already installed extensions
|
|
|
1241 |
}
|
1242 |
|
1243 |
if ($verbose) {
|
1298 |
|
1299 |
$merge_result = $this->merge_extension(
|
1300 |
$wp_fw_downloaded_dir,
|
1301 |
+
FW_WP_Filesystem::real_path_to_filesystem_path(
|
1302 |
+
$destination_path[$destination] . $current_extension_path
|
1303 |
+
)
|
1304 |
);
|
1305 |
|
1306 |
if (is_wp_error($merge_result)) {
|
1515 |
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
1516 |
if (!isset($_POST[$nonce['name']]) || !wp_verify_nonce($_POST[$nonce['name']], $nonce['action'])) {
|
1517 |
$skin->error(__('Invalid nonce.', 'fw'));
|
1518 |
+
break;
|
1519 |
}
|
1520 |
|
1521 |
if (!FW_WP_Filesystem::request_access(
|
2443 |
/**
|
2444 |
* Download an extension
|
2445 |
*
|
2446 |
+
* global $wp_filesystem; must be initialized
|
2447 |
*
|
2448 |
* @param string $extension_name
|
2449 |
* @param array $data Extension data from the "available extensions" array
|
2453 |
{
|
2454 |
$wp_error_id = 'fw_extension_download';
|
2455 |
|
2456 |
+
// TODO: more checks for $data['download']
|
2457 |
if (empty($data['download'])) {
|
2458 |
return new WP_Error(
|
2459 |
$wp_error_id,
|
2486 |
}
|
2487 |
}
|
2488 |
|
2489 |
+
require_once dirname( __FILE__ ) . '/includes/download-source/class--fw-ext-download-source.php';
|
2490 |
+
require_once dirname( __FILE__ ) . '/includes/download-source/class--fw-ext-download-source-register.php';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2491 |
|
2492 |
+
require_once dirname( __FILE__ ) . '/includes/download-source/types/init.php';
|
2493 |
|
2494 |
+
$register = new _FW_Ext_Download_Source_Register(self::get_access_key()->get_key());
|
|
|
|
|
|
|
2495 |
|
2496 |
+
/**
|
2497 |
+
* Register download sources for extensions.
|
2498 |
+
*
|
2499 |
+
* Usage:
|
2500 |
+
* $download_source = new FW_Ext_Download_Source();
|
2501 |
+
* $register->register($download_source);
|
2502 |
+
*/
|
2503 |
+
do_action( 'fw_register_ext_download_sources', $register );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2504 |
|
2505 |
+
$download_source = $register->_get_type(
|
2506 |
+
self::get_access_key(), $data['download']['source']
|
2507 |
+
);
|
|
|
|
|
2508 |
|
2509 |
+
if (!$download_source) {
|
2510 |
+
return new WP_Error(
|
2511 |
+
'invalid_dl_source',
|
2512 |
+
sprintf(__('Invalid download source: %s', 'fw'), $data['download']['source'])
|
2513 |
+
);
|
2514 |
+
}
|
2515 |
|
2516 |
+
return $this->perform_zip_download(
|
2517 |
+
$download_source,
|
2518 |
+
array_merge(array(
|
2519 |
+
'extension_name' => $extension_name,
|
2520 |
+
'extension_title' => $this->get_extension_title($extension_name)
|
2521 |
+
), $data['download']['opts']),
|
2522 |
+
$wp_fs_tmp_dir
|
2523 |
+
);
|
2524 |
+
}
|
2525 |
|
2526 |
+
private function perform_zip_download(FW_Ext_Download_Source $download_source, array $opts, $wp_fs_tmp_dir)
|
2527 |
+
{
|
2528 |
+
$wp_error_id = 'fw_extension_download';
|
2529 |
|
2530 |
+
/** @var WP_Filesystem_Base $wp_filesystem */
|
2531 |
+
global $wp_filesystem;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2532 |
|
2533 |
+
$zip_path = $wp_fs_tmp_dir . '/temp.zip';
|
2534 |
|
2535 |
+
$download_result = $download_source->download($opts, $zip_path);
|
|
|
|
|
|
|
|
|
|
|
|
|
2536 |
|
2537 |
+
/**
|
2538 |
+
* Pass further the error, if the service returned one.
|
2539 |
+
*/
|
2540 |
+
if (is_wp_error($download_result)) {
|
2541 |
+
return $download_result;
|
2542 |
+
}
|
2543 |
|
2544 |
+
$extension_name = $opts['extension_name'];
|
|
|
|
|
|
|
2545 |
|
2546 |
+
$unzip_result = unzip_file(
|
2547 |
+
FW_WP_Filesystem::filesystem_path_to_real_path($zip_path),
|
2548 |
+
$wp_fs_tmp_dir
|
2549 |
+
);
|
2550 |
|
2551 |
+
if (is_wp_error($unzip_result)) {
|
2552 |
+
return $unzip_result;
|
2553 |
+
}
|
|
|
|
|
|
|
|
|
2554 |
|
2555 |
+
// remove zip file
|
2556 |
+
if (!$wp_filesystem->delete($zip_path, false, 'f')) {
|
2557 |
+
return new WP_Error(
|
2558 |
+
$wp_error_id,
|
2559 |
+
sprintf(__('Cannot remove the "%s" extension downloaded zip.', 'fw'), $this->get_extension_title($extension_name))
|
2560 |
+
);
|
2561 |
+
}
|
2562 |
|
2563 |
+
$unzipped_dir_files = $wp_filesystem->dirlist($wp_fs_tmp_dir);
|
|
|
|
|
|
|
|
|
|
|
2564 |
|
2565 |
+
if (!$unzipped_dir_files) {
|
2566 |
+
return new WP_Error(
|
2567 |
+
$wp_error_id,
|
2568 |
+
__('Cannot access the unzipped directory files.', 'fw')
|
2569 |
+
);
|
2570 |
+
}
|
|
|
|
|
|
|
2571 |
|
2572 |
+
/**
|
2573 |
+
* get first found directory
|
2574 |
+
* (if everything worked well, there should be only one directory)
|
2575 |
+
*/
|
2576 |
+
foreach ($unzipped_dir_files as $file) {
|
2577 |
+
if ($file['type'] == 'd') {
|
2578 |
+
return $wp_fs_tmp_dir .'/'. $file['name'];
|
|
|
|
|
|
|
|
|
2579 |
}
|
2580 |
}
|
2581 |
+
|
2582 |
+
return new WP_Error(
|
2583 |
+
$wp_error_id,
|
2584 |
+
sprintf(__('The unzipped "%s" extension directory not found.', 'fw'), $this->get_extension_title($extension_name))
|
2585 |
+
);
|
2586 |
}
|
2587 |
|
2588 |
/**
|
2600 |
|
2601 |
$wp_error_id = 'fw_extensions_merge';
|
2602 |
|
2603 |
+
// check source
|
2604 |
+
{
|
2605 |
+
$source_files = $wp_filesystem->dirlist($source_wp_fs_dir);
|
2606 |
|
2607 |
+
if ($source_files === false) {
|
2608 |
+
return new WP_Error(
|
2609 |
+
$wp_error_id,
|
2610 |
+
sprintf(__('Cannot read directory "%s".', 'fw'), $source_wp_fs_dir)
|
2611 |
+
);
|
2612 |
+
}
|
2613 |
|
2614 |
+
if (empty($source_files)) {
|
2615 |
+
return; // directory is empty, nothing to move
|
2616 |
+
}
|
2617 |
}
|
2618 |
|
2619 |
/**
|
2631 |
}
|
2632 |
|
2633 |
if (!empty($destination_files)) {
|
2634 |
+
if (
|
2635 |
+
count($source_files) == 1
|
2636 |
+
&&
|
2637 |
+
($file = reset($source_files))
|
2638 |
+
&&
|
2639 |
+
$file['name'] === 'extensions'
|
2640 |
+
&&
|
2641 |
+
$file['type'] === 'd'
|
2642 |
+
) {
|
2643 |
+
/**
|
2644 |
+
* Source extension is empty
|
2645 |
+
* It happens when you merge a directory which contains child extensions
|
2646 |
+
* Do not delete current destination files, just go in the next child extensions level
|
2647 |
+
* Used by https://github.com/ThemeFuse/Unyson/issues/1874
|
2648 |
+
*/
|
2649 |
+
} else {
|
2650 |
+
// the directory contains some files, delete everything
|
2651 |
+
foreach ($destination_files as $file) {
|
2652 |
+
if ($file['name'] === 'extensions' && $file['type'] === 'd') {
|
2653 |
+
// do not touch the extensions/ directory
|
2654 |
+
continue;
|
2655 |
+
}
|
2656 |
|
2657 |
+
if (!$wp_filesystem->delete(
|
2658 |
+
$destination_wp_fs_dir .'/'. $file['name'],
|
2659 |
+
true,
|
2660 |
+
$file['type']
|
2661 |
+
)) {
|
2662 |
+
return new WP_Error(
|
2663 |
+
$wp_error_id,
|
2664 |
+
sprintf(
|
2665 |
+
__('Cannot delete "%s".', 'fw'),
|
2666 |
+
$destination_wp_fs_dir .'/'. $file['name']
|
2667 |
+
)
|
2668 |
+
);
|
2669 |
+
}
|
2670 |
}
|
2671 |
}
|
2672 |
|
2681 |
}
|
2682 |
}
|
2683 |
|
2684 |
+
// Move files from source to destination
|
2685 |
+
{
|
2686 |
+
$has_sub_extensions = false;
|
2687 |
|
2688 |
+
foreach ($source_files as $file) {
|
2689 |
+
if ($file['name'] === 'extensions' && $file['type'] === 'd') {
|
2690 |
+
$has_sub_extensions = true; // do not touch the extensions/ directory
|
2691 |
+
continue;
|
2692 |
+
}
|
|
|
2693 |
|
2694 |
+
if (!$wp_filesystem->move($source_wp_fs_dir .'/'. $file['name'], $destination_wp_fs_dir .'/'. $file['name'])) {
|
2695 |
+
return new WP_Error(
|
2696 |
+
$wp_error_id,
|
2697 |
+
sprintf(
|
2698 |
+
__('Cannot move "%s" to "%s".', 'fw'),
|
2699 |
+
$source_wp_fs_dir .'/'. $file['name'],
|
2700 |
+
$destination_wp_fs_dir .'/'. $file['name']
|
2701 |
+
)
|
2702 |
+
);
|
2703 |
+
}
|
2704 |
}
|
|
|
2705 |
|
2706 |
+
unset($source_files);
|
2707 |
+
}
|
2708 |
|
2709 |
if (!$has_sub_extensions) {
|
2710 |
return;
|
2745 |
{
|
2746 |
$supported_extensions = fw()->theme->manifest->get('supported_extensions', array());
|
2747 |
|
2748 |
+
// Add Available Extensions registered by the theme
|
2749 |
+
foreach ($this->get_available_extensions() as $name => $extension) {
|
2750 |
+
if (isset($extension['theme']) && $extension['theme']) {
|
2751 |
+
$supported_extensions[$name] = array();
|
2752 |
+
}
|
2753 |
+
}
|
2754 |
+
|
2755 |
if (empty($supported_extensions)) {
|
2756 |
return array();
|
2757 |
}
|
3204 |
return $extensions;
|
3205 |
}
|
3206 |
|
3207 |
+
/**
|
3208 |
+
* @internal
|
3209 |
+
*/
|
3210 |
public function _action_admin_notices() {
|
3211 |
/**
|
3212 |
* In v2.4.12 was done a terrible mistake https://github.com/ThemeFuse/Unyson-Extensions-Approval/issues/160
|
3229 |
, '</p></div>';
|
3230 |
}
|
3231 |
}
|
3232 |
+
|
3233 |
+
/**
|
3234 |
+
* Copy Theme Available Extensions to a tmp directory
|
3235 |
+
* Used before theme update
|
3236 |
+
* @since 2.6.0
|
3237 |
+
* @return null|WP_Error
|
3238 |
+
*/
|
3239 |
+
public function theme_available_extensions_copy() {
|
3240 |
+
/** @var WP_Filesystem_Base $wp_filesystem */
|
3241 |
+
global $wp_filesystem;
|
3242 |
+
|
3243 |
+
if (!$wp_filesystem || (is_wp_error($wp_filesystem->errors) && $wp_filesystem->errors->get_error_code())) {
|
3244 |
+
return new WP_Error(
|
3245 |
+
'fs_not_initialized',
|
3246 |
+
__('WP Filesystem is not initialized', 'fw')
|
3247 |
+
);
|
3248 |
+
}
|
3249 |
+
|
3250 |
+
// Prepare temporary directory
|
3251 |
+
{
|
3252 |
+
$wpfs_tmp_dir = FW_WP_Filesystem::real_path_to_filesystem_path(
|
3253 |
+
$this->get_tmp_dir('/theme-ext')
|
3254 |
+
);
|
3255 |
+
|
3256 |
+
if (
|
3257 |
+
$wp_filesystem->exists( $wpfs_tmp_dir )
|
3258 |
+
&&
|
3259 |
+
! $wp_filesystem->rmdir( $wpfs_tmp_dir, true )
|
3260 |
+
) {
|
3261 |
+
return new WP_Error(
|
3262 |
+
'tmp_dir_rm_fail',
|
3263 |
+
sprintf(__('Temporary directory cannot be removed: %s', 'fw'), $wpfs_tmp_dir)
|
3264 |
+
);
|
3265 |
+
}
|
3266 |
+
|
3267 |
+
if ( ! FW_WP_Filesystem::mkdir_recursive( $wpfs_tmp_dir ) ) {
|
3268 |
+
return new WP_Error(
|
3269 |
+
'tmp_dir_rm_fail',
|
3270 |
+
sprintf(__('Temporary directory cannot be created: %s', 'fw'), $wpfs_tmp_dir)
|
3271 |
+
);
|
3272 |
+
}
|
3273 |
+
}
|
3274 |
+
|
3275 |
+
$available_extensions = $this->get_available_extensions();
|
3276 |
+
$installed_extensions = $this->get_installed_extensions(true);
|
3277 |
+
$base_dir = fw_get_template_customizations_directory('/extensions');
|
3278 |
+
|
3279 |
+
foreach ($installed_extensions as $name => $ext) {
|
3280 |
+
if ( ! (
|
3281 |
+
isset($available_extensions[$name])
|
3282 |
+
&&
|
3283 |
+
isset($available_extensions[$name]['theme'])
|
3284 |
+
&&
|
3285 |
+
$available_extensions[$name]['theme']
|
3286 |
+
) ) {
|
3287 |
+
continue;
|
3288 |
+
}
|
3289 |
+
|
3290 |
+
if ( ($rel_path = preg_replace('/^'. preg_quote($base_dir, '/') .'/', '', $ext['path'])) === $base_dir ) {
|
3291 |
+
return new WP_Error(
|
3292 |
+
'rel_path_failed',
|
3293 |
+
sprintf(__('Failed to extract relative directory from: %s', 'fw'), $ext['path'])
|
3294 |
+
);
|
3295 |
+
}
|
3296 |
+
|
3297 |
+
if ( ($wpfs_path = FW_WP_Filesystem::real_path_to_filesystem_path($ext['path'])) === false) {
|
3298 |
+
return new WP_Error(
|
3299 |
+
'real_to_wpfs_filed',
|
3300 |
+
sprintf(__('Failed to extract relative directory from: %s', 'fw'), $ext['path'])
|
3301 |
+
);
|
3302 |
+
}
|
3303 |
+
|
3304 |
+
$wpfs_dest_dir = $wpfs_tmp_dir . $rel_path;
|
3305 |
+
|
3306 |
+
if ( ! FW_WP_Filesystem::mkdir_recursive($wpfs_dest_dir) ) {
|
3307 |
+
return new WP_Error(
|
3308 |
+
'dest_dir_mk_fail',
|
3309 |
+
sprintf(__('Failed to create directory %s', 'fw'), $wpfs_dest_dir)
|
3310 |
+
);
|
3311 |
+
}
|
3312 |
+
|
3313 |
+
if ( is_wp_error( $copy_result = copy_dir($wpfs_path, $wpfs_dest_dir) ) ) {
|
3314 |
+
/** @var WP_Error $copy_result */
|
3315 |
+
return new WP_Error(
|
3316 |
+
'ext_copy_failed',
|
3317 |
+
sprintf( __('Failed to copy extension to %s', 'fw'), $wpfs_dest_dir )
|
3318 |
+
);
|
3319 |
+
}
|
3320 |
+
}
|
3321 |
+
}
|
3322 |
+
|
3323 |
+
/**
|
3324 |
+
* Copy Theme Available Extensions from tmp directory to theme
|
3325 |
+
* Used after theme update
|
3326 |
+
* @since 2.6.0
|
3327 |
+
* @return null|WP_Error
|
3328 |
+
*/
|
3329 |
+
public function theme_available_extensions_restore() {
|
3330 |
+
/** @var WP_Filesystem_Base $wp_filesystem */
|
3331 |
+
global $wp_filesystem;
|
3332 |
+
|
3333 |
+
if (!$wp_filesystem || (is_wp_error($wp_filesystem->errors) && $wp_filesystem->errors->get_error_code())) {
|
3334 |
+
return new WP_Error(
|
3335 |
+
'fs_not_initialized',
|
3336 |
+
__('WP Filesystem is not initialized', 'fw')
|
3337 |
+
);
|
3338 |
+
}
|
3339 |
+
|
3340 |
+
if ( ! $wp_filesystem->exists(
|
3341 |
+
$wpfs_tmp_dir = FW_WP_Filesystem::real_path_to_filesystem_path(
|
3342 |
+
$this->get_tmp_dir('/theme-ext')
|
3343 |
+
)
|
3344 |
+
) ) {
|
3345 |
+
return new WP_Error(
|
3346 |
+
'no_tmp_dir',
|
3347 |
+
sprintf(__('Temporary directory does not exist: %s', 'fw'), $wpfs_tmp_dir)
|
3348 |
+
);
|
3349 |
+
}
|
3350 |
+
|
3351 |
+
/**
|
3352 |
+
* Fixes the case when the theme path before update was
|
3353 |
+
* wp-content/themes/theme-name/theme-name-parent
|
3354 |
+
* but after update it became
|
3355 |
+
* wp-content/themes/theme-name-parent
|
3356 |
+
*
|
3357 |
+
* and at this point get_template_directory() returns old theme directory
|
3358 |
+
* so fw_get_template_customizations_directory() also returns old path
|
3359 |
+
*/
|
3360 |
+
$theme_dir = wp_get_theme()->get_theme_root() .'/'. wp_get_theme()->get_template();
|
3361 |
+
|
3362 |
+
if ( ! ($wpfs_base_dir = FW_WP_Filesystem::real_path_to_filesystem_path(
|
3363 |
+
$base_dir = $theme_dir . fw_get_framework_customizations_dir_rel_path('/extensions')
|
3364 |
+
) ) ) {
|
3365 |
+
return new WP_Error(
|
3366 |
+
'base_dir_to_wpfs_fail',
|
3367 |
+
sprintf( __('Cannot obtain WP Filesystem dir for %s', 'fw'), $base_dir )
|
3368 |
+
);
|
3369 |
+
}
|
3370 |
+
|
3371 |
+
if ( ! ( $dirlist = $wp_filesystem->dirlist($wpfs_tmp_dir) ) ) {
|
3372 |
+
return;
|
3373 |
+
}
|
3374 |
+
|
3375 |
+
foreach ( $dirlist as $filename => $fileinfo ) {
|
3376 |
+
if ( 'd' !== $fileinfo['type'] ) {
|
3377 |
+
continue;
|
3378 |
+
}
|
3379 |
+
|
3380 |
+
if ( is_wp_error($merge_result = $this->merge_extension(
|
3381 |
+
$wpfs_tmp_dir .'/'. $filename,
|
3382 |
+
$wpfs_base_dir .'/'. $filename
|
3383 |
+
)) ) {
|
3384 |
+
return $merge_result;
|
3385 |
+
}
|
3386 |
+
}
|
3387 |
+
|
3388 |
+
$wp_filesystem->rmdir( $wpfs_tmp_dir, true );
|
3389 |
+
}
|
3390 |
+
|
3391 |
+
/**
|
3392 |
+
* Copy Theme Available Extensions to tmp dir
|
3393 |
+
* @param bool|WP_Error $result
|
3394 |
+
* @param array $data
|
3395 |
+
*
|
3396 |
+
* @return bool|WP_Error
|
3397 |
+
*/
|
3398 |
+
public function _filter_theme_available_extensions_copy($result, $data) {
|
3399 |
+
if (
|
3400 |
+
!is_wp_error($result)
|
3401 |
+
&&
|
3402 |
+
is_array($data)
|
3403 |
+
&&
|
3404 |
+
isset($data['theme'])
|
3405 |
+
&&
|
3406 |
+
$data['theme'] === wp_get_theme()->get_template()
|
3407 |
+
) {
|
3408 |
+
if ( is_wp_error( $copy_result = fw()->extensions->manager->theme_available_extensions_copy() ) ) {
|
3409 |
+
return $copy_result;
|
3410 |
+
}
|
3411 |
+
}
|
3412 |
+
|
3413 |
+
return $result;
|
3414 |
+
}
|
3415 |
+
|
3416 |
+
/**
|
3417 |
+
* Restore Theme Available Extensions from tmp dir
|
3418 |
+
* @param Theme_Upgrader $instance
|
3419 |
+
* @param array $data
|
3420 |
+
*
|
3421 |
+
* @return bool|WP_Error
|
3422 |
+
*/
|
3423 |
+
public function _action_theme_available_extensions_restore($instance, $data) {
|
3424 |
+
if (
|
3425 |
+
!is_wp_error($instance->skin->result)
|
3426 |
+
&&
|
3427 |
+
is_array($data)
|
3428 |
+
&&
|
3429 |
+
isset($data['action']) && $data['action'] === 'update'
|
3430 |
+
&&
|
3431 |
+
isset($data['type']) && $data['type'] === 'theme'
|
3432 |
+
&&
|
3433 |
+
isset($data['themes'])
|
3434 |
+
&&
|
3435 |
+
($template = wp_get_theme()->get_template())
|
3436 |
+
&&
|
3437 |
+
(
|
3438 |
+
in_array($template, $data['themes'])
|
3439 |
+
||
|
3440 |
+
/**
|
3441 |
+
* Fixes the case when the theme path before update was
|
3442 |
+
* wp-content/themes/theme-name/theme-name-parent
|
3443 |
+
* but after update it became
|
3444 |
+
* wp-content/themes/theme-name-parent
|
3445 |
+
*/
|
3446 |
+
( preg_match($regex = '/\-parent$/', $template)
|
3447 |
+
? in_array( preg_replace($regex, '', $template) .'/'. $template, $data['themes'] )
|
3448 |
+
: false )
|
3449 |
+
)
|
3450 |
+
) {
|
3451 |
+
fw()->extensions->manager->theme_available_extensions_restore();
|
3452 |
+
}
|
3453 |
+
}
|
3454 |
}
|
framework/core/components/extensions/manager/includes/available-ext/class--fw-available-extensions-register.php
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if (!defined('FW')) die('Forbidden');
|
2 |
+
|
3 |
+
class _FW_Available_Extensions_Register extends FW_Type_Register {
|
4 |
+
protected function validate_type( FW_Type $type ) {
|
5 |
+
return $type instanceof FW_Available_Extension;
|
6 |
+
}
|
7 |
+
}
|
framework/core/components/extensions/manager/includes/available-ext/class-fw-available-extension.php
ADDED
@@ -0,0 +1,131 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if (!defined('FW')) die('Forbidden');
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Used to define extension in framework Available Extensions list
|
5 |
+
* @since 2.5.12
|
6 |
+
*/
|
7 |
+
class FW_Available_Extension extends FW_Type {
|
8 |
+
/**
|
9 |
+
* Extension (directory) name
|
10 |
+
*/
|
11 |
+
private $name;
|
12 |
+
|
13 |
+
/**
|
14 |
+
* @var null|string Parent extension name
|
15 |
+
*/
|
16 |
+
private $parent = null;
|
17 |
+
|
18 |
+
/**
|
19 |
+
* @var bool If visible in extensions list
|
20 |
+
*/
|
21 |
+
private $display = true;
|
22 |
+
|
23 |
+
/**
|
24 |
+
* @var string
|
25 |
+
*/
|
26 |
+
private $title;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* @var string
|
30 |
+
*/
|
31 |
+
private $description;
|
32 |
+
|
33 |
+
/**
|
34 |
+
* @var string Image url
|
35 |
+
*/
|
36 |
+
private $thumbnail = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2PUsHf9DwAC8AGtfm5YCAAAAABJRU5ErkJgggAA';
|
37 |
+
|
38 |
+
/**
|
39 |
+
* @var array {source: id, opts: {...}}
|
40 |
+
* @see FW_Ext_Download_Source::get_type() is id
|
41 |
+
* @see FW_Ext_Download_Source
|
42 |
+
*/
|
43 |
+
private $download_source = array();
|
44 |
+
|
45 |
+
/**
|
46 |
+
* @return bool
|
47 |
+
* @since 2.6.0
|
48 |
+
*/
|
49 |
+
public function is_valid() {
|
50 |
+
return (
|
51 |
+
!empty($this->name) && is_string($this->name)
|
52 |
+
&&
|
53 |
+
!empty($this->title) && is_string($this->title)
|
54 |
+
&&
|
55 |
+
!empty($this->description) && is_string($this->description)
|
56 |
+
&&
|
57 |
+
!empty($this->download_source)
|
58 |
+
&&
|
59 |
+
is_bool($this->display)
|
60 |
+
&&
|
61 |
+
(is_null($this->parent) || is_string($this->parent))
|
62 |
+
);
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* @return string
|
67 |
+
* @internal
|
68 |
+
*/
|
69 |
+
final public function get_type() {
|
70 |
+
return $this->get_name();
|
71 |
+
}
|
72 |
+
|
73 |
+
public function get_name() {
|
74 |
+
return $this->name;
|
75 |
+
}
|
76 |
+
|
77 |
+
public function set_name($name) {
|
78 |
+
$this->name = $name;
|
79 |
+
}
|
80 |
+
|
81 |
+
public function get_parent() {
|
82 |
+
return $this->parent;
|
83 |
+
}
|
84 |
+
|
85 |
+
public function set_parent($parent) {
|
86 |
+
$this->parent = $parent;
|
87 |
+
}
|
88 |
+
|
89 |
+
public function get_display() {
|
90 |
+
return $this->display;
|
91 |
+
}
|
92 |
+
|
93 |
+
public function set_display($display) {
|
94 |
+
$this->display = $display;
|
95 |
+
}
|
96 |
+
|
97 |
+
public function get_title() {
|
98 |
+
return $this->title;
|
99 |
+
}
|
100 |
+
|
101 |
+
public function set_title($title) {
|
102 |
+
$this->title = $title;
|
103 |
+
}
|
104 |
+
|
105 |
+
public function get_description() {
|
106 |
+
return $this->description;
|
107 |
+
}
|
108 |
+
|
109 |
+
public function set_description($description) {
|
110 |
+
$this->description = $description;
|
111 |
+
}
|
112 |
+
|
113 |
+
public function get_thumbnail() {
|
114 |
+
return $this->thumbnail;
|
115 |
+
}
|
116 |
+
|
117 |
+
public function set_thumbnail($thumbnail) {
|
118 |
+
$this->thumbnail = $thumbnail;
|
119 |
+
}
|
120 |
+
|
121 |
+
public function get_download_source() {
|
122 |
+
return $this->download_source;
|
123 |
+
}
|
124 |
+
|
125 |
+
public function set_download_source($id, $data) {
|
126 |
+
$this->download_source = array(
|
127 |
+
'source' => $id,
|
128 |
+
'opts' => $data
|
129 |
+
);
|
130 |
+
}
|
131 |
+
}
|
framework/core/components/extensions/manager/includes/download-source/class--fw-ext-download-source-register.php
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if (! defined('FW')) { die('Forbidden'); }
|
2 |
+
|
3 |
+
class _FW_Ext_Download_Source_Register extends FW_Type_Register
|
4 |
+
{
|
5 |
+
protected function validate_type( FW_Type $type ) {
|
6 |
+
return $type instanceof FW_Ext_Download_Source;
|
7 |
+
}
|
8 |
+
}
|
9 |
+
|
framework/core/components/extensions/manager/includes/download-source/class--fw-ext-download-source.php
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if (! defined('FW')) { die('Forbidden'); }
|
2 |
+
|
3 |
+
/**
|
4 |
+
* User to specify multiple download sources for an extension.
|
5 |
+
* @since 2.5.12
|
6 |
+
*/
|
7 |
+
abstract class FW_Ext_Download_Source extends FW_Type
|
8 |
+
{
|
9 |
+
/**
|
10 |
+
* Perform the actual download.
|
11 |
+
* It should download, by convention, a zip file which absolute path
|
12 |
+
* is $path.
|
13 |
+
*
|
14 |
+
* @param array $opts {extension_name: '...', extension_title: '...', ...}
|
15 |
+
* @param string $zip_path Absolute file of the future ZIP file
|
16 |
+
* @return null|WP_Error
|
17 |
+
*/
|
18 |
+
abstract public function download(array $opts, $zip_path);
|
19 |
+
}
|
20 |
+
|
framework/core/components/extensions/manager/includes/download-source/types/class-fw-download-source-github.php
ADDED
@@ -0,0 +1,187 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if (! defined('FW')) { die('Forbidden'); }
|
2 |
+
|
3 |
+
class FW_Ext_Download_Source_Github extends FW_Ext_Download_Source
|
4 |
+
{
|
5 |
+
private $download_timeout = 300;
|
6 |
+
|
7 |
+
public function get_type() {
|
8 |
+
return 'github';
|
9 |
+
}
|
10 |
+
|
11 |
+
/**
|
12 |
+
* @param array $opts {user_repo: 'ThemeFuse/Unyson'}
|
13 |
+
* @param string $zip_path
|
14 |
+
*
|
15 |
+
* @return WP_Error
|
16 |
+
*/
|
17 |
+
public function download(array $opts, $zip_path) {
|
18 |
+
$wp_error_id = 'fw_ext_github_download_source';
|
19 |
+
$theme_ext_requirements = fw()->theme->manifest->get('requirements/extensions');
|
20 |
+
|
21 |
+
/** @var WP_Filesystem_Base $wp_filesystem */
|
22 |
+
global $wp_filesystem;
|
23 |
+
|
24 |
+
$extension_name = $opts['extension_name'];
|
25 |
+
$extension_title = $opts['extension_title'];
|
26 |
+
|
27 |
+
if (empty($opts['user_repo'])) {
|
28 |
+
return new WP_Error(
|
29 |
+
$wp_error_id,
|
30 |
+
sprintf(__('"%s" extension github source "user_repo" parameter is required', 'fw'), $extension_title)
|
31 |
+
);
|
32 |
+
}
|
33 |
+
|
34 |
+
{
|
35 |
+
$transient_name = 'fw_ext_mngr_gh_dl';
|
36 |
+
$transient_ttl = HOUR_IN_SECONDS;
|
37 |
+
|
38 |
+
$cache = get_site_transient($transient_name);
|
39 |
+
|
40 |
+
if ($cache === false) {
|
41 |
+
$cache = array();
|
42 |
+
}
|
43 |
+
}
|
44 |
+
|
45 |
+
if (isset($cache[ $opts['user_repo'] ])) {
|
46 |
+
$download_link = $cache[ $opts['user_repo'] ]['zipball_url'];
|
47 |
+
} else {
|
48 |
+
$http = new WP_Http();
|
49 |
+
|
50 |
+
if (
|
51 |
+
isset($theme_ext_requirements[$extension_name])
|
52 |
+
&&
|
53 |
+
isset($theme_ext_requirements[$extension_name]['max_version'])
|
54 |
+
) {
|
55 |
+
$tag = 'tags/v'. $theme_ext_requirements[$extension_name]['max_version'];
|
56 |
+
} else {
|
57 |
+
$tag = 'latest';
|
58 |
+
}
|
59 |
+
|
60 |
+
$response = $http->get(
|
61 |
+
apply_filters('fw_github_api_url', 'https://api.github.com')
|
62 |
+
. '/repos/'. $opts['user_repo'] .'/releases/'. $tag
|
63 |
+
);
|
64 |
+
|
65 |
+
unset($http);
|
66 |
+
|
67 |
+
$response_code = intval(wp_remote_retrieve_response_code($response));
|
68 |
+
|
69 |
+
if ($response_code !== 200) {
|
70 |
+
if ($response_code === 403) {
|
71 |
+
if ($json_response = json_decode($response['body'], true)) {
|
72 |
+
return new WP_Error(
|
73 |
+
$wp_error_id,
|
74 |
+
__('Github error:', 'fw') .' '. $json_response['message']
|
75 |
+
);
|
76 |
+
} else {
|
77 |
+
return new WP_Error(
|
78 |
+
$wp_error_id,
|
79 |
+
sprintf(
|
80 |
+
__( 'Failed to access Github repository "%s" releases. (Response code: %d)', 'fw' ),
|
81 |
+
$opts['user_repo'], $response_code
|
82 |
+
)
|
83 |
+
);
|
84 |
+
}
|
85 |
+
} elseif ($response_code) {
|
86 |
+
return new WP_Error(
|
87 |
+
$wp_error_id,
|
88 |
+
sprintf(
|
89 |
+
__( 'Failed to access Github repository "%s" releases. (Response code: %d)', 'fw' ),
|
90 |
+
$opts['user_repo'], $response_code
|
91 |
+
)
|
92 |
+
);
|
93 |
+
} elseif (is_wp_error($response)) {
|
94 |
+
return new WP_Error(
|
95 |
+
$wp_error_id,
|
96 |
+
sprintf(
|
97 |
+
__( 'Failed to access Github repository "%s" releases. (%s)', 'fw' ),
|
98 |
+
$opts['user_repo'], $response->get_error_message()
|
99 |
+
)
|
100 |
+
);
|
101 |
+
} else {
|
102 |
+
return new WP_Error(
|
103 |
+
$wp_error_id,
|
104 |
+
sprintf(
|
105 |
+
__( 'Failed to access Github repository "%s" releases.', 'fw' ),
|
106 |
+
$opts['user_repo']
|
107 |
+
)
|
108 |
+
);
|
109 |
+
}
|
110 |
+
}
|
111 |
+
|
112 |
+
$release = json_decode($response['body'], true);
|
113 |
+
|
114 |
+
unset($response);
|
115 |
+
|
116 |
+
if (empty($release)) {
|
117 |
+
return new WP_Error(
|
118 |
+
$wp_error_id,
|
119 |
+
sprintf(
|
120 |
+
__('"%s" extension github repository "%s" has no releases.', 'fw'),
|
121 |
+
$extension_title, $opts['user_repo']
|
122 |
+
)
|
123 |
+
);
|
124 |
+
}
|
125 |
+
|
126 |
+
{
|
127 |
+
$cache[ $opts['user_repo'] ] = array(
|
128 |
+
'zipball_url' => 'https://github.com/'. $opts['user_repo'] .'/archive/'. $release['tag_name'] .'.zip',
|
129 |
+
'tag_name' => $release['tag_name']
|
130 |
+
);
|
131 |
+
|
132 |
+
set_site_transient($transient_name, $cache, $transient_ttl);
|
133 |
+
}
|
134 |
+
|
135 |
+
$download_link = $cache[ $opts['user_repo'] ]['zipball_url'];
|
136 |
+
|
137 |
+
|
138 |
+
unset($release);
|
139 |
+
}
|
140 |
+
|
141 |
+
{
|
142 |
+
$http = new WP_Http();
|
143 |
+
|
144 |
+
$response = $http->request($download_link, array(
|
145 |
+
'timeout' => $this->download_timeout,
|
146 |
+
));
|
147 |
+
|
148 |
+
unset($http);
|
149 |
+
|
150 |
+
if (($response_code = intval(wp_remote_retrieve_response_code($response))) !== 200) {
|
151 |
+
if ($response_code) {
|
152 |
+
return new WP_Error(
|
153 |
+
$wp_error_id,
|
154 |
+
sprintf( __( 'Cannot download the "%s" extension zip. (Response code: %d)', 'fw' ),
|
155 |
+
$extension_title, $response_code
|
156 |
+
)
|
157 |
+
);
|
158 |
+
} elseif (is_wp_error($response)) {
|
159 |
+
return new WP_Error(
|
160 |
+
$wp_error_id,
|
161 |
+
sprintf( __( 'Cannot download the "%s" extension zip. %s', 'fw' ),
|
162 |
+
$extension_title,
|
163 |
+
$response->get_error_message()
|
164 |
+
)
|
165 |
+
);
|
166 |
+
} else {
|
167 |
+
return new WP_Error(
|
168 |
+
$wp_error_id,
|
169 |
+
sprintf( __( 'Cannot download the "%s" extension zip.', 'fw' ),
|
170 |
+
$extension_title
|
171 |
+
)
|
172 |
+
);
|
173 |
+
}
|
174 |
+
}
|
175 |
+
|
176 |
+
// save zip to file
|
177 |
+
if (!$wp_filesystem->put_contents($zip_path, $response['body'])) {
|
178 |
+
return new WP_Error(
|
179 |
+
$wp_error_id,
|
180 |
+
sprintf(__('Cannot save the "%s" extension zip.', 'fw'), $extension_title)
|
181 |
+
);
|
182 |
+
}
|
183 |
+
|
184 |
+
unset($response);
|
185 |
+
}
|
186 |
+
}
|
187 |
+
}
|
framework/core/components/extensions/manager/includes/download-source/types/init.php
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if (! defined('FW')) { die('Forbidden'); }
|
2 |
+
|
3 |
+
if ( ! function_exists( '_action_fw_register_ext_download_sources' ) ) {
|
4 |
+
function _action_fw_register_ext_download_sources(_FW_Ext_Download_Source_Register $download_sources) {
|
5 |
+
$dir = dirname(__FILE__);
|
6 |
+
|
7 |
+
require_once $dir . '/class-fw-download-source-github.php';
|
8 |
+
$download_sources->register(new FW_Ext_Download_Source_Github());
|
9 |
+
}
|
10 |
+
}
|
11 |
+
|
12 |
+
add_action(
|
13 |
+
'fw_register_ext_download_sources',
|
14 |
+
'_action_fw_register_ext_download_sources'
|
15 |
+
);
|
framework/core/components/extensions/manager/static/extensions-page.css
CHANGED
@@ -134,9 +134,13 @@
|
|
134 |
width: 10px;
|
135 |
}
|
136 |
|
137 |
-
.fw-extensions-list .fw-extensions-list-item .fw-extension-list-item-table > .fw-extension-list-item-table-row > .fw-extension-list-item-table-cell:not(:first-child) {
|
138 |
padding-left: 20px;
|
139 |
}
|
|
|
|
|
|
|
|
|
140 |
|
141 |
.fw-extensions-list .fw-extensions-list-item .fw-extension-list-item-table > .fw-extension-list-item-table-row > .fw-extension-list-item-table-cell > p:last-child {
|
142 |
margin-bottom: 0;
|
@@ -149,6 +153,10 @@
|
|
149 |
right: 20px;
|
150 |
width: auto;
|
151 |
}
|
|
|
|
|
|
|
|
|
152 |
|
153 |
.fw-extensions-list .fw-extensions-list-item .fw-extension-list-item-table > .fw-extension-list-item-table-row > .fw-extension-list-item-table-cell.cell-3 form {
|
154 |
display: inline-block;
|
@@ -158,6 +166,9 @@
|
|
158 |
padding: 0 0 4px 15px;
|
159 |
vertical-align: bottom;
|
160 |
}
|
|
|
|
|
|
|
161 |
|
162 |
.fw-extensions-list .fw-extensions-list-item .fw-extension-list-item-table > .fw-extension-list-item-table-row > .fw-extension-list-item-table-cell.cell-3 form.extension-delete-form .btn-icon {
|
163 |
font-size: 16px;
|
134 |
width: 10px;
|
135 |
}
|
136 |
|
137 |
+
.fw-extensions-list .fw-extensions-list-item .fw-extension-list-item-table > .fw-extension-list-item-table-row > .fw-extension-list-item-table-cell:not(:first-child):not(:last-child) {
|
138 |
padding-left: 20px;
|
139 |
}
|
140 |
+
body.rtl .fw-extensions-list .fw-extensions-list-item .fw-extension-list-item-table > .fw-extension-list-item-table-row > .fw-extension-list-item-table-cell:not(:first-child):not(:last-child) {
|
141 |
+
padding-left: 0;
|
142 |
+
padding-right: 20px;
|
143 |
+
}
|
144 |
|
145 |
.fw-extensions-list .fw-extensions-list-item .fw-extension-list-item-table > .fw-extension-list-item-table-row > .fw-extension-list-item-table-cell > p:last-child {
|
146 |
margin-bottom: 0;
|
153 |
right: 20px;
|
154 |
width: auto;
|
155 |
}
|
156 |
+
body.rtl .fw-extensions-list .fw-extensions-list-item .fw-extension-list-item-table > .fw-extension-list-item-table-row > .fw-extension-list-item-table-cell.cell-3 {
|
157 |
+
right: auto;
|
158 |
+
left: 20px;
|
159 |
+
}
|
160 |
|
161 |
.fw-extensions-list .fw-extensions-list-item .fw-extension-list-item-table > .fw-extension-list-item-table-row > .fw-extension-list-item-table-cell.cell-3 form {
|
162 |
display: inline-block;
|
166 |
padding: 0 0 4px 15px;
|
167 |
vertical-align: bottom;
|
168 |
}
|
169 |
+
body.rtl .fw-extensions-list .fw-extensions-list-item .fw-extension-list-item-table > .fw-extension-list-item-table-row > .fw-extension-list-item-table-cell.cell-3 form.extension-delete-form {
|
170 |
+
padding: 0 13px 4px 0;
|
171 |
+
}
|
172 |
|
173 |
.fw-extensions-list .fw-extensions-list-item .fw-extension-list-item-table > .fw-extension-list-item-table-row > .fw-extension-list-item-table-cell.cell-3 form.extension-delete-form .btn-icon {
|
174 |
font-size: 16px;
|
framework/core/components/theme.php
CHANGED
@@ -46,15 +46,21 @@ final class _FW_Component_Theme
|
|
46 |
*/
|
47 |
public function locate_path($rel_path)
|
48 |
{
|
49 |
-
|
50 |
-
return
|
51 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
52 |
|
53 |
-
|
54 |
-
return fw_get_template_customizations_directory('/theme'. $rel_path);
|
55 |
-
}
|
56 |
|
57 |
-
|
|
|
58 |
}
|
59 |
|
60 |
/**
|
46 |
*/
|
47 |
public function locate_path($rel_path)
|
48 |
{
|
49 |
+
try {
|
50 |
+
return FW_File_Cache::get($cache_key = 'core:theme:path:'. $rel_path);
|
51 |
+
} catch (FW_File_Cache_Not_Found_Exception $e) {
|
52 |
+
if (is_child_theme() && file_exists(fw_get_stylesheet_customizations_directory('/theme'. $rel_path))) {
|
53 |
+
$path = fw_get_stylesheet_customizations_directory('/theme'. $rel_path);
|
54 |
+
} elseif (file_exists(fw_get_template_customizations_directory('/theme'. $rel_path))) {
|
55 |
+
$path = fw_get_template_customizations_directory('/theme'. $rel_path);
|
56 |
+
} else {
|
57 |
+
$path = false;
|
58 |
+
}
|
59 |
|
60 |
+
FW_File_Cache::set($cache_key, $path);
|
|
|
|
|
61 |
|
62 |
+
return $path;
|
63 |
+
}
|
64 |
}
|
65 |
|
66 |
/**
|
framework/core/extends/class-fw-extension.php
CHANGED
@@ -152,15 +152,26 @@ abstract class FW_Extension
|
|
152 |
*/
|
153 |
final public function locate_path($rel_path)
|
154 |
{
|
155 |
-
|
156 |
-
|
|
|
|
|
|
|
|
|
157 |
|
158 |
-
|
159 |
-
|
160 |
-
|
|
|
|
|
161 |
}
|
|
|
|
|
|
|
|
|
162 |
}
|
163 |
|
|
|
164 |
return false;
|
165 |
}
|
166 |
|
@@ -170,16 +181,24 @@ abstract class FW_Extension
|
|
170 |
*/
|
171 |
final public function locate_URI($rel_path)
|
172 |
{
|
173 |
-
|
174 |
-
|
|
|
|
|
|
|
|
|
175 |
|
176 |
-
|
177 |
-
|
178 |
-
|
|
|
|
|
179 |
}
|
180 |
-
}
|
181 |
|
182 |
-
|
|
|
|
|
|
|
183 |
}
|
184 |
|
185 |
/**
|
152 |
*/
|
153 |
final public function locate_path($rel_path)
|
154 |
{
|
155 |
+
try {
|
156 |
+
return FW_File_Cache::get($cache_key = 'ext:'. $this->get_name() .':path:'. $rel_path);
|
157 |
+
} catch (FW_File_Cache_Not_Found_Exception $e) {
|
158 |
+
$result = false;
|
159 |
+
$locations = $this->customizations_locations;
|
160 |
+
$locations[$this->get_path()] = $this->get_uri();
|
161 |
|
162 |
+
foreach ($locations as $path => $uri) {
|
163 |
+
if (file_exists($path . $rel_path)) {
|
164 |
+
$result = $path . $rel_path;
|
165 |
+
break;
|
166 |
+
}
|
167 |
}
|
168 |
+
|
169 |
+
FW_File_Cache::set($cache_key, $result);
|
170 |
+
|
171 |
+
return $result;
|
172 |
}
|
173 |
|
174 |
+
|
175 |
return false;
|
176 |
}
|
177 |
|
181 |
*/
|
182 |
final public function locate_URI($rel_path)
|
183 |
{
|
184 |
+
try {
|
185 |
+
return FW_File_Cache::get($cache_key = 'ext:'. $this->get_name() .':uri:'. $rel_path);
|
186 |
+
} catch (FW_File_Cache_Not_Found_Exception $e) {
|
187 |
+
$result = false;
|
188 |
+
$locations = $this->customizations_locations;
|
189 |
+
$locations[$this->get_path()] = $this->get_uri();
|
190 |
|
191 |
+
foreach ($locations as $path => $uri) {
|
192 |
+
if (file_exists($path . $rel_path)) {
|
193 |
+
$result = $uri . $rel_path;
|
194 |
+
break;
|
195 |
+
}
|
196 |
}
|
|
|
197 |
|
198 |
+
FW_File_Cache::set($cache_key, $result);
|
199 |
+
|
200 |
+
return $result;
|
201 |
+
}
|
202 |
}
|
203 |
|
204 |
/**
|
framework/extensions/update/manifest.php
CHANGED
@@ -6,5 +6,5 @@ $manifest['name'] = __('Update', 'fw');
|
|
6 |
$manifest['description'] = __('Keep you framework, extensions and theme up to date.', 'fw');
|
7 |
$manifest['standalone'] = true;
|
8 |
|
9 |
-
$manifest['version'] = '1.0.
|
10 |
$manifest['github_update'] = 'ThemeFuse/Unyson-Update-Extension';
|
6 |
$manifest['description'] = __('Keep you framework, extensions and theme up to date.', 'fw');
|
7 |
$manifest['standalone'] = true;
|
8 |
|
9 |
+
$manifest['version'] = '1.0.11';
|
10 |
$manifest['github_update'] = 'ThemeFuse/Unyson-Update-Extension';
|
framework/extensions/update/views/updates-list.php
CHANGED
@@ -32,7 +32,7 @@
|
|
32 |
<?php if ($updates['theme'] !== false): ?>
|
33 |
<div id="fw-ext-update-theme">
|
34 |
<a name="fw-theme"></a>
|
35 |
-
<h3><?php $theme = wp_get_theme(); _e(sprintf('%s Theme', $theme->parent()->get('Name')), 'fw') ?></h3>
|
36 |
<?php if (empty($updates['theme'])): ?>
|
37 |
<p><?php _e('Your theme is up to date.', 'fw') ?></p>
|
38 |
<?php else: ?>
|
32 |
<?php if ($updates['theme'] !== false): ?>
|
33 |
<div id="fw-ext-update-theme">
|
34 |
<a name="fw-theme"></a>
|
35 |
+
<h3><?php $theme = wp_get_theme(); _e(sprintf('%s Theme', (is_child_theme() ? $theme->parent()->get('Name') : $theme->get('Name'))), 'fw') ?></h3>
|
36 |
<?php if (empty($updates['theme'])): ?>
|
37 |
<p><?php _e('Your theme is up to date.', 'fw') ?></p>
|
38 |
<?php else: ?>
|
framework/helpers/class-fw-cache.php
CHANGED
@@ -2,7 +2,6 @@
|
|
2 |
|
3 |
/**
|
4 |
* Memory Cache
|
5 |
-
* Only for internal usage in other functions/methods, because it throws exceptions
|
6 |
*
|
7 |
* Recommended usage example:
|
8 |
* try {
|
@@ -151,14 +150,17 @@ class FW_Cache
|
|
151 |
'clean_user_cache' => true,
|
152 |
'process_text_diff_html' => true,
|
153 |
) as $hook => $tmp) {
|
154 |
-
add_filter($hook, array(__CLASS__, 'free_memory'),
|
155 |
}
|
156 |
|
157 |
/**
|
158 |
-
*
|
159 |
*/
|
160 |
foreach (array(
|
161 |
'switch_blog' => true,
|
|
|
|
|
|
|
162 |
) as $hook => $tmp) {
|
163 |
add_filter($hook, array(__CLASS__, 'clear'), 1);
|
164 |
}
|
@@ -263,7 +265,7 @@ class FW_Cache
|
|
263 |
|
264 |
/**
|
265 |
* Empty the cache
|
266 |
-
* @param mixed $dummy
|
267 |
* @return mixed
|
268 |
*/
|
269 |
public static function clear($dummy = null)
|
2 |
|
3 |
/**
|
4 |
* Memory Cache
|
|
|
5 |
*
|
6 |
* Recommended usage example:
|
7 |
* try {
|
150 |
'clean_user_cache' => true,
|
151 |
'process_text_diff_html' => true,
|
152 |
) as $hook => $tmp) {
|
153 |
+
add_filter($hook, array(__CLASS__, 'free_memory'), 1);
|
154 |
}
|
155 |
|
156 |
/**
|
157 |
+
* Flush the cache when something major is changed (files or db values)
|
158 |
*/
|
159 |
foreach (array(
|
160 |
'switch_blog' => true,
|
161 |
+
'upgrader_post_install' => true,
|
162 |
+
'upgrader_process_complete' => true,
|
163 |
+
'switch_theme' => true,
|
164 |
) as $hook => $tmp) {
|
165 |
add_filter($hook, array(__CLASS__, 'clear'), 1);
|
166 |
}
|
265 |
|
266 |
/**
|
267 |
* Empty the cache
|
268 |
+
* @param mixed $dummy When method is used in add_filter()
|
269 |
* @return mixed
|
270 |
*/
|
271 |
public static function clear($dummy = null)
|
framework/helpers/class-fw-file-cache.php
ADDED
@@ -0,0 +1,237 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if (!defined('FW')) die('Forbidden');
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Persistent cache saved in uploads/fw-file-cache.php
|
5 |
+
*
|
6 |
+
* It is reset when:
|
7 |
+
* - the user is logged in as administrator
|
8 |
+
* - important action related to theme switch or file changes is triggered (for e.g. JetPack can do changes remotely)
|
9 |
+
*
|
10 |
+
* Usage:
|
11 |
+
* try {
|
12 |
+
* return FW_File_Cache::get($cache_key = '...'. $rel_path);
|
13 |
+
* } catch (FW_File_Cache_Not_Found_Exception $e) {
|
14 |
+
* $result = ...;
|
15 |
+
*
|
16 |
+
* FW_File_Cache::set($cache_key, $result);
|
17 |
+
*
|
18 |
+
* return $result; // IMPORTANT: Do not use FW_File_Cache::get($cache_key) again
|
19 |
+
* }
|
20 |
+
*
|
21 |
+
* @since 2.6.0
|
22 |
+
*/
|
23 |
+
class FW_File_Cache {
|
24 |
+
/**
|
25 |
+
* @var int
|
26 |
+
*/
|
27 |
+
private static $expires = 3600;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @var bool
|
31 |
+
*/
|
32 |
+
private static $changed = false;
|
33 |
+
|
34 |
+
/**
|
35 |
+
* @var string
|
36 |
+
*/
|
37 |
+
private static $path;
|
38 |
+
|
39 |
+
/**
|
40 |
+
* @var array
|
41 |
+
*/
|
42 |
+
private static $cache;
|
43 |
+
|
44 |
+
private static function get_defaults() {
|
45 |
+
return array(
|
46 |
+
'created' => time(),
|
47 |
+
'updated' => time(),
|
48 |
+
'data' => array(),
|
49 |
+
);
|
50 |
+
}
|
51 |
+
|
52 |
+
private static function load() {
|
53 |
+
if ( is_array( self::$cache ) ) {
|
54 |
+
return true; // already loaded
|
55 |
+
}
|
56 |
+
|
57 |
+
$dir = dirname(self::$path);
|
58 |
+
$path = self::$path;
|
59 |
+
$code = '<?php return array();';
|
60 |
+
$shhh = defined('DOING_AJAX') && DOING_AJAX; // prevent warning in ajax requests
|
61 |
+
|
62 |
+
// check directory
|
63 |
+
if ( ! file_exists($dir) ) {
|
64 |
+
if ( ! mkdir($dir, 0755, true) ) {
|
65 |
+
return false;
|
66 |
+
}
|
67 |
+
}
|
68 |
+
|
69 |
+
// check file
|
70 |
+
if ( file_exists($path) ) {
|
71 |
+
if ( ! is_writable($path) ) {
|
72 |
+
if (
|
73 |
+
( $shhh
|
74 |
+
? @unlink($path)
|
75 |
+
: unlink($path)
|
76 |
+
)
|
77 |
+
&&
|
78 |
+
file_put_contents($path, $code)
|
79 |
+
) {
|
80 |
+
// file re-created
|
81 |
+
} else {
|
82 |
+
return false;
|
83 |
+
}
|
84 |
+
}
|
85 |
+
} elseif ( ! ( $shhh
|
86 |
+
? @file_put_contents($path, $code)
|
87 |
+
: file_put_contents($path, $code)
|
88 |
+
) ) {
|
89 |
+
return false; // cannot create the file
|
90 |
+
}
|
91 |
+
|
92 |
+
self::$cache = include $path;
|
93 |
+
|
94 |
+
// check the loaded cache
|
95 |
+
{
|
96 |
+
$reset = false;
|
97 |
+
|
98 |
+
do {
|
99 |
+
foreach ( self::get_defaults() as $def_key => $def_val ) {
|
100 |
+
if (
|
101 |
+
!isset( self::$cache[ $def_key ] )
|
102 |
+
||
|
103 |
+
gettype( self::$cache[ $def_key ] ) !== gettype($def_val)
|
104 |
+
) {
|
105 |
+
$reset = true;
|
106 |
+
break 2;
|
107 |
+
}
|
108 |
+
}
|
109 |
+
|
110 |
+
if ( self::$cache['created'] < ( time() - self::$expires ) ) {
|
111 |
+
$reset = true;
|
112 |
+
break;
|
113 |
+
}
|
114 |
+
} while(false);
|
115 |
+
|
116 |
+
if ($reset) {
|
117 |
+
self::$cache = self::get_defaults();
|
118 |
+
self::$changed = true;
|
119 |
+
}
|
120 |
+
}
|
121 |
+
|
122 |
+
return true;
|
123 |
+
}
|
124 |
+
|
125 |
+
private static function update_path() {
|
126 |
+
$path = wp_upload_dir();
|
127 |
+
$path = fw_fix_path($path['basedir']) .'/fw/file-cache.php';
|
128 |
+
|
129 |
+
self::$path = $path;
|
130 |
+
}
|
131 |
+
|
132 |
+
/**
|
133 |
+
* @param mixed $filter_value When this method is used in filter, it must return the unchanged filter value
|
134 |
+
* @return bool
|
135 |
+
*/
|
136 |
+
public static function reset($filter_value = null) {
|
137 |
+
if ( ! self::load() ) {
|
138 |
+
return is_null($filter_value) ? true : $filter_value;
|
139 |
+
}
|
140 |
+
|
141 |
+
self::save();
|
142 |
+
self::update_path();
|
143 |
+
self::$cache = self::get_defaults();
|
144 |
+
self::$changed = true;
|
145 |
+
|
146 |
+
return is_null($filter_value) ? true : $filter_value;
|
147 |
+
}
|
148 |
+
|
149 |
+
public static function save() {
|
150 |
+
if ( ! self::$changed ) {
|
151 |
+
return;
|
152 |
+
}
|
153 |
+
|
154 |
+
file_put_contents(self::$path, '<?php return '. var_export(self::$cache, true) .';');
|
155 |
+
|
156 |
+
self::$changed = false;
|
157 |
+
}
|
158 |
+
|
159 |
+
/**
|
160 |
+
* @internal
|
161 |
+
*/
|
162 |
+
public static function _init() {
|
163 |
+
self::update_path();
|
164 |
+
|
165 |
+
/**
|
166 |
+
* Reset when current user is administrator
|
167 |
+
* because it can be a developer that added/removed some files
|
168 |
+
*/
|
169 |
+
if ( current_user_can('manage_options') ) {
|
170 |
+
self::reset();
|
171 |
+
} else {
|
172 |
+
/**
|
173 |
+
* Reset on actions which may change something related to files
|
174 |
+
* - themes/plugins activation (new files must be loaded from other paths)
|
175 |
+
* - after some files was added/deleted
|
176 |
+
*/
|
177 |
+
foreach (array(
|
178 |
+
'switch_blog' => true,
|
179 |
+
'fw_extensions_before_activation' => true,
|
180 |
+
'fw_extensions_after_activation' => true,
|
181 |
+
'fw_extensions_before_deactivation' => true,
|
182 |
+
'fw_extensions_after_deactivation' => true,
|
183 |
+
'fw_extensions_install' => true,
|
184 |
+
'fw_extensions_uninstall' => true,
|
185 |
+
'activated_plugin' => true,
|
186 |
+
'deactivated_plugin' => true,
|
187 |
+
'switch_theme' => true,
|
188 |
+
'after_switch_theme' => true,
|
189 |
+
'upgrader_post_install' => true,
|
190 |
+
'automatic_updates_complete' => true,
|
191 |
+
'upgrader_process_complete' => true,
|
192 |
+
) as $action => $x) {
|
193 |
+
add_action( $action, array(__CLASS__, 'reset') );
|
194 |
+
}
|
195 |
+
}
|
196 |
+
|
197 |
+
add_action( 'shutdown', array(__CLASS__, 'save') );
|
198 |
+
}
|
199 |
+
|
200 |
+
/**
|
201 |
+
* @param string $key No multiKey because it must be fast
|
202 |
+
* @return mixed
|
203 |
+
* @throws FW_File_Cache_Not_Found_Exception
|
204 |
+
*/
|
205 |
+
public static function get($key) {
|
206 |
+
if ( ! self::load() ) {
|
207 |
+
throw new FW_File_Cache_Not_Found_Exception();
|
208 |
+
}
|
209 |
+
|
210 |
+
if (array_key_exists($key, self::$cache['data'])) {
|
211 |
+
return self::$cache['data'][$key];
|
212 |
+
} else {
|
213 |
+
throw new FW_File_Cache_Not_Found_Exception();
|
214 |
+
}
|
215 |
+
}
|
216 |
+
|
217 |
+
/**
|
218 |
+
* @param string $key
|
219 |
+
* @param mixed $value
|
220 |
+
* @return bool
|
221 |
+
*/
|
222 |
+
public static function set($key, $value) {
|
223 |
+
if ( ! self::load() ) {
|
224 |
+
return false;
|
225 |
+
}
|
226 |
+
|
227 |
+
self::$changed = true;
|
228 |
+
self::$cache['updated'] = time();
|
229 |
+
self::$cache['data'][ $key ] = $value;
|
230 |
+
|
231 |
+
return true;
|
232 |
+
}
|
233 |
+
}
|
234 |
+
|
235 |
+
class FW_File_Cache_Not_Found_Exception extends Exception {}
|
236 |
+
|
237 |
+
FW_File_Cache::_init();
|
framework/helpers/class-fw-wp-filesystem.php
CHANGED
@@ -302,7 +302,7 @@ class FW_WP_Filesystem
|
|
302 |
}
|
303 |
}
|
304 |
|
305 |
-
if (!$wp_filesystem->mkdir($path
|
306 |
return false;
|
307 |
}
|
308 |
}
|
302 |
}
|
303 |
}
|
304 |
|
305 |
+
if (!$wp_filesystem->mkdir($path)) {
|
306 |
return false;
|
307 |
}
|
308 |
}
|
framework/helpers/database.php
CHANGED
@@ -26,6 +26,31 @@ class FW_Db_Options_Model_Settings extends FW_Db_Options_Model {
|
|
26 |
);
|
27 |
}
|
28 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
29 |
protected function _init() {
|
30 |
/**
|
31 |
* Get a theme settings option value from the database
|
@@ -136,15 +161,15 @@ class FW_Db_Options_Model_Post extends FW_Db_Options_Model {
|
|
136 |
}
|
137 |
|
138 |
protected function get_values($item_id, array $extra_data = array()) {
|
139 |
-
return FW_WP_Meta::get( 'post', $item_id, 'fw_options', array() );
|
140 |
}
|
141 |
|
142 |
protected function set_values($item_id, $values, array $extra_data = array()) {
|
143 |
-
FW_WP_Meta::set( 'post', $item_id, 'fw_options', $values );
|
144 |
}
|
145 |
|
146 |
protected function get_fw_storage_params($item_id, array $extra_data = array()) {
|
147 |
-
return array( 'post-id' => $item_id );
|
148 |
}
|
149 |
|
150 |
protected function _get_cache_key($key, $item_id, array $extra_data = array()) {
|
@@ -169,23 +194,14 @@ class FW_Db_Options_Model_Post extends FW_Db_Options_Model {
|
|
169 |
/**
|
170 |
* Option id
|
171 |
* First level multi-key
|
172 |
-
*
|
173 |
-
* For e.g.
|
174 |
-
*
|
175 |
-
* if $option_id is 'hello/world/7'
|
176 |
-
* this will be 'hello'
|
177 |
*/
|
178 |
$option_id,
|
179 |
/**
|
180 |
* The remaining sub-keys
|
181 |
-
*
|
182 |
* For e.g.
|
183 |
-
*
|
184 |
-
* if $option_id is 'hello
|
185 |
-
* $option_id_keys will be array('world', '7')
|
186 |
-
*
|
187 |
-
* if $option_id is 'hello'
|
188 |
-
* $option_id_keys will be array()
|
189 |
*/
|
190 |
explode('/', $sub_keys),
|
191 |
/**
|
@@ -234,11 +250,15 @@ class FW_Db_Options_Model_Term extends FW_Db_Options_Model {
|
|
234 |
}
|
235 |
|
236 |
protected function get_values($item_id, array $extra_data = array()) {
|
237 |
-
|
|
|
|
|
238 |
}
|
239 |
|
240 |
protected function set_values($item_id, $values, array $extra_data = array()) {
|
241 |
-
|
|
|
|
|
242 |
}
|
243 |
|
244 |
protected function get_options($item_id, array $extra_data = array()) {
|
@@ -260,6 +280,123 @@ class FW_Db_Options_Model_Term extends FW_Db_Options_Model {
|
|
260 |
}
|
261 |
}
|
262 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
263 |
protected function _init() {
|
264 |
/**
|
265 |
* Get term option value from the database
|
@@ -301,6 +438,9 @@ class FW_Db_Options_Model_Term extends FW_Db_Options_Model {
|
|
301 |
'taxonomy' => $taxonomy
|
302 |
));
|
303 |
}
|
|
|
|
|
|
|
304 |
}
|
305 |
}
|
306 |
new FW_Db_Options_Model_Term();
|
@@ -393,6 +533,31 @@ class FW_Db_Options_Model_Customizer extends FW_Db_Options_Model {
|
|
393 |
);
|
394 |
}
|
395 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
396 |
protected function _init() {
|
397 |
/**
|
398 |
* Get a customizer framework option value from the database
|
26 |
);
|
27 |
}
|
28 |
|
29 |
+
protected function _after_set($item_id, $option_id, $sub_keys, $old_value, array $extra_data = array()) {
|
30 |
+
/**
|
31 |
+
* @since 2.6.0
|
32 |
+
*/
|
33 |
+
do_action('fw_settings_options_update', array(
|
34 |
+
/**
|
35 |
+
* Option id
|
36 |
+
* First level multi-key
|
37 |
+
* For e.g. if $option_id is 'hello/world/7' this will be 'hello'
|
38 |
+
*/
|
39 |
+
'option_id' => $option_id,
|
40 |
+
/**
|
41 |
+
* The remaining sub-keys
|
42 |
+
* For e.g.
|
43 |
+
* if $option_id is 'hello/world/7' this will be array('world', '7')
|
44 |
+
* if $option_id is 'hello' this will be array()
|
45 |
+
*/
|
46 |
+
'sub_keys' => explode('/', $sub_keys),
|
47 |
+
/**
|
48 |
+
* Old option(s) value
|
49 |
+
*/
|
50 |
+
'old_value' => $old_value
|
51 |
+
));
|
52 |
+
}
|
53 |
+
|
54 |
protected function _init() {
|
55 |
/**
|
56 |
* Get a theme settings option value from the database
|
161 |
}
|
162 |
|
163 |
protected function get_values($item_id, array $extra_data = array()) {
|
164 |
+
return FW_WP_Meta::get( 'post', $this->get_post_id($item_id), 'fw_options', array() );
|
165 |
}
|
166 |
|
167 |
protected function set_values($item_id, $values, array $extra_data = array()) {
|
168 |
+
FW_WP_Meta::set( 'post', $this->get_post_id($item_id), 'fw_options', $values );
|
169 |
}
|
170 |
|
171 |
protected function get_fw_storage_params($item_id, array $extra_data = array()) {
|
172 |
+
return array( 'post-id' => $this->get_post_id($item_id) );
|
173 |
}
|
174 |
|
175 |
protected function _get_cache_key($key, $item_id, array $extra_data = array()) {
|
194 |
/**
|
195 |
* Option id
|
196 |
* First level multi-key
|
197 |
+
* For e.g. if $option_id is 'hello/world/7' this will be 'hello'
|
|
|
|
|
|
|
|
|
198 |
*/
|
199 |
$option_id,
|
200 |
/**
|
201 |
* The remaining sub-keys
|
|
|
202 |
* For e.g.
|
203 |
+
* if $option_id is 'hello/world/7' this will be array('world', '7')
|
204 |
+
* if $option_id is 'hello' this will be array()
|
|
|
|
|
|
|
|
|
205 |
*/
|
206 |
explode('/', $sub_keys),
|
207 |
/**
|
250 |
}
|
251 |
|
252 |
protected function get_values($item_id, array $extra_data = array()) {
|
253 |
+
self::migrate($item_id);
|
254 |
+
|
255 |
+
return (array)get_term_meta( $item_id, 'fw_options', true);
|
256 |
}
|
257 |
|
258 |
protected function set_values($item_id, $values, array $extra_data = array()) {
|
259 |
+
self::migrate($item_id);
|
260 |
+
|
261 |
+
update_term_meta($item_id, 'fw_options', $values);
|
262 |
}
|
263 |
|
264 |
protected function get_options($item_id, array $extra_data = array()) {
|
280 |
}
|
281 |
}
|
282 |
|
283 |
+
/**
|
284 |
+
* Cache termmeta table name if exists
|
285 |
+
* @var string|false
|
286 |
+
*/
|
287 |
+
private static $old_table_name;
|
288 |
+
|
289 |
+
/**
|
290 |
+
* @return string|false
|
291 |
+
*/
|
292 |
+
private static function get_old_table_name() {
|
293 |
+
if (is_null(self::$old_table_name)) {
|
294 |
+
/** @var WPDB $wpdb */
|
295 |
+
global $wpdb;
|
296 |
+
|
297 |
+
$table_name = $wpdb->get_results( "show tables like '{$wpdb->prefix}fw_termmeta'", ARRAY_A );
|
298 |
+
$table_name = $table_name ? array_pop($table_name[0]) : false;
|
299 |
+
|
300 |
+
if ( $table_name && ! $wpdb->get_results( "SELECT 1 FROM `{$table_name}` LIMIT 1" ) ) {
|
301 |
+
// The table is empty, delete it
|
302 |
+
$wpdb->query( "DROP TABLE `{$table_name}`" );
|
303 |
+
$table_name = false;
|
304 |
+
}
|
305 |
+
|
306 |
+
self::$old_table_name = $table_name;
|
307 |
+
}
|
308 |
+
|
309 |
+
return self::$old_table_name;
|
310 |
+
}
|
311 |
+
|
312 |
+
/**
|
313 |
+
* @internal
|
314 |
+
*/
|
315 |
+
public static function _action_switch_blog() {
|
316 |
+
self::$old_table_name = null; // reset
|
317 |
+
}
|
318 |
+
|
319 |
+
/**
|
320 |
+
* When a term is deleted, delete its meta from old fw_termmeta table
|
321 |
+
*
|
322 |
+
* @param mixed $term_id
|
323 |
+
*
|
324 |
+
* @return void
|
325 |
+
* @internal
|
326 |
+
*/
|
327 |
+
public static function _action_fw_delete_term( $term_id ) {
|
328 |
+
if ( ! ( $table_name = self::get_old_table_name() ) ) {
|
329 |
+
return;
|
330 |
+
}
|
331 |
+
|
332 |
+
$term_id = (int) $term_id;
|
333 |
+
|
334 |
+
if ( ! $term_id ) {
|
335 |
+
return;
|
336 |
+
}
|
337 |
+
|
338 |
+
/** @var WPDB $wpdb */
|
339 |
+
global $wpdb;
|
340 |
+
|
341 |
+
$wpdb->delete( $table_name, array( 'fw_term_id' => $term_id ), array( '%d' ) );
|
342 |
+
}
|
343 |
+
|
344 |
+
/**
|
345 |
+
* In WP 4.4 was introduced native term meta https://codex.wordpress.org/Version_4.4#For_Developers
|
346 |
+
* All data from old table must be migrated to native term meta
|
347 |
+
* @param int $term_id
|
348 |
+
* @return bool
|
349 |
+
*/
|
350 |
+
private static function migrate($term_id) {
|
351 |
+
global $wpdb; /** @var wpdb $wpdb */
|
352 |
+
|
353 |
+
if (
|
354 |
+
( $old_table_name = self::get_old_table_name() )
|
355 |
+
&&
|
356 |
+
( $value = $wpdb->get_col( $wpdb->prepare(
|
357 |
+
"SELECT meta_value FROM `{$old_table_name}` WHERE fw_term_id = %d AND meta_key = 'fw_options' LIMIT 1",
|
358 |
+
$term_id
|
359 |
+
) ) )
|
360 |
+
&&
|
361 |
+
( $value = unserialize( $value[0] ) )
|
362 |
+
) {
|
363 |
+
$wpdb->delete( $old_table_name, array( 'fw_term_id' => $term_id ), array( '%d' ) );
|
364 |
+
|
365 |
+
update_term_meta( $term_id, 'fw_options', $value );
|
366 |
+
|
367 |
+
return true;
|
368 |
+
} else {
|
369 |
+
return false;
|
370 |
+
}
|
371 |
+
}
|
372 |
+
|
373 |
+
protected function _after_set($item_id, $option_id, $sub_keys, $old_value, array $extra_data = array()) {
|
374 |
+
/**
|
375 |
+
* @since 2.6.0
|
376 |
+
*/
|
377 |
+
do_action('fw_term_options_update', array(
|
378 |
+
'term_id' => $item_id,
|
379 |
+
'taxonomy' => $extra_data['taxonomy'],
|
380 |
+
/**
|
381 |
+
* Option id
|
382 |
+
* First level multi-key
|
383 |
+
* For e.g. if $option_id is 'hello/world/7' this will be 'hello'
|
384 |
+
*/
|
385 |
+
'option_id' => $option_id,
|
386 |
+
/**
|
387 |
+
* The remaining sub-keys
|
388 |
+
* For e.g.
|
389 |
+
* if $option_id is 'hello/world/7' this will be array('world', '7')
|
390 |
+
* if $option_id is 'hello' this will be array()
|
391 |
+
*/
|
392 |
+
'sub_keys' => explode('/', $sub_keys),
|
393 |
+
/**
|
394 |
+
* Old option(s) value
|
395 |
+
*/
|
396 |
+
'old_value' => $old_value
|
397 |
+
));
|
398 |
+
}
|
399 |
+
|
400 |
protected function _init() {
|
401 |
/**
|
402 |
* Get term option value from the database
|
438 |
'taxonomy' => $taxonomy
|
439 |
));
|
440 |
}
|
441 |
+
|
442 |
+
add_action( 'switch_blog', array( __CLASS__, '_action_switch_blog' ) );
|
443 |
+
add_action( 'delete_term', array( __CLASS__, '_action_fw_delete_term' ) );
|
444 |
}
|
445 |
}
|
446 |
new FW_Db_Options_Model_Term();
|
533 |
);
|
534 |
}
|
535 |
|
536 |
+
protected function _after_set($item_id, $option_id, $sub_keys, $old_value, array $extra_data = array()) {
|
537 |
+
/**
|
538 |
+
* @since 2.6.0
|
539 |
+
*/
|
540 |
+
do_action('fw_customizer_options_update', array(
|
541 |
+
/**
|
542 |
+
* Option id
|
543 |
+
* First level multi-key
|
544 |
+
* For e.g. if $option_id is 'hello/world/7' this will be 'hello'
|
545 |
+
*/
|
546 |
+
'option_id' => $option_id,
|
547 |
+
/**
|
548 |
+
* The remaining sub-keys
|
549 |
+
* For e.g.
|
550 |
+
* if $option_id is 'hello/world/7' this will be array('world', '7')
|
551 |
+
* if $option_id is 'hello' this will be array()
|
552 |
+
*/
|
553 |
+
'sub_keys' => explode('/', $sub_keys),
|
554 |
+
/**
|
555 |
+
* Old option(s) value
|
556 |
+
*/
|
557 |
+
'old_value' => $old_value
|
558 |
+
));
|
559 |
+
}
|
560 |
+
|
561 |
protected function _init() {
|
562 |
/**
|
563 |
* Get a customizer framework option value from the database
|
framework/helpers/general.php
CHANGED
@@ -489,15 +489,21 @@ function fw_current_screen_match(array $rules) {
|
|
489 |
* @return string URI
|
490 |
*/
|
491 |
function fw_locate_theme_path_uri($rel_path) {
|
492 |
-
|
493 |
-
return
|
494 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
495 |
|
496 |
-
|
497 |
-
return get_template_directory_uri() . $rel_path;
|
498 |
-
}
|
499 |
|
500 |
-
|
|
|
501 |
}
|
502 |
|
503 |
/**
|
@@ -507,15 +513,21 @@ function fw_locate_theme_path_uri($rel_path) {
|
|
507 |
* @return string URI
|
508 |
*/
|
509 |
function fw_locate_theme_path($rel_path) {
|
510 |
-
|
511 |
-
return
|
512 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
513 |
|
514 |
-
|
515 |
-
return get_template_directory() . $rel_path;
|
516 |
-
}
|
517 |
|
518 |
-
|
|
|
519 |
}
|
520 |
|
521 |
/**
|
@@ -741,33 +753,38 @@ function fw_collect_options(&$result, &$options, $settings = array(), $_recursio
|
|
741 |
* @type int Limit the number of options that will be collected
|
742 |
*/
|
743 |
'limit' => 0,
|
|
|
|
|
|
|
|
|
|
|
744 |
);
|
745 |
|
746 |
static $access_key = null;
|
747 |
|
748 |
-
if (is_null($access_key)) {
|
749 |
-
$access_key = new FW_Access_Key('fw_collect_options');
|
750 |
-
}
|
751 |
-
|
752 |
if (empty($options)) {
|
753 |
return;
|
754 |
}
|
755 |
|
756 |
-
$settings = array_merge($default_settings, $settings);
|
757 |
-
|
758 |
if (empty($_recursion_data)) {
|
|
|
|
|
|
|
|
|
|
|
|
|
759 |
$_recursion_data = array(
|
760 |
'level' => 1,
|
761 |
'access_key' => $access_key,
|
762 |
// todo: maybe add 'parent' => array('id' => '{id}', 'type' => 'container|option') ?
|
763 |
);
|
764 |
-
} elseif (
|
765 |
-
|
766 |
-
|
767 |
-
|
768 |
-
|
769 |
-
|
770 |
-
) {
|
771 |
trigger_error('Call not allowed', E_USER_ERROR);
|
772 |
}
|
773 |
|
@@ -813,6 +830,14 @@ function fw_collect_options(&$result, &$options, $settings = array(), $_recursio
|
|
813 |
} else {
|
814 |
$result[$option_id] = &$option;
|
815 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
816 |
} while(false);
|
817 |
|
818 |
fw_collect_options(
|
@@ -884,6 +909,14 @@ function fw_collect_options(&$result, &$options, $settings = array(), $_recursio
|
|
884 |
} else {
|
885 |
$result[$option_id] = &$option;
|
886 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
887 |
} else {
|
888 |
trigger_error('Invalid option: '. $option_id, E_USER_WARNING);
|
889 |
}
|
489 |
* @return string URI
|
490 |
*/
|
491 |
function fw_locate_theme_path_uri($rel_path) {
|
492 |
+
try {
|
493 |
+
return FW_File_Cache::get($cache_key = 'theme-uri:'. $rel_path);
|
494 |
+
} catch (FW_File_Cache_Not_Found_Exception $e) {
|
495 |
+
if (is_child_theme() && file_exists(get_stylesheet_directory() . $rel_path)) {
|
496 |
+
$result = get_stylesheet_directory_uri() . $rel_path;
|
497 |
+
} elseif (file_exists(get_template_directory() . $rel_path)) {
|
498 |
+
$result = get_template_directory_uri() . $rel_path;
|
499 |
+
} else {
|
500 |
+
$result = 'about:blank#theme-file-not-found:'. $rel_path;
|
501 |
+
}
|
502 |
|
503 |
+
FW_File_Cache::set($cache_key, $result);
|
|
|
|
|
504 |
|
505 |
+
return $result;
|
506 |
+
}
|
507 |
}
|
508 |
|
509 |
/**
|
513 |
* @return string URI
|
514 |
*/
|
515 |
function fw_locate_theme_path($rel_path) {
|
516 |
+
try {
|
517 |
+
return FW_File_Cache::get($cache_key = 'theme-path:'. $rel_path);
|
518 |
+
} catch (FW_File_Cache_Not_Found_Exception $e) {
|
519 |
+
if (is_child_theme() && file_exists(get_stylesheet_directory() . $rel_path)) {
|
520 |
+
$result = get_stylesheet_directory() . $rel_path;
|
521 |
+
} elseif (file_exists(get_template_directory() . $rel_path)) {
|
522 |
+
$result = get_template_directory() . $rel_path;
|
523 |
+
} else {
|
524 |
+
$result = false;
|
525 |
+
}
|
526 |
|
527 |
+
FW_File_Cache::set($cache_key, $result);
|
|
|
|
|
528 |
|
529 |
+
return $result;
|
530 |
+
}
|
531 |
}
|
532 |
|
533 |
/**
|
753 |
* @type int Limit the number of options that will be collected
|
754 |
*/
|
755 |
'limit' => 0,
|
756 |
+
/**
|
757 |
+
* @type callable Executed on each collected option
|
758 |
+
* @since 2.6.0
|
759 |
+
*/
|
760 |
+
'callback' => null,
|
761 |
);
|
762 |
|
763 |
static $access_key = null;
|
764 |
|
|
|
|
|
|
|
|
|
765 |
if (empty($options)) {
|
766 |
return;
|
767 |
}
|
768 |
|
|
|
|
|
769 |
if (empty($_recursion_data)) {
|
770 |
+
if (is_null($access_key)) {
|
771 |
+
$access_key = new FW_Access_Key('fw_collect_options');
|
772 |
+
}
|
773 |
+
|
774 |
+
$settings = array_merge($default_settings, $settings);
|
775 |
+
|
776 |
$_recursion_data = array(
|
777 |
'level' => 1,
|
778 |
'access_key' => $access_key,
|
779 |
// todo: maybe add 'parent' => array('id' => '{id}', 'type' => 'container|option') ?
|
780 |
);
|
781 |
+
} elseif (!(
|
782 |
+
isset($_recursion_data['access_key'])
|
783 |
+
&&
|
784 |
+
($_recursion_data['access_key'] instanceof FW_Access_Key)
|
785 |
+
&&
|
786 |
+
($_recursion_data['access_key']->get_key() === 'fw_collect_options')
|
787 |
+
)) {
|
788 |
trigger_error('Call not allowed', E_USER_ERROR);
|
789 |
}
|
790 |
|
830 |
} else {
|
831 |
$result[$option_id] = &$option;
|
832 |
}
|
833 |
+
|
834 |
+
if ($settings['callback']) {
|
835 |
+
call_user_func_array($settings['callback'], array(array(
|
836 |
+
'group' => 'container',
|
837 |
+
'id' => $option_id,
|
838 |
+
'option' => &$option,
|
839 |
+
)));
|
840 |
+
}
|
841 |
} while(false);
|
842 |
|
843 |
fw_collect_options(
|
909 |
} else {
|
910 |
$result[$option_id] = &$option;
|
911 |
}
|
912 |
+
|
913 |
+
if ($settings['callback']) {
|
914 |
+
call_user_func_array($settings['callback'], array(array(
|
915 |
+
'group' => 'option',
|
916 |
+
'id' => $option_id,
|
917 |
+
'option' => &$option,
|
918 |
+
)));
|
919 |
+
}
|
920 |
} else {
|
921 |
trigger_error('Invalid option: '. $option_id, E_USER_WARNING);
|
922 |
}
|
framework/helpers/type/class-fw-type-register.php
CHANGED
@@ -1,6 +1,10 @@
|
|
1 |
<?php if ( ! defined( 'FW' ) ) die( 'Forbidden' );
|
2 |
|
3 |
/**
|
|
|
|
|
|
|
|
|
4 |
* @since 2.4.10
|
5 |
*/
|
6 |
abstract class FW_Type_Register {
|
@@ -14,13 +18,13 @@ abstract class FW_Type_Register {
|
|
14 |
/**
|
15 |
* @var FW_Type[]
|
16 |
*/
|
17 |
-
|
18 |
|
19 |
/**
|
20 |
* Only these access keys will be able to access the registered types
|
21 |
* @var array {'key': true}
|
22 |
*/
|
23 |
-
|
24 |
|
25 |
final public function __construct($access_keys) {
|
26 |
{
|
@@ -66,4 +70,20 @@ abstract class FW_Type_Register {
|
|
66 |
|
67 |
return $this->types;
|
68 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
69 |
}
|
1 |
<?php if ( ! defined( 'FW' ) ) die( 'Forbidden' );
|
2 |
|
3 |
/**
|
4 |
+
* Give users the possibility to register a type safely
|
5 |
+
* Instead of doing apply_filters('my_types', $types) where someone can mess your data
|
6 |
+
* with this class you do do_action('register_my_types', $types)
|
7 |
+
* and users will be able only to $types->register(new Allowed_Type_Class())
|
8 |
* @since 2.4.10
|
9 |
*/
|
10 |
abstract class FW_Type_Register {
|
18 |
/**
|
19 |
* @var FW_Type[]
|
20 |
*/
|
21 |
+
protected $types = array();
|
22 |
|
23 |
/**
|
24 |
* Only these access keys will be able to access the registered types
|
25 |
* @var array {'key': true}
|
26 |
*/
|
27 |
+
protected $access_keys = array();
|
28 |
|
29 |
final public function __construct($access_keys) {
|
30 |
{
|
70 |
|
71 |
return $this->types;
|
72 |
}
|
73 |
+
|
74 |
+
/**
|
75 |
+
* @param FW_Access_Key $access_key
|
76 |
+
* @param $type
|
77 |
+
*
|
78 |
+
* @return FW_Type|null
|
79 |
+
* @internal
|
80 |
+
* @since 2.5.12
|
81 |
+
*/
|
82 |
+
public function _get_type(FW_Access_Key $access_key, $type) {
|
83 |
+
if (!isset($this->access_keys[$access_key->get_key()])) {
|
84 |
+
trigger_error('Method call denied', E_USER_ERROR);
|
85 |
+
}
|
86 |
+
|
87 |
+
return isset($this->types[$type]) ? $this->types[$type] : null;
|
88 |
+
}
|
89 |
}
|
framework/includes/hooks.php
CHANGED
@@ -41,63 +41,6 @@
|
|
41 |
add_action('fw_container_types_init', '_action_fw_init_container_types');
|
42 |
}
|
43 |
|
44 |
-
/**
|
45 |
-
* Term Meta
|
46 |
-
*/
|
47 |
-
{
|
48 |
-
/**
|
49 |
-
* Prepare $wpdb as soon as it's possible
|
50 |
-
* @internal
|
51 |
-
*/
|
52 |
-
function _action_term_meta_wpdb_fix() {
|
53 |
-
/** @var WPDB $wpdb */
|
54 |
-
global $wpdb;
|
55 |
-
|
56 |
-
$wpdb->fw_termmeta = $wpdb->prefix . 'fw_termmeta';
|
57 |
-
|
58 |
-
{
|
59 |
-
require_once dirname(__FILE__) .'/term-meta/function_fw_term_meta_setup_blog.php';
|
60 |
-
_fw_term_meta_setup_blog();
|
61 |
-
}
|
62 |
-
}
|
63 |
-
add_action( 'switch_blog', '_action_term_meta_wpdb_fix', 3 );
|
64 |
-
|
65 |
-
_action_term_meta_wpdb_fix();
|
66 |
-
|
67 |
-
/**
|
68 |
-
* When a term is deleted, delete its meta.
|
69 |
-
*
|
70 |
-
* @param mixed $term_id
|
71 |
-
*
|
72 |
-
* @return void
|
73 |
-
* @internal
|
74 |
-
*/
|
75 |
-
function _action_fw_delete_term( $term_id ) {
|
76 |
-
$term_id = (int) $term_id;
|
77 |
-
|
78 |
-
if ( ! $term_id ) {
|
79 |
-
return;
|
80 |
-
}
|
81 |
-
|
82 |
-
/** @var WPDB $wpdb */
|
83 |
-
global $wpdb;
|
84 |
-
|
85 |
-
$wpdb->delete( $wpdb->fw_termmeta, array( 'fw_term_id' => $term_id ), array( '%d' ) );
|
86 |
-
}
|
87 |
-
add_action( 'delete_term', '_action_fw_delete_term' );
|
88 |
-
|
89 |
-
/**
|
90 |
-
* Make sure to setup the fw_termmeta table
|
91 |
-
* (useful in cases when the framework is used not as a plugin)
|
92 |
-
* @internal
|
93 |
-
*/
|
94 |
-
function _action_fw_setup_term_meta_after_theme_switch() {
|
95 |
-
require_once dirname(__FILE__) .'/term-meta/function_fw_term_meta_setup_blog.php';
|
96 |
-
_fw_term_meta_setup_blog();
|
97 |
-
}
|
98 |
-
add_action('after_switch_theme', '_action_fw_setup_term_meta_after_theme_switch', 7);
|
99 |
-
}
|
100 |
-
|
101 |
/**
|
102 |
* Custom Github API service
|
103 |
* Provides the same responses but is "unlimited"
|
@@ -109,3 +52,27 @@ function _fw_filter_github_api_url($url) {
|
|
109 |
return 'http://github-api-cache.unyson.io';
|
110 |
}
|
111 |
add_filter('fw_github_api_url', '_fw_filter_github_api_url');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
41 |
add_action('fw_container_types_init', '_action_fw_init_container_types');
|
42 |
}
|
43 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
44 |
/**
|
45 |
* Custom Github API service
|
46 |
* Provides the same responses but is "unlimited"
|
52 |
return 'http://github-api-cache.unyson.io';
|
53 |
}
|
54 |
add_filter('fw_github_api_url', '_fw_filter_github_api_url');
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Javascript events related to tinymce init
|
58 |
+
* @since 2.6.0
|
59 |
+
*/
|
60 |
+
{
|
61 |
+
add_action('wp_tiny_mce_init', '_fw_action_tiny_mce_init');
|
62 |
+
function _fw_action_tiny_mce_init($mce_settings) {
|
63 |
+
?>
|
64 |
+
<script type="text/javascript">
|
65 |
+
if (typeof fwEvents != 'undefined') { fwEvents.trigger('fw:tinymce:init:before'); }
|
66 |
+
</script>
|
67 |
+
<?php
|
68 |
+
}
|
69 |
+
|
70 |
+
add_action('after_wp_tiny_mce', '_fw_action_after_wp_tiny_mce');
|
71 |
+
function _fw_action_after_wp_tiny_mce($mce_settings) {
|
72 |
+
?>
|
73 |
+
<script type="text/javascript">
|
74 |
+
if (typeof fwEvents != 'undefined') { fwEvents.trigger('fw:tinymce:init:after'); }
|
75 |
+
</script>
|
76 |
+
<?php
|
77 |
+
}
|
78 |
+
}
|
framework/includes/option-types/addable-box/static/js/scripts.js
CHANGED
@@ -253,19 +253,16 @@ jQuery(document).ready(function ($) {
|
|
253 |
|
254 |
$boxes.append($newBox);
|
255 |
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
$newBox
|
267 |
-
);
|
268 |
-
}
|
269 |
}
|
270 |
|
271 |
methods.initControls($newBox);
|
253 |
|
254 |
$boxes.append($newBox);
|
255 |
|
256 |
+
// Re-render wp-editor
|
257 |
+
if (
|
258 |
+
window.fwWpEditorRefreshIds
|
259 |
+
&&
|
260 |
+
$newBox.find('.fw-option-type-wp-editor:first').length
|
261 |
+
) {
|
262 |
+
fwWpEditorRefreshIds(
|
263 |
+
$newBox.find('.fw-option-type-wp-editor textarea:first').attr('id'),
|
264 |
+
$newBox
|
265 |
+
);
|
|
|
|
|
|
|
266 |
}
|
267 |
|
268 |
methods.initControls($newBox);
|
framework/includes/option-types/addable-option/static/js/scripts.js
CHANGED
@@ -71,9 +71,19 @@ jQuery(document).ready(function ($) {
|
|
71 |
|
72 |
$button.attr('data-increment', increment + 1);
|
73 |
|
74 |
-
$options.append(
|
75 |
-
|
76 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
77 |
|
78 |
// remove focus form "Add" button to prevent pressing space/enter to add easy many options
|
79 |
$newOption.find('input,select,textarea').first().focus();
|
71 |
|
72 |
$button.attr('data-increment', increment + 1);
|
73 |
|
74 |
+
$options.append($newOption);
|
75 |
+
|
76 |
+
// Re-render wp-editor
|
77 |
+
if (
|
78 |
+
window.fwWpEditorRefreshIds
|
79 |
+
&&
|
80 |
+
$newOption.find('.fw-option-type-wp-editor:first').length
|
81 |
+
) {
|
82 |
+
fwWpEditorRefreshIds(
|
83 |
+
$newOption.find('.fw-option-type-wp-editor textarea:first').attr('id'),
|
84 |
+
$newOption
|
85 |
+
);
|
86 |
+
}
|
87 |
|
88 |
// remove focus form "Add" button to prevent pressing space/enter to add easy many options
|
89 |
$newOption.find('input,select,textarea').first().focus();
|
framework/includes/option-types/addable-popup/class-fw-option-type-addable-popup.php
CHANGED
@@ -45,18 +45,26 @@ class FW_Option_Type_Addable_Popup extends FW_Option_Type
|
|
45 |
{
|
46 |
unset($option['attr']['name'], $option['attr']['value']);
|
47 |
|
48 |
-
$option['attr']['data-for-js'] =
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
54 |
));
|
55 |
|
56 |
$sortable_image = fw_get_framework_directory_uri('/static/img/sort-vertically.png');
|
57 |
|
58 |
return fw_render_view(
|
59 |
-
fw_get_framework_directory('/includes/option-types/' . $this->get_type() . '/
|
60 |
compact('id', 'option', 'data', 'sortable_image')
|
61 |
);
|
62 |
}
|
45 |
{
|
46 |
unset($option['attr']['name'], $option['attr']['value']);
|
47 |
|
48 |
+
$option['attr']['data-for-js'] =
|
49 |
+
/**
|
50 |
+
* Prevent js error when the generated html is used in another option type js template with {{...}}
|
51 |
+
* Do this trick because {{ is not escaped/encoded by fw_htmlspecialchars()
|
52 |
+
* Fixes https://github.com/ThemeFuse/Unyson/issues/1877
|
53 |
+
*/
|
54 |
+
json_encode(explode('{{',
|
55 |
+
json_encode(array(
|
56 |
+
'title' => empty($option['popup-title']) ? $option['label'] : $option['popup-title'],
|
57 |
+
'options' => $this->transform_options($option['popup-options']),
|
58 |
+
'template' => $option['template'],
|
59 |
+
'size' => $option['size'],
|
60 |
+
'limit' => $option['limit']
|
61 |
+
))
|
62 |
));
|
63 |
|
64 |
$sortable_image = fw_get_framework_directory_uri('/static/img/sort-vertically.png');
|
65 |
|
66 |
return fw_render_view(
|
67 |
+
fw_get_framework_directory('/includes/option-types/' . $this->get_type() . '/view.php'),
|
68 |
compact('id', 'option', 'data', 'sortable_image')
|
69 |
);
|
70 |
}
|
framework/includes/option-types/addable-popup/static/css/styles.css
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
-
.fw-option-type-addable-popup .item{
|
2 |
position: relative;
|
3 |
background-color: #fff;
|
4 |
min-height: 40px;
|
@@ -10,23 +10,23 @@
|
|
10 |
word-wrap: break-word;
|
11 |
}
|
12 |
|
13 |
-
.fw-option-type-addable-popup .item
|
14 |
border-top: 1px dashed #E1E1E1;
|
15 |
}
|
16 |
|
17 |
-
.fw-option-type-addable-popup .items-wrapper{
|
18 |
border: 1px solid #e1e1e1;
|
19 |
margin-bottom: 20px;
|
20 |
}
|
21 |
|
22 |
-
.fw-option-type-addable-popup .delete-item{
|
23 |
position: absolute;
|
24 |
right: 7px;
|
25 |
top:50%;
|
26 |
margin-top: -10px;
|
27 |
}
|
28 |
|
29 |
-
.fw-option-type-addable-popup .sort-item{
|
30 |
position: absolute;
|
31 |
left: 11px;
|
32 |
top:50%;
|
@@ -34,10 +34,7 @@
|
|
34 |
width: 7px;
|
35 |
}
|
36 |
|
37 |
-
.fw-option-type-addable-popup .item
|
38 |
-
display: none;
|
39 |
-
}
|
40 |
-
|
41 |
.fw-option-type-addable-popup:not(.is-sortable) .sort-item {
|
42 |
display: none;
|
43 |
}
|
1 |
+
.fw-option-type-addable-popup .item {
|
2 |
position: relative;
|
3 |
background-color: #fff;
|
4 |
min-height: 40px;
|
10 |
word-wrap: break-word;
|
11 |
}
|
12 |
|
13 |
+
.fw-option-type-addable-popup .item + .item {
|
14 |
border-top: 1px dashed #E1E1E1;
|
15 |
}
|
16 |
|
17 |
+
.fw-option-type-addable-popup .items-wrapper {
|
18 |
border: 1px solid #e1e1e1;
|
19 |
margin-bottom: 20px;
|
20 |
}
|
21 |
|
22 |
+
.fw-option-type-addable-popup .delete-item {
|
23 |
position: absolute;
|
24 |
right: 7px;
|
25 |
top:50%;
|
26 |
margin-top: -10px;
|
27 |
}
|
28 |
|
29 |
+
.fw-option-type-addable-popup .sort-item {
|
30 |
position: absolute;
|
31 |
left: 11px;
|
32 |
top:50%;
|
34 |
width: 7px;
|
35 |
}
|
36 |
|
37 |
+
.fw-option-type-addable-popup .default-item,
|
|
|
|
|
|
|
38 |
.fw-option-type-addable-popup:not(.is-sortable) .sort-item {
|
39 |
display: none;
|
40 |
}
|
framework/includes/option-types/addable-popup/static/js/addable-popup.js
CHANGED
@@ -1,16 +1,18 @@
|
|
1 |
(function ($, _, fwEvents, window) {
|
2 |
var addablePopup = function () {
|
3 |
var $this = $(this),
|
4 |
-
$defaultItem = $this.find('.item
|
5 |
nodes = {
|
6 |
$optionWrapper: $this,
|
7 |
$addButton: $this.find('.add-new-item'),
|
8 |
$itemsWrapper: $this.find('.items-wrapper'),
|
9 |
getDefaultItem: function () {
|
10 |
-
return $defaultItem.clone().removeClass('default');
|
11 |
}
|
12 |
},
|
13 |
-
data = JSON.parse(
|
|
|
|
|
14 |
utils = {
|
15 |
modal: new fw.OptionsModal({
|
16 |
title: data.title,
|
@@ -18,10 +20,10 @@
|
|
18 |
size : data.size
|
19 |
}),
|
20 |
countItems: function () {
|
21 |
-
return nodes.$itemsWrapper.find('.item
|
22 |
},
|
23 |
removeDefaultItem: function () {
|
24 |
-
nodes.$
|
25 |
},
|
26 |
toogleNodes : function(){
|
27 |
utils.toogleItemsWrapper();
|
@@ -54,7 +56,7 @@
|
|
54 |
}
|
55 |
|
56 |
nodes.$itemsWrapper.sortable({
|
57 |
-
items: '.item
|
58 |
cursor: 'move',
|
59 |
distance: 2,
|
60 |
tolerance: 'pointer',
|
@@ -73,7 +75,7 @@
|
|
73 |
});
|
74 |
},
|
75 |
initItemsTemplates: function () {
|
76 |
-
var $items = nodes.$itemsWrapper.find('.item
|
77 |
if ($items.length > 0) {
|
78 |
$items.each(function () {
|
79 |
utils.editItem($(this), JSON.parse($(this).find('input').val()));
|
@@ -134,7 +136,7 @@
|
|
134 |
nodes.$optionWrapper.trigger('change'); // for customizer
|
135 |
});
|
136 |
|
137 |
-
nodes.$itemsWrapper.on('click', '.item', function (e) {
|
138 |
e.preventDefault();
|
139 |
|
140 |
var values = {};
|
1 |
(function ($, _, fwEvents, window) {
|
2 |
var addablePopup = function () {
|
3 |
var $this = $(this),
|
4 |
+
$defaultItem = $this.find('.default-item:first'),
|
5 |
nodes = {
|
6 |
$optionWrapper: $this,
|
7 |
$addButton: $this.find('.add-new-item'),
|
8 |
$itemsWrapper: $this.find('.items-wrapper'),
|
9 |
getDefaultItem: function () {
|
10 |
+
return $defaultItem.clone().removeClass('default-item').addClass('item');
|
11 |
}
|
12 |
},
|
13 |
+
data = JSON.parse(
|
14 |
+
JSON.parse(nodes.$optionWrapper.attr('data-for-js')).join('{{') // check option php class
|
15 |
+
),
|
16 |
utils = {
|
17 |
modal: new fw.OptionsModal({
|
18 |
title: data.title,
|
20 |
size : data.size
|
21 |
}),
|
22 |
countItems: function () {
|
23 |
+
return nodes.$itemsWrapper.find('> .item').length;
|
24 |
},
|
25 |
removeDefaultItem: function () {
|
26 |
+
nodes.$optionWrapper.find('.default-item:first').remove();
|
27 |
},
|
28 |
toogleNodes : function(){
|
29 |
utils.toogleItemsWrapper();
|
56 |
}
|
57 |
|
58 |
nodes.$itemsWrapper.sortable({
|
59 |
+
items: '> .item',
|
60 |
cursor: 'move',
|
61 |
distance: 2,
|
62 |
tolerance: 'pointer',
|
75 |
});
|
76 |
},
|
77 |
initItemsTemplates: function () {
|
78 |
+
var $items = nodes.$itemsWrapper.find('> .item');
|
79 |
if ($items.length > 0) {
|
80 |
$items.each(function () {
|
81 |
utils.editItem($(this), JSON.parse($(this).find('input').val()));
|
136 |
nodes.$optionWrapper.trigger('change'); // for customizer
|
137 |
});
|
138 |
|
139 |
+
nodes.$itemsWrapper.on('click', '> .item', function (e) {
|
140 |
e.preventDefault();
|
141 |
|
142 |
var values = {};
|
framework/includes/option-types/addable-popup/{views/view.php → view.php}
RENAMED
@@ -17,24 +17,12 @@ if ($option['sortable']) {
|
|
17 |
$increment_placeholder = '###-addable-popup-increment-'. fw_rand_md5() .'-###';
|
18 |
?>
|
19 |
<div <?php echo fw_attr_to_html($attr); ?>>
|
|
|
|
|
|
|
|
|
|
|
20 |
<div class="items-wrapper">
|
21 |
-
<!-- Fixes https://github.com/ThemeFuse/Unyson/issues/1278 -->
|
22 |
-
<?php echo fw()->backend->option_type('hidden')->render($id, array('value' => '~'), array(
|
23 |
-
'id_prefix' => $data['id_prefix'],
|
24 |
-
'name_prefix' => $data['name_prefix'],
|
25 |
-
)); ?>
|
26 |
-
<div class="item default">
|
27 |
-
<div class="input-wrapper">
|
28 |
-
<?php echo fw()->backend->option_type('hidden')->render('', array('value' => '[]'), array(
|
29 |
-
'id_prefix' => $data['id_prefix'] . $id . '-' . $increment_placeholder,
|
30 |
-
'name_prefix' => $data['name_prefix'] . '[' . $id . ']',
|
31 |
-
)); ?>
|
32 |
-
</div>
|
33 |
-
<img src="<?php echo esc_attr($sortable_image); ?>" class="sort-item"/>
|
34 |
-
|
35 |
-
<div class="content"></div>
|
36 |
-
<a href="#" class="dashicons fw-x delete-item"></a>
|
37 |
-
</div>
|
38 |
<?php foreach ($data['value'] as $key => $value): ?>
|
39 |
<div class="item">
|
40 |
<div class="input-wrapper">
|
@@ -50,7 +38,18 @@ $increment_placeholder = '###-addable-popup-increment-'. fw_rand_md5() .'-###';
|
|
50 |
</div>
|
51 |
<?php endforeach; ?>
|
52 |
</div>
|
53 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
54 |
<?php
|
55 |
echo fw_html_tag('button', array(
|
56 |
'type' => 'button',
|
17 |
$increment_placeholder = '###-addable-popup-increment-'. fw_rand_md5() .'-###';
|
18 |
?>
|
19 |
<div <?php echo fw_attr_to_html($attr); ?>>
|
20 |
+
<!-- Fixes https://github.com/ThemeFuse/Unyson/issues/1278 -->
|
21 |
+
<?php echo fw()->backend->option_type('hidden')->render($id, array('value' => '~'), array(
|
22 |
+
'id_prefix' => $data['id_prefix'],
|
23 |
+
'name_prefix' => $data['name_prefix'],
|
24 |
+
)); ?>
|
25 |
<div class="items-wrapper">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
26 |
<?php foreach ($data['value'] as $key => $value): ?>
|
27 |
<div class="item">
|
28 |
<div class="input-wrapper">
|
38 |
</div>
|
39 |
<?php endforeach; ?>
|
40 |
</div>
|
41 |
+
<div class="default-item">
|
42 |
+
<div class="input-wrapper">
|
43 |
+
<?php echo fw()->backend->option_type('hidden')->render('', array('value' => '[]'), array(
|
44 |
+
'id_prefix' => $data['id_prefix'] . $id . '-' . $increment_placeholder,
|
45 |
+
'name_prefix' => $data['name_prefix'] . '[' . $id . ']',
|
46 |
+
)); ?>
|
47 |
+
</div>
|
48 |
+
<img src="<?php echo esc_attr($sortable_image); ?>" class="sort-item"/>
|
49 |
+
|
50 |
+
<div class="content"></div>
|
51 |
+
<a href="#" class="dashicons fw-x delete-item"></a>
|
52 |
+
</div>
|
53 |
<?php
|
54 |
echo fw_html_tag('button', array(
|
55 |
'type' => 'button',
|
framework/includes/option-types/color-picker/static/js/scripts.js
CHANGED
@@ -2,7 +2,7 @@ jQuery(document).ready(function($){
|
|
2 |
var helpers = {
|
3 |
optionClass: 'fw-option-type-color-picker',
|
4 |
eventNamespace: '.fwOptionTypeColorPicker',
|
5 |
-
colorRegex: /^#[a-f0-9]{3}([a-f0-9]{3})
|
6 |
localized: window._fw_option_type_color_picker_localized,
|
7 |
/**
|
8 |
* Return true if color is dark
|
2 |
var helpers = {
|
3 |
optionClass: 'fw-option-type-color-picker',
|
4 |
eventNamespace: '.fwOptionTypeColorPicker',
|
5 |
+
colorRegex: /^#[a-f0-9]{3}([a-f0-9]{3})?$/i,
|
6 |
localized: window._fw_option_type_color_picker_localized,
|
7 |
/**
|
8 |
* Return true if color is dark
|
framework/includes/option-types/icon-v2/static/js/icon-picker.js
CHANGED
@@ -13,9 +13,32 @@ window.fwOptionTypeIconV2Picker = (function ($) {
|
|
13 |
$(document).on(
|
14 |
'input',
|
15 |
'.fw-icon-v2-icons-library .fw-icon-v2-toolbar input',
|
16 |
-
|
17 |
);
|
18 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
return {
|
20 |
pick: pick
|
21 |
};
|
@@ -439,5 +462,5 @@ window.fwOptionTypeIconV2Picker = (function ($) {
|
|
439 |
).height() - toolbarHeight - 50
|
440 |
);
|
441 |
}
|
442 |
-
|
443 |
})(jQuery);
|
|
13 |
$(document).on(
|
14 |
'input',
|
15 |
'.fw-icon-v2-icons-library .fw-icon-v2-toolbar input',
|
16 |
+
handleInput
|
17 |
);
|
18 |
|
19 |
+
var throttledApplyFilters = _.throttle(applyFilters, 200);
|
20 |
+
|
21 |
+
var previousSearch = '';
|
22 |
+
|
23 |
+
function handleInput () {
|
24 |
+
console.log(previousSearch);
|
25 |
+
|
26 |
+
if (
|
27 |
+
previousSearch.trim().length === 0
|
28 |
+
&&
|
29 |
+
$(this).val().trim().length === 0
|
30 |
+
) return;
|
31 |
+
|
32 |
+
if ( $(this).val().trim().length === 0 ) {
|
33 |
+
throttledApplyFilters();
|
34 |
+
}
|
35 |
+
|
36 |
+
if ($(this).val().trim().length > 2)
|
37 |
+
throttledApplyFilters();
|
38 |
+
|
39 |
+
previousSearch = $(this).val();
|
40 |
+
}
|
41 |
+
|
42 |
return {
|
43 |
pick: pick
|
44 |
};
|
462 |
).height() - toolbarHeight - 50
|
463 |
);
|
464 |
}
|
|
|
465 |
})(jQuery);
|
466 |
+
|
framework/includes/option-types/image-picker/class-fw-option-type-image-picker.php
CHANGED
@@ -117,8 +117,7 @@ class Fw_Option_Type_Image_Picker extends FW_Option_Type
|
|
117 |
$attr['selected'] = 'selected';
|
118 |
}
|
119 |
|
120 |
-
if (is_string($choice)) {
|
121 |
-
// is 'http://.../small.png'
|
122 |
$choice = array(
|
123 |
'small' => array(
|
124 |
'src' => $choice
|
@@ -126,16 +125,14 @@ class Fw_Option_Type_Image_Picker extends FW_Option_Type
|
|
126 |
);
|
127 |
}
|
128 |
|
129 |
-
if (is_string($choice['small'])) {
|
130 |
-
// is 'http://.../small.png'
|
131 |
$choice['small'] = array(
|
132 |
'src' => $choice['small']
|
133 |
);
|
134 |
}
|
135 |
$attr['data-small-img-attr'] = json_encode($choice['small']);
|
136 |
|
137 |
-
// required by image-picker plugin
|
138 |
-
$attr['data-img-src'] = $choice['small']['src'];
|
139 |
|
140 |
if (!empty($choice['large'])) {
|
141 |
if (is_string($choice['large'])) {
|
@@ -155,6 +152,10 @@ class Fw_Option_Type_Image_Picker extends FW_Option_Type
|
|
155 |
$attr['data-extra-data'] = json_encode($choice['data']);
|
156 |
}
|
157 |
|
|
|
|
|
|
|
|
|
158 |
$html .= fw_html_tag('option', $attr, fw_htmlspecialchars(isset($choice['label']) ? $choice['label'] : ''));
|
159 |
}
|
160 |
|
117 |
$attr['selected'] = 'selected';
|
118 |
}
|
119 |
|
120 |
+
if (is_string($choice)) { // is 'http://.../small.png'
|
|
|
121 |
$choice = array(
|
122 |
'small' => array(
|
123 |
'src' => $choice
|
125 |
);
|
126 |
}
|
127 |
|
128 |
+
if (is_string($choice['small'])) { // is 'http://.../small.png'
|
|
|
129 |
$choice['small'] = array(
|
130 |
'src' => $choice['small']
|
131 |
);
|
132 |
}
|
133 |
$attr['data-small-img-attr'] = json_encode($choice['small']);
|
134 |
|
135 |
+
$attr['data-img-src'] = $choice['small']['src']; // required by image-picker plugin
|
|
|
136 |
|
137 |
if (!empty($choice['large'])) {
|
138 |
if (is_string($choice['large'])) {
|
152 |
$attr['data-extra-data'] = json_encode($choice['data']);
|
153 |
}
|
154 |
|
155 |
+
if (!empty($choice['attr'])) {
|
156 |
+
$attr = array_merge($choice['attr'], $attr);
|
157 |
+
}
|
158 |
+
|
159 |
$html .= fw_html_tag('option', $attr, fw_htmlspecialchars(isset($choice['label']) ? $choice['label'] : ''));
|
160 |
}
|
161 |
|
framework/includes/option-types/oembed/static/js/oembed.js
CHANGED
@@ -1,23 +1,34 @@
|
|
1 |
(function ($, _, fwEvents) {
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
var oembed = function () {
|
3 |
var $wrapper = $(this);
|
4 |
var $input = $wrapper.find('input[type=text]');
|
5 |
var $iframeWrapper = $wrapper.find('.fw-oembed-preview');
|
6 |
|
7 |
$input.on('input',
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
|
|
|
|
|
|
|
|
|
|
21 |
);
|
22 |
};
|
23 |
|
1 |
(function ($, _, fwEvents) {
|
2 |
+
|
3 |
+
var is_url = function(str) {
|
4 |
+
var pattern = new RegExp(/^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/, 'i');
|
5 |
+
return pattern.test(str);
|
6 |
+
};
|
7 |
+
|
8 |
var oembed = function () {
|
9 |
var $wrapper = $(this);
|
10 |
var $input = $wrapper.find('input[type=text]');
|
11 |
var $iframeWrapper = $wrapper.find('.fw-oembed-preview');
|
12 |
|
13 |
$input.on('input',
|
14 |
+
_.debounce(function () {
|
15 |
+
if( $input.val() && is_url( $input.val() ) ) {
|
16 |
+
wp.ajax.post(
|
17 |
+
'get_oembed_response',
|
18 |
+
{
|
19 |
+
'_nonce': $wrapper.data('nonce'),
|
20 |
+
'preview': $wrapper.data('preview'),
|
21 |
+
'url': $input.val()
|
22 |
+
}).done(function (data) {
|
23 |
+
$iframeWrapper.html(data.response);
|
24 |
+
}).fail(function () {
|
25 |
+
$iframeWrapper.html('');
|
26 |
+
console.error('Get Oembed Response: Ajax error.', error);
|
27 |
+
})
|
28 |
+
} else {
|
29 |
+
$iframeWrapper.html('');
|
30 |
+
}
|
31 |
+
}, 300)
|
32 |
);
|
33 |
};
|
34 |
|
framework/includes/option-types/rgba-color-picker/static/js/scripts.js
CHANGED
@@ -35,7 +35,7 @@ jQuery(function($){
|
|
35 |
var helpers = {
|
36 |
optionClass: 'fw-option-type-rgba-color-picker',
|
37 |
eventNamespace: '.fwOptionTypeRgbaColorPicker',
|
38 |
-
hexColorRegex: /^#[a-f0-9]{3}([a-f0-9]{3})
|
39 |
localized: window._fw_option_type_rgba_color_picker_localized,
|
40 |
increment: 0,
|
41 |
isColorDark: function(rgbaColor) {
|
@@ -97,7 +97,7 @@ jQuery(function($){
|
|
97 |
*/
|
98 |
$input.one('focus', function(){
|
99 |
if (!$.trim($input.val()).length) { // If the input value is empty, there a glitches with opacity slider
|
100 |
-
$input.val('rgba(
|
101 |
}
|
102 |
|
103 |
$input.iris({
|
35 |
var helpers = {
|
36 |
optionClass: 'fw-option-type-rgba-color-picker',
|
37 |
eventNamespace: '.fwOptionTypeRgbaColorPicker',
|
38 |
+
hexColorRegex: /^#[a-f0-9]{3}([a-f0-9]{3})?$/i,
|
39 |
localized: window._fw_option_type_rgba_color_picker_localized,
|
40 |
increment: 0,
|
41 |
isColorDark: function(rgbaColor) {
|
97 |
*/
|
98 |
$input.one('focus', function(){
|
99 |
if (!$.trim($input.val()).length) { // If the input value is empty, there a glitches with opacity slider
|
100 |
+
$input.val('rgba(255,255,255,1)');
|
101 |
}
|
102 |
|
103 |
$input.iris({
|
framework/includes/option-types/wp-editor/includes/class-fw-wp-editor-settings.php
CHANGED
@@ -182,17 +182,19 @@ class FW_WP_Editor_Manager {
|
|
182 |
/**
|
183 |
* Loop thought all settings and decode json values
|
184 |
*/
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
|
|
|
|
196 |
}
|
197 |
}
|
198 |
|
182 |
/**
|
183 |
* Loop thought all settings and decode json values
|
184 |
*/
|
185 |
+
if ($mce_settings) {
|
186 |
+
foreach ($mce_settings as &$setting) {
|
187 |
+
if (
|
188 |
+
is_string($setting)
|
189 |
+
&&
|
190 |
+
!empty($setting)
|
191 |
+
&&
|
192 |
+
in_array($setting{0}, array('[', '{'), true)
|
193 |
+
&&
|
194 |
+
! is_null($decoded = json_decode($setting))
|
195 |
+
) {
|
196 |
+
$setting = $decoded;
|
197 |
+
}
|
198 |
}
|
199 |
}
|
200 |
|
framework/includes/option-types/wp-editor/static/scripts.js
CHANGED
@@ -93,6 +93,9 @@
|
|
93 |
|
94 |
try {
|
95 |
tinymce.init( tinyMCEPreInit.mceInit[ id ] );
|
|
|
|
|
|
|
96 |
} catch(e){
|
97 |
console.error('wp-editor init error', id, e);
|
98 |
return;
|
@@ -101,10 +104,8 @@
|
|
101 |
// fixes https://github.com/ThemeFuse/Unyson/issues/1615
|
102 |
if (typeof window.wpLink != 'undefined') {
|
103 |
try {
|
104 |
-
|
105 |
-
} catch (e) {}
|
106 |
|
107 |
-
try {
|
108 |
window.wpLink.close();
|
109 |
|
110 |
/**
|
93 |
|
94 |
try {
|
95 |
tinymce.init( tinyMCEPreInit.mceInit[ id ] );
|
96 |
+
|
97 |
+
// Remove garbage. This caused lag on page scroll after OptionsModal with wp-editor close
|
98 |
+
$option.on('remove', function(){ tinymce.execCommand('mceRemoveEditor', false, id); });
|
99 |
} catch(e){
|
100 |
console.error('wp-editor init error', id, e);
|
101 |
return;
|
104 |
// fixes https://github.com/ThemeFuse/Unyson/issues/1615
|
105 |
if (typeof window.wpLink != 'undefined') {
|
106 |
try {
|
107 |
+
// do not do .open() // fixes https://github.com/ThemeFuse/Unyson/issues/1901
|
|
|
108 |
|
|
|
109 |
window.wpLink.close();
|
110 |
|
111 |
/**
|
framework/includes/term-meta/function_fw_term_meta_setup_blog.php
DELETED
@@ -1,38 +0,0 @@
|
|
1 |
-
<?php if (!defined('FW')) die('Forbidden');
|
2 |
-
|
3 |
-
if (!function_exists('_fw_term_meta_setup_blog')):
|
4 |
-
|
5 |
-
/**
|
6 |
-
* Setup term meta storage for current blog
|
7 |
-
* @internal
|
8 |
-
*/
|
9 |
-
function _fw_term_meta_setup_blog() {
|
10 |
-
/** @var WPDB $wpdb */
|
11 |
-
global $wpdb;
|
12 |
-
|
13 |
-
$charset_collate = '';
|
14 |
-
if ( ! empty( $wpdb->charset ) ) {
|
15 |
-
$charset_collate = "DEFAULT CHARACTER SET $wpdb->charset";
|
16 |
-
}
|
17 |
-
if ( ! empty( $wpdb->collate ) ) {
|
18 |
-
$charset_collate .= " COLLATE $wpdb->collate";
|
19 |
-
}
|
20 |
-
|
21 |
-
$table_name = $wpdb->prefix .'fw_termmeta'; // note: same table name is used in hooks.php for $wpdb->fw_termmeta
|
22 |
-
|
23 |
-
$tables = $wpdb->get_results( "show tables like '{$table_name}'" );
|
24 |
-
if ( empty( $tables ) ) {
|
25 |
-
$wpdb->query( "CREATE TABLE {$table_name} (
|
26 |
-
meta_id bigint(20) unsigned NOT NULL auto_increment,
|
27 |
-
fw_term_id bigint(20) unsigned NOT NULL default '0',
|
28 |
-
meta_key varchar(255) default NULL,
|
29 |
-
meta_value longtext,
|
30 |
-
PRIMARY KEY (meta_id),
|
31 |
-
KEY fw_term_id (fw_term_id),
|
32 |
-
KEY `meta_key` (`meta_key`(191))
|
33 |
-
) $charset_collate;"
|
34 |
-
);
|
35 |
-
}
|
36 |
-
}
|
37 |
-
|
38 |
-
endif;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
framework/manifest.php
CHANGED
@@ -4,4 +4,4 @@ $manifest = array();
|
|
4 |
|
5 |
$manifest['name'] = __('Unyson', 'fw');
|
6 |
|
7 |
-
$manifest['version'] = '2.
|
4 |
|
5 |
$manifest['name'] = __('Unyson', 'fw');
|
6 |
|
7 |
+
$manifest['version'] = '2.6.0';
|
readme.txt
CHANGED
@@ -1,9 +1,9 @@
|
|
1 |
=== Unyson ===
|
2 |
Contributors: unyson
|
3 |
Tags: page builder, grid, layout, responsive, back up, backup, db backup, dump, migrate, schedule, search engine optimization, seo, media, slideshow, shortcode, slide, slideshare, slideshow, google sitemaps, sitemaps, analytics, google analytics, calendar, event, events, google maps, learning, lessons, sidebars, breadcrumbs, review, portfolio, framework
|
4 |
-
Requires at least: 4.
|
5 |
Tested up to: 4.6
|
6 |
-
Stable tag: 2.
|
7 |
License: GPLv2 or later
|
8 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
9 |
|
@@ -44,9 +44,9 @@ Theme developers can test the compatibility of their themes with new extensions
|
|
44 |
|
45 |
= Minimum Requirements =
|
46 |
|
47 |
-
* WordPress 4.
|
48 |
* PHP version 5.2.4 or greater
|
49 |
-
* MySQL version 5.
|
50 |
|
51 |
= Installation =
|
52 |
|
@@ -83,6 +83,12 @@ Yes; Unyson will work with any theme.
|
|
83 |
|
84 |
== Changelog ==
|
85 |
|
|
|
|
|
|
|
|
|
|
|
|
|
86 |
= 2.5.12 =
|
87 |
* Fixed `wp-editor` option error when used in Theme Settings [#1860](https://github.com/ThemeFuse/Unyson/issues/1860)
|
88 |
|
@@ -305,73 +311,4 @@ Yes; Unyson will work with any theme.
|
|
305 |
* Options can be used in [Customizer](https://codex.wordpress.org/Theme_Customization_API) [#410](https://github.com/ThemeFuse/Unyson/issues/410)
|
306 |
* Fixed [#77](https://github.com/ThemeFuse/Unyson/issues/77)
|
307 |
|
308 |
-
= 2.2.10 =
|
309 |
-
* Fixed [#539](https://github.com/ThemeFuse/Unyson/issues/539)
|
310 |
-
|
311 |
-
= 2.2.9 =
|
312 |
-
* Fixed [#530](https://github.com/ThemeFuse/Unyson/issues/530), [#529](https://github.com/ThemeFuse/Unyson/issues/529), [#502](https://github.com/ThemeFuse/Unyson/issues/502)
|
313 |
-
* Fixes for [#520](https://github.com/ThemeFuse/Unyson/issues/520)
|
314 |
-
* Minor fix in autosave
|
315 |
-
|
316 |
-
= 2.2.8 =
|
317 |
-
* Fixed [#453](https://github.com/ThemeFuse/Unyson/issues/453)
|
318 |
-
* Improved option type `multi-picker` html render [#442](https://github.com/ThemeFuse/Unyson/issues/442)
|
319 |
-
* Option type `rgba-color-picker` optimizations [#442](https://github.com/ThemeFuse/Unyson/issues/442)
|
320 |
-
* `fw_resize()` improvements [#447](https://github.com/ThemeFuse/Unyson/issues/447)
|
321 |
-
* Fixed [#445](https://github.com/ThemeFuse/Unyson/issues/445), [#161](https://github.com/ThemeFuse/Unyson/issues/161), [#484](https://github.com/ThemeFuse/Unyson/issues/484), [#456](https://github.com/ThemeFuse/Unyson/issues/456)
|
322 |
-
* Added the possibility to prevent box auto-close [#466](https://github.com/ThemeFuse/Unyson/issues/466)
|
323 |
-
* Fixed the `_get_value_from_input()` method in some option types [#275](https://github.com/ThemeFuse/Unyson/issues/275#issuecomment-94084590)
|
324 |
-
* Added the `limit` parameter for option type `addable-popup` [#478](https://github.com/ThemeFuse/Unyson/issues/478)
|
325 |
-
* Fixed popup position in IE [#483](https://github.com/ThemeFuse/Unyson/issues/483)
|
326 |
-
* Created `fw_post_options_update` action
|
327 |
-
* Improved post save: Options are saved in revision and autosave. Restore from revision works.
|
328 |
-
|
329 |
-
= 2.2.7 =
|
330 |
-
* Option type `popup` fixes
|
331 |
-
* Added "Show/Hide other extensions" button [#307](https://github.com/ThemeFuse/Unyson/issues/307)
|
332 |
-
* `fw.soleModal` added `afterOpen` and `afterClose` callbacks [#379](https://github.com/ThemeFuse/Unyson/issues/379)
|
333 |
-
* Fixed [#432](https://github.com/ThemeFuse/Unyson/issues/432), [#408](https://github.com/ThemeFuse/Unyson/issues/408)
|
334 |
-
|
335 |
-
= 2.2.6 =
|
336 |
-
* Fixed [#404](https://github.com/ThemeFuse/Unyson/issues/404)
|
337 |
-
* Added the Translation extension in Available Extensions list
|
338 |
-
|
339 |
-
= 2.2.5 =
|
340 |
-
* Fixed [PageBuilder#26](https://github.com/ThemeFuse/Unyson-PageBuilder-Extension/issues/26)
|
341 |
-
|
342 |
-
= 2.2.4 =
|
343 |
-
* Fixed [#398](https://github.com/ThemeFuse/Unyson/issues/398)
|
344 |
-
* Removed option type `runnable` [#399](https://github.com/ThemeFuse/Unyson/issues/399)
|
345 |
-
|
346 |
-
= 2.2.3 =
|
347 |
-
* Fixed [#397](https://github.com/ThemeFuse/Unyson/issues/397), [#394](https://github.com/ThemeFuse/Unyson/issues/394), [#389](https://github.com/ThemeFuse/Unyson/issues/389), [#384](https://github.com/ThemeFuse/Unyson/issues/384), [#355](https://github.com/ThemeFuse/Unyson/issues/355)
|
348 |
-
* Added option type `runnable`
|
349 |
-
|
350 |
-
= 2.2.2 =
|
351 |
-
* Added experimental `$option['option_handler']` [636ed56](https://github.com/ThemeFuse/Unyson/commit/636ed56fe499a4e855b5f49198747460833539a3)
|
352 |
-
* `<input required ... />` works in `fw.OptionsModal` [#274](https://github.com/ThemeFuse/Unyson/issues/274)
|
353 |
-
* Fixed [#381](https://github.com/ThemeFuse/Unyson/issues/381), [#382](https://github.com/ThemeFuse/Unyson/issues/382), [#385](https://github.com/ThemeFuse/Unyson/issues/385), [Shortcodes#15](https://github.com/ThemeFuse/Unyson-Shortcodes-Extension/issues/15)
|
354 |
-
|
355 |
-
= 2.2.1 =
|
356 |
-
* Fixed: Sub-extensions were not loaded [#368](https://github.com/ThemeFuse/Unyson/issues/368)
|
357 |
-
* Fixed: $extension->locate_URI('/...') bug
|
358 |
-
|
359 |
-
= 2.2.0 =
|
360 |
-
* Added the possibility to load extensions from any directory
|
361 |
-
|
362 |
-
```
|
363 |
-
function _filter_my_plugin_extensions($locations) {
|
364 |
-
$locations['/path/to/plugin/extensions'] = 'https://uri.to/plugin/extensions';
|
365 |
-
return $locations;
|
366 |
-
}
|
367 |
-
add_filter('fw_extensions_locations', '_filter_my_plugin_extensions');
|
368 |
-
```
|
369 |
-
|
370 |
-
**Important!** Prefix your extension names to prevent conflicts.
|
371 |
-
|
372 |
-
* Removed `array_merge($old_opts, $new_opts)` from options save [#266](https://github.com/ThemeFuse/Unyson/issues/266)
|
373 |
-
* Tabs, Boxes, Groups, Options are now displayed in the order they are in array (not grouped) [#319](https://github.com/ThemeFuse/Unyson/issues/319)
|
374 |
-
* Option type `multi-picker` fixes [#296](https://github.com/ThemeFuse/Unyson/issues/296)
|
375 |
-
* Added the possibility to use custom `framework-customizations` directory name [#276](https://github.com/ThemeFuse/Unyson/issues/276)
|
376 |
-
* Minor fixes
|
377 |
|
1 |
=== Unyson ===
|
2 |
Contributors: unyson
|
3 |
Tags: page builder, grid, layout, responsive, back up, backup, db backup, dump, migrate, schedule, search engine optimization, seo, media, slideshow, shortcode, slide, slideshare, slideshow, google sitemaps, sitemaps, analytics, google analytics, calendar, event, events, google maps, learning, lessons, sidebars, breadcrumbs, review, portfolio, framework
|
4 |
+
Requires at least: 4.4
|
5 |
Tested up to: 4.6
|
6 |
+
Stable tag: 2.6.0
|
7 |
License: GPLv2 or later
|
8 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
9 |
|
44 |
|
45 |
= Minimum Requirements =
|
46 |
|
47 |
+
* WordPress 4.4 or greater
|
48 |
* PHP version 5.2.4 or greater
|
49 |
+
* MySQL version 5.6 or greater
|
50 |
|
51 |
= Installation =
|
52 |
|
83 |
|
84 |
== Changelog ==
|
85 |
|
86 |
+
= 2.6.0 =
|
87 |
+
* Added [File Cache](https://github.com/ThemeFuse/Unyson/blob/16709330f1acc29453928fce0fafe69a8ea592c7/framework/helpers/class-fw-file-cache.php) [#1828](https://github.com/ThemeFuse/Unyson/issues/1828)
|
88 |
+
* Migration to native term meta [#1745](https://github.com/ThemeFuse/Unyson/issues/1745)
|
89 |
+
* The possibility to [register Available Extensions from theme](https://github.com/ThemeFuse/Unyson/blob/16709330f1acc29453928fce0fafe69a8ea592c7/framework/core/components/extensions/manager/class--fw-extensions-manager.php#L232-L238)
|
90 |
+
* Fixed [#1860](https://github.com/ThemeFuse/Unyson/issues/1860), [#1877](https://github.com/ThemeFuse/Unyson/issues/1877), [#1897](https://github.com/ThemeFuse/Unyson/issues/1897), [#1810](https://github.com/ThemeFuse/Unyson/issues/1810)
|
91 |
+
|
92 |
= 2.5.12 =
|
93 |
* Fixed `wp-editor` option error when used in Theme Settings [#1860](https://github.com/ThemeFuse/Unyson/issues/1860)
|
94 |
|
311 |
* Options can be used in [Customizer](https://codex.wordpress.org/Theme_Customization_API) [#410](https://github.com/ThemeFuse/Unyson/issues/410)
|
312 |
* Fixed [#77](https://github.com/ThemeFuse/Unyson/issues/77)
|
313 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
314 |
|
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 |
* Author: ThemeFuse
|
8 |
* Author URI: http://themefuse.com
|
9 |
* License: GPL2+
|
@@ -38,26 +38,7 @@ if (defined('FW')) {
|
|
38 |
{
|
39 |
/** @internal */
|
40 |
function _action_fw_plugin_activate() {
|
41 |
-
|
42 |
-
require_once dirname(__FILE__) .'/framework/includes/term-meta/function_fw_term_meta_setup_blog.php';
|
43 |
-
|
44 |
-
if (is_multisite() && is_network_admin()) {
|
45 |
-
global $wpdb;
|
46 |
-
|
47 |
-
$blogs = $wpdb->get_col( "SELECT blog_id FROM {$wpdb->blogs} WHERE site_id = '{$wpdb->siteid}'" );
|
48 |
-
foreach ( $blogs as $blog_id ) {
|
49 |
-
switch_to_blog( $blog_id );
|
50 |
-
_fw_term_meta_setup_blog( $blog_id );
|
51 |
-
}
|
52 |
-
|
53 |
-
do {} while ( restore_current_blog() );
|
54 |
-
} else {
|
55 |
-
_fw_term_meta_setup_blog();
|
56 |
-
}
|
57 |
-
}
|
58 |
-
|
59 |
-
// add special option (is used in another action)
|
60 |
-
update_option('_fw_plugin_activated', true, false);
|
61 |
}
|
62 |
register_activation_hook( __FILE__, '_action_fw_plugin_activate' );
|
63 |
|
@@ -69,20 +50,11 @@ if (defined('FW')) {
|
|
69 |
do_action('fw_after_plugin_activate');
|
70 |
}
|
71 |
}
|
72 |
-
add_action(
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
if ( is_plugin_active_for_network( plugin_basename( __FILE__ ) ) ) {
|
78 |
-
require_once dirname(__FILE__) .'/framework/includes/term-meta/function_fw_term_meta_setup_blog.php';
|
79 |
-
|
80 |
-
switch_to_blog( $blog_id );
|
81 |
-
_fw_term_meta_setup_blog();
|
82 |
-
do {} while ( restore_current_blog() );
|
83 |
-
}
|
84 |
-
}
|
85 |
-
add_action( 'wpmu_new_blog', '_action_fw_term_meta_new_blog', 10, 6 );
|
86 |
|
87 |
/**
|
88 |
* @param int $blog_id Blog ID
|
@@ -90,13 +62,11 @@ if (defined('FW')) {
|
|
90 |
* @internal
|
91 |
*/
|
92 |
function _action_fw_delete_blog( $blog_id, $drop ) {
|
93 |
-
if ($drop) {
|
94 |
-
/** @var WPDB $wpdb */
|
95 |
-
global $wpdb;
|
96 |
|
97 |
-
|
98 |
-
|
99 |
-
}
|
100 |
}
|
101 |
}
|
102 |
add_action( 'delete_blog', '_action_fw_delete_blog', 10, 2 );
|
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.6.0
|
7 |
* Author: ThemeFuse
|
8 |
* Author URI: http://themefuse.com
|
9 |
* License: GPL2+
|
38 |
{
|
39 |
/** @internal */
|
40 |
function _action_fw_plugin_activate() {
|
41 |
+
update_option('_fw_plugin_activated', true, false); // add special option (is used in another action)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
42 |
}
|
43 |
register_activation_hook( __FILE__, '_action_fw_plugin_activate' );
|
44 |
|
50 |
do_action('fw_after_plugin_activate');
|
51 |
}
|
52 |
}
|
53 |
+
add_action(
|
54 |
+
'current_screen', // as late as possible, but to be able to make redirects (content not started)
|
55 |
+
'_action_fw_plugin_check_if_was_activated',
|
56 |
+
100
|
57 |
+
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
58 |
|
59 |
/**
|
60 |
* @param int $blog_id Blog ID
|
62 |
* @internal
|
63 |
*/
|
64 |
function _action_fw_delete_blog( $blog_id, $drop ) {
|
65 |
+
if ($drop) {
|
66 |
+
global $wpdb; /** @var WPDB $wpdb */
|
|
|
67 |
|
68 |
+
// delete old termmeta table
|
69 |
+
$wpdb->query("DROP TABLE IF EXISTS `{$wpdb->prefix}fw_termmeta`;");
|
|
|
70 |
}
|
71 |
}
|
72 |
add_action( 'delete_blog', '_action_fw_delete_blog', 10, 2 );
|