Version Description
- ADD: CRON scheduled image generation (New option in settings) - PREMIUM
- FIX: Compatibility with ShortPixel plugin
- FIX: Generating images after importing via XML-RPC
- FIX: Optimization of image generation
Download this release
Release Info
Developer | webtemyk |
Plugin | Auto Post Thumbnail |
Version | 3.9.12 |
Comparing to | |
See all releases |
Code changes from version 3.9.11 to 3.9.12
- admin/assets/css/generate.css +14 -7
- admin/assets/css/generate.less +14 -6
- admin/pages/settings.php +85 -28
- admin/views/tab-generate.php +8 -6
- auto-post-thumbnail.php +2 -2
- includes/class-apt.php +88 -106
- includes/class-plugin.php +2 -13
- includes/class.generate-result.php +14 -10
- includes/image-search/class-google-images.php +14 -10
- libs/factory/processing/boot.php +54 -0
- libs/factory/processing/includes/classes/wp-async-request.php +187 -0
- libs/factory/processing/includes/classes/wp-background-process.php +555 -0
- libs/factory/processing/includes/wp-background-processing.php +27 -0
- preview.jpg +0 -0
- readme.txt +7 -1
admin/assets/css/generate.css
CHANGED
@@ -8,15 +8,22 @@
|
|
8 |
#wapt-generate-page .wapt-chart-container {
|
9 |
position: relative;
|
10 |
}
|
|
|
|
|
|
|
|
|
|
|
11 |
#wapt-generate-page .wapt-chart-percent {
|
12 |
-
position: absolute;
|
13 |
-
left: 55px;
|
14 |
-
top: 75px;
|
15 |
-
line-height: 1;
|
16 |
-
text-align: center;
|
17 |
-
font-size: 40px;
|
18 |
-
font-weight: bold;
|
19 |
color: #afafaf;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
}
|
21 |
#wapt-generate-page #wapt-overview-chart-legend {
|
22 |
overflow: hidden;
|
8 |
#wapt-generate-page .wapt-chart-container {
|
9 |
position: relative;
|
10 |
}
|
11 |
+
#wapt-generate-page .wapt-chart-wrapper {
|
12 |
+
position: relative;
|
13 |
+
width: 200px;
|
14 |
+
height: 200px;
|
15 |
+
}
|
16 |
#wapt-generate-page .wapt-chart-percent {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
color: #afafaf;
|
18 |
+
position: absolute;
|
19 |
+
font-size: 45px;
|
20 |
+
font-weight: 600;
|
21 |
+
left: 50%;
|
22 |
+
bottom: 160px;
|
23 |
+
z-index: 100;
|
24 |
+
transform: translateX(-45%);
|
25 |
+
-webkit-transform: translateX(-45%);
|
26 |
+
-ms-transform: translateX(-45%);
|
27 |
}
|
28 |
#wapt-generate-page #wapt-overview-chart-legend {
|
29 |
overflow: hidden;
|
admin/assets/css/generate.less
CHANGED
@@ -13,15 +13,23 @@
|
|
13 |
position: relative;
|
14 |
}
|
15 |
|
|
|
|
|
|
|
|
|
|
|
|
|
16 |
.wapt-chart-percent {
|
|
|
17 |
position: absolute;
|
18 |
-
left: 50px;
|
19 |
-
top: 65px;
|
20 |
-
line-height: 1;
|
21 |
-
text-align: center;
|
22 |
font-size: 45px;
|
23 |
-
font-weight:
|
24 |
-
|
|
|
|
|
|
|
|
|
|
|
25 |
}
|
26 |
|
27 |
#wapt-overview-chart-legend {
|
13 |
position: relative;
|
14 |
}
|
15 |
|
16 |
+
.wapt-chart-wrapper {
|
17 |
+
position: relative;
|
18 |
+
width: 200px;
|
19 |
+
height: 200px;
|
20 |
+
}
|
21 |
+
|
22 |
.wapt-chart-percent {
|
23 |
+
color: #afafaf;
|
24 |
position: absolute;
|
|
|
|
|
|
|
|
|
25 |
font-size: 45px;
|
26 |
+
font-weight: 600;
|
27 |
+
left: 50%;
|
28 |
+
bottom: 160px;
|
29 |
+
z-index: 100;
|
30 |
+
transform: translateX(-45%);
|
31 |
+
-webkit-transform: translateX(-45%);
|
32 |
+
-ms-transform: translateX(-45%);
|
33 |
}
|
34 |
|
35 |
#wapt-overview-chart-legend {
|
admin/pages/settings.php
CHANGED
@@ -87,23 +87,19 @@ class WAPT_Settings extends WAPT_Page {
|
|
87 |
public function assets( $scripts, $styles ) {
|
88 |
parent::assets( $scripts, $styles );
|
89 |
|
90 |
-
$this->scripts->request(
|
91 |
-
[
|
92 |
'control.list',
|
93 |
'bootstrap.accordion',
|
94 |
'bootstrap.tab',
|
95 |
-
|
96 |
-
|
97 |
-
);
|
98 |
|
99 |
-
$this->styles->request(
|
100 |
-
[
|
101 |
'control.list',
|
102 |
'bootstrap.accordion',
|
103 |
'bootstrap.tab',
|
104 |
-
|
105 |
-
|
106 |
-
);
|
107 |
|
108 |
$this->scripts->add( WAPT_PLUGIN_URL . '/admin/assets/js/settings.js', [ 'jquery' ], 'wapt-settings-script', WAPT_PLUGIN_VERSION );
|
109 |
$this->styles->add( WAPT_PLUGIN_URL . '/admin/assets/css/settings.css', [], 'wapt-settings-style', WAPT_PLUGIN_VERSION );
|
@@ -135,31 +131,92 @@ class WAPT_Settings extends WAPT_Page {
|
|
135 |
'hint' => __( 'Automatically add featured image when saving a post', 'apt' ),
|
136 |
];
|
137 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
138 |
$options[] = [
|
139 |
'type' => 'dropdown',
|
140 |
-
'way' => '
|
141 |
'name' => 'generate_autoimage',
|
142 |
'data' => [
|
143 |
-
[
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
149 |
],
|
150 |
'default' => 'find',
|
151 |
'title' => __( 'Featured image', 'apt' ),
|
152 |
-
'hint' => __(
|
153 |
-
'How to generate featured image:
|
154 |
-
<br> <b>Find in post:</b> search for the first image in the post text
|
155 |
-
<br> <b>Generate from title:</b> created from the title on a colored background
|
156 |
-
<br> <b>Find or generate:</b> find an image in the post text, if it is not present, generate it from the title
|
157 |
-
<br> <b>Google:</b> search for an image by title of the post in Google
|
158 |
-
<br> <b>Find or Google:</b> find an image in the post text, if it is not present, search for an image by title of the post in Google
|
159 |
-
<br> <b>Find or use default Image</b> find an image in the post text, if it is not present, use default image for posts',
|
160 |
-
|
161 |
-
'apt'
|
162 |
-
),
|
163 |
'cssClass' => ( ! $is_premium ) ? [ 'wapt-icon-pro-item' ] : [],
|
164 |
];
|
165 |
|
87 |
public function assets( $scripts, $styles ) {
|
88 |
parent::assets( $scripts, $styles );
|
89 |
|
90 |
+
$this->scripts->request( [
|
|
|
91 |
'control.list',
|
92 |
'bootstrap.accordion',
|
93 |
'bootstrap.tab',
|
94 |
+
'plugin.ddslick',
|
95 |
+
], 'bootstrap' );
|
|
|
96 |
|
97 |
+
$this->styles->request( [
|
|
|
98 |
'control.list',
|
99 |
'bootstrap.accordion',
|
100 |
'bootstrap.tab',
|
101 |
+
'plugin.ddslick',
|
102 |
+
], 'bootstrap' );
|
|
|
103 |
|
104 |
$this->scripts->add( WAPT_PLUGIN_URL . '/admin/assets/js/settings.js', [ 'jquery' ], 'wapt-settings-script', WAPT_PLUGIN_VERSION );
|
105 |
$this->styles->add( WAPT_PLUGIN_URL . '/admin/assets/css/settings.css', [], 'wapt-settings-style', WAPT_PLUGIN_VERSION );
|
131 |
'hint' => __( 'Automatically add featured image when saving a post', 'apt' ),
|
132 |
];
|
133 |
|
134 |
+
$options[] = [
|
135 |
+
'type' => 'checkbox',
|
136 |
+
'way' => 'buttons',
|
137 |
+
'name' => 'scheduled_generation',
|
138 |
+
'title' => __( 'Add featured image on a schedule', 'apt' ),
|
139 |
+
'default' => false,
|
140 |
+
'hint' => __( 'Automatically add featured image according to a CRON schedule', 'apt' ),
|
141 |
+
'eventsOn' => [
|
142 |
+
'show' => '.factory-control-auto_generation_schedule',
|
143 |
+
],
|
144 |
+
'eventsOff' => [
|
145 |
+
'hide' => '.factory-control-auto_generation_schedule',
|
146 |
+
],
|
147 |
+
'cssClass' => ( ! $is_premium ) ? [ 'wapt-icon-pro' ] : [],
|
148 |
+
];
|
149 |
+
|
150 |
+
$options[] = [
|
151 |
+
'type' => 'dropdown',
|
152 |
+
'way' => 'ddslick',
|
153 |
+
'name' => 'auto_generation_schedule',
|
154 |
+
'title' => __( 'Image generation schedule', 'apt' ),
|
155 |
+
'data' => [
|
156 |
+
[
|
157 |
+
'title' => __( 'Once an hour', 'apt' ),
|
158 |
+
'value' => 'hourly',
|
159 |
+
],
|
160 |
+
[
|
161 |
+
'title' => __( 'Once a day', 'apt' ),
|
162 |
+
'value' => 'daily',
|
163 |
+
],
|
164 |
+
[
|
165 |
+
'title' => __( 'Twice a day', 'apt' ),
|
166 |
+
'value' => 'twicedaily',
|
167 |
+
],
|
168 |
+
[
|
169 |
+
'title' => __( 'Once a week', 'apt' ),
|
170 |
+
'value' => 'weekly',
|
171 |
+
],
|
172 |
+
[
|
173 |
+
'title' => __( 'Once a month', 'apt' ),
|
174 |
+
'value' => 'monthly',
|
175 |
+
],
|
176 |
+
],
|
177 |
+
'default' => 'daily',
|
178 |
+
'hint' => __( 'How often to run image generation', 'apt' ),
|
179 |
+
];
|
180 |
+
|
181 |
$options[] = [
|
182 |
'type' => 'dropdown',
|
183 |
+
'way' => 'ddslick',
|
184 |
'name' => 'generate_autoimage',
|
185 |
'data' => [
|
186 |
+
[
|
187 |
+
'title' => __( 'Find in post', 'apt' ),
|
188 |
+
'value' => 'find',
|
189 |
+
'hint' => __( 'Search for the first image in the post text', 'apt' ),
|
190 |
+
],
|
191 |
+
[
|
192 |
+
'title' => __( 'Generate from title', 'apt' ),
|
193 |
+
'value' => 'generate',
|
194 |
+
'hint' => __( 'Create from the title on a colored background', 'apt' ),
|
195 |
+
],
|
196 |
+
[
|
197 |
+
'title' => __( 'Find or generate', 'apt' ),
|
198 |
+
'value' => 'both',
|
199 |
+
'hint' => __( 'Find an image in the post text, if it is not present, generate it from the title', 'apt' ),
|
200 |
+
],
|
201 |
+
[
|
202 |
+
'title' => __( 'Google', 'apt' ),
|
203 |
+
'value' => 'google',
|
204 |
+
'hint' => __( 'Search for an image by title of the post in Google', 'apt' ),
|
205 |
+
],
|
206 |
+
[
|
207 |
+
'title' => __( 'Find or Google', 'apt' ),
|
208 |
+
'value' => 'find_google',
|
209 |
+
'hint' => __( 'Find an image in the post text, if it is not present, search for an image by title of the post in Google', 'apt' ),
|
210 |
+
],
|
211 |
+
[
|
212 |
+
'title' => __( 'Find or use default image', 'apt' ),
|
213 |
+
'value' => 'use_default',
|
214 |
+
'hint' => __( 'Find an image in the post text, if it is not present, use default image for posts', 'apt' ),
|
215 |
+
],
|
216 |
],
|
217 |
'default' => 'find',
|
218 |
'title' => __( 'Featured image', 'apt' ),
|
219 |
+
'hint' => __( 'How to generate featured image', 'apt' ),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
220 |
'cssClass' => ( ! $is_premium ) ? [ 'wapt-icon-pro-item' ] : [],
|
221 |
];
|
222 |
|
admin/views/tab-generate.php
CHANGED
@@ -12,12 +12,14 @@ $log = $data['log'] ?? [];
|
|
12 |
<div class="row wapt-statistic-row">
|
13 |
<div class="wapt-generate-statistic">
|
14 |
<div class="wapt-chart-container">
|
15 |
-
<
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
|
|
|
|
21 |
<div id="wapt-overview-chart-percent" class="wapt-chart-percent">
|
22 |
<?php echo esc_attr( trim( $stats['featured_image_percent'] ) ); ?><span>%</span>
|
23 |
</div>
|
12 |
<div class="row wapt-statistic-row">
|
13 |
<div class="wapt-generate-statistic">
|
14 |
<div class="wapt-chart-container">
|
15 |
+
<div class="wapt-chart-wrapper">
|
16 |
+
<canvas id="wapt-main-chart" width="200" height="200"
|
17 |
+
data-no_featured_image="<?php echo esc_attr( $stats['no_featured_image'] ); ?>"
|
18 |
+
data-w_featured_image="<?php echo esc_attr( $stats['w_featured_image'] ); ?>"
|
19 |
+
data-errors="<?php echo esc_attr( $stats['error'] ); ?>"
|
20 |
+
style="display: block;">
|
21 |
+
</canvas>
|
22 |
+
</div>
|
23 |
<div id="wapt-overview-chart-percent" class="wapt-chart-percent">
|
24 |
<?php echo esc_attr( trim( $stats['featured_image_percent'] ) ); ?><span>%</span>
|
25 |
</div>
|
auto-post-thumbnail.php
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
Plugin Name: Auto Featured Image (Auto Post Thumbnail)
|
4 |
Plugin URI: https://cm-wp.com/apt
|
5 |
Description: Automatically generate the Featured Image from the first image in post or any custom post type only if Featured Image is not set manually. Featured Image Generation From Title. Native image search for Elementor, Gutenberg, Classic Editor.
|
6 |
-
Version: 3.9.
|
7 |
Author: Creative Motion <support@cm-wp.com>
|
8 |
Author URI: https://cm-wp.com
|
9 |
Text Domain: apt
|
@@ -97,6 +97,7 @@ $plugin_info = [
|
|
97 |
[ 'libs/factory/adverts', 'factory_adverts_135', 'admin' ],
|
98 |
[ 'libs/factory/feedback', 'factory_feedback_118', 'admin' ],
|
99 |
[ 'libs/factory/logger', 'factory_logger_123', 'all' ],
|
|
|
100 |
],
|
101 |
];
|
102 |
|
@@ -144,7 +145,6 @@ require_once WAPT_PLUGIN_DIR . '/includes/class-apt.php';
|
|
144 |
require_once WAPT_PLUGIN_DIR . '/includes/class-post-images.php';
|
145 |
require_once WAPT_PLUGIN_DIR . '/includes/class-plugin.php';
|
146 |
require_once WAPT_PLUGIN_DIR . '/includes/class-wapt-image.php';
|
147 |
-
|
148 |
require_once WAPT_PLUGIN_DIR . '/includes/image-search/boot.php';
|
149 |
|
150 |
try {
|
3 |
Plugin Name: Auto Featured Image (Auto Post Thumbnail)
|
4 |
Plugin URI: https://cm-wp.com/apt
|
5 |
Description: Automatically generate the Featured Image from the first image in post or any custom post type only if Featured Image is not set manually. Featured Image Generation From Title. Native image search for Elementor, Gutenberg, Classic Editor.
|
6 |
+
Version: 3.9.12
|
7 |
Author: Creative Motion <support@cm-wp.com>
|
8 |
Author URI: https://cm-wp.com
|
9 |
Text Domain: apt
|
97 |
[ 'libs/factory/adverts', 'factory_adverts_135', 'admin' ],
|
98 |
[ 'libs/factory/feedback', 'factory_feedback_118', 'admin' ],
|
99 |
[ 'libs/factory/logger', 'factory_logger_123', 'all' ],
|
100 |
+
[ 'libs/factory/processing', 'factory_processing_103', 'all' ],
|
101 |
],
|
102 |
];
|
103 |
|
145 |
require_once WAPT_PLUGIN_DIR . '/includes/class-post-images.php';
|
146 |
require_once WAPT_PLUGIN_DIR . '/includes/class-plugin.php';
|
147 |
require_once WAPT_PLUGIN_DIR . '/includes/class-wapt-image.php';
|
|
|
148 |
require_once WAPT_PLUGIN_DIR . '/includes/image-search/boot.php';
|
149 |
|
150 |
try {
|
includes/class-apt.php
CHANGED
@@ -50,6 +50,9 @@ class AutoPostThumbnails {
|
|
50 |
*/
|
51 |
public $is_in_medialibrary = false;
|
52 |
|
|
|
|
|
|
|
53 |
public $allowed_generate_post_types;
|
54 |
|
55 |
/**
|
@@ -65,7 +68,7 @@ class AutoPostThumbnails {
|
|
65 |
'pixabay' => '',
|
66 |
'unsplash' => '',
|
67 |
];
|
68 |
-
if (
|
69 |
$this->sources = [
|
70 |
'recommend' => '',
|
71 |
'google' => WAPT_PLUGIN_SLUG,
|
@@ -102,15 +105,15 @@ class AutoPostThumbnails {
|
|
102 |
* Initiate all required hooks.
|
103 |
*/
|
104 |
private function init() {
|
105 |
-
$is_auto_generate =
|
106 |
-
$is_auto_upload =
|
107 |
-
$allowed_import_post_types = explode( ',',
|
108 |
|
109 |
-
$this->allowed_generate_post_types = explode( ',',
|
110 |
|
111 |
add_filter( 'mime_types', [ $this, 'allow_upload_webp' ] );
|
112 |
|
113 |
-
if ( $is_auto_upload &&
|
114 |
add_filter( 'wp_insert_post_data', [ $this, 'auto_upload' ], 10, 2 );
|
115 |
|
116 |
// This hook handle update post via rest api. for example WordPress mobile apps
|
@@ -130,7 +133,7 @@ class AutoPostThumbnails {
|
|
130 |
// This hook will now handle all sort publishing including posts, custom types, scheduled posts, etc.
|
131 |
add_action( 'transition_post_status', [ $this, 'check_required_transition' ], 10, 3 );
|
132 |
} else {
|
133 |
-
if (
|
134 |
add_action( 'admin_notices', [ $this, 'notice_auto_generation' ] );
|
135 |
}
|
136 |
}
|
@@ -174,7 +177,7 @@ class AutoPostThumbnails {
|
|
174 |
}
|
175 |
check_ajax_referer( 'get-posts' );
|
176 |
|
177 |
-
$generate =
|
178 |
|
179 |
$this->plugin->logger->info( "START generate in mode: {$generate}" );
|
180 |
|
@@ -192,7 +195,7 @@ class AutoPostThumbnails {
|
|
192 |
|
193 |
$has_thumb = sanitize_text_field( wp_unslash( $_POST['withThumb'] ?? false ) );
|
194 |
$type = sanitize_text_field( wp_unslash( $_POST['posttype'] ?? '' ) );
|
195 |
-
if (
|
196 |
$status = sanitize_text_field( wp_unslash( $_POST['poststatus'] ?? '' ) );
|
197 |
$category = sanitize_text_field( wp_unslash( $_POST['category'] ?? '' ) );
|
198 |
$date_start = sanitize_text_field( wp_unslash( $_POST['date_start'] ?? '' ) );
|
@@ -200,10 +203,21 @@ class AutoPostThumbnails {
|
|
200 |
$date_start = $date_start ? \DateTime::createFromFormat( 'd.m.Y', $date_start )->format( 'd.m.Y' ) : 0;
|
201 |
$date_end = $date_end ? \DateTime::createFromFormat( 'd.m.Y', $date_end )->setTime( 23, 59 )->format( 'd.m.Y H:i' ) : 0;
|
202 |
// Get id's of the posts that satisfy the filters
|
203 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
204 |
} else {
|
205 |
// Get id's of all the published posts for which post thumbnails exist or does not exist
|
206 |
-
$query = $this->get_posts_query(
|
|
|
|
|
|
|
207 |
}
|
208 |
|
209 |
$ids = [];
|
@@ -214,7 +228,8 @@ class AutoPostThumbnails {
|
|
214 |
}
|
215 |
}
|
216 |
|
217 |
-
$
|
|
|
218 |
|
219 |
wp_send_json_success( $ids );
|
220 |
}
|
@@ -243,9 +258,11 @@ class AutoPostThumbnails {
|
|
243 |
$thumb_id = $result->thumbnail_id;
|
244 |
|
245 |
if ( $thumb_id ) {
|
246 |
-
|
|
|
247 |
} else {
|
248 |
-
|
|
|
249 |
}
|
250 |
}
|
251 |
|
@@ -299,7 +316,7 @@ class AutoPostThumbnails {
|
|
299 |
*/
|
300 |
public function hide_notice_auto_generation() {
|
301 |
if ( isset( $_POST['action'] ) && 'hide_notice_auto_generation' === $_POST['action'] ) {
|
302 |
-
|
303 |
}
|
304 |
}
|
305 |
|
@@ -322,35 +339,48 @@ class AutoPostThumbnails {
|
|
322 |
/**
|
323 |
* Return sql query, which allows to receive all the posts without thumbnails
|
324 |
*
|
|
|
|
|
325 |
* @return WP_Query
|
326 |
*/
|
327 |
-
public function get_posts_query( $
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
328 |
|
|
|
329 |
// phpcs:disable WordPress.PHP.DevelopmentFunctions
|
330 |
-
if ( $is_log ) {
|
331 |
$this->plugin->logger->info( 'Posts query: ' . var_export( [
|
332 |
-
'has_thumb' => $has_thumb,
|
333 |
-
'type' => $
|
334 |
-
'status' => $
|
335 |
-
'category' => $category,
|
336 |
-
'date_start' => $date_start,
|
337 |
-
'date_end' => $date_end,
|
338 |
], true ) );
|
339 |
}
|
340 |
// phpcs:enable
|
341 |
|
342 |
-
$q_status = $status ? $status : 'any';
|
343 |
-
$q_type = $type ? $type : 'any';
|
344 |
-
$q_has_thumb = $has_thumb ? 'EXISTS' : 'NOT EXISTS';
|
345 |
|
346 |
$args = [
|
347 |
-
'posts_per_page' => - 1,
|
348 |
'post_status' => $q_status,
|
349 |
'post_type' => $q_type,
|
350 |
'suppress_filters' => true,
|
351 |
'fields' => 'ids',
|
352 |
'meta_query' => [
|
353 |
-
'relation' => '
|
354 |
[
|
355 |
'key' => '_thumbnail_id',
|
356 |
'compare' => $q_has_thumb,
|
@@ -361,13 +391,13 @@ class AutoPostThumbnails {
|
|
361 |
],
|
362 |
],
|
363 |
];
|
364 |
-
if ( $category ) {
|
365 |
-
$args['cat'] = $category;
|
366 |
}
|
367 |
-
if ( $date_start && $date_end ) {
|
368 |
$args['date_query'][] = [
|
369 |
-
'after' => $date_start,
|
370 |
-
'before' => $date_end,
|
371 |
'inclusive' => true,
|
372 |
];
|
373 |
}
|
@@ -384,67 +414,12 @@ class AutoPostThumbnails {
|
|
384 |
* @return int
|
385 |
*/
|
386 |
public function get_posts_count( $has_thumb = false, $type = 'post' ) {
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
'order' => 'DESC ',
|
392 |
-
'post_type' => $type,
|
393 |
-
'posts_per_page' => - 1,
|
394 |
-
'fields' => 'ids',
|
395 |
-
'meta_query' => [
|
396 |
-
'relation' => 'AND',
|
397 |
-
[
|
398 |
-
'key' => '_thumbnail_id',
|
399 |
-
'compare' => 'EXISTS',
|
400 |
-
],
|
401 |
-
[
|
402 |
-
'key' => '_thumbnail_id',
|
403 |
-
'compare' => '!=',
|
404 |
-
'value' => '',
|
405 |
-
'type' => 'NUMERIC ',
|
406 |
-
],
|
407 |
-
],
|
408 |
-
];
|
409 |
-
|
410 |
-
/*$query = "SELECT {$wpdb->posts}.ID FROM {$wpdb->posts}
|
411 |
-
LEFT JOIN {$wpdb->postmeta} ON ( {$wpdb->posts}.ID = {$wpdb->postmeta}.post_id )
|
412 |
-
LEFT JOIN {$wpdb->postmeta} AS mt1 ON ( {$wpdb->posts}.ID = mt1.post_id AND mt1.meta_key = 'skip_post_thumb' )
|
413 |
-
WHERE ({$wpdb->postmeta}.meta_key = '_thumbnail_id' AND mt1.post_id IS NULL)
|
414 |
-
AND {$wpdb->posts}.post_type = '{$type}' GROUP BY {$wpdb->posts}.ID ORDER BY {$wpdb->posts}.post_date DESC";*/
|
415 |
-
} else {
|
416 |
-
$args = [
|
417 |
-
'orderby' => 'date',
|
418 |
-
'order' => 'DESC ',
|
419 |
-
'post_type' => $type,
|
420 |
-
'posts_per_page' => - 1,
|
421 |
-
'fields' => 'ids',
|
422 |
-
'meta_query' => [
|
423 |
-
'relation' => 'OR',
|
424 |
-
[
|
425 |
-
'key' => '_thumbnail_id',
|
426 |
-
'compare' => 'NOT EXISTS',
|
427 |
-
],
|
428 |
-
[
|
429 |
-
'key' => '_thumbnail_id',
|
430 |
-
'compare' => '=',
|
431 |
-
'value' => '',
|
432 |
-
],
|
433 |
-
],
|
434 |
-
];
|
435 |
-
|
436 |
-
/*$query = "SELECT {$wpdb->posts}.ID FROM {$wpdb->posts}
|
437 |
-
LEFT JOIN {$wpdb->postmeta} ON ( {$wpdb->posts}.ID = {$wpdb->postmeta}.post_id AND {$wpdb->postmeta}.meta_key = '_thumbnail_id' )
|
438 |
-
LEFT JOIN {$wpdb->postmeta} AS mt1 ON ( {$wpdb->posts}.ID = mt1.post_id AND mt1.meta_key = 'skip_post_thumb' )
|
439 |
-
WHERE ({$wpdb->postmeta}.post_id IS NULL AND mt1.post_id IS NULL)
|
440 |
-
AND (mt1.meta_key = '_thumbnail_id' AND mt1.meta_value = '')
|
441 |
-
AND {$wpdb->posts}.post_type = '{$type}' GROUP BY {$wpdb->posts}.ID ORDER BY {$wpdb->posts}.post_date DESC";*/
|
442 |
-
}
|
443 |
-
|
444 |
-
//$result = $wpdb->get_results( $query );
|
445 |
-
$query = new WP_Query( $args );
|
446 |
|
447 |
-
return $query->post_count;
|
448 |
}
|
449 |
|
450 |
/**
|
@@ -463,7 +438,7 @@ class AutoPostThumbnails {
|
|
463 |
* Look for this id in the IMG tag.
|
464 |
*/
|
465 |
if ( isset( $image['tag'] ) && ! empty( $image['tag'] ) ) {
|
466 |
-
preg_match( '/wp-image-([\d]*)/i', $image['tag'], $thumb_id );
|
467 |
|
468 |
if ( $thumb_id ) {
|
469 |
$thumb_id = $thumb_id[1];
|
@@ -479,8 +454,9 @@ class AutoPostThumbnails {
|
|
479 |
if ( isset( $image['url'] ) && ! empty( $image['url'] ) ) {
|
480 |
$image_url = $image['url'];
|
481 |
// если ссылка на миниатюру, то регулярка сделает ссылку на оригинал. убирает в конце названия файла -150x150
|
482 |
-
$image_url = preg_replace( '
|
483 |
-
|
|
|
484 |
}
|
485 |
}
|
486 |
|
@@ -522,13 +498,17 @@ class AutoPostThumbnails {
|
|
522 |
* @param \WP_Post $post
|
523 |
* @param bool $update
|
524 |
*
|
525 |
-
* @return GenerateResult
|
526 |
* @throws Exception
|
527 |
*/
|
528 |
public function publish_post( $post_id, $post = null, $update = true ) {
|
529 |
global $wpdb;
|
530 |
|
531 |
-
|
|
|
|
|
|
|
|
|
532 |
$generation = new GenerateResult( $post_id, $autoimage );
|
533 |
|
534 |
if ( ! $post ) {
|
@@ -564,7 +544,7 @@ class AutoPostThumbnails {
|
|
564 |
update_post_meta( $post_id, '_thumbnail_id', $thumb_id );
|
565 |
$this->plugin->logger->info( "Featured image ($thumb_id) is set for post ($post_id)" );
|
566 |
} else {
|
567 |
-
if (
|
568 |
$thumb_id = apply_filters( 'wapt/generate_post_thumb', $image, $post_id );
|
569 |
|
570 |
if ( $thumb_id ) {
|
@@ -617,7 +597,7 @@ class AutoPostThumbnails {
|
|
617 |
* @param array $postarr
|
618 |
*/
|
619 |
public function auto_upload( $data, $postarr = [] ) {
|
620 |
-
$allowed_post_types = explode( ',',
|
621 |
|
622 |
if ( $data instanceof \WP_Post ) {
|
623 |
$post_type = $data->post_type ?? '';
|
@@ -915,7 +895,7 @@ class AutoPostThumbnails {
|
|
915 |
if ( isset( $_POST['source'] ) && ! empty( $_POST['source'] ) ) {
|
916 |
$source = str_replace( 'tab-', '', sanitize_text_field( $_POST['source'] ) );
|
917 |
|
918 |
-
// if( empty($this->sources[$source]) &&
|
919 |
if ( empty( $this->sources[ $source ] ) ) {
|
920 |
require_once WAPT_PLUGIN_DIR . '/admin/views/pro.php';
|
921 |
} else {
|
@@ -1026,6 +1006,8 @@ class AutoPostThumbnails {
|
|
1026 |
|
1027 |
$attach_data = wp_generate_attachment_metadata( $attach_id, $target_file_name );
|
1028 |
$result = wp_update_attachment_metadata( $attach_id, $attach_data );
|
|
|
|
|
1029 |
if ( ! $result ) {
|
1030 |
// die( 'Error: File attachment metadata error' );
|
1031 |
}
|
@@ -1194,13 +1176,13 @@ class AutoPostThumbnails {
|
|
1194 |
|
1195 |
public function check_api_notice( $notices, $plugin_name ) {
|
1196 |
// Если экшен вызывал не этот плагин, то не выводим это уведомления
|
1197 |
-
if ( $plugin_name !==
|
1198 |
return $notices;
|
1199 |
}
|
1200 |
// Получаем заголовок плагина
|
1201 |
-
$plugin_title =
|
1202 |
|
1203 |
-
if ( !
|
1204 |
// Задаем текст уведомления
|
1205 |
$notice_text = '<p><b>' . $plugin_title . ':</b> <br>' . sprintf( __( "To download images from Google, specify Google API keys in the <a href='%s'>settings</a>.", 'apt' ), admin_url( 'admin.php?page=wapt_settings-wbcr_apt' ) ) . '</p>';
|
1206 |
|
@@ -1366,7 +1348,7 @@ class AutoPostThumbnails {
|
|
1366 |
public function generate_and_attachment( $post_id ) {
|
1367 |
$this->plugin->logger->info( "Start generate attachment for post ID = {$post_id}" );
|
1368 |
|
1369 |
-
$format =
|
1370 |
switch ( $format ) {
|
1371 |
case 'png':
|
1372 |
$extension = 'png';
|
@@ -1414,7 +1396,7 @@ class AutoPostThumbnails {
|
|
1414 |
public function UseDefault( $post_id ) {
|
1415 |
$this->plugin->logger->info( "Start set default attachment for post ID = {$post_id}" );
|
1416 |
|
1417 |
-
$thumb_id =
|
1418 |
|
1419 |
if ( ! is_wp_error( $thumb_id ) ) {
|
1420 |
$this->plugin->logger->info( "Successful set default attachment ID = {$thumb_id}" );
|
50 |
*/
|
51 |
public $is_in_medialibrary = false;
|
52 |
|
53 |
+
/**
|
54 |
+
* @var
|
55 |
+
*/
|
56 |
public $allowed_generate_post_types;
|
57 |
|
58 |
/**
|
68 |
'pixabay' => '',
|
69 |
'unsplash' => '',
|
70 |
];
|
71 |
+
if ( $this->plugin->is_premium() ) {
|
72 |
$this->sources = [
|
73 |
'recommend' => '',
|
74 |
'google' => WAPT_PLUGIN_SLUG,
|
105 |
* Initiate all required hooks.
|
106 |
*/
|
107 |
private function init() {
|
108 |
+
$is_auto_generate = $this->plugin->getPopulateOption( 'auto_generation', true );
|
109 |
+
$is_auto_upload = $this->plugin->getPopulateOption( 'auto_upload_images' );
|
110 |
+
$allowed_import_post_types = explode( ',', $this->plugin->getPopulateOption( 'import_post_types', 'post' ) );
|
111 |
|
112 |
+
$this->allowed_generate_post_types = explode( ',', $this->plugin->getPopulateOption( 'auto_post_types', 'post,page' ) );
|
113 |
|
114 |
add_filter( 'mime_types', [ $this, 'allow_upload_webp' ] );
|
115 |
|
116 |
+
if ( $is_auto_upload && $this->plugin->is_premium() ) {
|
117 |
add_filter( 'wp_insert_post_data', [ $this, 'auto_upload' ], 10, 2 );
|
118 |
|
119 |
// This hook handle update post via rest api. for example WordPress mobile apps
|
133 |
// This hook will now handle all sort publishing including posts, custom types, scheduled posts, etc.
|
134 |
add_action( 'transition_post_status', [ $this, 'check_required_transition' ], 10, 3 );
|
135 |
} else {
|
136 |
+
if ( $this->plugin->getPopulateOption( 'auto_generation_notice', 1 ) ) {
|
137 |
add_action( 'admin_notices', [ $this, 'notice_auto_generation' ] );
|
138 |
}
|
139 |
}
|
177 |
}
|
178 |
check_ajax_referer( 'get-posts' );
|
179 |
|
180 |
+
$generate = $this->plugin->getPopulateOption( 'generate_autoimage', 'find' );
|
181 |
|
182 |
$this->plugin->logger->info( "START generate in mode: {$generate}" );
|
183 |
|
195 |
|
196 |
$has_thumb = sanitize_text_field( wp_unslash( $_POST['withThumb'] ?? false ) );
|
197 |
$type = sanitize_text_field( wp_unslash( $_POST['posttype'] ?? '' ) );
|
198 |
+
if ( $this->plugin->is_premium() ) {
|
199 |
$status = sanitize_text_field( wp_unslash( $_POST['poststatus'] ?? '' ) );
|
200 |
$category = sanitize_text_field( wp_unslash( $_POST['category'] ?? '' ) );
|
201 |
$date_start = sanitize_text_field( wp_unslash( $_POST['date_start'] ?? '' ) );
|
203 |
$date_start = $date_start ? \DateTime::createFromFormat( 'd.m.Y', $date_start )->format( 'd.m.Y' ) : 0;
|
204 |
$date_end = $date_end ? \DateTime::createFromFormat( 'd.m.Y', $date_end )->setTime( 23, 59 )->format( 'd.m.Y H:i' ) : 0;
|
205 |
// Get id's of the posts that satisfy the filters
|
206 |
+
//$query = $this->get_posts_query( $has_thumb, $type, $status, $category, $date_start, $date_end );
|
207 |
+
$query = $this->get_posts_query( [
|
208 |
+
'has_thumb' => $has_thumb,
|
209 |
+
'type' => $type,
|
210 |
+
'status' => $status,
|
211 |
+
'category' => $category,
|
212 |
+
'date_start' => $date_start,
|
213 |
+
'date_end' => $date_end,
|
214 |
+
] );
|
215 |
} else {
|
216 |
// Get id's of all the published posts for which post thumbnails exist or does not exist
|
217 |
+
$query = $this->get_posts_query( [
|
218 |
+
'has_thumb' => $has_thumb,
|
219 |
+
'type' => $type,
|
220 |
+
] );
|
221 |
}
|
222 |
|
223 |
$ids = [];
|
228 |
}
|
229 |
}
|
230 |
|
231 |
+
$ids_str = implode( ',', $ids );
|
232 |
+
$this->plugin->logger->info( "Queried posts IDs: {$ids_str}" );
|
233 |
|
234 |
wp_send_json_success( $ids );
|
235 |
}
|
258 |
$thumb_id = $result->thumbnail_id;
|
259 |
|
260 |
if ( $thumb_id ) {
|
261 |
+
$result->write_to_log();
|
262 |
+
wp_send_json_success( $result->getData() );
|
263 |
} else {
|
264 |
+
$result->write_to_log();
|
265 |
+
wp_send_json_error( $result->getData() );
|
266 |
}
|
267 |
}
|
268 |
|
316 |
*/
|
317 |
public function hide_notice_auto_generation() {
|
318 |
if ( isset( $_POST['action'] ) && 'hide_notice_auto_generation' === $_POST['action'] ) {
|
319 |
+
$this->plugin->updateOption( 'auto_generation_notice', 0 );
|
320 |
}
|
321 |
}
|
322 |
|
339 |
/**
|
340 |
* Return sql query, which allows to receive all the posts without thumbnails
|
341 |
*
|
342 |
+
* @param array $args
|
343 |
+
*
|
344 |
* @return WP_Query
|
345 |
*/
|
346 |
+
public function get_posts_query( $params ) {
|
347 |
+
$default_params = [
|
348 |
+
'has_thumb' => false,
|
349 |
+
'type' => 'post',
|
350 |
+
'status' => 'publish',
|
351 |
+
'category' => 0,
|
352 |
+
'date_start' => 0,
|
353 |
+
'date_end' => 0,
|
354 |
+
'is_log' => true,
|
355 |
+
'count' => 0,
|
356 |
+
];
|
357 |
|
358 |
+
$params = wp_parse_args( $params, $default_params );
|
359 |
// phpcs:disable WordPress.PHP.DevelopmentFunctions
|
360 |
+
if ( $params['is_log'] ) {
|
361 |
$this->plugin->logger->info( 'Posts query: ' . var_export( [
|
362 |
+
'has_thumb' => $params['has_thumb'],
|
363 |
+
'type' => $params['is_log'],
|
364 |
+
'status' => $params['type'],
|
365 |
+
'category' => $params['category'],
|
366 |
+
'date_start' => $params['date_start'],
|
367 |
+
'date_end' => $params['date_end'],
|
368 |
], true ) );
|
369 |
}
|
370 |
// phpcs:enable
|
371 |
|
372 |
+
$q_status = $params['status'] ? $params['status'] : 'any';
|
373 |
+
$q_type = $params['type'] ? $params['type'] : 'any';
|
374 |
+
$q_has_thumb = $params['has_thumb'] ? 'EXISTS' : 'NOT EXISTS';
|
375 |
|
376 |
$args = [
|
377 |
+
'posts_per_page' => $params['count'] ? $params['count'] : - 1,
|
378 |
'post_status' => $q_status,
|
379 |
'post_type' => $q_type,
|
380 |
'suppress_filters' => true,
|
381 |
'fields' => 'ids',
|
382 |
'meta_query' => [
|
383 |
+
'relation' => ' and ',
|
384 |
[
|
385 |
'key' => '_thumbnail_id',
|
386 |
'compare' => $q_has_thumb,
|
391 |
],
|
392 |
],
|
393 |
];
|
394 |
+
if ( $params['category'] ) {
|
395 |
+
$args['cat'] = $params['category'];
|
396 |
}
|
397 |
+
if ( $params['date_start'] && $params['date_end'] ) {
|
398 |
$args['date_query'][] = [
|
399 |
+
'after' => $params['date_start'],
|
400 |
+
'before' => $params['date_end'],
|
401 |
'inclusive' => true,
|
402 |
];
|
403 |
}
|
414 |
* @return int
|
415 |
*/
|
416 |
public function get_posts_count( $has_thumb = false, $type = 'post' ) {
|
417 |
+
$query = $this->get_posts_query( [
|
418 |
+
'has_thumb' => $has_thumb,
|
419 |
+
'type' => $type,
|
420 |
+
] );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
421 |
|
422 |
+
return $query->post_count ?? 0;
|
423 |
}
|
424 |
|
425 |
/**
|
438 |
* Look for this id in the IMG tag.
|
439 |
*/
|
440 |
if ( isset( $image['tag'] ) && ! empty( $image['tag'] ) ) {
|
441 |
+
preg_match( ' / wp - image - ( [ \d ] *) / i', $image['tag'], $thumb_id );
|
442 |
|
443 |
if ( $thumb_id ) {
|
444 |
$thumb_id = $thumb_id[1];
|
454 |
if ( isset( $image['url'] ) && ! empty( $image['url'] ) ) {
|
455 |
$image_url = $image['url'];
|
456 |
// если ссылка на миниатюру, то регулярка сделает ссылку на оригинал. убирает в конце названия файла -150x150
|
457 |
+
$image_url = preg_replace( ' / - [ 0 - 9 ]{
|
458 |
+
1,}x[ 0 - 9 ]{1,}\./', ' . ', $image_url );
|
459 |
+
$thumb_id = $wpdb->get_var( "SELECT ID FROM {$wpdb->posts} WHERE guid LIKE ' % " . esc_sql( $image_url ) . " % '" );
|
460 |
}
|
461 |
}
|
462 |
|
498 |
* @param \WP_Post $post
|
499 |
* @param bool $update
|
500 |
*
|
501 |
+
* @return GenerateResult|null
|
502 |
* @throws Exception
|
503 |
*/
|
504 |
public function publish_post( $post_id, $post = null, $update = true ) {
|
505 |
global $wpdb;
|
506 |
|
507 |
+
if ( $post->post_status === 'auto-draft' ) {
|
508 |
+
return null;
|
509 |
+
}
|
510 |
+
|
511 |
+
$autoimage = $this->plugin->getPopulateOption( 'generate_autoimage', 'find' );
|
512 |
$generation = new GenerateResult( $post_id, $autoimage );
|
513 |
|
514 |
if ( ! $post ) {
|
544 |
update_post_meta( $post_id, '_thumbnail_id', $thumb_id );
|
545 |
$this->plugin->logger->info( "Featured image ($thumb_id) is set for post ($post_id)" );
|
546 |
} else {
|
547 |
+
if ( $this->plugin->is_premium() ) {
|
548 |
$thumb_id = apply_filters( 'wapt/generate_post_thumb', $image, $post_id );
|
549 |
|
550 |
if ( $thumb_id ) {
|
597 |
* @param array $postarr
|
598 |
*/
|
599 |
public function auto_upload( $data, $postarr = [] ) {
|
600 |
+
$allowed_post_types = explode( ',', $this->plugin->getPopulateOption( 'import_post_types', '' ) );
|
601 |
|
602 |
if ( $data instanceof \WP_Post ) {
|
603 |
$post_type = $data->post_type ?? '';
|
895 |
if ( isset( $_POST['source'] ) && ! empty( $_POST['source'] ) ) {
|
896 |
$source = str_replace( 'tab-', '', sanitize_text_field( $_POST['source'] ) );
|
897 |
|
898 |
+
// if( empty($this->sources[$source]) && !$this->plugin->premium->is_activate() )
|
899 |
if ( empty( $this->sources[ $source ] ) ) {
|
900 |
require_once WAPT_PLUGIN_DIR . '/admin/views/pro.php';
|
901 |
} else {
|
1006 |
|
1007 |
$attach_data = wp_generate_attachment_metadata( $attach_id, $target_file_name );
|
1008 |
$result = wp_update_attachment_metadata( $attach_id, $attach_data );
|
1009 |
+
update_attached_file( $attach_id, $target_file_name );
|
1010 |
+
|
1011 |
if ( ! $result ) {
|
1012 |
// die( 'Error: File attachment metadata error' );
|
1013 |
}
|
1176 |
|
1177 |
public function check_api_notice( $notices, $plugin_name ) {
|
1178 |
// Если экшен вызывал не этот плагин, то не выводим это уведомления
|
1179 |
+
if ( $plugin_name !== $this->plugin->getPluginName() ) {
|
1180 |
return $notices;
|
1181 |
}
|
1182 |
// Получаем заголовок плагина
|
1183 |
+
$plugin_title = $this->plugin->getPluginTitle();
|
1184 |
|
1185 |
+
if ( ! $this->plugin->getPopulateOption( 'google_apikey' ) && ! $this->plugin->getPopulateOption( 'google_cse' ) ) {
|
1186 |
// Задаем текст уведомления
|
1187 |
$notice_text = '<p><b>' . $plugin_title . ':</b> <br>' . sprintf( __( "To download images from Google, specify Google API keys in the <a href='%s'>settings</a>.", 'apt' ), admin_url( 'admin.php?page=wapt_settings-wbcr_apt' ) ) . '</p>';
|
1188 |
|
1348 |
public function generate_and_attachment( $post_id ) {
|
1349 |
$this->plugin->logger->info( "Start generate attachment for post ID = {$post_id}" );
|
1350 |
|
1351 |
+
$format = $this->plugin->getPopulateOption( 'image-type', 'jpg' );
|
1352 |
switch ( $format ) {
|
1353 |
case 'png':
|
1354 |
$extension = 'png';
|
1396 |
public function UseDefault( $post_id ) {
|
1397 |
$this->plugin->logger->info( "Start set default attachment for post ID = {$post_id}" );
|
1398 |
|
1399 |
+
$thumb_id = $this->plugin->getPopulateOption( 'default-background', '' );
|
1400 |
|
1401 |
if ( ! is_wp_error( $thumb_id ) ) {
|
1402 |
$this->plugin->logger->info( "Successful set default attachment ID = {$thumb_id}" );
|
includes/class-plugin.php
CHANGED
@@ -1,8 +1,5 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
use WBCR\APT;
|
4 |
-
use WBCR\APT\PostImagesPro;
|
5 |
-
|
6 |
// Exit if accessed directly
|
7 |
if ( ! defined( 'ABSPATH' ) ) {
|
8 |
exit;
|
@@ -11,8 +8,6 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|
11 |
/**
|
12 |
* Основной класс плагина Auto Featured Image
|
13 |
*
|
14 |
-
* @author Alexander Kovalev <alex.kovalevv@gmail.com>
|
15 |
-
* @copyright (c) 2018 Webraftic Ltd
|
16 |
* @version 1.0
|
17 |
*/
|
18 |
class WAPT_Plugin extends Wbcr_Factory458_Plugin {
|
@@ -48,13 +43,13 @@ class WAPT_Plugin extends Wbcr_Factory458_Plugin {
|
|
48 |
parent::__construct( $plugin_path, $data );
|
49 |
|
50 |
self::$app = $this;
|
|
|
51 |
|
52 |
if ( is_admin() ) {
|
53 |
// Регистрации класса активации/деактивации плагина
|
54 |
$this->initActivation();
|
55 |
|
56 |
$this->numberOfColumn = 4;
|
57 |
-
$this->apt = \WBCR\APT\AutoPostThumbnails::instance();
|
58 |
|
59 |
require WAPT_PLUGIN_DIR . '/admin/ajax/check-license.php';
|
60 |
|
@@ -62,11 +57,6 @@ class WAPT_Plugin extends Wbcr_Factory458_Plugin {
|
|
62 |
$this->admin_scripts();
|
63 |
}
|
64 |
|
65 |
-
if ( $this->doing_rest_api() ) {
|
66 |
-
require_once WAPT_PLUGIN_DIR . '/includes/class.generate-result.php';
|
67 |
-
$this->apt = \WBCR\APT\AutoPostThumbnails::instance();
|
68 |
-
}
|
69 |
-
|
70 |
$this->global_scripts();
|
71 |
}
|
72 |
|
@@ -116,8 +106,6 @@ class WAPT_Plugin extends Wbcr_Factory458_Plugin {
|
|
116 |
/**
|
117 |
*/
|
118 |
private function admin_scripts() {
|
119 |
-
require_once WAPT_PLUGIN_DIR . '/includes/class.generate-result.php';
|
120 |
-
|
121 |
//$this->register_pages();
|
122 |
|
123 |
//------ ACTIONS ------
|
@@ -171,6 +159,7 @@ class WAPT_Plugin extends Wbcr_Factory458_Plugin {
|
|
171 |
/**
|
172 |
*/
|
173 |
private function global_scripts() {
|
|
|
174 |
}
|
175 |
|
176 |
/**
|
1 |
<?php
|
2 |
|
|
|
|
|
|
|
3 |
// Exit if accessed directly
|
4 |
if ( ! defined( 'ABSPATH' ) ) {
|
5 |
exit;
|
8 |
/**
|
9 |
* Основной класс плагина Auto Featured Image
|
10 |
*
|
|
|
|
|
11 |
* @version 1.0
|
12 |
*/
|
13 |
class WAPT_Plugin extends Wbcr_Factory458_Plugin {
|
43 |
parent::__construct( $plugin_path, $data );
|
44 |
|
45 |
self::$app = $this;
|
46 |
+
$this->apt = \WBCR\APT\AutoPostThumbnails::instance();
|
47 |
|
48 |
if ( is_admin() ) {
|
49 |
// Регистрации класса активации/деактивации плагина
|
50 |
$this->initActivation();
|
51 |
|
52 |
$this->numberOfColumn = 4;
|
|
|
53 |
|
54 |
require WAPT_PLUGIN_DIR . '/admin/ajax/check-license.php';
|
55 |
|
57 |
$this->admin_scripts();
|
58 |
}
|
59 |
|
|
|
|
|
|
|
|
|
|
|
60 |
$this->global_scripts();
|
61 |
}
|
62 |
|
106 |
/**
|
107 |
*/
|
108 |
private function admin_scripts() {
|
|
|
|
|
109 |
//$this->register_pages();
|
110 |
|
111 |
//------ ACTIONS ------
|
159 |
/**
|
160 |
*/
|
161 |
private function global_scripts() {
|
162 |
+
require_once WAPT_PLUGIN_DIR . '/includes/class.generate-result.php';
|
163 |
}
|
164 |
|
165 |
/**
|
includes/class.generate-result.php
CHANGED
@@ -55,6 +55,7 @@ class GenerateResult {
|
|
55 |
'both' => __( 'Find or generate', 'apt' ),
|
56 |
'google' => __( 'Google', 'apt' ),
|
57 |
'find_google' => __( 'Find or Google', 'apt' ),
|
|
|
58 |
];
|
59 |
|
60 |
$this->post_id = $post_id;
|
@@ -86,6 +87,7 @@ class GenerateResult {
|
|
86 |
*/
|
87 |
public function result( $message = '', $thumbnail_id = 0, $status = '' ) {
|
88 |
$this->setResult( $message, $thumbnail_id, $status );
|
|
|
89 |
|
90 |
return $this;
|
91 |
}
|
@@ -120,7 +122,7 @@ class GenerateResult {
|
|
120 |
$file = ABSPATH . ltrim( $parsed_url['path'], '/' );
|
121 |
if ( file_exists( $file ) ) {
|
122 |
$bytes = filesize( $file );
|
123 |
-
$s =
|
124 |
$e = floor( log( $bytes ) / log( 1024 ) );
|
125 |
|
126 |
return sprintf( '%d ' . $s[ $e ], ( $bytes / pow( 1024, floor( $e ) ) ) );
|
@@ -131,11 +133,10 @@ class GenerateResult {
|
|
131 |
}
|
132 |
|
133 |
/**
|
134 |
-
* @param bool $write_to_log is write to log?
|
135 |
*
|
136 |
* @return array
|
137 |
*/
|
138 |
-
public function getData(
|
139 |
if ( $this->thumbnail_id ) {
|
140 |
$data = [
|
141 |
[
|
@@ -161,14 +162,17 @@ class GenerateResult {
|
|
161 |
];
|
162 |
}
|
163 |
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
|
|
|
|
|
|
170 |
}
|
|
|
171 |
|
172 |
-
return $data;
|
173 |
}
|
174 |
}
|
55 |
'both' => __( 'Find or generate', 'apt' ),
|
56 |
'google' => __( 'Google', 'apt' ),
|
57 |
'find_google' => __( 'Find or Google', 'apt' ),
|
58 |
+
'use_default' => __( 'Find or use default image', 'apt' ),
|
59 |
];
|
60 |
|
61 |
$this->post_id = $post_id;
|
87 |
*/
|
88 |
public function result( $message = '', $thumbnail_id = 0, $status = '' ) {
|
89 |
$this->setResult( $message, $thumbnail_id, $status );
|
90 |
+
$this->write_to_log();
|
91 |
|
92 |
return $this;
|
93 |
}
|
122 |
$file = ABSPATH . ltrim( $parsed_url['path'], '/' );
|
123 |
if ( file_exists( $file ) ) {
|
124 |
$bytes = filesize( $file );
|
125 |
+
$s = [ 'b', 'Kb', 'Mb', 'Gb' ];
|
126 |
$e = floor( log( $bytes ) / log( 1024 ) );
|
127 |
|
128 |
return sprintf( '%d ' . $s[ $e ], ( $bytes / pow( 1024, floor( $e ) ) ) );
|
133 |
}
|
134 |
|
135 |
/**
|
|
|
136 |
*
|
137 |
* @return array
|
138 |
*/
|
139 |
+
public function getData() {
|
140 |
if ( $this->thumbnail_id ) {
|
141 |
$data = [
|
142 |
[
|
162 |
];
|
163 |
}
|
164 |
|
165 |
+
return $data;
|
166 |
+
}
|
167 |
+
|
168 |
+
public function write_to_log() {
|
169 |
+
$data = $this->getData();
|
170 |
+
|
171 |
+
$log = \WAPT_Plugin::app()->getPopulateOption( 'generation_log', [] );
|
172 |
+
if ( count( $log ) > 100 ) {
|
173 |
+
$log = array_slice( $log, 0, 100 );
|
174 |
}
|
175 |
+
\WAPT_Plugin::app()->updatePopulateOption( 'generation_log', array_merge( $data, $log ) );
|
176 |
|
|
|
177 |
}
|
178 |
}
|
includes/image-search/class-google-images.php
CHANGED
@@ -36,24 +36,28 @@ class GoogleImages implements ImageSearch {
|
|
36 |
* @throws Exception
|
37 |
*/
|
38 |
public function search( $query, $page ) {
|
39 |
-
/*
|
40 |
-
if ( isset( $_POST['rights'] ) && (int) $_POST['rights'] ) {
|
41 |
-
$rights = '&rights=(cc_publicdomain%7Ccc_attribute%7Ccc_sharealike).-(cc_noncommercial%7Ccc_nonderived)';
|
42 |
-
} else {
|
43 |
-
$rights = '';
|
44 |
-
}
|
45 |
-
*/
|
46 |
$rights = '(cc_publicdomain%7Ccc_attribute%7Ccc_sharealike).-(cc_noncommercial%7Ccc_nonderived)';
|
47 |
|
48 |
-
$start
|
49 |
-
$
|
50 |
'searchType' => 'image',
|
51 |
'start' => $start,
|
52 |
'rights' => $rights,
|
53 |
'q' => $query,
|
54 |
'key' => $this->key,
|
55 |
'cx' => $this->cse,
|
56 |
-
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
57 |
|
58 |
/**
|
59 |
* @var array|null $limit = [
|
36 |
* @throws Exception
|
37 |
*/
|
38 |
public function search( $query, $page ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
39 |
$rights = '(cc_publicdomain%7Ccc_attribute%7Ccc_sharealike).-(cc_noncommercial%7Ccc_nonderived)';
|
40 |
|
41 |
+
$start = ( ( $page - 1 ) * 10 ) + 1;
|
42 |
+
$params = [
|
43 |
'searchType' => 'image',
|
44 |
'start' => $start,
|
45 |
'rights' => $rights,
|
46 |
'q' => $query,
|
47 |
'key' => $this->key,
|
48 |
'cx' => $this->cse,
|
49 |
+
];
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Filters the list of GET params for Google search query.
|
53 |
+
*
|
54 |
+
* @param array $params Array of GET params for search query.
|
55 |
+
*
|
56 |
+
* @since 3.9.12
|
57 |
+
*/
|
58 |
+
$params = apply_filters( 'wysc/generation/google_search_params', $params, $query );
|
59 |
+
|
60 |
+
$url = sprintf( '%s?%s', self::URL, http_build_query( $params ) );
|
61 |
|
62 |
/**
|
63 |
* @var array|null $limit = [
|
libs/factory/processing/boot.php
ADDED
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Factory Processing
|
5 |
+
*
|
6 |
+
* Use https://github.com/deliciousbrains/wp-background-processing
|
7 |
+
*
|
8 |
+
* @author Artem Prihodko <webtemyk@yandex.ru>
|
9 |
+
* @since 1.0.0
|
10 |
+
*
|
11 |
+
* @package factory-processing
|
12 |
+
* @copyright (c) 2021, Webcraftic Ltd
|
13 |
+
*
|
14 |
+
* @version 1.0.0
|
15 |
+
*/
|
16 |
+
|
17 |
+
// Exit if accessed directly
|
18 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
19 |
+
exit;
|
20 |
+
}
|
21 |
+
|
22 |
+
if ( defined( 'FACTORY_PROCESSING_103_LOADED' ) || ( defined( 'FACTORY_PROCESSING_STOP' ) && FACTORY_PROCESSING_STOP ) ) {
|
23 |
+
return;
|
24 |
+
}
|
25 |
+
|
26 |
+
define( 'FACTORY_PROCESSING_103_LOADED', true );
|
27 |
+
define( 'FACTORY_PROCESSING_103_VERSION', '1.0.3' );
|
28 |
+
define( 'FACTORY_PROCESSING_103_DIR', dirname( __FILE__ ) );
|
29 |
+
define( 'FACTORY_PROCESSING_103_URL', plugins_url( null, __FILE__ ) );
|
30 |
+
|
31 |
+
//load_plugin_textdomain( 'wbcr_factory_processing_103', false, dirname( plugin_basename( __FILE__ ) ) . '/langs' );
|
32 |
+
|
33 |
+
require_once( FACTORY_PROCESSING_103_DIR . '/includes/classes/wp-async-request.php' );
|
34 |
+
require_once( FACTORY_PROCESSING_103_DIR . '/includes/classes/wp-background-process.php' );
|
35 |
+
|
36 |
+
|
37 |
+
/**
|
38 |
+
* @param Wbcr_Factory458_Plugin $plugin
|
39 |
+
*/
|
40 |
+
add_action( 'wbcr_factory_processing_103_plugin_created', function ( $plugin ) {
|
41 |
+
/* @var Wbcr_Factory458_Plugin $plugin */
|
42 |
+
|
43 |
+
/* Settings of Processing
|
44 |
+
$settings = [
|
45 |
+
'dir' => null,
|
46 |
+
'file' => 'app.log',
|
47 |
+
'flush_interval' => 1000,
|
48 |
+
'rotate_size' => 5000000,
|
49 |
+
'rotate_limit' => 3,
|
50 |
+
];
|
51 |
+
|
52 |
+
$plugin->set_logger( "WBCR\Factory_Processing_103\Processing", $settings );
|
53 |
+
*/
|
54 |
+
} );
|
libs/factory/processing/includes/classes/wp-async-request.php
ADDED
@@ -0,0 +1,187 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WBCR\Factory_Processing_103;
|
4 |
+
|
5 |
+
use WP_Error;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* WP Async Request
|
9 |
+
*
|
10 |
+
* @package WP-Background-Processing
|
11 |
+
*/
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Abstract WP_Async_Request class.
|
15 |
+
*
|
16 |
+
* @abstract
|
17 |
+
*/
|
18 |
+
abstract class WP_Async_Request {
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Prefix
|
22 |
+
*
|
23 |
+
* (default value: 'wp')
|
24 |
+
*
|
25 |
+
* @var string
|
26 |
+
* @access protected
|
27 |
+
*/
|
28 |
+
protected $prefix = 'wp';
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Action
|
32 |
+
*
|
33 |
+
* (default value: 'async_request')
|
34 |
+
*
|
35 |
+
* @var string
|
36 |
+
* @access protected
|
37 |
+
*/
|
38 |
+
protected $action = 'async_request';
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Identifier
|
42 |
+
*
|
43 |
+
* @var mixed
|
44 |
+
* @access protected
|
45 |
+
*/
|
46 |
+
protected $identifier;
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Data
|
50 |
+
*
|
51 |
+
* (default value: array())
|
52 |
+
*
|
53 |
+
* @var array
|
54 |
+
* @access protected
|
55 |
+
*/
|
56 |
+
protected $data = [];
|
57 |
+
|
58 |
+
/**
|
59 |
+
* Initiate new async request
|
60 |
+
*/
|
61 |
+
public function __construct() {
|
62 |
+
$this->identifier = $this->prefix . '_' . str_replace( '-', '_', $this->action );
|
63 |
+
|
64 |
+
add_action( 'wp_ajax_' . $this->identifier, [ $this, 'maybe_handle' ] );
|
65 |
+
add_action( 'wp_ajax_nopriv_' . $this->identifier, [ $this, 'maybe_handle' ] );
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Set data used during the request
|
70 |
+
*
|
71 |
+
* @param array $data Data.
|
72 |
+
*
|
73 |
+
* @return $this
|
74 |
+
*/
|
75 |
+
public function data( $data ) {
|
76 |
+
$this->data = $data;
|
77 |
+
|
78 |
+
return $this;
|
79 |
+
}
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Dispatch the async request
|
83 |
+
*
|
84 |
+
* @return array|WP_Error
|
85 |
+
*/
|
86 |
+
public function dispatch() {
|
87 |
+
$url = add_query_arg( $this->get_query_args(), $this->get_query_url() );
|
88 |
+
$args = $this->get_post_args();
|
89 |
+
|
90 |
+
return wp_remote_post( esc_url_raw( $url ), $args );
|
91 |
+
}
|
92 |
+
|
93 |
+
/**
|
94 |
+
* Get query args
|
95 |
+
*
|
96 |
+
* @return array
|
97 |
+
*/
|
98 |
+
protected function get_query_args() {
|
99 |
+
if ( property_exists( $this, 'query_args' ) ) {
|
100 |
+
return $this->query_args;
|
101 |
+
}
|
102 |
+
|
103 |
+
$args = [
|
104 |
+
'action' => $this->identifier,
|
105 |
+
'scope' => $this->scope,
|
106 |
+
'nonce' => \wp_create_nonce( $this->identifier ),
|
107 |
+
];
|
108 |
+
|
109 |
+
/**
|
110 |
+
* Filters the post arguments used during an async request.
|
111 |
+
*
|
112 |
+
* @param array $url
|
113 |
+
*/
|
114 |
+
return apply_filters( $this->identifier . '_query_args', $args );
|
115 |
+
}
|
116 |
+
|
117 |
+
/**
|
118 |
+
* Get query URL
|
119 |
+
*
|
120 |
+
* @return string
|
121 |
+
*/
|
122 |
+
protected function get_query_url() {
|
123 |
+
if ( property_exists( $this, 'query_url' ) ) {
|
124 |
+
return $this->query_url;
|
125 |
+
}
|
126 |
+
|
127 |
+
$url = admin_url( 'admin-ajax.php' );
|
128 |
+
|
129 |
+
/**
|
130 |
+
* Filters the post arguments used during an async request.
|
131 |
+
*
|
132 |
+
* @param string $url
|
133 |
+
*/
|
134 |
+
return apply_filters( $this->identifier . '_query_url', $url );
|
135 |
+
}
|
136 |
+
|
137 |
+
/**
|
138 |
+
* Get post args
|
139 |
+
*
|
140 |
+
* @return array
|
141 |
+
*/
|
142 |
+
protected function get_post_args() {
|
143 |
+
if ( property_exists( $this, 'post_args' ) ) {
|
144 |
+
return $this->post_args;
|
145 |
+
}
|
146 |
+
|
147 |
+
$args = [
|
148 |
+
'timeout' => 0.01,
|
149 |
+
'blocking' => false,
|
150 |
+
'body' => $this->data,
|
151 |
+
'cookies' => $_COOKIE,
|
152 |
+
'sslverify' => apply_filters( 'https_local_ssl_verify', false ),
|
153 |
+
];
|
154 |
+
|
155 |
+
/**
|
156 |
+
* Filters the post arguments used during an async request.
|
157 |
+
*
|
158 |
+
* @param array $args
|
159 |
+
*/
|
160 |
+
return apply_filters( $this->identifier . '_post_args', $args );
|
161 |
+
}
|
162 |
+
|
163 |
+
/**
|
164 |
+
* Maybe handle
|
165 |
+
*
|
166 |
+
* Check for correct nonce and pass to handler.
|
167 |
+
*/
|
168 |
+
public function maybe_handle() {
|
169 |
+
// Don't lock up other requests while processing
|
170 |
+
session_write_close();
|
171 |
+
|
172 |
+
check_ajax_referer( $this->identifier, 'nonce' );
|
173 |
+
|
174 |
+
$this->handle();
|
175 |
+
|
176 |
+
wp_die();
|
177 |
+
}
|
178 |
+
|
179 |
+
/**
|
180 |
+
* Handle
|
181 |
+
*
|
182 |
+
* Override this method to perform any actions required
|
183 |
+
* during the async request.
|
184 |
+
*/
|
185 |
+
abstract protected function handle();
|
186 |
+
|
187 |
+
}
|
libs/factory/processing/includes/classes/wp-background-process.php
ADDED
@@ -0,0 +1,555 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WBCR\Factory_Processing_103;
|
4 |
+
/**
|
5 |
+
* WP Background Process
|
6 |
+
*
|
7 |
+
* @package WP-Background-Processing
|
8 |
+
*/
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Abstract WP_Background_Process class.
|
12 |
+
*
|
13 |
+
* @abstract
|
14 |
+
* @extends WP_Async_Request
|
15 |
+
*/
|
16 |
+
abstract class WP_Background_Process extends WP_Async_Request {
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Action
|
20 |
+
*
|
21 |
+
* (default value: 'background_process')
|
22 |
+
*
|
23 |
+
* @var string
|
24 |
+
* @access protected
|
25 |
+
*/
|
26 |
+
protected $action = 'background_process';
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Start time of current process.
|
30 |
+
*
|
31 |
+
* (default value: 0)
|
32 |
+
*
|
33 |
+
* @var int
|
34 |
+
* @access protected
|
35 |
+
*/
|
36 |
+
protected $start_time = 0;
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Cron_hook_identifier
|
40 |
+
*
|
41 |
+
* @var mixed
|
42 |
+
* @access protected
|
43 |
+
*/
|
44 |
+
protected $cron_hook_identifier;
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Cron_interval_identifier
|
48 |
+
*
|
49 |
+
* @var mixed
|
50 |
+
* @access protected
|
51 |
+
*/
|
52 |
+
protected $cron_interval_identifier;
|
53 |
+
|
54 |
+
/**
|
55 |
+
* Initiate new background process
|
56 |
+
*/
|
57 |
+
public function __construct() {
|
58 |
+
parent::__construct();
|
59 |
+
|
60 |
+
$this->cron_hook_identifier = $this->identifier . '_cron';
|
61 |
+
$this->cron_interval_identifier = $this->identifier . '_cron_interval';
|
62 |
+
|
63 |
+
add_action( $this->cron_hook_identifier, [ $this, 'handle_cron_healthcheck' ] );
|
64 |
+
add_filter( 'cron_schedules', [ $this, 'schedule_cron_healthcheck' ] );
|
65 |
+
}
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Dispatch
|
69 |
+
*
|
70 |
+
* @access public
|
71 |
+
* @return array|\WP_Error
|
72 |
+
*/
|
73 |
+
public function dispatch() {
|
74 |
+
// Schedule the cron healthcheck.
|
75 |
+
$this->schedule_event();
|
76 |
+
|
77 |
+
// Perform remote post.
|
78 |
+
return parent::dispatch();
|
79 |
+
}
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Push to queue
|
83 |
+
*
|
84 |
+
* @param mixed $data Data.
|
85 |
+
*
|
86 |
+
* @return $this
|
87 |
+
*/
|
88 |
+
public function push_to_queue( $data ) {
|
89 |
+
$this->data[] = $data;
|
90 |
+
|
91 |
+
return $this;
|
92 |
+
}
|
93 |
+
|
94 |
+
/**
|
95 |
+
* Count of queue
|
96 |
+
*
|
97 |
+
* @return int
|
98 |
+
*/
|
99 |
+
public function count_queue() {
|
100 |
+
return count( $this->data );
|
101 |
+
}
|
102 |
+
|
103 |
+
/**
|
104 |
+
* Save queue
|
105 |
+
*
|
106 |
+
* @return $this
|
107 |
+
*/
|
108 |
+
public function save() {
|
109 |
+
$key = $this->generate_key();
|
110 |
+
|
111 |
+
if ( ! empty( $this->data ) ) {
|
112 |
+
update_site_option( $key, $this->data );
|
113 |
+
}
|
114 |
+
|
115 |
+
return $this;
|
116 |
+
}
|
117 |
+
|
118 |
+
/**
|
119 |
+
* Update queue
|
120 |
+
*
|
121 |
+
* @param string $key Key.
|
122 |
+
* @param array $data Data.
|
123 |
+
*
|
124 |
+
* @return $this
|
125 |
+
*/
|
126 |
+
public function update( $key, $data ) {
|
127 |
+
if ( ! empty( $data ) ) {
|
128 |
+
update_site_option( $key, $data );
|
129 |
+
}
|
130 |
+
|
131 |
+
return $this;
|
132 |
+
}
|
133 |
+
|
134 |
+
/**
|
135 |
+
* Delete queue
|
136 |
+
*
|
137 |
+
* @param string $key Key.
|
138 |
+
*
|
139 |
+
* @return $this
|
140 |
+
*/
|
141 |
+
public function delete( $key ) {
|
142 |
+
delete_site_option( $key );
|
143 |
+
|
144 |
+
return $this;
|
145 |
+
}
|
146 |
+
|
147 |
+
/**
|
148 |
+
* Stop queue
|
149 |
+
*
|
150 |
+
* @param string $key Key.
|
151 |
+
*
|
152 |
+
* @return $this
|
153 |
+
*/
|
154 |
+
public function stop( $key ) {
|
155 |
+
$batch = get_site_option( $key );
|
156 |
+
$batch2[] = array_shift( $batch );
|
157 |
+
|
158 |
+
update_site_option( $key, $batch2 );
|
159 |
+
|
160 |
+
return $this;
|
161 |
+
}
|
162 |
+
|
163 |
+
/**
|
164 |
+
* Generate key
|
165 |
+
*
|
166 |
+
* Generates a unique key based on microtime. Queue items are
|
167 |
+
* given a unique key so that they can be merged upon save.
|
168 |
+
*
|
169 |
+
* @param int $length Length.
|
170 |
+
*
|
171 |
+
* @return string
|
172 |
+
*/
|
173 |
+
protected function generate_key( $length = 64 ) {
|
174 |
+
$unique = md5( microtime() . rand() );
|
175 |
+
$prepend = $this->identifier . '_batch_';
|
176 |
+
|
177 |
+
return substr( $prepend . $unique, 0, $length );
|
178 |
+
}
|
179 |
+
|
180 |
+
/**
|
181 |
+
* Maybe process queue
|
182 |
+
*
|
183 |
+
* Checks whether data exists within the queue and that
|
184 |
+
* the process is not already running.
|
185 |
+
*/
|
186 |
+
public function maybe_handle() {
|
187 |
+
// Don't lock up other requests while processing
|
188 |
+
session_write_close();
|
189 |
+
|
190 |
+
if ( $this->is_process_running() ) {
|
191 |
+
// Background process already running.
|
192 |
+
wp_die();
|
193 |
+
}
|
194 |
+
|
195 |
+
if ( $this->is_queue_empty() ) {
|
196 |
+
// No data to process.
|
197 |
+
wp_die();
|
198 |
+
}
|
199 |
+
|
200 |
+
check_ajax_referer( $this->identifier, 'nonce' );
|
201 |
+
|
202 |
+
$this->handle();
|
203 |
+
|
204 |
+
wp_die();
|
205 |
+
}
|
206 |
+
|
207 |
+
/**
|
208 |
+
* Is queue empty
|
209 |
+
*
|
210 |
+
* @return bool
|
211 |
+
*/
|
212 |
+
protected function is_queue_empty() {
|
213 |
+
global $wpdb;
|
214 |
+
|
215 |
+
$table = $wpdb->options;
|
216 |
+
$column = 'option_name';
|
217 |
+
|
218 |
+
if ( is_multisite() ) {
|
219 |
+
$table = $wpdb->sitemeta;
|
220 |
+
$column = 'meta_key';
|
221 |
+
}
|
222 |
+
|
223 |
+
$key = $wpdb->esc_like( $this->identifier . '_batch_' ) . '%';
|
224 |
+
|
225 |
+
$count = $wpdb->get_var( $wpdb->prepare( "
|
226 |
+
SELECT COUNT(*)
|
227 |
+
FROM {$table}
|
228 |
+
WHERE {$column} LIKE %s
|
229 |
+
", $key ) );
|
230 |
+
|
231 |
+
return ( $count > 0 ) ? false : true;
|
232 |
+
}
|
233 |
+
|
234 |
+
/**
|
235 |
+
* Is process running
|
236 |
+
*
|
237 |
+
* Check whether the current process is already running
|
238 |
+
* in a background process.
|
239 |
+
*/
|
240 |
+
protected function is_process_running() {
|
241 |
+
if ( get_site_transient( $this->identifier . '_process_lock' ) ) {
|
242 |
+
// Process already running.
|
243 |
+
return true;
|
244 |
+
}
|
245 |
+
|
246 |
+
return false;
|
247 |
+
}
|
248 |
+
|
249 |
+
/**
|
250 |
+
* Lock process
|
251 |
+
*
|
252 |
+
* Lock the process so that multiple instances can't run simultaneously.
|
253 |
+
* Override if applicable, but the duration should be greater than that
|
254 |
+
* defined in the time_exceeded() method.
|
255 |
+
*/
|
256 |
+
protected function lock_process() {
|
257 |
+
$this->start_time = time(); // Set start time of current process.
|
258 |
+
|
259 |
+
$lock_duration = ( property_exists( $this, 'queue_lock_time' ) ) ? $this->queue_lock_time : 60; // 1 minute
|
260 |
+
$lock_duration = apply_filters( $this->identifier . '_queue_lock_time', $lock_duration );
|
261 |
+
|
262 |
+
set_site_transient( $this->identifier . '_process_lock', microtime(), $lock_duration );
|
263 |
+
}
|
264 |
+
|
265 |
+
/**
|
266 |
+
* Unlock process
|
267 |
+
*
|
268 |
+
* Unlock the process so that other instances can spawn.
|
269 |
+
*
|
270 |
+
* @return $this
|
271 |
+
*/
|
272 |
+
protected function unlock_process() {
|
273 |
+
delete_site_transient( $this->identifier . '_process_lock' );
|
274 |
+
|
275 |
+
return $this;
|
276 |
+
}
|
277 |
+
|
278 |
+
/**
|
279 |
+
* Get batch
|
280 |
+
*
|
281 |
+
* @return \stdClass Return the first batch from the queue
|
282 |
+
*/
|
283 |
+
protected function get_batch() {
|
284 |
+
global $wpdb;
|
285 |
+
|
286 |
+
$table = $wpdb->options;
|
287 |
+
$column = 'option_name';
|
288 |
+
$key_column = 'option_id';
|
289 |
+
$value_column = 'option_value';
|
290 |
+
|
291 |
+
if ( is_multisite() ) {
|
292 |
+
$table = $wpdb->sitemeta;
|
293 |
+
$column = 'meta_key';
|
294 |
+
$key_column = 'meta_id';
|
295 |
+
$value_column = 'meta_value';
|
296 |
+
}
|
297 |
+
|
298 |
+
$key = $wpdb->esc_like( $this->identifier . '_batch_' ) . '%';
|
299 |
+
|
300 |
+
$query = $wpdb->get_row( $wpdb->prepare( "
|
301 |
+
SELECT *
|
302 |
+
FROM {$table}
|
303 |
+
WHERE {$column} LIKE %s
|
304 |
+
ORDER BY {$key_column} ASC
|
305 |
+
LIMIT 1
|
306 |
+
", $key ) );
|
307 |
+
|
308 |
+
$batch = new \stdClass();
|
309 |
+
$batch->key = $query->$column;
|
310 |
+
$batch->data = maybe_unserialize( $query->$value_column );
|
311 |
+
|
312 |
+
return $batch;
|
313 |
+
}
|
314 |
+
|
315 |
+
/**
|
316 |
+
* Handle
|
317 |
+
*
|
318 |
+
* Pass each queue item to the task handler, while remaining
|
319 |
+
* within server memory and time limit constraints.
|
320 |
+
*/
|
321 |
+
protected function handle() {
|
322 |
+
$this->handle_before();
|
323 |
+
|
324 |
+
$this->lock_process();
|
325 |
+
do {
|
326 |
+
$batch = $this->get_batch();
|
327 |
+
|
328 |
+
foreach ( $batch->data as $key => $value ) {
|
329 |
+
$task = $this->task( $value );
|
330 |
+
|
331 |
+
if ( false !== $task ) {
|
332 |
+
$batch->data[ $key ] = $task;
|
333 |
+
} else {
|
334 |
+
unset( $batch->data[ $key ] );
|
335 |
+
}
|
336 |
+
|
337 |
+
if ( $this->time_exceeded() || $this->memory_exceeded() ) {
|
338 |
+
// Batch limits reached.
|
339 |
+
break;
|
340 |
+
}
|
341 |
+
}
|
342 |
+
|
343 |
+
// Update or delete current batch.
|
344 |
+
if ( ! empty( $batch->data ) ) {
|
345 |
+
if ( ! $this->is_queue_empty() ) {
|
346 |
+
$this->update( $batch->key, $batch->data );
|
347 |
+
}
|
348 |
+
} else {
|
349 |
+
$this->delete( $batch->key );
|
350 |
+
}
|
351 |
+
} while ( ! $this->time_exceeded() && ! $this->memory_exceeded() && ! $this->is_queue_empty() );
|
352 |
+
$this->unlock_process();
|
353 |
+
|
354 |
+
$this->handle_after();
|
355 |
+
|
356 |
+
// Start next batch or complete process.
|
357 |
+
if ( ! $this->is_queue_empty() ) {
|
358 |
+
$this->dispatch();
|
359 |
+
} else {
|
360 |
+
$this->complete();
|
361 |
+
$this->handle_after_complete();
|
362 |
+
}
|
363 |
+
|
364 |
+
wp_die();
|
365 |
+
}
|
366 |
+
|
367 |
+
/**
|
368 |
+
* Fire before start handle the tasks
|
369 |
+
*/
|
370 |
+
protected function handle_before() {
|
371 |
+
}
|
372 |
+
|
373 |
+
/**
|
374 |
+
* Fire after end handle the tasks
|
375 |
+
*/
|
376 |
+
protected function handle_after() {
|
377 |
+
}
|
378 |
+
|
379 |
+
/**
|
380 |
+
* Fire after complete handle
|
381 |
+
*/
|
382 |
+
protected function handle_after_complete() {
|
383 |
+
}
|
384 |
+
|
385 |
+
/**
|
386 |
+
* Memory exceeded
|
387 |
+
*
|
388 |
+
* Ensures the batch process never exceeds 90%
|
389 |
+
* of the maximum WordPress memory.
|
390 |
+
*
|
391 |
+
* @return bool
|
392 |
+
*/
|
393 |
+
protected function memory_exceeded() {
|
394 |
+
$memory_limit = $this->get_memory_limit() * 0.9; // 90% of max memory
|
395 |
+
$current_memory = memory_get_usage( true );
|
396 |
+
$return = false;
|
397 |
+
|
398 |
+
if ( $current_memory >= $memory_limit ) {
|
399 |
+
$return = true;
|
400 |
+
}
|
401 |
+
|
402 |
+
return apply_filters( $this->identifier . '_memory_exceeded', $return );
|
403 |
+
}
|
404 |
+
|
405 |
+
/**
|
406 |
+
* Get memory limit
|
407 |
+
*
|
408 |
+
* @return int
|
409 |
+
*/
|
410 |
+
protected function get_memory_limit() {
|
411 |
+
if ( function_exists( 'ini_get' ) ) {
|
412 |
+
$memory_limit = ini_get( 'memory_limit' );
|
413 |
+
} else {
|
414 |
+
// Sensible default.
|
415 |
+
$memory_limit = '128M';
|
416 |
+
}
|
417 |
+
|
418 |
+
if ( ! $memory_limit || - 1 === intval( $memory_limit ) ) {
|
419 |
+
// Unlimited, set to 32GB.
|
420 |
+
$memory_limit = '32000M';
|
421 |
+
}
|
422 |
+
|
423 |
+
return wp_convert_hr_to_bytes( $memory_limit );
|
424 |
+
}
|
425 |
+
|
426 |
+
/**
|
427 |
+
* Time exceeded.
|
428 |
+
*
|
429 |
+
* Ensures the batch never exceeds a sensible time limit.
|
430 |
+
* A timeout limit of 30s is common on shared hosting.
|
431 |
+
*
|
432 |
+
* @return bool
|
433 |
+
*/
|
434 |
+
protected function time_exceeded() {
|
435 |
+
$finish = $this->start_time + apply_filters( $this->identifier . '_default_time_limit', 20 ); // 20 seconds
|
436 |
+
$return = false;
|
437 |
+
|
438 |
+
if ( time() >= $finish ) {
|
439 |
+
$return = true;
|
440 |
+
}
|
441 |
+
|
442 |
+
return apply_filters( $this->identifier . '_time_exceeded', $return );
|
443 |
+
}
|
444 |
+
|
445 |
+
/**
|
446 |
+
* Complete.
|
447 |
+
*
|
448 |
+
* Override if applicable, but ensure that the below actions are
|
449 |
+
* performed, or, call parent::complete().
|
450 |
+
*/
|
451 |
+
protected function complete() {
|
452 |
+
// Unschedule the cron healthcheck.
|
453 |
+
$this->clear_scheduled_event();
|
454 |
+
}
|
455 |
+
|
456 |
+
/**
|
457 |
+
* Schedule cron healthcheck
|
458 |
+
*
|
459 |
+
* @access public
|
460 |
+
*
|
461 |
+
* @param mixed $schedules Schedules.
|
462 |
+
*
|
463 |
+
* @return mixed
|
464 |
+
*/
|
465 |
+
public function schedule_cron_healthcheck( $schedules ) {
|
466 |
+
$interval = apply_filters( $this->identifier . '_cron_interval', 5 );
|
467 |
+
|
468 |
+
if ( property_exists( $this, 'cron_interval' ) ) {
|
469 |
+
$interval = apply_filters( $this->identifier . '_cron_interval', $this->cron_interval );
|
470 |
+
}
|
471 |
+
|
472 |
+
// Adds every 5 minutes to the existing schedules.
|
473 |
+
$schedules[ $this->identifier . '_cron_interval' ] = [
|
474 |
+
'interval' => MINUTE_IN_SECONDS * $interval,
|
475 |
+
'display' => sprintf( __( 'Every %d Minutes' ), $interval ),
|
476 |
+
];
|
477 |
+
|
478 |
+
return $schedules;
|
479 |
+
}
|
480 |
+
|
481 |
+
/**
|
482 |
+
* Handle cron healthcheck
|
483 |
+
*
|
484 |
+
* Restart the background process if not already running
|
485 |
+
* and data exists in the queue.
|
486 |
+
*/
|
487 |
+
public function handle_cron_healthcheck() {
|
488 |
+
if ( $this->is_process_running() ) {
|
489 |
+
// Background process already running.
|
490 |
+
exit;
|
491 |
+
}
|
492 |
+
|
493 |
+
if ( $this->is_queue_empty() ) {
|
494 |
+
// No data to process.
|
495 |
+
$this->clear_scheduled_event();
|
496 |
+
exit;
|
497 |
+
}
|
498 |
+
|
499 |
+
$this->handle();
|
500 |
+
|
501 |
+
exit;
|
502 |
+
}
|
503 |
+
|
504 |
+
/**
|
505 |
+
* Schedule event
|
506 |
+
*/
|
507 |
+
protected function schedule_event() {
|
508 |
+
if ( ! wp_next_scheduled( $this->cron_hook_identifier ) ) {
|
509 |
+
wp_schedule_event( time(), $this->cron_interval_identifier, $this->cron_hook_identifier );
|
510 |
+
}
|
511 |
+
}
|
512 |
+
|
513 |
+
/**
|
514 |
+
* Clear scheduled event
|
515 |
+
*/
|
516 |
+
protected function clear_scheduled_event() {
|
517 |
+
$timestamp = wp_next_scheduled( $this->cron_hook_identifier );
|
518 |
+
|
519 |
+
if ( $timestamp ) {
|
520 |
+
wp_unschedule_event( $timestamp, $this->cron_hook_identifier );
|
521 |
+
}
|
522 |
+
}
|
523 |
+
|
524 |
+
/**
|
525 |
+
* Cancel Process
|
526 |
+
*
|
527 |
+
* Stop processing queue items, clear cronjob and delete batch.
|
528 |
+
*
|
529 |
+
*/
|
530 |
+
public function cancel_process() {
|
531 |
+
if ( ! $this->is_queue_empty() ) {
|
532 |
+
$batch = $this->get_batch();
|
533 |
+
|
534 |
+
$this->delete( $batch->key );
|
535 |
+
|
536 |
+
wp_clear_scheduled_hook( $this->cron_hook_identifier );
|
537 |
+
}
|
538 |
+
|
539 |
+
}
|
540 |
+
|
541 |
+
/**
|
542 |
+
* Task
|
543 |
+
*
|
544 |
+
* Override this method to perform any actions required on each
|
545 |
+
* queue item. Return the modified item for further processing
|
546 |
+
* in the next pass through. Or, return false to remove the
|
547 |
+
* item from the queue.
|
548 |
+
*
|
549 |
+
* @param mixed $item Queue item to iterate over.
|
550 |
+
*
|
551 |
+
* @return mixed
|
552 |
+
*/
|
553 |
+
abstract protected function task( $item );
|
554 |
+
|
555 |
+
}
|
libs/factory/processing/includes/wp-background-processing.php
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
use WBCR\Factory_Processing_103;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* WP-Background Processing
|
7 |
+
*
|
8 |
+
* @package WP-Background-Processing
|
9 |
+
*/
|
10 |
+
|
11 |
+
/*
|
12 |
+
Plugin Name: WP Background Processing
|
13 |
+
Plugin URI: https://github.com/A5hleyRich/wp-background-processing
|
14 |
+
Description: Asynchronous requests and background processing in WordPress.
|
15 |
+
Author: Delicious Brains Inc.
|
16 |
+
Version: 1.0
|
17 |
+
Author URI: https://deliciousbrains.com/
|
18 |
+
GitHub Plugin URI: https://github.com/A5hleyRich/wp-background-processing
|
19 |
+
GitHub Branch: master
|
20 |
+
*/
|
21 |
+
|
22 |
+
if ( ! class_exists( 'WP_Async_Request' ) ) {
|
23 |
+
require_once plugin_dir_path( __FILE__ ) . 'classes/wp-async-request.php';
|
24 |
+
}
|
25 |
+
if ( ! class_exists( 'WP_Background_Process' ) ) {
|
26 |
+
require_once plugin_dir_path( __FILE__ ) . 'classes/wp-background-process.php';
|
27 |
+
}
|
preview.jpg
CHANGED
Binary file
|
readme.txt
CHANGED
@@ -4,7 +4,7 @@ Tags: post thumbnails, featured image, elementor, thumbnails, featured image fro
|
|
4 |
Requires at least: 4.8
|
5 |
Tested up to: 6.0
|
6 |
Requires PHP: 7.0
|
7 |
-
Stable tag:
|
8 |
License: GPLv2
|
9 |
License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
10 |
|
@@ -113,6 +113,12 @@ This section describes how to install the plugin and get it working.
|
|
113 |
|
114 |
== Changelog ==
|
115 |
|
|
|
|
|
|
|
|
|
|
|
|
|
116 |
= 3.9.11 =
|
117 |
* FIX: Google search API issue
|
118 |
|
4 |
Requires at least: 4.8
|
5 |
Tested up to: 6.0
|
6 |
Requires PHP: 7.0
|
7 |
+
Stable tag: 4.0.0
|
8 |
License: GPLv2
|
9 |
License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
10 |
|
113 |
|
114 |
== Changelog ==
|
115 |
|
116 |
+
= 3.9.12 =
|
117 |
+
* ADD: CRON scheduled image generation (New option in settings) - PREMIUM
|
118 |
+
* FIX: Compatibility with ShortPixel plugin
|
119 |
+
* FIX: Generating images after importing via XML-RPC
|
120 |
+
* FIX: Optimization of image generation
|
121 |
+
|
122 |
= 3.9.11 =
|
123 |
* FIX: Google search API issue
|
124 |
|