PluginProbe
Yatra – Travel Booking & Tour Operator Software / 2.2.10
Yatra – Travel Booking & Tour Operator Software v2.2.10
3.0.17 3.0.16 3.0.15 3.0.14 3.0.14.1 3.0.14.2 3.0.12 3.0.13 3.0.11 3.0.10 3.0.9 3.0.8 3.0.7 3.0.6 3.0.5 3.0.5.1 3.0.4 3.0.3 3.0.2.9 3.0.2.7 3.0.2.8 3.0.2.6 trunk 1.0.0 2.0.0 All 85 releases
yatra / includes / modules / status / sections / class-yatra-module-section-system-status.php

class-yatra-module-section-system-status.php in Yatra – Travel Booking & Tour Operator Software 2.2.10, at includes/modules/status/sections/class-yatra-module-section-system-status.php

727 lines 27.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 class Yatra_Module_Section_System_Status
4 {
5 public function __construct()
6 {
7 include YATRA_ABSPATH . 'includes/modules/status/templates/html-admin-page-status-report.php';
8 }
9
10
11 function get_server_database_version()
12 {
13 global $wpdb;
14
15 if (empty($wpdb->is_mysql)) {
16 return array(
17 'string' => '',
18 'number' => '',
19 );
20 }
21
22 // phpcs:disable WordPress.DB.RestrictedFunctions, PHPCompatibility.Extensions.RemovedExtensions.mysql_DeprecatedRemoved
23 if ($wpdb->use_mysqli) {
24 $server_info = mysqli_get_server_info($wpdb->dbh);
25 } else {
26 $server_info = mysql_get_server_info($wpdb->dbh);
27 }
28 // phpcs:enable WordPress.DB.RestrictedFunctions, PHPCompatibility.Extensions.RemovedExtensions.mysql_DeprecatedRemoved
29
30 return array(
31 'string' => $server_info,
32 'number' => preg_replace('/([^\d.]+).*/', '', $server_info),
33 );
34 }
35
36 public function get_database_info()
37 {
38 global $wpdb;
39
40 $tables = array();
41 $database_size = array();
42
43 // It is not possible to get the database name from some classes that replace wpdb (e.g., HyperDB)
44 // and that is why this if condition is needed.
45 if (defined('DB_NAME')) {
46 $database_table_information = $wpdb->get_results(
47 $wpdb->prepare(
48 "SELECT
49 table_name AS 'name',
50 engine AS 'engine',
51 round( ( data_length / 1024 / 1024 ), 2 ) 'data',
52 round( ( index_length / 1024 / 1024 ), 2 ) 'index'
53 FROM information_schema.TABLES
54 WHERE table_schema = %s
55 ORDER BY name ASC;",
56 DB_NAME
57 )
58 );
59
60 $core_tables = apply_filters(
61 'yatra_database_tables',
62 array(
63 'yatra_tour_dates',
64 'yatra_tour_enquiries',
65 'yatra_tour_booking_stats',
66 'yatra_logs',
67 )
68 );
69
70 /**
71 * Adding the prefix to the tables array, for backwards compatibility.
72 *
73 * If we changed the tables above to include the prefix, then any filters against that table could break.
74 */
75 $core_tables = array_map(array($this, 'add_db_table_prefix'), $core_tables);
76
77
78 $tables = array(
79 'yatra' => array_fill_keys($core_tables, false),
80 'other' => array(),
81 );
82
83 $database_size = array(
84 'data' => 0,
85 'index' => 0,
86 );
87
88 $site_tables_prefix = $wpdb->get_blog_prefix(get_current_blog_id());
89 $global_tables = $wpdb->tables('global', true);
90 foreach ($database_table_information as $table) {
91 // Only include tables matching the prefix of the current site, this is to prevent displaying all tables on a MS install not relating to the current.
92 if (is_multisite() && 0 !== strpos($table->name, $site_tables_prefix) && !in_array($table->name, $global_tables, true)) {
93 continue;
94 }
95 $table_type = in_array($table->name, $core_tables, true) ? 'yatra' : 'other';
96
97 $tables[$table_type][$table->name] = array(
98 'data' => $table->data,
99 'index' => $table->index,
100 'engine' => $table->engine,
101 );
102
103 $database_size['data'] += $table->data;
104 $database_size['index'] += $table->index;
105 }
106 }
107
108 // Return all database info. Described by JSON Schema.
109 return array(
110 'database_prefix' => $wpdb->prefix,
111 'database_tables' => $tables,
112 'database_size' => $database_size,
113 );
114 }
115
116
117 /**
118 * Get array of counts of objects. Orders, products, etc.
119 *
120 * @return array
121 */
122 public function get_post_type_counts()
123 {
124 global $wpdb;
125
126 $post_type_counts = $wpdb->get_results("SELECT post_type AS 'type', count(1) AS 'count' FROM {$wpdb->posts} GROUP BY post_type;", ARRAY_A);
127
128 return is_array($post_type_counts) ? $post_type_counts : array();
129 }
130
131 /**
132 * Get a list of plugins active on the site.
133 *
134 * @return array
135 */
136 public function get_active_plugins()
137 {
138 require_once ABSPATH . 'wp-admin/includes/plugin.php';
139
140 if (!function_exists('get_plugin_data')) {
141 return array();
142 }
143
144 $active_plugins = (array)get_option('active_plugins', array());
145 if (is_multisite()) {
146 $network_activated_plugins = array_keys(get_site_option('active_sitewide_plugins', array()));
147 $active_plugins = array_merge($active_plugins, $network_activated_plugins);
148 }
149
150 $active_plugins_data = array();
151
152 foreach ($active_plugins as $plugin) {
153
154 if (file_exists(WP_PLUGIN_DIR . '/' . $plugin)) {
155 $data = get_plugin_data(WP_PLUGIN_DIR . '/' . $plugin);
156 $active_plugins_data[] = $this->format_plugin_data($plugin, $data);
157 }
158 }
159
160 return $active_plugins_data;
161 }
162
163 /**
164 * Get a list of inplugins active on the site.
165 *
166 * @return array
167 */
168 public function get_inactive_plugins()
169 {
170 require_once ABSPATH . 'wp-admin/includes/plugin.php';
171
172 if (!function_exists('get_plugins')) {
173 return array();
174 }
175
176 $plugins = get_plugins();
177 $active_plugins = (array)get_option('active_plugins', array());
178
179 if (is_multisite()) {
180 $network_activated_plugins = array_keys(get_site_option('active_sitewide_plugins', array()));
181 $active_plugins = array_merge($active_plugins, $network_activated_plugins);
182 }
183
184 $plugins_data = array();
185
186 foreach ($plugins as $plugin => $data) {
187 if (in_array($plugin, $active_plugins, true)) {
188 continue;
189 }
190 $plugins_data[] = $this->format_plugin_data($plugin, $data);
191 }
192
193 return $plugins_data;
194 }
195
196 /**
197 * Format plugin data, including data on updates, into a standard format.
198 *
199 * @param string $plugin Plugin directory/file.
200 * @param array $data Plugin data from WP.
201 * @return array Formatted data.
202 */
203 protected function format_plugin_data($plugin, $data)
204 {
205 require_once ABSPATH . 'wp-admin/includes/update.php';
206
207 if (!function_exists('get_plugin_updates')) {
208 return array();
209 }
210
211 if (empty($this->available_updates)) {
212 $this->available_updates = get_plugin_updates();
213 }
214
215 $version_latest = $data['Version'];
216
217 // Find latest version.
218 if (isset($this->available_updates[$plugin]->update->new_version)) {
219 $version_latest = $this->available_updates[$plugin]->update->new_version;
220 }
221
222 return array(
223 'plugin' => $plugin,
224 'name' => $data['Name'],
225 'version' => $data['Version'],
226 'version_latest' => $version_latest,
227 'url' => $data['PluginURI'],
228 'author_name' => $data['AuthorName'],
229 'author_url' => esc_url_raw($data['AuthorURI']),
230 'network_activated' => $data['Network'],
231 );
232 }
233
234 /**
235 * Get a list of Dropins and MU plugins.
236 *
237 * @return array
238 */
239 public function get_dropins_mu_plugins()
240 {
241 $dropins = get_dropins();
242 $plugins = array(
243 'dropins' => array(),
244 'mu_plugins' => array(),
245 );
246 foreach ($dropins as $key => $dropin) {
247 $plugins['dropins'][] = array(
248 'plugin' => $key,
249 'name' => $dropin['Name'],
250 );
251 }
252
253 $mu_plugins = get_mu_plugins();
254 foreach ($mu_plugins as $plugin => $mu_plugin) {
255 $plugins['mu_plugins'][] = array(
256 'plugin' => $plugin,
257 'name' => $mu_plugin['Name'],
258 'version' => $mu_plugin['Version'],
259 'url' => $mu_plugin['PluginURI'],
260 'author_name' => $mu_plugin['AuthorName'],
261 'author_url' => esc_url_raw($mu_plugin['AuthorURI']),
262 );
263 }
264 return $plugins;
265 }
266
267 public static function get_file_version($file)
268 {
269
270 // Avoid notices if file does not exist.
271 if (!file_exists($file)) {
272 return '';
273 }
274
275 // We don't need to write to the file, so just open for reading.
276 $fp = fopen($file, 'r'); // @codingStandardsIgnoreLine.
277
278 // Pull only the first 8kiB of the file in.
279 $file_data = fread($fp, 8192); // @codingStandardsIgnoreLine.
280
281 // PHP will close file handle, but we are good citizens.
282 fclose($fp); // @codingStandardsIgnoreLine.
283
284 // Make sure we catch CR-only line endings.
285 $file_data = str_replace("\r", "\n", $file_data);
286 $version = '';
287
288 if (preg_match('/^[ \t\/*#@]*' . preg_quote('@version', '/') . '(.*)$/mi', $file_data, $match) && $match[1]) {
289 $version = _cleanup_header_comment($match[1]);
290 }
291
292 return $version;
293 }
294
295 /**
296 * Get info on the current active theme, info on parent theme (if presnet)
297 * and a list of template overrides.
298 *
299 * @return array
300 */
301 public function get_theme_info()
302 {
303 $active_theme = wp_get_theme();
304
305 // Get parent theme info if this theme is a child theme, otherwise
306 // pass empty info in the response.
307 if (is_child_theme()) {
308 $parent_theme = wp_get_theme($active_theme->template);
309 $parent_theme_info = array(
310 'parent_name' => $parent_theme->name,
311 'parent_version' => $parent_theme->version,
312 'parent_version_latest' => self::get_latest_theme_version($parent_theme),
313 'parent_author_url' => $parent_theme->{'Author URI'},
314 );
315 } else {
316 $parent_theme_info = array(
317 'parent_name' => '',
318 'parent_version' => '',
319 'parent_version_latest' => '',
320 'parent_author_url' => '',
321 );
322 }
323
324
325 $override_files = array();
326 $outdated_templates = false;
327 $scan_files = array();
328 $scan_files[] = 'single-tour.php';
329 $scan_files[] = 'archive-tour.php';
330 $scan_files[] = 'taxonomy-activity.php';
331 $scan_files[] = 'taxonomy-destination.php';
332 foreach ($scan_files as $file) {
333 $located = apply_filters('yatra_get_template', $file, $file, array(), yatra()->template_path(), yatra()->plugin_path() . '/templates/');
334
335 if (file_exists($located)) {
336 $theme_file = $located;
337 } elseif (file_exists(get_stylesheet_directory() . '/' . $file)) {
338 $theme_file = get_stylesheet_directory() . '/' . $file;
339 } elseif (file_exists(get_stylesheet_directory() . '/' . yatra()->template_path() . $file)) {
340 $theme_file = get_stylesheet_directory() . '/' . yatra()->template_path() . $file;
341 } elseif (file_exists(get_template_directory() . '/' . $file)) {
342 $theme_file = get_template_directory() . '/' . $file;
343 } elseif (file_exists(get_template_directory() . '/' . yatra()->template_path() . $file)) {
344 $theme_file = get_template_directory() . '/' . yatra()->template_path() . $file;
345 } else {
346 $theme_file = false;
347 }
348
349 if (!empty($theme_file)) {
350 $core_file = $file;
351
352 $core_version = self::get_file_version(yatra()->plugin_path() . '/templates/' . $core_file);
353 $theme_version = self::get_file_version($theme_file);
354 if ($core_version && (empty($theme_version) || version_compare($theme_version, $core_version, '<'))) {
355 if (!$outdated_templates) {
356 $outdated_templates = true;
357 }
358 }
359 $override_files[] = array(
360 'file' => str_replace(WP_CONTENT_DIR . '/themes/', '', $theme_file),
361 'version' => $theme_version,
362 'core_version' => $core_version,
363 );
364 }
365 }
366
367 $active_theme_info = array(
368 'name' => $active_theme->name,
369 'version' => $active_theme->version,
370 'version_latest' => self::get_latest_theme_version($active_theme),
371 'author_url' => esc_url_raw($active_theme->{'Author URI'}),
372 'is_child_theme' => is_child_theme(),
373 'has_yatra_file' => (file_exists(get_stylesheet_directory() . '/yatra.php') || file_exists(get_template_directory() . '/yatra.php')),
374 'has_outdated_templates' => $outdated_templates,
375 'overrides' => $override_files,
376 );
377
378 return array_merge($active_theme_info, $parent_theme_info);
379 }
380
381 public static function get_latest_theme_version($theme)
382 {
383 include_once ABSPATH . 'wp-admin/includes/theme.php';
384
385 $api = themes_api(
386 'theme_information',
387 array(
388 'slug' => $theme->get_stylesheet(),
389 'fields' => array(
390 'sections' => false,
391 'tags' => false,
392 ),
393 )
394 );
395
396 $update_theme_version = 0;
397
398 // Check .org for updates.
399 if (is_object($api) && !is_wp_error($api)) {
400 $update_theme_version = $api->version;
401 } elseif (strstr($theme->{'Author URI'}, 'mantrabrain')) { //
402 $theme_dir = substr(strtolower(str_replace(' ', '', $theme->Name)), 0, 45); // @codingStandardsIgnoreLine.
403 $theme_version_data = get_transient($theme_dir . '_version_data');
404
405 if (false === $theme_version_data) {
406 $theme_changelog = wp_safe_remote_get('http://dzv365zjfbd8v.cloudfront.net/changelogs/' . $theme_dir . '/changelog.txt');
407 $cl_lines = explode("\n", wp_remote_retrieve_body($theme_changelog));
408 if (!empty($cl_lines)) {
409 foreach ($cl_lines as $line_num => $cl_line) {
410 if (preg_match('/^[0-9]/', $cl_line)) {
411 $theme_date = str_replace('.', '-', trim(substr($cl_line, 0, strpos($cl_line, '-'))));
412 $theme_version = preg_replace('~[^0-9,.]~', '', stristr($cl_line, 'version'));
413 $theme_update = trim(str_replace('*', '', $cl_lines[$line_num + 1]));
414 $theme_version_data = array(
415 'date' => $theme_date,
416 'version' => $theme_version,
417 'update' => $theme_update,
418 'changelog' => $theme_changelog,
419 );
420 set_transient($theme_dir . '_version_data', $theme_version_data, DAY_IN_SECONDS);
421 break;
422 }
423 }
424 }
425 }
426
427 if (!empty($theme_version_data['version'])) {
428 $update_theme_version = $theme_version_data['version'];
429 }
430 }
431
432 return $update_theme_version;
433 }
434
435 public function get_settings()
436 {
437 $all_positions = yatra_get_currency_positions();
438 $currency_position = get_option('yatra_currency_position', 'left');
439 $currency_position = isset($all_positions[$currency_position]) ? $all_positions[$currency_position] : 'Left';
440 return array(
441 'currency' => yatra_get_current_currency(),
442 'currency_symbol' => yatra_get_current_currency_symbol(),
443 'currency_position' => $currency_position,
444 'thousand_separator' => get_option('yatra_thousand_separator', ','),
445 'decimal_separator' => get_option('yatra_decimal_separator', '.'),
446 'number_of_decimals' => get_option('yatra_price_number_decimals', '2'),
447 );
448 }
449
450 /**
451 * Returns security tips.
452 *
453 * @return array
454 */
455 public function get_security_info()
456 {
457 return array(
458 'secure_connection' => is_ssl(),
459 'hide_errors' => !(defined('WP_DEBUG') && defined('WP_DEBUG_DISPLAY') && WP_DEBUG && WP_DEBUG_DISPLAY) || 0 === intval(ini_get('display_errors')),
460 );
461 }
462
463 public function get_pages()
464 {
465 $check_pages = array(
466
467 _x('Cart', 'Page setting', 'yatra') => array(
468 'option' => 'yatra_cart_page',
469 'shortcode' => '[' . apply_filters('yatra_cart_shortcode_tag', 'yatra_cart') . ']',
470 'block' => '',
471 ),
472 _x('Checkout', 'Page setting', 'yatra') => array(
473 'option' => 'yatra_checkout_page',
474 'shortcode' => '[' . apply_filters('yatra_checkout_shortcode_tag', 'yatra_checkout') . ']',
475 'block' => '',
476 ),
477 _x('My account', 'Page setting', 'yatra') => array(
478 'option' => 'yatra_my_account_page',
479 'shortcode' => '[' . apply_filters('yatra_my_account_shortcode_tag', 'yatra_my_account') . ']',
480 'block' => '',
481 ),
482 _x('Terms and conditions', 'Page setting', 'yatra') => array(
483 'option' => 'yatra_terms_and_conditions_page',
484 'shortcode' => '',
485 'block' => '',
486 ),
487 );
488
489 $pages_output = array();
490
491 foreach ($check_pages as $page_name => $values) {
492 $page_id = get_option($values['option']);
493 $page_set = false;
494 $page_exists = false;
495 $page_visible = false;
496 $shortcode_present = false;
497 $shortcode_required = false;
498 $block_present = false;
499 $block_required = false;
500
501 // Page checks.
502 if ($page_id) {
503 $page_set = true;
504 }
505 if (get_post($page_id)) {
506 $page_exists = true;
507 }
508 if ('publish' === get_post_status($page_id)) {
509 $page_visible = true;
510 }
511
512 // Shortcode checks.
513 if ($values['shortcode'] && get_post($page_id)) {
514 $shortcode_required = true;
515 $page = get_post($page_id);
516 if (strstr($page->post_content, $values['shortcode'])) {
517 $shortcode_present = true;
518 }
519 }
520
521 // Block checks.
522 if ($values['block'] && get_post($page_id)) {
523 $block_required = true;
524 $block_present = $this->has_block_in_page($page_id, $values['block']);
525 }
526
527 // Wrap up our findings into an output array.
528 $pages_output[] = array(
529 'page_name' => $page_name,
530 'page_id' => $page_id,
531 'page_set' => $page_set,
532 'page_exists' => $page_exists,
533 'page_visible' => $page_visible,
534 'shortcode' => $values['shortcode'],
535 'block' => $values['block'],
536 'shortcode_required' => $shortcode_required,
537 'shortcode_present' => $shortcode_present,
538 'block_present' => $block_present,
539 'block_required' => $block_required,
540 );
541 }
542
543 return $pages_output;
544 }
545
546 public function has_block_in_page($page, $block_name)
547 {
548 $page_to_check = get_post($page);
549 if (null === $page_to_check) {
550 return false;
551 }
552
553 $blocks = parse_blocks($page_to_check->post_content);
554 foreach ($blocks as $block) {
555 if ($block_name === $block['blockName']) {
556 return true;
557 }
558 }
559
560 return false;
561 }
562
563 protected function add_db_table_prefix($table)
564 {
565 global $wpdb;
566 return $wpdb->prefix . $table;
567 }
568
569 public function environment()
570 {
571 global $wpdb;
572
573
574 // Figure out cURL version, if installed.
575 $curl_version = '';
576 if (function_exists('curl_version')) {
577 $curl_version = curl_version();
578 $curl_version = $curl_version['version'] . ', ' . $curl_version['ssl_version'];
579 } elseif (extension_loaded('curl')) {
580 $curl_version = __('cURL installed but unable to retrieve version.', 'yatra');
581 }
582
583 // WP memory limit.
584 $wp_memory_limit = yatra_let_to_num(WP_MEMORY_LIMIT);
585 if (function_exists('memory_get_usage')) {
586 $wp_memory_limit = max($wp_memory_limit, yatra_let_to_num(@ini_get('memory_limit'))); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
587 }
588
589 // Test POST requests.
590 $post_response_successful = null;
591
592 $post_response_code = null;
593
594 $post_response_code = get_transient('yatra_test_remote_post');
595
596 if (false === $post_response_code || is_wp_error($post_response_code)) {
597 $response = wp_safe_remote_post(
598 'https://www.paypal.com/cgi-bin/webscr',
599 array(
600 'timeout' => 10,
601 'user-agent' => 'Yatra/' . YATRA_VERSION,
602 'httpversion' => '1.1',
603 'body' => array(
604 'cmd' => '_notify-validate',
605 ),
606 )
607 );
608 if (!is_wp_error($response)) {
609 $post_response_code = $response['response']['code'];
610 }
611 set_transient('yatra_test_remote_post', $post_response_code, HOUR_IN_SECONDS);
612 }
613
614 $post_response_successful = !is_wp_error($post_response_code) && $post_response_code >= 200 && $post_response_code < 300;
615
616
617 // Test GET requests.
618 $get_response_successful = null;
619 $get_response_code = null;
620
621 $get_response_code = get_transient('yatra_test_remote_get');
622
623 if (false === $get_response_code || is_wp_error($get_response_code)) {
624 $response = wp_safe_remote_get('https://mantrabrain.com/?request=ping&network=' . (is_multisite() ? '1' : '0'));
625 if (!is_wp_error($response)) {
626 $get_response_code = $response['response']['code'];
627 }
628 set_transient('yatra_test_remote_get', $get_response_code, HOUR_IN_SECONDS);
629 }
630
631 $get_response_successful = !is_wp_error($get_response_code) && $get_response_code >= 200 && $get_response_code < 300;
632
633
634 $database_version = $this->get_server_database_version();
635
636 // Return all environment info. Described by JSON Schema.
637 return array(
638 'home_url' => get_option('home'),
639 'site_url' => get_option('siteurl'),
640 'version' => YATRA_VERSION,
641 'log_directory' => yatra()->get_log_dir(),
642 'log_directory_writable' => (bool)@fopen(yatra()->get_log_dir() . 'test-log.log', 'a'), // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged, WordPress.WP.AlternativeFunctions.file_system_read_fopen
643 'wp_version' => get_bloginfo('version'),
644 'wp_multisite' => is_multisite(),
645 'wp_memory_limit' => $wp_memory_limit,
646 'wp_debug_mode' => (defined('WP_DEBUG') && WP_DEBUG),
647 'wp_cron' => !(defined('DISABLE_WP_CRON') && DISABLE_WP_CRON),
648 'language' => get_locale(),
649 'external_object_cache' => wp_using_ext_object_cache(),
650 'server_info' => isset($_SERVER['SERVER_SOFTWARE']) ? yatra_clean(wp_unslash($_SERVER['SERVER_SOFTWARE'])) : '',
651 'php_version' => phpversion(),
652 'php_post_max_size' => yatra_let_to_num(ini_get('post_max_size')),
653 'php_max_execution_time' => (int)ini_get('max_execution_time'),
654 'php_max_input_vars' => (int)ini_get('max_input_vars'),
655 'curl_version' => $curl_version,
656 'suhosin_installed' => extension_loaded('suhosin'),
657 'max_upload_size' => wp_max_upload_size(),
658 'mysql_version' => $database_version['number'],
659 'mysql_version_string' => $database_version['string'],
660 'default_timezone' => date_default_timezone_get(),
661 'fsockopen_or_curl_enabled' => (function_exists('fsockopen') || function_exists('curl_init')),
662 'soapclient_enabled' => class_exists('SoapClient'),
663 'domdocument_enabled' => class_exists('DOMDocument'),
664 'gzip_enabled' => is_callable('gzopen'),
665 'mbstring_enabled' => extension_loaded('mbstring'),
666 'remote_post_successful' => $post_response_successful,
667 'remote_post_response' => is_wp_error($post_response_code) ? $post_response_code->get_error_message() : $post_response_code,
668 'remote_get_successful' => $get_response_successful,
669 'remote_get_response' => is_wp_error($get_response_code) ? $get_response_code->get_error_message() : $get_response_code,
670 );
671 }
672
673 private static function output_plugins_info($plugins, $untested_plugins = array())
674 {
675 $yatra_version = YATRA_VERSION;
676
677
678 foreach ($plugins as $plugin) {
679 if (!empty($plugin['name'])) {
680 // Link the plugin name to the plugin url if available.
681 $plugin_name = esc_html($plugin['name']);
682 if (!empty($plugin['url'])) {
683 $plugin_name = '<a href="' . esc_url($plugin['url']) . '" aria-label="' . esc_attr__('Visit plugin homepage', 'yatra') . '" target="_blank">' . $plugin_name . '</a>';
684 }
685
686 $has_newer_version = false;
687 $version_string = $plugin['version'];
688 $network_string = '';
689 if (strstr($plugin['url'], 'woothemes.com') || strstr($plugin['url'], 'yatra.com')) {
690 if (!empty($plugin['version_latest']) && version_compare($plugin['version_latest'], $plugin['version'], '>')) {
691 /* translators: 1: current version. 2: latest version */
692 $version_string = sprintf(__('%1$s (update to version %2$s is available)', 'yatra'), $plugin['version'], $plugin['version_latest']);
693 }
694
695 if (false !== $plugin['network_activated']) {
696 $network_string = ' &ndash; <strong style="color: black;">' . esc_html__('Network enabled', 'yatra') . '</strong>';
697 }
698 }
699 $untested_string = '';
700 if (array_key_exists($plugin['plugin'], $untested_plugins)) {
701 $untested_string = ' &ndash; <strong style="color: #a00;">';
702
703 /* translators: %s: version */
704 $untested_string .= esc_html(sprintf(__('Installed version not tested with active version of Yatra %s', 'yatra'), $yatra_version));
705
706 $untested_string .= '</strong>';
707 }
708 ?>
709 <tr>
710 <td><?php echo wp_kses_post($plugin_name); ?></td>
711 <td class="help">&nbsp;</td>
712 <td>
713 <?php
714 /* translators: %s: plugin author */
715 printf(esc_html__('by %s', 'yatra'), esc_html($plugin['author_name']));
716 echo ' &ndash; ' . esc_html($version_string) . $untested_string . $network_string; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
717 ?>
718 </td>
719 </tr>
720 <?php
721 }
722 }
723 }
724
725 }
726
727 new Yatra_Module_Section_System_Status();