Auto Post Thumbnail - Version 3.9.12

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 Icon 128x128 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 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: bold;
24
- color: #afafaf;
 
 
 
 
 
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
- 'bootstrap'
97
- );
98
 
99
- $this->styles->request(
100
- [
101
  'control.list',
102
  'bootstrap.accordion',
103
  'bootstrap.tab',
104
- ],
105
- 'bootstrap'
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' => 'buttons',
141
  'name' => 'generate_autoimage',
142
  'data' => [
143
- [ 'find', __( 'Find in post', 'apt' ) ],
144
- [ 'generate', __( 'Generate from title', 'apt' ) ],
145
- [ 'both', __( 'Find or generate', 'apt' ) ],
146
- [ 'google', __( 'Google', 'apt' ) ],
147
- [ 'find_google', __( 'Find or Google', 'apt' ) ],
148
- [ 'use_default', __('Find or use default image', 'apt' )]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
- <canvas id="wapt-main-chart" width="180" height="180"
16
- data-no_featured_image="<?php echo esc_attr( $stats['no_featured_image'] ); ?>"
17
- data-w_featured_image="<?php echo esc_attr( $stats['w_featured_image'] ); ?>"
18
- data-errors="<?php echo esc_attr( $stats['error'] ); ?>"
19
- style="display: block;">
20
- </canvas>
 
 
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.11
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 ( \WAPT_Plugin::app()->is_premium() ) {
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 = \WAPT_Plugin::app()->getPopulateOption( 'auto_generation', true );
106
- $is_auto_upload = \WAPT_Plugin::app()->getPopulateOption( 'auto_upload_images' );
107
- $allowed_import_post_types = explode( ',', \WAPT_Plugin::app()->getPopulateOption( 'import_post_types', 'post' ) );
108
 
109
- $this->allowed_generate_post_types = explode( ',', \WAPT_Plugin::app()->getPopulateOption( 'auto_post_types', 'post,page' ) );
110
 
111
  add_filter( 'mime_types', [ $this, 'allow_upload_webp' ] );
112
 
113
- if ( $is_auto_upload && \WAPT_Plugin::app()->is_premium() ) {
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 ( \WAPT_Plugin::app()->getPopulateOption( 'auto_generation_notice', 1 ) ) {
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 = \WAPT_Plugin::app()->getPopulateOption( 'generate_autoimage', 'find' );
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 ( \WAPT_Plugin::app()->is_premium() ) {
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
- $query = $this->get_posts_query( $has_thumb, $type, $status, $category, $date_start, $date_end );
 
 
 
 
 
 
 
 
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( $has_thumb, $type );
 
 
 
207
  }
208
 
209
  $ids = [];
@@ -214,7 +228,8 @@ class AutoPostThumbnails {
214
  }
215
  }
216
 
217
- $this->plugin->logger->info( "Queried posts IDs: {$ids}" );
 
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
- wp_send_json_success( $result->getData( true ) );
 
247
  } else {
248
- wp_send_json_error( $result->getData( true ) );
 
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
- \WAPT_Plugin::app()->updateOption( 'auto_generation_notice', 0 );
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( $has_thumb = false, $type = 'post', $status = 'publish', $category = 0, $date_start = 0, $date_end = 0, $is_log = true ) {
 
 
 
 
 
 
 
 
 
 
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' => $type,
334
- 'status' => $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' => 'AND',
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
- //global $wpdb;
388
- if ( $has_thumb ) {
389
- $args = [
390
- 'orderby' => 'date',
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( '/-[0-9]{1,}x[0-9]{1,}\./', '.', $image_url );
483
- $thumb_id = $wpdb->get_var( "SELECT ID FROM {$wpdb->posts} WHERE guid LIKE '%" . esc_sql( $image_url ) . "%'" );
 
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
- $autoimage = \WAPT_Plugin::app()->getPopulateOption( 'generate_autoimage', 'find' );
 
 
 
 
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 ( \WAPT_Plugin::app()->is_premium() ) {
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( ',', \WAPT_Plugin::app()->getPopulateOption( 'import_post_types', '' ) );
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]) && !\WAPT_Plugin::app()->premium->is_activate() )
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 !== \WAPT_Plugin::app()->getPluginName() ) {
1198
  return $notices;
1199
  }
1200
  // Получаем заголовок плагина
1201
- $plugin_title = \WAPT_Plugin::app()->getPluginTitle();
1202
 
1203
- if ( ! \WAPT_Plugin::app()->getPopulateOption( 'google_apikey' ) && ! \WAPT_Plugin::app()->getPopulateOption( 'google_cse' ) ) {
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 = \WAPT_Plugin::app()->getPopulateOption( 'image-type', 'jpg' );
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 = \WAPT_Plugin::app()->getPopulateOption( 'default-background', '' );
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 = array( 'b', 'Kb', 'Mb', 'Gb' );
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( $write_to_log = false ) {
139
  if ( $this->thumbnail_id ) {
140
  $data = [
141
  [
@@ -161,14 +162,17 @@ class GenerateResult {
161
  ];
162
  }
163
 
164
- if ( $write_to_log ) {
165
- $log = \WAPT_Plugin::app()->getPopulateOption( 'generation_log', [] );
166
- if ( count( $log ) > 100 ) {
167
- $log = array_slice( $log, 0, 100 );
168
- }
169
- \WAPT_Plugin::app()->updatePopulateOption( 'generation_log', array_merge( $data, $log ) );
 
 
 
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 = ( ( $page - 1 ) * 10 ) + 1;
49
- $url = sprintf( '%s?%s', self::URL, http_build_query( [
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: 3.9.11
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