PluginProbe ʕ •ᴥ•ʔ
XML Feed for Skroutz & BestPrice for WooCommerce / 1.0.3
XML Feed for Skroutz & BestPrice for WooCommerce v1.0.3
trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.1.0 1.1.1 1.1.2 1.2.0 1.2.1 1.2.3 1.2.4
xml-feed-for-skroutz-for-woocommerce / admin / class-dc-skroutz-feed-admin.php
xml-feed-for-skroutz-for-woocommerce / admin Last commit date
css 1 year ago js 1 year ago class-dc-skroutz-feed-admin.php 1 year ago class-dc-skroutz-feed-creator.php 1 year ago class-dc-skroutz-feed-data-helper.php 1 year ago index.php 1 year ago mod_simplexml.php 1 year ago
class-dc-skroutz-feed-admin.php
1678 lines
1 <?php
2
3 /**
4 * The admin-specific functionality of the plugin.
5 *
6 * Defines the plugin name, version, and two examples hooks for how to
7 * enqueue the admin-specific stylesheet and JavaScript.
8 *
9 * @noinspection PhpUnused
10 * @noinspection HtmlUnknownTarget
11 */
12 class Dicha_Skroutz_Feed_Admin {
13
14 /**
15 * The ID of this plugin.
16 *
17 * @var string $plugin_name
18 */
19 private string $plugin_name;
20
21 /**
22 * The current version of this plugin.
23 *
24 * @var string $version
25 */
26 private string $version;
27
28 /**
29 * A list of attribute slug/labels, ready for display in inputs.
30 *
31 * @var array $attributes_list
32 */
33 private array $attributes_list;
34
35 /**
36 * The installed version of WooCommerce plugin.
37 *
38 * @var string $woo_version
39 */
40 private string $woo_version;
41
42
43 /**
44 * Initialize the class and set its properties.
45 *
46 * @param string $plugin_name The name of this plugin.
47 * @param string $version The version of this plugin.
48 */
49 public function __construct( string $plugin_name, string $version ) {
50
51 $this->plugin_name = $plugin_name;
52 $this->version = $version;
53 $this->woo_version = defined( 'WC_VERSION' ) ? WC_VERSION : '6.2.0';
54 }
55
56
57 /**
58 *****************************
59 ***** MENU AND SETTINGS *****
60 *****************************
61 */
62
63 /**
64 * Register top-level menu page if not created already by other DC plugin.
65 */
66 public function create_dc_toplevel_menu(): void {
67
68 if ( empty ( $GLOBALS['admin_page_hooks']['digital_challenge_plugins'] ) ) {
69 add_menu_page(
70 'Digital Challenge',
71 'Digital Challenge',
72 'manage_options',
73 'digital_challenge_plugins',
74 [ $this, 'digital_challenge_plugin_settings' ],
75 'data:image/svg+xml;base64,PHN2ZyBpZD0iZGNfbG9nb19zdmciIGRhdGEtbmFtZT0iZGNfbG9nb19zdmciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjQwMCIgaGVpZ2h0PSI0MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCI+PHBhdGggZmlsbD0iI2E3YWFhZCIgZD0iTTIwNy40IDQuNjQ5Yy0zOS41MDMgNC4wMTMtNzAuNTI5IDE3LjQyMy0xMDQuMjk1IDQ1LjA3Ni0xLjcwMiAxLjM5NS0xMS4xNTIgOC4yMjktMjEgMTUuMTg3TDQ4LjYgODguNjA1bC0yNS4zNzUgMTcuOTE4QzkuNzE3IDExNi4wMjYgOS4wOTQgMTE2LjY4IDEwLjY1OSAxMTkuNzJjLjM2Mi43MDQgNy4wODggMTAuMzcgMTQuOTQ2IDIxLjQ4QzQzLjA0NyAxNjUuODU5IDQxLjQ0OSAxNjMuMDEyIDQxLjIgMTY5Yy0uMzk0IDkuNDU5LS4yIDMwLjMzMi4zMjEgMzQuNkM1MC4yNzcgMjc1LjI1MyA5OS4wNSAzMzEuOTgxIDE2Ny40IDM1MC4wMDdjMi42NC42OTYgNS41MiAxLjY4MyA2LjQgMi4xOTQgMS45MjMgMS4xMTUgMS4xMjQuMDUxIDE4LjQzMyAyNC41NTEgMTQuMTU4IDIwLjA0MSAxNS4wMjkgMjEuMTIgMTYuNyAyMC43MDEuNTE2LS4xMyAxMy43MDItOS4yNjYgMjkuMzAyLTIwLjMwM2w2Ni4xNjUtNDYuMzM5YzU3LjkzOC0zNS4wMiA4OS4yODEtODcuNDI3IDg5LjM1Ny0xNDkuNDExLjA0Ni0zNy44NTYtOC44NjUtNjguNTk0LTI4LjI5Ny05Ny42LTMxLjMzNC00Ni43NzMtNjguNzY2LTcwLjMxNS0xMjQuNDM4LTc4LjI2Mi01LjM5NS0uNzctMjguNzIxLTEuMzg3LTMzLjYyMi0uODg5bTIxIDIyLjE2MWMxNy41MjkgMS4yMTMgNDMuNjk4IDcuNjgyIDQ4LjEgMTEuODg4IDEuODEgMS43MyAxLjYyMiAyLjQwOS03LjE1MSAyNS44NTMtMTEuMTI4IDI5LjczNC05LjU5NSAyNy40NTYtMTYuOTc5IDI1LjIzNS0zMy4wMzItOS45MzktNjAuMzQ3LTYuNTctODYuMDgyIDEwLjYxNy00MC42MjkgMjcuMTM0LTUzLjYzOCA3My45NzEtMzIuNTE4IDExNy4wODEgMjguMTI3IDU3LjQxMyA4OC41MzcgNzUuMTA2IDEzOC42MyA0MC42MDEgMjYuNzA2LTE4LjM5NSAzOS42My00Mi4zMyA0Mi4xNDItNzguMDQ1LjY0My05LjEzNC41NzctOS4wMzcgNi4zMzUtOS4zOSA4Ljc2Mi0uNTM4IDQ3LjMzNy0uNzE4IDQ4LjQxNy0uMjI2IDIuMDA4LjkxNiAyLjMwNiAyLjMyIDIuMzA2IDEwLjg4IDAgNTIuODY3LTI3Ljk4NCA5OS41MjQtNzcuNzEgMTI5LjU2My0zNy4wNTMgMjIuMzgzLTg0Ljc5MiAyOC41MDktMTI1LjY5IDE2LjEyOS0zNC4wNzktMTAuMzE2LTYwLjAyMS0yOS44ODUtODAuODYzLTYwLjk5Ni0yOC41NzEtNDIuNjQ4LTMyLjIzMi05Ni44NDMtOS44NDktMTQ1LjggMjYuMjY4LTU3LjQ1NCA5MS4wMzktOTcuNTM2IDE1MC45MTItOTMuMzltLTEuNDU0IDgxLjAyOWMzMy45NTQgNS4zNzEgNjUuMDg0IDQ2LjMxOSA2MS44ODMgODEuNC0yLjE1IDIzLjU1OS0xMy4zMTkgNDEuMDczLTM0LjEzMiA1My41MjMtNi45NTMgNC4xNTktMTYuNTIgOC4wMzgtMTkuODI1IDguMDM4LTIuODA0IDAtLjM4NCAzLjE1NS0zMy4yODctNDMuNGwtMzcuOTA4LTUzLjZjLTguNDk5LTEyLjAwOS04LjQwNC0xMS4zODktMi44MjItMTguNDU1IDExLjMxNS0xNC4zMjUgMjkuNDMzLTI1LjIwNSA0NS44MzktMjcuNTI1IDguMDAxLTEuMTMxIDEzLjAxLTEuMTI2IDIwLjI1Mi4wMTkiLz48L3N2Zz4=',
76 20
77 );
78 }
79
80 add_submenu_page( 'digital_challenge_plugins', esc_html__( 'Skroutz/BestPrice XML', 'xml-feed-for-skroutz-for-woocommerce' ), esc_html__( 'Skroutz/BestPrice XML', 'xml-feed-for-skroutz-for-woocommerce' ), 'manage_options', DICHA_SKROUTZ_FEED_SLUG, [
81 $this,
82 'digital_challenge_plugin_settings'
83 ] );
84 }
85
86
87 /**
88 * Creates main page and tab menu <ul>. Also provides a hook for other plugins to hook their own tab <li>.
89 */
90 public function digital_challenge_plugin_settings(): void {
91
92 if ( ! current_user_can( 'manage_options' ) ) return;
93
94 ?>
95 <div class="wrap">
96 <h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
97 <?php $this->print_notices(); ?>
98 </div>
99 <div class="settings-tabs">
100 <ul class="subsubsub">
101 <li class="dc-plugin-tab">
102 <?php if ( isset( $_GET['page'] ) && $_GET['page'] === 'digital_challenge_plugins' ) : ?>
103 <span class="active"><?php esc_html_e( 'Plugin\'s Homepage', 'xml-feed-for-skroutz-for-woocommerce' ); ?></span>
104 <?php else : ?>
105 <a href="admin.php?page=digital_challenge_plugins"><?php esc_html_e( 'Plugin\'s Homepage', 'xml-feed-for-skroutz-for-woocommerce' ); ?></a>
106 <?php endif; ?>
107 </li>
108 <?php do_action( 'digital_challenge_plugin_settings_tabs' ); ?>
109 </ul>
110 </div>
111 <div class="clear"></div>
112 <div class="render-settings">
113 <?php do_action( 'digital_challenge_plugin_settings' ); ?>
114 </div>
115 <?php
116 }
117
118
119 /**
120 * Creates the tab menu item which contains the plugin's settings.
121 */
122 public function create_plugin_settings_tab(): void {
123 ?>
124 <li class="dc-plugin-tab">
125 <?php if ( isset( $_GET['page'] ) && $_GET['page'] === DICHA_SKROUTZ_FEED_SLUG ) : ?>
126 | <span class="active">Skroutz/BestPrice XML</span>
127 <?php else : ?>
128 | <a href="admin.php?page=<?php echo esc_attr( $this->plugin_name ); ?>">Skroutz/BestPrice XML</a>
129 <?php endif; ?>
130 </li>
131 <?php
132 }
133
134
135 /**
136 * Displays an external link to see all Digital Challenge plugins, if no plugin tab is selected.
137 */
138 function dc_render_settings_homepage(): void {
139 ?>
140 <a href="https://www.dicha.gr/plugins/" target="_blank" title="Digital Challenge Plugins"><?php esc_html_e( 'Δείτε όλα τα plugins της Digital Challenge', 'xml-feed-for-skroutz-for-woocommerce' ); ?></a>
141 <?php
142 }
143
144
145 /**
146 * Creates settings sections and fields.
147 * Registers settings.
148 */
149 function register_plugin_settings(): void {
150
151 add_settings_section(
152 'dicha_skroutz_feed_cron_section',
153 __( 'Feed generation schedule', 'xml-feed-for-skroutz-for-woocommerce' ),
154 [ $this, 'print_cron_settings_info' ],
155 'dicha_skroutz_feed_settings'
156 );
157
158 add_settings_section(
159 'dicha_skroutz_feed_settings_section',
160 __( 'Settings for Plugin Skroutz/Best Price XML', 'xml-feed-for-skroutz-for-woocommerce' ),
161 [ $this, 'print_skroutz_settings_info' ],
162 'dicha_skroutz_feed_settings'
163 );
164
165 add_settings_section(
166 'dicha_skroutz_feed_logs_section',
167 __( 'Log settings', 'xml-feed-for-skroutz-for-woocommerce' ),
168 [ $this, 'print_logs_settings_info' ],
169 'dicha_skroutz_feed_settings'
170 );
171
172 $settings = [
173 [
174 'dicha_skroutz_feed_cron' => [
175 __( 'WP Cron Schedule', 'xml-feed-for-skroutz-for-woocommerce' ),
176 'dicha_skroutz_feed_cron_section'
177 ]
178 ],
179 [
180 'dicha_skroutz_feed_manufacturer' => [
181 __( 'Manufacturer', 'xml-feed-for-skroutz-for-woocommerce' ),
182 'dicha_skroutz_feed_settings_section'
183 ]
184 ],
185 [
186 'dicha_skroutz_feed_color' => [
187 __( 'Color', 'xml-feed-for-skroutz-for-woocommerce' ),
188 'dicha_skroutz_feed_settings_section'
189 ]
190 ],
191 [
192 'dicha_skroutz_feed_size' => [
193 __( 'Size', 'xml-feed-for-skroutz-for-woocommerce' ),
194 'dicha_skroutz_feed_settings_section'
195 ]
196 ],
197 [
198 'dicha_skroutz_feed_availability' => [
199 __( 'Default Availability', 'xml-feed-for-skroutz-for-woocommerce' ),
200 'dicha_skroutz_feed_settings_section'
201 ]
202 ],
203 [
204 'dicha_skroutz_feed_include_backorders' => [
205 __( 'Include products on backorder', 'xml-feed-for-skroutz-for-woocommerce' ),
206 'dicha_skroutz_feed_settings_section'
207 ]
208 ],
209 [
210 'dicha_skroutz_feed_title_attributes' => [
211 __( 'Attributes in Product name', 'xml-feed-for-skroutz-for-woocommerce' ),
212 'dicha_skroutz_feed_settings_section'
213 ]
214 ],
215 [
216 'dicha_skroutz_feed_description' => [
217 __( 'Description to display', 'xml-feed-for-skroutz-for-woocommerce' ),
218 'dicha_skroutz_feed_settings_section'
219 ]
220 ],
221 [
222 'dicha_skroutz_feed_enable_ean_field' => [
223 __( 'EAN/Barcode field', 'xml-feed-for-skroutz-for-woocommerce' ),
224 'dicha_skroutz_feed_settings_section'
225 ]
226 ],
227 [
228 'dicha_skroutz_incl_excl_mode_categories' => [
229 '',
230 'dicha_skroutz_feed_settings_section'
231 ]
232 ],
233 [
234 'dicha_skroutz_incl_excl_mode_tags' => [
235 '',
236 'dicha_skroutz_feed_settings_section'
237 ]
238 ],
239 [
240 'dicha_skroutz_feed_filter_categories' => [
241 __( 'Product categories filter', 'xml-feed-for-skroutz-for-woocommerce' ),
242 'dicha_skroutz_feed_settings_section'
243 ]
244 ],
245 [
246 'dicha_skroutz_feed_filter_tags' => [
247 __( 'Product tags filter', 'xml-feed-for-skroutz-for-woocommerce' ),
248 'dicha_skroutz_feed_settings_section'
249 ]
250 ],
251 [
252 'dicha_skroutz_feed_shipping_cost' => [
253 __( 'Fixed Shipping Cost', 'xml-feed-for-skroutz-for-woocommerce' ),
254 'dicha_skroutz_feed_settings_section'
255 ]
256 ],
257 [
258 'dicha_skroutz_feed_free_shipping' => [
259 __( 'Free Shipping over', 'xml-feed-for-skroutz-for-woocommerce' ),
260 'dicha_skroutz_feed_settings_section'
261 ]
262 ],
263 [
264 'dicha_skroutz_feed_log_level' => [
265 __( 'Log level', 'xml-feed-for-skroutz-for-woocommerce' ),
266 'dicha_skroutz_feed_logs_section'
267 ]
268 ],
269 ];
270
271 // don't add labels for these, they will be added manually
272 $no_input_label_for_these = [
273 'dicha_skroutz_feed_cron',
274 'dicha_skroutz_feed_enable_ean_field',
275 'dicha_skroutz_feed_description'
276 ];
277
278 foreach ( $settings as $setting ) {
279
280 foreach ( $setting as $key => $item ) {
281
282 if ( ! empty( $item[0] ) ) {
283 add_settings_field(
284 $key,
285 $item[0],
286 [ $this, $key . '_callback' ],
287 'dicha_skroutz_feed_settings',
288 $item[1],
289 [
290 'class' => $key,
291 'label_for' => !in_array( $key, $no_input_label_for_these ) ? $key : ''
292 ]
293 );
294 }
295
296 register_setting(
297 'dicha_skroutz_feed_option_group',
298 $key,
299 [
300 'sanitize_callback' => [ $this, 'sanitize_own_settings' ]
301 ]
302 );
303 }
304 }
305 }
306
307
308 /**
309 * Sanitizes our own settings.
310 *
311 * @param mixed $value The sanitized option value.
312 */
313 function sanitize_own_settings( $value ) {
314
315 if ( is_array( $value ) ) {
316 $value = array_map( 'sanitize_text_field', $value );
317 }
318 else {
319 $value = sanitize_text_field( $value );
320 }
321
322 return $value;
323 }
324
325
326 /**
327 * Prints the Settings form and XML Feed Tools.
328 */
329 function render_plugin_settings(): void {
330
331 // todo maybe create an options migrator
332
333 $last_run = get_option( 'dicha_skroutz_feed_last_run' );
334 ?>
335 <div class="wrap <?php echo esc_attr( $this->plugin_name ); ?>-settings">
336 <form action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" method="post" class="dicha-skroutz-feed-tools-wrapper">
337 <h2><?php esc_html_e( 'XML Feed Tools', 'xml-feed-for-skroutz-for-woocommerce' ); ?></h2>
338 <p><?php esc_html_e( 'Last XML feed generated at:', 'xml-feed-for-skroutz-for-woocommerce' ); ?>
339 <strong><?php echo esc_html( $last_run ?: __( 'Never', 'xml-feed-for-skroutz-for-woocommerce' ) ); ?></strong>
340 </p>
341 <p><?php esc_html_e( 'Submit the following URL to Skroutz or BestPrice:', 'xml-feed-for-skroutz-for-woocommerce' ); ?>
342 <br>
343 <code><?php echo esc_url( $this->get_default_xml_file_url() ); ?></code>
344 </p>
345 <p class="submit">
346 <?php if ( $last_run ) : ?>
347 <a href="<?php echo esc_url( $this->get_default_xml_file_url() ); ?>" target="_blank"
348 class="button button-primary">
349 <?php esc_html_e( 'View XML feed', 'xml-feed-for-skroutz-for-woocommerce' ); ?>
350 </a>
351 <?php endif; ?>
352 <input type="submit" name="submit" id="submit" class="button button-primary"
353 value="<?php echo esc_html( $last_run ? __( 'Update XML feed', 'xml-feed-for-skroutz-for-woocommerce' ) : __( 'Create XML feed', 'xml-feed-for-skroutz-for-woocommerce' ) ); ?>">
354 </p>
355 <input type="hidden" name="action" value="dicha_skroutz_feed_create_feed">
356 </form>
357 <form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>">
358 <?php
359 // This prints out all hidden setting fields
360 settings_fields( 'dicha_skroutz_feed_option_group' );
361 do_settings_sections( 'dicha_skroutz_feed_settings' );
362 submit_button();
363 ?>
364 <input type="hidden" name="action" value="save_settings">
365 </form>
366 </div>
367 <?php
368 }
369
370
371 /**
372 * Saves the plugin's Settings.
373 */
374 function save_settings(): void {
375
376 if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ?? '' ) ), 'dicha_skroutz_feed_option_group-options' ) ) return;
377 if ( ! current_user_can( 'manage_options' ) ) return;
378
379 update_option( 'dicha_skroutz_feed_manufacturer', ! empty( $_POST['dicha_skroutz_feed_manufacturer'] ) ? wc_clean( wp_unslash( $_POST['dicha_skroutz_feed_manufacturer'] ) ) : [], false );
380 update_option( 'dicha_skroutz_feed_color', ! empty( $_POST['dicha_skroutz_feed_color'] ) ? wc_clean( wp_unslash( $_POST['dicha_skroutz_feed_color'] ) ) : [], false );
381 update_option( 'dicha_skroutz_feed_size', ! empty( $_POST['dicha_skroutz_feed_size'] ) ? wc_clean( wp_unslash( $_POST['dicha_skroutz_feed_size'] ) ) : [], false );
382 update_option( 'dicha_skroutz_feed_availability', wc_clean( wp_unslash( $_POST['dicha_skroutz_feed_availability'] ?? '' ) ), false );
383 update_option( 'dicha_skroutz_feed_include_backorders', wc_clean( wp_unslash( $_POST['dicha_skroutz_feed_include_backorders'] ?? '' ) ), false );
384 update_option( 'dicha_skroutz_feed_title_attributes', ! empty( $_POST['dicha_skroutz_feed_title_attributes'] ) ? wc_clean( wp_unslash( $_POST['dicha_skroutz_feed_title_attributes'] ) ) : [], false );
385 update_option( 'dicha_skroutz_feed_description', wc_clean( wp_unslash( $_POST['dicha_skroutz_feed_description'] ?? '' ) ), false );
386 update_option( 'dicha_skroutz_feed_enable_ean_field', wc_clean( wp_unslash( $_POST['dicha_skroutz_feed_enable_ean_field'] ?? '' ) ), false );
387 update_option( 'dicha_skroutz_feed_filter_categories', ! empty( $_POST['dicha_skroutz_feed_filter_categories'] ) ? wc_clean( wp_unslash( $_POST['dicha_skroutz_feed_filter_categories'] ) ) : [], false );
388 update_option( 'dicha_skroutz_feed_filter_tags', ! empty( $_POST['dicha_skroutz_feed_filter_tags'] ) ? wc_clean( wp_unslash( $_POST['dicha_skroutz_feed_filter_tags'] ) ) : [], false );
389 update_option( 'dicha_skroutz_incl_excl_mode_categories', wc_clean( wp_unslash( $_POST['dicha_skroutz_incl_excl_mode_categories'] ?? '' ) ), false );
390 update_option( 'dicha_skroutz_incl_excl_mode_tags', wc_clean( wp_unslash( $_POST['dicha_skroutz_incl_excl_mode_tags'] ?? '' ) ), false );
391 update_option( 'dicha_skroutz_feed_shipping_cost', wc_clean( wp_unslash( $_POST['dicha_skroutz_feed_shipping_cost'] ?? '' ) ), false );
392 update_option( 'dicha_skroutz_feed_free_shipping', wc_clean( wp_unslash( $_POST['dicha_skroutz_feed_free_shipping'] ?? '' ) ), false );
393 update_option( 'dicha_skroutz_feed_log_level', wc_clean( wp_unslash( $_POST['dicha_skroutz_feed_log_level'] ?? '' ) ), false );
394
395
396 // Cron options and handling
397 $cron_hour = wc_clean( wp_unslash( $_POST['dicha_skroutz_feed_cron_hour'] ?? '' ) );
398 $cron_hour = is_numeric( $cron_hour ) && $cron_hour > 0 && $cron_hour <= 24 ? (int) $cron_hour : '';
399
400 $cron_min = wc_clean( wp_unslash( $_POST['dicha_skroutz_feed_cron_minute'] ?? '' ) );
401 $cron_min = is_numeric( $cron_min ) && $cron_min >= 0 && $cron_min < 60 ? (int) $cron_min : 0;
402
403 // Maybe set cron and then update setting
404 $new_cron_options = [
405 'h' => $cron_hour,
406 'm' => $cron_min
407 ];
408
409 $this->maybe_set_cron( $new_cron_options );
410 update_option( 'dicha_skroutz_feed_cron', $new_cron_options, false );
411
412 // redirect with success update notice
413 wp_redirect( admin_url( 'admin.php?page=' . DICHA_SKROUTZ_FEED_SLUG . '&updated=1' ) );
414 exit;
415 }
416
417
418 /**
419 * Updates the scheduled cron actions for XML feed generation.
420 *
421 * @param array $new_cron_options
422 *
423 * @return void
424 */
425 function maybe_set_cron( array $new_cron_options ): void {
426
427 $hook = 'dicha_skroutz_feed_generation';
428 $args = [];
429 $group = 'dicha_feeds_generation';
430
431 as_unschedule_all_actions( $hook, $args, $group );
432
433 if ( $new_cron_options['h'] !== '' && $new_cron_options['m'] !== '' ) {
434
435 $cron_schedule = sprintf( '%1$d %2$s * * *', $new_cron_options['m'], $new_cron_options['h'] > 1 ? "*/{$new_cron_options['h']}" : "*" );
436
437 as_schedule_cron_action( time(), $cron_schedule, $hook, $args, $group, true, 9 );
438 }
439 }
440
441
442 /**
443 * Prints a notice in the settings page about the outcome of the manual XML generation process.
444 *
445 * @return void
446 */
447 function print_notices(): void {
448
449 if ( isset( $_GET['updated'] ) && '1' === $_GET['updated'] ) : ?>
450 <div class="updated">
451 <p><?php esc_html_e( 'Changes have been saved.', 'xml-feed-for-skroutz-for-woocommerce' ); ?></p>
452 </div>
453 <?php endif; ?>
454 <?php if ( isset( $_GET['feed_success'] ) ) : ?>
455 <?php if ( '1' === $_GET['feed_success'] ) : ?>
456 <div class="notice notice-success">
457 <p><?php esc_html_e( 'XML feed was generated successfully!', 'xml-feed-for-skroutz-for-woocommerce' ); ?>
458 <a href="<?php echo esc_url( $this->get_default_xml_file_url() ); ?>"
459 target="_blank"><?php esc_html_e( 'View XML', 'xml-feed-for-skroutz-for-woocommerce' ); ?></a>
460 </p>
461 </div>
462 <?php else: ?>
463 <div class="notice notice-error">
464 <p><?php esc_html_e( 'XML feed generation failed. Enable and then check plugin logs for more details.', 'xml-feed-for-skroutz-for-woocommerce' ); ?>
465 </p>
466 </div>
467 <?php endif; ?>
468 <?php endif;
469 }
470
471
472
473 /**
474 ***************************
475 ***** SETTINGS INPUTS *****
476 ***************************
477 */
478
479 /**
480 * Prints the Feed generation schedule section description.
481 */
482 function print_cron_settings_info(): void {
483 esc_html_e( 'Settings about the scheduling of Skroutz/BestPrice XML feed generation.', 'xml-feed-for-skroutz-for-woocommerce' );
484 }
485
486
487 /**
488 * Prints the XML Settings section description.
489 */
490 function print_skroutz_settings_info(): void {
491 esc_html_e( 'Settings to control the product data for the XML feed.', 'xml-feed-for-skroutz-for-woocommerce' );
492 echo '<br>';
493 esc_html_e( 'Do NOT use the same attribute in multiple fields, for example in both Color and Size.', 'xml-feed-for-skroutz-for-woocommerce' );
494 }
495
496
497 /**
498 * Prints the logs settings section description.
499 */
500 function print_logs_settings_info(): void {
501 esc_html_e( 'Settings about logging during the feed generation.', 'xml-feed-for-skroutz-for-woocommerce' );
502 }
503
504
505 /**
506 * Prints the HTML for the cron schedule field in the settings.
507 */
508 function dicha_skroutz_feed_cron_callback(): void {
509
510 $current_cron_options = get_option( 'dicha_skroutz_feed_cron', [ 'h' => '', 'm' => '50' ] );
511
512 // compatibility with old option
513 if ( is_string( $current_cron_options ) ) {
514
515 if ( 'hourly' === $current_cron_options ) {
516 $current_cron_options = [
517 'h' => 1,
518 'm' => 50
519 ];
520 }
521 elseif ( 'twicedaily' === $current_cron_options ) {
522 $current_cron_options = [
523 'h' => 12,
524 'm' => 50
525 ];
526 }
527 elseif ( 'daily' === $current_cron_options ) {
528 $current_cron_options = [
529 'h' => 24,
530 'm' => 50
531 ];
532 }
533 }
534
535 $allowed_html_for_inputs = $this->get_allowed_html_tags_for_inputs();
536
537 printf(
538 /* translators: 1: A select input for cron schedule. 2: the CSS class for schedule description. 3: CSS styles. 4: Number representing the minute */
539 wp_kses_post( __( '%1$s<span class="%2$s" style="%3$s">, starting at 00:XX, where XX is the %4$s minute.</span>', 'xml-feed-for-skroutz-for-woocommerce' ) ),
540 wp_kses( $this->get_html_for_cron_hour_field( $current_cron_options ), $allowed_html_for_inputs ),
541 'dicha-skroutz-cron-minute-input-wrapper',
542 empty( $current_cron_options['h'] ) ? 'display:none' : 'display:inline',
543 wp_kses( $this->get_html_for_cron_minute_field( $current_cron_options ), $allowed_html_for_inputs ),
544 );
545
546 ?>
547 <p class="desc">
548 <?php esc_html_e( 'Select how frequently the XML feed will be updated.', 'xml-feed-for-skroutz-for-woocommerce' ); ?>
549 </p>
550 <ol>
551 <li><?php echo wp_kses_post( __( 'Select the frequency of the XML feed generation, or disable automatic generation using WP Cron scheduling.', 'xml-feed-for-skroutz-for-woocommerce' ) ); ?></li>
552 <li><?php echo wp_kses_post( __( '<strong>Fill the "minute" field with a number between 0-59.</strong> If you insert the value "45", then the import will start running at 00:45 at night (UTC time), and then every X hours, depending on the "hour" field. Suggested values: 45-55 so that the feed is ready when Skroutz fetches your XML.', 'xml-feed-for-skroutz-for-woocommerce' ) ); ?></li>
553 <li><?php esc_html_e( 'If "No WP Cron" is selected, then the XML generation will not run automatically using WP Cron, so you need to setup server cron jobs manually. This option is best for large eshops that need frequent updates on specific time, and need more server resources.', 'xml-feed-for-skroutz-for-woocommerce' ); ?></li>
554 </ol>
555 <?php
556 }
557
558
559 /**
560 * Retrieves a list of allowed HTML tags and their permitted attributes for form inputs.
561 *
562 * @return array The allowed HTML tags and their attributes.
563 */
564 private function get_allowed_html_tags_for_inputs(): array {
565 return [
566 'select' => [
567 'id' => [],
568 'name' => [],
569 'value' => [],
570 'aria-label' => []
571 ],
572 'option' => [
573 'value' => [],
574 'selected' => []
575 ],
576 'input' => [
577 'id' => [],
578 'type' => [],
579 'min' => [],
580 'max' => [],
581 'step' => [],
582 'name' => [],
583 'value' => [],
584 'selected' => [],
585 'aria-label' => []
586 ],
587 ];
588 }
589
590
591 /**
592 * Prints the HTML for the cron schedule hour field in the settings.
593 *
594 * @param $current_cron_options array
595 *
596 * @return string
597 */
598 private function get_html_for_cron_hour_field( array $current_cron_options ): string {
599
600 $current_cron_hour = ! empty( $current_cron_options['h'] ) ? (int) $current_cron_options['h'] : '';
601 $cron_hour_options = [ 1, 2, 3, 4, 6, 8, 12, 24 ];
602
603 ob_start();
604 ?>
605 <select id="dicha_skroutz_feed_cron_hour" name="dicha_skroutz_feed_cron_hour" aria-label="<?php esc_html_e( 'Frequency of feed generation in hours.', 'xml-feed-for-skroutz-for-woocommerce' ); ?>">
606 <option value=""><?php esc_html_e( 'No WP Cron', 'xml-feed-for-skroutz-for-woocommerce' ); ?></option>
607 <?php foreach ( $cron_hour_options as $cron_hour_option ) : ?>
608 <option value="<?php echo esc_attr( $cron_hour_option ); ?>"<?php selected( $current_cron_hour === $cron_hour_option ); ?>>
609 <?php
610 /* translators: %d: A number representing the hour interval. */
611 printf( esc_html( _n( 'Every %d hour', 'Every %d hours', $cron_hour_option , 'xml-feed-for-skroutz-for-woocommerce' ) ), esc_attr( $cron_hour_option ) );
612 ?>
613 </option>
614 <?php endforeach; ?>
615 </select>
616 <?php
617
618 return ob_get_clean();
619 }
620
621
622 /**
623 * Prints the HTML for the cron schedule minute field in the settings.
624 *
625 * @param $current_cron_options array
626 *
627 * @return string
628 */
629 private function get_html_for_cron_minute_field( array $current_cron_options ): string {
630
631 $current_cron_minute = ! empty( $current_cron_options['m'] ) ? (int) $current_cron_options['m'] : 0;
632
633 ob_start();
634 ?>
635 <input id="dicha_skroutz_feed_cron_minute" name="dicha_skroutz_feed_cron_minute" type="number"
636 min="0" max="59" step="1" value="<?php echo esc_attr( $current_cron_minute ); ?>"
637 aria-label="<?php esc_html_e( 'Exact minute (0-59) of the hour to start the feed generation.', 'xml-feed-for-skroutz-for-woocommerce' ); ?>" />
638 <?php
639
640 return ob_get_clean();
641 }
642
643
644 /**
645 * Prints the HTML for the manufacturer field in the settings.
646 */
647 function dicha_skroutz_feed_manufacturer_callback(): void {
648
649 $selected_values = get_option( 'dicha_skroutz_feed_manufacturer', [] );
650 $options = $this->prepare_attributes_list();
651 $custom_brand_options = [];
652
653 if ( ! empty( $options['custom_taxonomies'] ) ) {
654 if ( isset( $options['custom_taxonomies']['product_brand'] ) ) {
655 $custom_brand_options['woo__product_brand'] = __( 'WooCommerce Brands', 'xml-feed-for-skroutz-for-woocommerce' );
656 }
657 // maybe add support for other brands plugins here...
658 }
659
660 ?>
661 <!--suppress HtmlFormInputWithoutLabel -->
662 <select id="dicha_skroutz_feed_manufacturer" name="dicha_skroutz_feed_manufacturer[]" class="select-woo-input" multiple="multiple">
663 <optgroup label="<?php esc_html_e( 'Available product attributes:', 'xml-feed-for-skroutz-for-woocommerce' ); ?>">
664 <?php foreach ( $options['attribute_taxonomies'] as $attr_slug => $attr_name ) : ?>
665 <option value="<?php echo esc_attr( $attr_slug ); ?>"<?php selected( in_array( $attr_slug, $selected_values ) ); ?>>
666 <?php echo esc_html( $attr_name ); ?>
667 </option>
668 <?php endforeach; ?>
669 </optgroup>
670 <?php if ( ! empty( $custom_brand_options ) ) : ?>
671 <optgroup label="<?php esc_html_e( 'Other brand taxonomies:', 'xml-feed-for-skroutz-for-woocommerce' ); ?>">
672 <?php foreach ( $custom_brand_options as $tax_slug => $tax_name ) : ?>
673 <option value="<?php echo esc_attr( $tax_slug ); ?>"<?php selected( in_array( $tax_slug, $selected_values ) ); ?>>
674 <?php echo esc_html( $tax_name ); ?>
675 </option>
676 <?php endforeach; ?>
677 </optgroup>
678 <?php endif; ?>
679 </select>
680 <?php
681 }
682
683
684 /**
685 * Prints the HTML for the color field in the settings.
686 */
687 function dicha_skroutz_feed_color_callback(): void {
688
689 $options = $this->prepare_attributes_list();
690 $selected_values = get_option( 'dicha_skroutz_feed_color', [] );
691 ?>
692 <!--suppress HtmlFormInputWithoutLabel -->
693 <select id="dicha_skroutz_feed_color" name="dicha_skroutz_feed_color[]" class="select-woo-input" multiple="multiple">
694 <optgroup label="<?php esc_html_e( 'Available product attributes:', 'xml-feed-for-skroutz-for-woocommerce' ); ?>">
695 <?php foreach ( $options['attribute_taxonomies'] as $attr_slug => $attr_name ) : ?>
696 <option value="<?php echo esc_attr( $attr_slug ); ?>"<?php selected( in_array( $attr_slug, $selected_values ) ); ?>>
697 <?php echo esc_html( $attr_name ); ?>
698 </option>
699 <?php endforeach; ?>
700 </optgroup>
701 </select>
702 <?php
703 }
704
705
706 /**
707 * Prints the HTML for the size field in the settings.
708 */
709 function dicha_skroutz_feed_size_callback(): void {
710
711 $options = $this->prepare_attributes_list();
712 $selected_values = get_option( 'dicha_skroutz_feed_size', [] );
713 ?>
714 <!--suppress HtmlFormInputWithoutLabel -->
715 <select id="dicha_skroutz_feed_size" name="dicha_skroutz_feed_size[]" class="select-woo-input" multiple="multiple">
716 <optgroup label="<?php esc_html_e( 'Available product attributes:', 'xml-feed-for-skroutz-for-woocommerce' ); ?>">
717 <?php foreach ( $options['attribute_taxonomies'] as $attr_slug => $attr_name ) : ?>
718 <option value="<?php echo esc_attr( $attr_slug ); ?>"<?php selected( in_array( $attr_slug, $selected_values ) ); ?>>
719 <?php echo esc_html( $attr_name ); ?>
720 </option>
721 <?php endforeach; ?>
722 </optgroup>
723 </select>
724 <?php
725 }
726
727
728 /**
729 * Prints the HTML for the availability field in the settings.
730 */
731 function dicha_skroutz_feed_availability_callback(): void {
732
733 $selected_availability = get_option( 'dicha_skroutz_feed_availability' );
734 $skroutz_availabilities = self::skroutz_get_availability_options( false, true );
735 ?>
736 <!--suppress HtmlFormInputWithoutLabel -->
737 <select id="dicha_skroutz_feed_availability" name="dicha_skroutz_feed_availability">
738 <?php foreach ( $skroutz_availabilities as $key => $availability_label ) : ?>
739 <option value="<?php echo esc_attr( $key ); ?>"<?php selected( $selected_availability, $key ); ?>>
740 <?php echo esc_html( $availability_label ); ?>
741 </option>
742 <?php endforeach; ?>
743 </select>
744 <p class="desc">
745 <?php echo wp_kses_post( __( 'If you are not sure what to choose, consult <a href="https://developer.skroutz.gr/el/feedspec/#availability" target="_blank">Skroutz instructions</a>.', 'xml-feed-for-skroutz-for-woocommerce' ) ); ?>
746 </p>
747 <?php
748 }
749
750
751 /**
752 * Prints the HTML for the backorders inclusion field in the settings.
753 */
754 function dicha_skroutz_feed_include_backorders_callback(): void {
755
756 $dicha_skroutz_feed_include_backorders = get_option( 'dicha_skroutz_feed_include_backorders', 'no' );
757 ?>
758 <label for="dicha_skroutz_feed_include_backorders">
759 <input type="checkbox" id="dicha_skroutz_feed_include_backorders" name="dicha_skroutz_feed_include_backorders" value="yes"<?php checked( 'yes', $dicha_skroutz_feed_include_backorders ); ?>>
760 <?php esc_html_e( 'Include products on backorder in XML', 'xml-feed-for-skroutz-for-woocommerce' ); ?>
761 </label>
762 <?php
763 }
764
765
766 /**
767 * Prints the HTML for the attributes in product name field in the settings.
768 */
769 function dicha_skroutz_feed_title_attributes_callback(): void {
770
771 $selected_values = get_option( 'dicha_skroutz_feed_title_attributes', [] );
772 $options = $this->prepare_attributes_list();
773 $custom_taxonomy_options = [];
774
775 if ( ! empty( $options['custom_taxonomies'] ) ) {
776 if ( isset( $options['custom_taxonomies']['product_brand'] ) ) {
777 $custom_taxonomy_options['woo__product_brand'] = __( 'WooCommerce Brands', 'xml-feed-for-skroutz-for-woocommerce' );
778 }
779 // maybe add support for other custom taxonomies here...
780 }
781
782 ?>
783 <!--suppress HtmlFormInputWithoutLabel -->
784 <select id="dicha_skroutz_feed_title_attributes" name="dicha_skroutz_feed_title_attributes[]"
785 class="select-woo-input" multiple="multiple">
786 <optgroup label="<?php esc_html_e( 'Available product attributes:', 'xml-feed-for-skroutz-for-woocommerce' ); ?>">
787 <?php foreach ( $options['attribute_taxonomies'] as $attr_slug => $attr_name ) : ?>
788 <option
789 value="<?php echo esc_attr( $attr_slug ); ?>"<?php selected( in_array( $attr_slug, $selected_values ) ); ?>>
790 <?php echo esc_html( $attr_name ); ?>
791 </option>
792 <?php endforeach; ?>
793 </optgroup>
794 <?php if ( ! empty( $custom_taxonomy_options ) ) : ?>
795 <optgroup label="<?php esc_html_e( 'Other taxonomies:', 'xml-feed-for-skroutz-for-woocommerce' ); ?>">
796 <?php foreach ( $custom_taxonomy_options as $tax_slug => $tax_name ) : ?>
797 <option value="<?php echo esc_attr( $tax_slug ); ?>"<?php selected( in_array( $tax_slug, $selected_values ) ); ?>>
798 <?php echo esc_html( $tax_name ); ?>
799 </option>
800 <?php endforeach; ?>
801 </optgroup>
802 <?php endif; ?>
803 </select>
804 <p class="desc">
805 <?php echo wp_kses_post( __( 'These attributes will be added to XML product name (if not included already).', 'xml-feed-for-skroutz-for-woocommerce' ) ); ?>
806 </p>
807 <?php
808 }
809
810
811 /**
812 * Prints the HTML for the description field in the settings.
813 */
814 function dicha_skroutz_feed_description_callback(): void {
815
816 $dicha_skroutz_feed_description = get_option( 'dicha_skroutz_feed_description', 'short' );
817 ?>
818 <input type="radio" name="dicha_skroutz_feed_description"
819 id="dicha_skroutz_feed_description_short"
820 value="short"<?php checked( $dicha_skroutz_feed_description, 'short' ); ?>>
821 <label for="dicha_skroutz_feed_description_short">
822 <?php esc_html_e( 'Short description', 'xml-feed-for-skroutz-for-woocommerce' ); ?>
823 </label>
824 <br>
825 <input type="radio" name="dicha_skroutz_feed_description" id="dicha_skroutz_feed_description_long"
826 value="long"<?php checked( $dicha_skroutz_feed_description, 'long' ); ?>>
827 <label for="dicha_skroutz_feed_description_long">
828 <?php esc_html_e( 'Description', 'xml-feed-for-skroutz-for-woocommerce' ); ?>
829 </label>
830 <?php
831 }
832
833
834 /**
835 * Prints the HTML for the ean field in the settings.
836 */
837 function dicha_skroutz_feed_enable_ean_field_callback(): void {
838
839 $default_ean_enabled = version_compare( $this->woo_version, '9.2', '>=' ) ? 'no' : 'yes';
840 $dicha_skroutz_feed_enable_ean_field = get_option( 'dicha_skroutz_feed_enable_ean_field', $default_ean_enabled );
841 ?>
842 <label for="dicha_skroutz_feed_enable_ean_field">
843 <input type="checkbox" id="dicha_skroutz_feed_enable_ean_field" name="dicha_skroutz_feed_enable_ean_field" value="yes"<?php checked( 'yes', $dicha_skroutz_feed_enable_ean_field ); ?>>
844 <?php esc_html_e( 'Add new field for inserting the EAN/Barcode info. The field will appear under WooCommerce SKU field.', 'xml-feed-for-skroutz-for-woocommerce' ); ?>
845 <?php if ( ! wc_string_to_bool( $dicha_skroutz_feed_enable_ean_field ) && version_compare( $this->woo_version, '9.2', '>=' ) ) : ?>
846 <br><?php esc_html_e( 'We suggest keeping this unchecked. Use the new native WooCommerce field called "GTIN, UPC, EAN, or ISBN" which is located under the "SKU" field.', 'xml-feed-for-skroutz-for-woocommerce' ); ?>
847 <?php endif; ?>
848 </label>
849 <?php
850 }
851
852
853 /**
854 * Prints the HTML for the categories filter field in the settings.
855 */
856 function dicha_skroutz_feed_filter_categories_callback(): void {
857
858 $terms = $this->get_taxonomy_list_tree( 'product_cat' );
859 $include_exclude_mode = get_option( 'dicha_skroutz_incl_excl_mode_categories' );
860 $selected_terms = get_option( 'dicha_skroutz_feed_filter_categories', [] );
861 $selected_terms = is_array( $selected_terms ) ? $selected_terms : [];
862
863 ?>
864 <select name="dicha_skroutz_incl_excl_mode_categories" style="vertical-align:top;"
865 aria-label="<?php esc_html_e( 'Include/Exclude mode', 'xml-feed-for-skroutz-for-woocommerce' ); ?>">
866 <option value="0"<?php selected( $include_exclude_mode, '0' ); ?>>
867 <?php esc_html_e( 'Exclude', 'xml-feed-for-skroutz-for-woocommerce' ); ?>
868 </option>
869 <option value="1"<?php selected( $include_exclude_mode, '1' ); ?>>
870 <?php esc_html_e( 'Include', 'xml-feed-for-skroutz-for-woocommerce' ); ?>
871 </option>
872 </select>
873 <!--suppress HtmlFormInputWithoutLabel -->
874 <select id="dicha_skroutz_feed_filter_categories"
875 name="dicha_skroutz_feed_filter_categories[]" class="select-woo-input" multiple="multiple">
876 <?php foreach ( $terms as $term_id => $term_name ) : ?>
877 <option value="<?php echo (int) $term_id; ?>"<?php selected( in_array( $term_id, $selected_terms ) ); ?>>
878 <?php echo esc_html( $term_name ); ?>
879 </option>
880 <?php endforeach; ?>
881 </select>
882 <?php
883 }
884
885
886 /**
887 * Prints the HTML for the tags filter field in the settings.
888 */
889 function dicha_skroutz_feed_filter_tags_callback(): void {
890
891 $terms = $this->get_taxonomy_list_tree( 'product_tag' );
892 $include_exclude_mode = get_option( 'dicha_skroutz_incl_excl_mode_tags' );
893 $selected_terms = get_option( 'dicha_skroutz_feed_filter_tags', [] );
894 $selected_terms = is_array( $selected_terms ) ? $selected_terms : [];
895
896 ?>
897 <select name="dicha_skroutz_incl_excl_mode_tags" style="vertical-align:top;"
898 aria-label="<?php esc_html_e( 'Include/Exclude mode', 'xml-feed-for-skroutz-for-woocommerce' ); ?>">
899 <option value="0"<?php selected( $include_exclude_mode, '0' ); ?>>
900 <?php esc_html_e( 'Exclude', 'xml-feed-for-skroutz-for-woocommerce' ); ?>
901 </option>
902 <option value="1"<?php selected( $include_exclude_mode, '1' ); ?>>
903 <?php esc_html_e( 'Include', 'xml-feed-for-skroutz-for-woocommerce' ); ?>
904 </option>
905 </select>
906 <!--suppress HtmlFormInputWithoutLabel -->
907 <select id="dicha_skroutz_feed_filter_tags"
908 name="dicha_skroutz_feed_filter_tags[]" class="select-woo-input" multiple="multiple">
909 <?php foreach ( $terms as $term_id => $term_name ) : ?>
910 <option value="<?php echo (int) $term_id; ?>"<?php selected( in_array( $term_id, $selected_terms ) ); ?>>
911 <?php echo esc_html( $term_name ); ?>
912 </option>
913 <?php endforeach; ?>
914 </select>
915 <?php
916 }
917
918
919 /**
920 * Prints the HTML for the shipping cost field in the settings.
921 */
922 function dicha_skroutz_feed_shipping_cost_callback(): void {
923 printf(
924 '<input type="text" id="dicha_skroutz_feed_shipping_cost" name="dicha_skroutz_feed_shipping_cost" value="%s" />',
925 esc_attr( get_option( 'dicha_skroutz_feed_shipping_cost' ) )
926 );
927 }
928
929
930 /**
931 * Prints the HTML for the free shipping field in the settings.
932 */
933 function dicha_skroutz_feed_free_shipping_callback(): void {
934 printf(
935 '<input type="text" id="dicha_skroutz_feed_free_shipping" name="dicha_skroutz_feed_free_shipping" value="%s" />',
936 esc_attr( get_option( 'dicha_skroutz_feed_free_shipping' ) )
937 );
938 }
939
940
941 /**
942 * Prints the HTML for the logs level field in the settings.
943 *
944 * @noinspection HtmlUnknownTarget
945 */
946 function dicha_skroutz_feed_log_level_callback(): void {
947
948 $current_val = get_option( 'dicha_skroutz_feed_log_level', 'minimal' );
949 $options = [
950 'disabled' => __( 'No logging', 'xml-feed-for-skroutz-for-woocommerce' ),
951 'minimal' => __( 'Basic logging', 'xml-feed-for-skroutz-for-woocommerce' ),
952 'full' => __( 'Full logging', 'xml-feed-for-skroutz-for-woocommerce' ),
953 ];
954
955 ?>
956 <!--suppress HtmlFormInputWithoutLabel -->
957 <select id="dicha_skroutz_feed_log_level" name="dicha_skroutz_feed_log_level">
958 <?php foreach ( $options as $key => $option ) : ?>
959 <option value="<?php echo esc_attr( $key ); ?>"<?php selected( $current_val === $key ); ?>>
960 <?php echo esc_html( $option ); ?>
961 </option>
962 <?php endforeach; ?>
963 </select>
964 <p class="desc">
965 <?php /* translators: %s: Link to WooCommerce Logs page */ ?>
966 <?php echo wp_kses_post( sprintf( __( 'You can find the logs in the <a href="%s" target="_blank">WooCommerce Logs</a> page.', 'xml-feed-for-skroutz-for-woocommerce' ), admin_url( 'admin.php?page=wc-status&tab=logs' ) ) ); ?>
967 <br>
968 <?php esc_html_e( 'Basic logging only shows info about feed generation.', 'xml-feed-for-skroutz-for-woocommerce' ); ?>
969 <br>
970 <?php esc_html_e( 'Full logging also shows problematic products and the reasons for skipping them.', 'xml-feed-for-skroutz-for-woocommerce' ); ?>
971 </p>
972 <?php
973 }
974
975
976
977 /**
978 *************************************
979 ***** SETTINGS HELPER FUNCTIONS *****
980 *************************************
981 */
982
983 /**
984 * Prepare attribute slug/labels for display in settings inputs.
985 *
986 * @return array
987 */
988 function prepare_attributes_list(): array {
989
990 if ( ! empty( $this->attributes_list ) ) return $this->attributes_list;
991
992 $all_product_taxonomies = wp_list_pluck( get_object_taxonomies( 'product', 'objects' ), 'label', 'name' );
993 $attribute_taxonomies = wp_list_pluck( wc_get_attribute_taxonomies(), 'attribute_label', 'attribute_name' );
994 $woo_native_taxonomies = [
995 'product_type',
996 'product_visibility',
997 'product_cat',
998 'product_tag',
999 'product_shipping_class'
1000 ];
1001
1002 $attribute_taxonomies_prefixed = array_map( function( $v ) { return 'pa_' . $v; }, array_keys( $attribute_taxonomies ) );
1003 $custom_taxonomies = array_filter( $all_product_taxonomies, function( $tax_slug ) use ( $attribute_taxonomies_prefixed, $woo_native_taxonomies ) {
1004 return ! in_array( $tax_slug, array_merge( $attribute_taxonomies_prefixed, $woo_native_taxonomies ) );
1005 }, ARRAY_FILTER_USE_KEY );
1006
1007 $this->attributes_list = [
1008 'attribute_taxonomies' => $attribute_taxonomies,
1009 'custom_taxonomies' => $custom_taxonomies
1010 ];
1011
1012 return $this->attributes_list;
1013 }
1014
1015
1016 /**
1017 * Returns an hierarchical list of the selected taxonomy.
1018 *
1019 * @param string $taxonomy The taxonomy slug.
1020 *
1021 * @return array
1022 */
1023 function get_taxonomy_list_tree( string $taxonomy ): array {
1024
1025 $taxonomy_terms_list = [];
1026
1027 $parent_terms = get_terms( [
1028 'taxonomy' => $taxonomy,
1029 'parent' => 0,
1030 'hide_empty' => false,
1031 'orderby' => 'name',
1032 ] );
1033
1034 $this->build_taxonomy_tree( $taxonomy_terms_list, $parent_terms, $taxonomy );
1035
1036 return $taxonomy_terms_list;
1037 }
1038
1039
1040 /**
1041 * Adds recursively taxonomy terms to the hierarchical list.
1042 *
1043 * @param array $taxonomy_terms_list
1044 * @param array|WP_Error $parent_terms
1045 * @param string $taxonomy
1046 * @param int $depth
1047 * @param string $separator
1048 */
1049 function build_taxonomy_tree( array &$taxonomy_terms_list, $parent_terms, string $taxonomy, int $depth = 0, string $separator = '' ): void {
1050
1051 if ( ! empty( $parent_terms ) && is_array( $parent_terms ) ) {
1052
1053 foreach ( $parent_terms as $term ) {
1054
1055 $term_id = $term->term_id;
1056 $term_name = str_repeat( $separator, $depth ) . $term->name;
1057
1058 $taxonomy_terms_list[ $term_id ] = $term_name;
1059
1060 $child_terms = get_terms( [
1061 'taxonomy' => $taxonomy,
1062 'parent' => $term_id,
1063 'hide_empty' => false,
1064 'orderby' => 'name',
1065 ] );
1066
1067 if ( ! empty( $child_terms ) && is_array( $child_terms ) ) {
1068 $this->build_taxonomy_tree( $taxonomy_terms_list, $child_terms, $taxonomy, $depth + 1, $separator );
1069 }
1070 }
1071 }
1072 }
1073
1074
1075 /**
1076 * Returns an array with the availability options.
1077 *
1078 * @param $include_default bool If a default option is included in the beggining of the returned array.
1079 * @param $for_admin bool If true, a localized version of the options is returned for display inside admin UI, depending on admin lanuguage.
1080 * If false, greek strings will be returned, ready for display in the XML.
1081 *
1082 * @return array
1083 */
1084 public static function skroutz_get_availability_options( bool $include_default = false, bool $for_admin = false ): array {
1085
1086 /*
1087 * Do NOT ever change keys for backward compatibility reasons.
1088 * Change only display labels if you need to (because Skroutz changed its XML requirements).
1089 * Texts for admin interface are translatable, BUT texts for XML are NOT. XML texts are always in greek, just like Skroutz requires.
1090 */
1091 $options = [
1092 '1' => $for_admin ? __( 'Available', 'xml-feed-for-skroutz-for-woocommerce' ) : 'Άμεσα διαθέσιμο',
1093 '2' => $for_admin ? __( 'Available from 1 to 3 days', 'xml-feed-for-skroutz-for-woocommerce' ) : 'Διαθέσιμο από 1 έως 3 ημέρες',
1094 '3' => $for_admin ? __( 'Available from 4 to 10 days', 'xml-feed-for-skroutz-for-woocommerce' ) : 'Διαθέσιμο από 4 έως 10 ημέρες',
1095 '4' => $for_admin ? __( 'Available up to 30 days', 'xml-feed-for-skroutz-for-woocommerce' ) : 'Διαθέσιμο από 10 έως 30 ημέρες',
1096 '5' => $for_admin ? __( 'Hide from XML', 'xml-feed-for-skroutz-for-woocommerce' ) : 'Απόκρ�
1097 ψη από το XML'
1098 ];
1099
1100 if ( $include_default ) {
1101 $default_option = [ '' => __( 'Default availability', 'xml-feed-for-skroutz-for-woocommerce' ) ];
1102 $options = $default_option + $options;
1103 }
1104
1105 return $options;
1106 }
1107
1108
1109 /**
1110 * Get the default name for the feed upload folder, optionally customized by a filter.
1111 *
1112 * @return string The default folder name with any leading or trailing slashes removed.
1113 */
1114 public static function get_default_feed_upload_folder_name(): string {
1115
1116 $default_folder = 'dc-export-feeds';
1117
1118 // remove slashes from start or end, if added by mistake
1119 return trim( trim( apply_filters( 'dicha_skroutz_feed_upload_folder', $default_folder ) ), '/\\' );
1120 }
1121
1122
1123 /**
1124 * Generates and returns the filename for a feed, optionally customized by a filter.
1125 *
1126 * @param string $feed_type The type of feed, default is 'skroutz'.
1127 *
1128 * @return string The final feed filename without the .xml extension.
1129 */
1130 public static function get_feed_filename( string $feed_type = 'skroutz' ): string {
1131
1132 $filename_final = trim( apply_filters( 'dicha_skroutz_feed_custom_xml_filename', $feed_type ) );
1133
1134 // remove .xml extension, if added by mistake
1135 return preg_replace( '/\.xml$/i', '', $filename_final );
1136 }
1137
1138
1139 /**
1140 * Get the default file path for the feed.
1141 *
1142 * @return string The full path to the default feed directory.
1143 */
1144 public static function get_default_feed_filepath(): string {
1145
1146 $uploads_path = wp_upload_dir()['basedir'];
1147 $feed_folder = self::get_default_feed_upload_folder_name();
1148
1149 return trailingslashit( $uploads_path . '/' . $feed_folder );
1150 }
1151
1152
1153 /**
1154 * Returns the default XML feed URL.
1155 * This is used only in the manual XML update via the XML Feed Tools section.
1156 *
1157 * @return string
1158 */
1159 private function get_default_xml_file_url(): string {
1160
1161 $uploads_baseurl = wp_upload_dir()['baseurl'];
1162 $feed_folder = self::get_default_feed_upload_folder_name();
1163 $feed_filename = self::get_feed_filename();
1164
1165 return $uploads_baseurl . '/' . $feed_folder . '/' . $feed_filename . '.xml';
1166 }
1167
1168
1169
1170 /**
1171 ****************************
1172 ***** PRODUCT DATA TAB *****
1173 ****************************
1174 */
1175
1176 /**
1177 * Add a new product tab for Export Feeds settings.
1178 *
1179 * @param array $product_data_tabs
1180 *
1181 * @return array
1182 */
1183 public function register_new_exports_tab( array $product_data_tabs ): array {
1184
1185 $product_data_tabs['dicha_export_feeds_settings'] = [
1186 'label' => __( 'Export Feeds', 'xml-feed-for-skroutz-for-woocommerce' ),
1187 'target' => 'dicha_export_feeds_settings_product_data',
1188 'class' => [ 'hide_if_grouped', 'hide_if_external' ], // maybe add 'hide_if_virtual'
1189 'priority' => 75, // after advanced tab (70)
1190 ];
1191
1192 return $product_data_tabs;
1193 }
1194
1195
1196 /**
1197 * Create Export Feeds settings tab content.
1198 */
1199 public function print_exports_tab_content(): void {
1200 global $post;
1201 ?>
1202 <div id='dicha_export_feeds_settings_product_data' class='panel woocommerce_options_panel'>
1203 <div class='options_group'>
1204 <?php
1205
1206 woocommerce_wp_select( [
1207 'id' => 'dicha_skroutz_feed_custom_availability',
1208 'label' => __( 'Skroutz/BestPrice Availability', 'xml-feed-for-skroutz-for-woocommerce' ),
1209 'class' => 'form-row-full',
1210 'desc_tip' => true,
1211 'description' => __( 'The availability to show in XML feed for Skroutz/BestPrice. If you select the "Default availability" option, the default availability from the plugin\'s settings will be used.', 'xml-feed-for-skroutz-for-woocommerce' ),
1212 'options' => self::skroutz_get_availability_options( true, true ),
1213 'value' => get_post_meta( $post->ID, 'dicha_skroutz_feed_custom_availability', true ),
1214 ] );
1215
1216 do_action( 'dicha_export_feeds_settings_tab_fields_inside' );
1217
1218 wp_nonce_field( 'dicha_skroutz_save_product_fields', 'dicha_skroutz_save_product_fields_nonce' );
1219 ?>
1220 </div>
1221 <?php do_action( 'dicha_export_feeds_settings_tab_fields_after' ); ?>
1222 </div>
1223 <?php
1224 }
1225
1226
1227 /**
1228 * Add a new custom field for EAN/Barcode under SKU in Inventory tab.
1229 * Adds EAN field only if enabled from global settings.
1230 *
1231 */
1232 function add_ean_field_under_sku(): void {
1233
1234 $default_ean_enabled = version_compare( $this->woo_version, '9.2', '>=' ) ? 'no' : 'yes';
1235 $dicha_skroutz_feed_enable_ean_field = get_option( 'dicha_skroutz_feed_enable_ean_field', $default_ean_enabled );
1236
1237 if ( ! wc_string_to_bool( $dicha_skroutz_feed_enable_ean_field ) ) return;
1238
1239 woocommerce_wp_text_input( [
1240 'id' => 'dicha_skroutz_feed_ean_barcode',
1241 'class' => 'form-row-full',
1242 'label' => __( 'EAN/Barcode', 'xml-feed-for-skroutz-for-woocommerce' ),
1243 'value' => get_post_meta( get_the_ID(), 'dicha_skroutz_feed_ean_barcode', true ),
1244 'desc_tip' => true,
1245 'description' => __( 'The product\'s official EAN code or Barcode. A unique EAN/Barcode is allocated to each separate retail product.', 'xml-feed-for-skroutz-for-woocommerce' )
1246 ] );
1247 }
1248
1249
1250 /**
1251 * Save product custom fields
1252 *
1253 * @param int $post_id WP post id.
1254 */
1255 function save_product_custom_fields( $post_id ): void {
1256
1257 if ( empty( $_POST['dicha_skroutz_save_product_fields_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['dicha_skroutz_save_product_fields_nonce'] ) ), 'dicha_skroutz_save_product_fields' ) ) {
1258 return;
1259 }
1260
1261 // Save EAN field only if enabled from global settings
1262 $default_ean_enabled = version_compare( $this->woo_version, '9.2', '>=' ) ? 'no' : 'yes';
1263 $dicha_skroutz_feed_enable_ean_field = get_option( 'dicha_skroutz_feed_enable_ean_field', $default_ean_enabled );
1264
1265 if ( wc_string_to_bool( $dicha_skroutz_feed_enable_ean_field ) ) {
1266
1267 $dicha_skroutz_feed_ean_barcode = sanitize_text_field( wp_unslash( $_POST['dicha_skroutz_feed_ean_barcode'] ?? '' ) );
1268
1269 if ( ! empty( $dicha_skroutz_feed_ean_barcode ) ) {
1270 update_post_meta( $post_id, 'dicha_skroutz_feed_ean_barcode', wc_clean( $dicha_skroutz_feed_ean_barcode ) );
1271 }
1272 else {
1273 delete_post_meta( $post_id, 'dicha_skroutz_feed_ean_barcode' );
1274 }
1275 }
1276
1277 $dicha_skroutz_feed_custom_availability = sanitize_text_field( wp_unslash( $_POST['dicha_skroutz_feed_custom_availability'] ?? '' ) );
1278
1279 if ( ! empty( $dicha_skroutz_feed_custom_availability ) ) {
1280 update_post_meta( $post_id, 'dicha_skroutz_feed_custom_availability', wc_clean( $dicha_skroutz_feed_custom_availability ) );
1281 }
1282 else {
1283 delete_post_meta( $post_id, 'dicha_skroutz_feed_custom_availability' );
1284 }
1285 }
1286
1287
1288 /**
1289 * Setup custom fields in product variations
1290 *
1291 * @param int $loop Position in the loop.
1292 * @param array $variation_data Variation data.
1293 * @param WP_Post $variation Post data.
1294 */
1295 function print_variation_custom_fields( int $loop, array $variation_data, WP_Post $variation ): void {
1296
1297 $default_ean_enabled = version_compare( $this->woo_version, '9.2', '>=' ) ? 'no' : 'yes';
1298 $dicha_skroutz_feed_enable_ean_field = get_option( 'dicha_skroutz_feed_enable_ean_field', $default_ean_enabled );
1299
1300 if ( wc_string_to_bool( $dicha_skroutz_feed_enable_ean_field ) ) {
1301
1302 echo '<div class="form-row form-row-full">';
1303 woocommerce_wp_text_input( [
1304 'id' => "variable_dicha_skroutz_feed_ean_barcode_$loop",
1305 'name' => "variable_dicha_skroutz_feed_ean_barcode[$loop]",
1306 'label' => __( 'EAN/Barcode', 'xml-feed-for-skroutz-for-woocommerce' ),
1307 'desc_tip' => true,
1308 'value' => get_post_meta( $variation->ID, 'dicha_skroutz_feed_ean_barcode', true ),
1309 'description' => __( 'The variation\'s official EAN code or Barcode. A unique EAN/Barcode is allocated to each separate retail product.', 'xml-feed-for-skroutz-for-woocommerce' )
1310 ] );
1311 echo '</div>';
1312 }
1313
1314 echo '<div class="form-row form-row-full">';
1315 woocommerce_wp_select( [
1316 'id' => "variable_dicha_skroutz_feed_custom_availability_$loop",
1317 'name' => "variable_dicha_skroutz_feed_custom_availability[$loop]",
1318 'label' => __( 'Skroutz/BestPrice Availability', 'xml-feed-for-skroutz-for-woocommerce' ),
1319 'desc_tip' => true,
1320 'description' => __( 'The availability to show in XML feed for Skroutz/BestPrice. If you select the "Default availability" option, the default availability from the plugin\'s settings will be used.', 'xml-feed-for-skroutz-for-woocommerce' ),
1321 'options' => self::skroutz_get_availability_options( true, true ),
1322 'value' => get_post_meta( $variation->ID, 'dicha_skroutz_feed_custom_availability', true ),
1323 ] );
1324
1325 wp_nonce_field( 'dicha_skroutz_save_variation_fields', 'dicha_skroutz_save_variation_fields_nonce' );
1326
1327 echo '</div>';
1328 }
1329
1330
1331 /**
1332 * Save custom fields in variations.
1333 *
1334 * @param int $variation_id
1335 * @param int $i
1336 */
1337 function save_variation_custom_fields( int $variation_id, int $i ): void {
1338
1339 if ( empty( $_POST['dicha_skroutz_save_variation_fields_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['dicha_skroutz_save_variation_fields_nonce'] ) ), 'dicha_skroutz_save_variation_fields' ) ) {
1340 return;
1341 }
1342
1343 // Save EAN field only if enabled from global settings
1344 $default_ean_enabled = version_compare( $this->woo_version, '9.2', '>=' ) ? 'no' : 'yes';
1345 $dicha_skroutz_feed_enable_ean_field = get_option( 'dicha_skroutz_feed_enable_ean_field', $default_ean_enabled );
1346
1347 if ( wc_string_to_bool( $dicha_skroutz_feed_enable_ean_field ) ) {
1348
1349 $dicha_skroutz_feed_ean_barcode = sanitize_text_field( wp_unslash( $_POST['variable_dicha_skroutz_feed_ean_barcode'][ $i ] ?? '' ) );
1350
1351 if ( ! empty( $dicha_skroutz_feed_ean_barcode ) ) {
1352 update_post_meta( $variation_id, 'dicha_skroutz_feed_ean_barcode', $dicha_skroutz_feed_ean_barcode );
1353 }
1354 else {
1355 delete_post_meta( $variation_id, 'dicha_skroutz_feed_ean_barcode' );
1356 }
1357 }
1358
1359 $custom_availability = sanitize_text_field( wp_unslash( $_POST['variable_dicha_skroutz_feed_custom_availability'][ $i ] ?? '' ) );
1360
1361 if ( ! empty( $custom_availability ) ) {
1362 update_post_meta( $variation_id, 'dicha_skroutz_feed_custom_availability', $custom_availability );
1363 }
1364 else {
1365 delete_post_meta( $variation_id, 'dicha_skroutz_feed_custom_availability' );
1366 }
1367 }
1368
1369
1370
1371 /**
1372 *******************************
1373 ***** ADMIN PRODUCTS LIST *****
1374 *******************************
1375 */
1376
1377 /**
1378 * New custom column in admin products list for Skroutz Availability.
1379 *
1380 * @param string[] $columns An associative array of column headings.
1381 *
1382 * @return string[]
1383 */
1384 public function register_availability_column( array $columns ): array {
1385
1386 $columns['dicha_skroutz_feed_custom_availability'] = __( 'Skroutz availability', 'xml-feed-for-skroutz-for-woocommerce' );
1387
1388 return $columns;
1389 }
1390
1391
1392 /**
1393 * Fill Skroutz Availability column with content.
1394 *
1395 * @param string $column_name The name of the column to display.
1396 * @param int $post_id The current post ID.
1397 */
1398 public function fill_availability_column( string $column_name, int $post_id ): void {
1399
1400 if ( 'dicha_skroutz_feed_custom_availability' === $column_name ) {
1401
1402 $availability_value = get_post_meta( $post_id, 'dicha_skroutz_feed_custom_availability', true );
1403 $availability_options = self::skroutz_get_availability_options( true, true );
1404 $availability_text = $availability_options[ $availability_value ] ?? array_shift( $availability_options );
1405
1406 // echo display text
1407 echo esc_html( $availability_text );
1408
1409 // echo hidden value for getting quick edit
1410 echo '<span class="hidden">' . esc_html( $availability_value ) . '</span>';
1411 }
1412 }
1413
1414
1415 /**
1416 * Add a filter for Skroutz Availability in admin products list.
1417 *
1418 */
1419 public function print_custom_fields_filter_in_admin_list(): void {
1420 // phpcs:disable WordPress.Security.NonceVerification.Recommended
1421 // nonce verification is handled by WordPress in post filters, so it's not needed when using the `restrict_manage_posts` hook
1422 global $typenow;
1423
1424 // only add filter to products list
1425 if ( 'product' === $typenow ) {
1426
1427 $availability_options = self::skroutz_get_availability_options( false, true );
1428 ?>
1429 <select name="dicha_skroutz_availability" id="dropdown_dicha_skroutz_availability" aria-label="<?php esc_html_e( 'Skroutz availability filter', 'xml-feed-for-skroutz-for-woocommerce' ); ?>">
1430 <option value=""><?php esc_html_e( 'Filter by Skroutz Availability', 'xml-feed-for-skroutz-for-woocommerce' ); ?></option>
1431 <?php
1432 $current_v = isset( $_GET['dicha_skroutz_availability'] ) ? sanitize_text_field( wp_unslash( $_GET['dicha_skroutz_availability'] ) ) : '';
1433
1434 foreach ( $availability_options as $avail_key => $avail_label ) :
1435 printf(
1436 '<option value="%1$s" %2$s>%3$s</option>',
1437 esc_html( $avail_key ),
1438 selected( $avail_key, $current_v ),
1439 esc_html( $avail_label )
1440 );
1441 endforeach; ?>
1442 </select>
1443 <?php
1444 }
1445
1446 // phpcs:enable WordPress.Security.NonceVerification.Recommended
1447 }
1448
1449
1450 /**
1451 * Filter Query for Product List for Skroutz Availability.
1452 *
1453 * @param WP_Query $query The WP_Query instance (passed by reference).
1454 */
1455 public function filter_by_custom_fields_query_mod( WP_Query $query ): void {
1456 // phpcs:disable WordPress.Security.NonceVerification.Recommended
1457 // nonce verification is handled by WordPress in post filters, so it's not needed when using the `restrict_manage_posts` hook
1458 global $pagenow;
1459 global $typenow;
1460
1461 if ( 'product' === $typenow && is_admin() && 'edit.php' === $pagenow && isset( $_GET['dicha_skroutz_availability'] ) && $_GET['dicha_skroutz_availability'] != '' ) {
1462
1463 // keep existing meta queries
1464 $meta_query = (array) $query->get( 'meta_query' );
1465
1466 // add our meta query
1467 $meta_query[] = [
1468 'key' => 'dicha_skroutz_feed_custom_availability',
1469 'value' => sanitize_text_field( wp_unslash( $_GET['dicha_skroutz_availability'] ) ),
1470 ];
1471
1472 $query->set( 'meta_query', $meta_query );
1473 }
1474
1475 // phpcs:enable WordPress.Security.NonceVerification.Recommended
1476 }
1477
1478
1479 /**
1480 * Add skroutz availability select field to quick edit box, along with other WooCommerce fields.
1481 */
1482 function add_availability_field_to_quick_edit_box(): void {
1483
1484 $availability_options = self::skroutz_get_availability_options( true, true );
1485
1486 ?>
1487 <br class="clear">
1488 <label class="alignleft dicha-skroutz-availability-field">
1489 <span class="title"><?php esc_html_e( 'Skroutz availability', 'xml-feed-for-skroutz-for-woocommerce' ); ?></span>
1490 <span class="input-text-wrap">
1491 <select class="dicha-skroutz-availability" name="dicha_skroutz_feed_custom_availability">
1492 <?php foreach ( $availability_options as $avail_key => $avail_label ) :
1493 printf(
1494 '<option value="%1$s">%2$s</option>',
1495 esc_html( $avail_key ),
1496 esc_html( $avail_label )
1497 );
1498 endforeach; ?>
1499 </select>
1500 </span>
1501 </label>
1502 <?php
1503 }
1504
1505
1506 /**
1507 * Add skroutz availability select field to Bulk Edit box, along with other WooCommerce fields.
1508 */
1509 function add_availability_field_to_bulk_edit_box(): void {
1510
1511 $availability_options = self::skroutz_get_availability_options( true, true );
1512 ?>
1513 <label class="alignleft dicha-skroutz-availability-field">
1514 <span class="title"><?php esc_html_e( 'Skroutz availability', 'xml-feed-for-skroutz-for-woocommerce' ); ?></span>
1515 <span class="input-text-wrap">
1516 <select class="dicha-skroutz-availability" name="change_dicha_skroutz_feed_custom_availability">
1517 <option value=""><?php esc_html_e( '— No Change —', 'xml-feed-for-skroutz-for-woocommerce' ) ?></option>
1518 <?php foreach ( $availability_options as $avail_key => $avail_label ) :
1519 printf(
1520 '<option value="%1$s">%2$s</option>',
1521 esc_html( $avail_key ?: 'restore_default' ), // temp value for default option because empty value is taken already
1522 esc_html( $avail_label )
1523 );
1524 endforeach; ?>
1525 </select>
1526 </span>
1527 </label>
1528 <?php
1529 }
1530
1531
1532 /**
1533 * Save skroutz availability field for quick edit and bulk edit actions.
1534 *
1535 * @param int $post_id
1536 */
1537 function quick_and_bulk_edit_save_availability( int $post_id ): void {
1538
1539 // check user capabilities
1540 if ( ! current_user_can( 'manage_woocommerce', $post_id ) ) return;
1541
1542 // if quick edit save
1543 if ( isset( $_REQUEST['_inline_edit'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_REQUEST['_inline_edit'] ) ), 'inlineeditnonce' ) ) {
1544
1545 if ( isset( $_REQUEST['dicha_skroutz_feed_custom_availability'] ) ) {
1546 update_post_meta( $post_id, 'dicha_skroutz_feed_custom_availability', sanitize_text_field( wp_unslash( $_REQUEST['dicha_skroutz_feed_custom_availability'] ) ) );
1547 }
1548 }
1549 // if bulk edit save
1550 elseif ( isset( $_REQUEST['_wpnonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_REQUEST['_wpnonce'] ) ), 'bulk-posts' ) ) {
1551
1552 if ( isset( $_REQUEST['change_dicha_skroutz_feed_custom_availability'] ) ) {
1553
1554 if ( $_REQUEST['change_dicha_skroutz_feed_custom_availability'] === 'restore_default' ) {
1555 delete_post_meta( $post_id, 'dicha_skroutz_feed_custom_availability' );
1556 }
1557 elseif ( ! empty( $_REQUEST['change_dicha_skroutz_feed_custom_availability'] ) ) { // empty value means "No change" was selected
1558 update_post_meta( $post_id, 'dicha_skroutz_feed_custom_availability', sanitize_text_field( wp_unslash( $_REQUEST['change_dicha_skroutz_feed_custom_availability'] ) ) );
1559 }
1560 }
1561 }
1562 }
1563
1564
1565
1566 /**
1567 ****************
1568 ***** MISC *****
1569 ****************
1570 */
1571
1572 /**
1573 * Add Settings link in plugin page.
1574 *
1575 * @param array $actions The actions array.
1576 * @param string $plugin_file Path to the plugin file relative to the 'plugins' directory.
1577 *
1578 * @return array The actions array.
1579 */
1580 public function add_plugin_action_links( array $actions, string $plugin_file ): array {
1581
1582 if ( $plugin_file === DICHA_SKROUTZ_FEED_BASE_FILE ) {
1583
1584 $settings_link = [
1585 'settings' => sprintf( '<a href="%1$s">%2$s</a>',
1586 esc_url( admin_url( 'admin.php?page=' . DICHA_SKROUTZ_FEED_SLUG ) ),
1587 esc_html__( 'Settings', 'xml-feed-for-skroutz-for-woocommerce' )
1588 )
1589 ];
1590
1591 $actions = array_merge( $settings_link, $actions );
1592 }
1593
1594 return $actions;
1595 }
1596
1597
1598
1599 /**
1600 ******************************
1601 ***** WC COMPATIBILITIES *****
1602 ******************************
1603 */
1604
1605 /**
1606 * Declare compatibility with WooCommerce Features (HPOS, Cart & Checkout Blocks)
1607 *
1608 * @return void
1609 * @noinspection PhpFullyQualifiedNameUsageInspection
1610 */
1611 function declare_compatibility_with_wc_features(): void {
1612 if ( class_exists( \Automattic\WooCommerce\Utilities\FeaturesUtil::class ) ) {
1613 \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'custom_order_tables', DICHA_SKROUTZ_FEED_FILE );
1614 \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'cart_checkout_blocks', DICHA_SKROUTZ_FEED_FILE );
1615 }
1616 }
1617
1618
1619
1620 /**
1621 ***************************
1622 ***** ASSETS ENQUEUES *****
1623 ***************************
1624 */
1625
1626 /**
1627 * Register the stylesheets for the admin area.
1628 *
1629 * @param string $hook The current admin page
1630 */
1631 public function enqueue_styles( string $hook ): void {
1632 global $typenow;
1633
1634 $env_type = wp_get_environment_type();
1635 $assets_version = in_array( $env_type, [ 'local', 'development' ] ) ? $this->version . time() : $this->version;
1636 $is_settings_page = 'digital-challenge__page_' . DICHA_SKROUTZ_FEED_SLUG === $hook || 'digital-challenge_page_' . DICHA_SKROUTZ_FEED_SLUG === $hook;
1637 $is_products_admin_list = 'edit.php' === $hook && 'product' === $typenow;
1638 $is_product_edit_page = ( 'post-new.php' === $hook || 'post.php' === $hook ) && 'product' === $typenow;
1639
1640 if ( $is_products_admin_list ) {
1641
1642 wp_enqueue_style( 'dc-skroutz-product-list', DICHA_SKROUTZ_FEED_PLUGIN_DIR_URL . 'admin/css/dc-skroutz-feed-product-list.css', [], $assets_version );
1643 }
1644 else if ( $is_settings_page ) {
1645
1646 wp_enqueue_style( 'select2', WC()->plugin_url() . '/assets/css/select2.css', [], WC()->version );
1647 wp_enqueue_style( 'dc-skroutz-admin-settings', DICHA_SKROUTZ_FEED_PLUGIN_DIR_URL . 'admin/css/dc-skroutz-feed-admin.css', [], $assets_version );
1648 }
1649 elseif( $is_product_edit_page ) {
1650
1651 wp_enqueue_style( 'dc-skroutz-product-edit', DICHA_SKROUTZ_FEED_PLUGIN_DIR_URL . 'admin/css/dc-skroutz-feed-product-edit.css', [], $assets_version );
1652 }
1653 }
1654
1655 /**
1656 * Register the JavaScript for the admin area.
1657 *
1658 * @param string $hook The current admin page
1659 */
1660 public function enqueue_scripts( string $hook ): void {
1661 global $typenow;
1662
1663 $env_type = wp_get_environment_type();
1664 $assets_version = in_array( $env_type, [ 'local', 'development' ] ) ? $this->version . time() : $this->version;
1665 $is_settings_page = 'digital-challenge__page_' . DICHA_SKROUTZ_FEED_SLUG === $hook || 'digital-challenge_page_' . DICHA_SKROUTZ_FEED_SLUG === $hook;
1666 $is_products_admin_list = 'edit.php' === $hook && 'product' === $typenow;
1667
1668 if ( $is_settings_page ) {
1669
1670 wp_enqueue_script( 'dc-skroutz-admin-settings', DICHA_SKROUTZ_FEED_PLUGIN_DIR_URL . 'admin/js/dc-skroutz-feed-admin.js', [ 'jquery', 'selectWoo' ], $assets_version, [ 'strategy' => 'defer' ] );
1671 }
1672 elseif ( $is_products_admin_list ) {
1673
1674 wp_enqueue_script( 'dc-skroutz-quick-edit', DICHA_SKROUTZ_FEED_PLUGIN_DIR_URL . 'admin/js/dc-skroutz-feed-quick-bulk-edit.js', [ 'jquery' ], $assets_version, [ 'strategy' => 'defer' ] );
1675 }
1676 }
1677
1678 }