Edit File by line
/home/zeestwma/richards.../wp-conte.../plugins/woocomme.../src/Internal/Features
File: FeaturesController.php
$compatibles = $this->compatibility_info_by_feature[ $feature ][ FeaturePluginCompatibility::COMPATIBLE ];
[1500] Fix | Delete
$this->compatibility_info_by_feature[ $feature ][ FeaturePluginCompatibility::COMPATIBLE ] = array_diff( $compatibles, array( $plugin_name ) );
[1501] Fix | Delete
[1502] Fix | Delete
$incompatibles = $this->compatibility_info_by_feature[ $feature ][ FeaturePluginCompatibility::INCOMPATIBLE ];
[1503] Fix | Delete
$this->compatibility_info_by_feature[ $feature ][ FeaturePluginCompatibility::INCOMPATIBLE ] = array_diff( $incompatibles, array( $plugin_name ) );
[1504] Fix | Delete
}
[1505] Fix | Delete
}
[1506] Fix | Delete
[1507] Fix | Delete
/**
[1508] Fix | Delete
* Handler for the all_plugins filter.
[1509] Fix | Delete
*
[1510] Fix | Delete
* Returns the list of plugins incompatible with a given plugin
[1511] Fix | Delete
* if we are in the plugins page and the query string of the current request
[1512] Fix | Delete
* looks like '?plugin_status=incompatible_with_feature&feature_id=<feature id>'.
[1513] Fix | Delete
*
[1514] Fix | Delete
* @param array $plugin_list The original list of plugins.
[1515] Fix | Delete
*
[1516] Fix | Delete
* @internal For exclusive usage of WooCommerce core, backwards compatibility not guaranteed.
[1517] Fix | Delete
*/
[1518] Fix | Delete
public function filter_plugins_list( $plugin_list ): array {
[1519] Fix | Delete
if ( ! $this->verify_did_woocommerce_init() ) {
[1520] Fix | Delete
return $plugin_list;
[1521] Fix | Delete
}
[1522] Fix | Delete
[1523] Fix | Delete
// phpcs:disable WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput
[1524] Fix | Delete
if ( ! function_exists( 'get_current_screen' ) ||
[1525] Fix | Delete
( get_current_screen() && 'plugins' !== get_current_screen()->id ) ||
[1526] Fix | Delete
'incompatible_with_feature' !== ArrayUtil::get_value_or_default( $_GET, 'plugin_status' ) ) {
[1527] Fix | Delete
return $plugin_list;
[1528] Fix | Delete
}
[1529] Fix | Delete
[1530] Fix | Delete
$feature_id = $_GET['feature_id'] ?? 'all';
[1531] Fix | Delete
if ( 'all' !== $feature_id && ! $this->feature_exists( $feature_id ) ) {
[1532] Fix | Delete
return $plugin_list;
[1533] Fix | Delete
}
[1534] Fix | Delete
[1535] Fix | Delete
return $this->get_incompatible_plugins( $feature_id, $plugin_list );
[1536] Fix | Delete
}
[1537] Fix | Delete
[1538] Fix | Delete
/**
[1539] Fix | Delete
* Returns the list of plugins incompatible with a given feature.
[1540] Fix | Delete
*
[1541] Fix | Delete
* @param string $feature_id ID of the feature. Can also be `all` to denote all features.
[1542] Fix | Delete
* @param array $plugin_list List of plugins to filter.
[1543] Fix | Delete
*
[1544] Fix | Delete
* @return array List of plugins incompatible with the given feature.
[1545] Fix | Delete
*/
[1546] Fix | Delete
public function get_incompatible_plugins( $feature_id, $plugin_list ) {
[1547] Fix | Delete
$incompatibles = array();
[1548] Fix | Delete
$plugin_list = array_diff_key( $plugin_list, array_flip( $this->plugins_excluded_from_compatibility_ui ) );
[1549] Fix | Delete
$feature_ids = 'all' === $feature_id ? array_keys( $this->get_feature_definitions() ) : array( $feature_id );
[1550] Fix | Delete
$only_enabled_features = 'all' === $feature_id;
[1551] Fix | Delete
[1552] Fix | Delete
// phpcs:enable WordPress.Security.NonceVerification, WordPress.Security.ValidatedSanitizedInput
[1553] Fix | Delete
foreach ( array_keys( $plugin_list ) as $plugin_name ) {
[1554] Fix | Delete
if ( ! $this->plugin_util->is_woocommerce_aware_plugin( $plugin_name ) || ! $this->proxy->call_function( 'is_plugin_active', $plugin_name ) ) {
[1555] Fix | Delete
continue;
[1556] Fix | Delete
}
[1557] Fix | Delete
[1558] Fix | Delete
$compatibility_info = $this->get_compatible_features_for_plugin( $plugin_name );
[1559] Fix | Delete
foreach ( $feature_ids as $feature_id ) {
[1560] Fix | Delete
$features_considered_incompatible = array_filter(
[1561] Fix | Delete
$this->plugin_util->get_items_considered_incompatible( $feature_id, $compatibility_info ),
[1562] Fix | Delete
$only_enabled_features ?
[1563] Fix | Delete
fn( $id ) => $this->feature_is_enabled( $id ) && ! $this->should_skip_compatibility_checks( $id ) :
[1564] Fix | Delete
fn( $id ) => ! $this->should_skip_compatibility_checks( $id )
[1565] Fix | Delete
);
[1566] Fix | Delete
if ( in_array( $feature_id, $features_considered_incompatible, true ) ) {
[1567] Fix | Delete
$incompatibles[] = $plugin_name;
[1568] Fix | Delete
}
[1569] Fix | Delete
}
[1570] Fix | Delete
}
[1571] Fix | Delete
[1572] Fix | Delete
return array_intersect_key( $plugin_list, array_flip( $incompatibles ) );
[1573] Fix | Delete
}
[1574] Fix | Delete
[1575] Fix | Delete
/**
[1576] Fix | Delete
* Handler for the admin_notices action.
[1577] Fix | Delete
*
[1578] Fix | Delete
* @internal For exclusive usage of WooCommerce core, backwards compatibility not guaranteed.
[1579] Fix | Delete
*/
[1580] Fix | Delete
public function display_notices_in_plugins_page(): void {
[1581] Fix | Delete
if ( ! $this->verify_did_woocommerce_init() ) {
[1582] Fix | Delete
return;
[1583] Fix | Delete
}
[1584] Fix | Delete
[1585] Fix | Delete
$feature_filter_description_shown = $this->maybe_display_current_feature_filter_description();
[1586] Fix | Delete
if ( ! $feature_filter_description_shown ) {
[1587] Fix | Delete
$this->maybe_display_feature_incompatibility_warning();
[1588] Fix | Delete
}
[1589] Fix | Delete
}
[1590] Fix | Delete
[1591] Fix | Delete
/**
[1592] Fix | Delete
* Shows a warning when there are any incompatibility between active plugins and enabled features.
[1593] Fix | Delete
* The warning is shown in on any admin screen except the plugins screen itself, since
[1594] Fix | Delete
* there's already a "You are viewing plugins that are incompatible" notice.
[1595] Fix | Delete
*/
[1596] Fix | Delete
private function maybe_display_feature_incompatibility_warning(): void {
[1597] Fix | Delete
if ( ! current_user_can( 'activate_plugins' ) ) {
[1598] Fix | Delete
return;
[1599] Fix | Delete
}
[1600] Fix | Delete
[1601] Fix | Delete
$incompatible_plugins = false;
[1602] Fix | Delete
$relevant_plugins = array_diff( $this->plugin_util->get_woocommerce_aware_plugins( true ), $this->plugins_excluded_from_compatibility_ui );
[1603] Fix | Delete
[1604] Fix | Delete
foreach ( $relevant_plugins as $plugin ) {
[1605] Fix | Delete
$compatibility_info = $this->get_compatible_features_for_plugin( $plugin, true );
[1606] Fix | Delete
[1607] Fix | Delete
$incompatibles = array_filter( $compatibility_info[ FeaturePluginCompatibility::INCOMPATIBLE ], fn( $id ) => ! $this->should_skip_compatibility_checks( $id ) );
[1608] Fix | Delete
if ( ! empty( $incompatibles ) ) {
[1609] Fix | Delete
$incompatible_plugins = true;
[1610] Fix | Delete
break;
[1611] Fix | Delete
}
[1612] Fix | Delete
[1613] Fix | Delete
$uncertains = array_filter( $compatibility_info[ FeaturePluginCompatibility::UNCERTAIN ], fn( $id ) => ! $this->should_skip_compatibility_checks( $id ) );
[1614] Fix | Delete
foreach ( $uncertains as $feature_id ) {
[1615] Fix | Delete
if ( FeaturePluginCompatibility::COMPATIBLE !== $this->get_default_plugin_compatibility( $feature_id ) ) {
[1616] Fix | Delete
$incompatible_plugins = true;
[1617] Fix | Delete
break;
[1618] Fix | Delete
}
[1619] Fix | Delete
}
[1620] Fix | Delete
[1621] Fix | Delete
if ( $incompatible_plugins ) {
[1622] Fix | Delete
break;
[1623] Fix | Delete
}
[1624] Fix | Delete
}
[1625] Fix | Delete
[1626] Fix | Delete
if ( ! $incompatible_plugins ) {
[1627] Fix | Delete
return;
[1628] Fix | Delete
}
[1629] Fix | Delete
[1630] Fix | Delete
$message = str_replace(
[1631] Fix | Delete
'<a>',
[1632] Fix | Delete
'<a href="' . esc_url( add_query_arg( array( 'plugin_status' => 'incompatible_with_feature' ), admin_url( 'plugins.php' ) ) ) . '">',
[1633] Fix | Delete
__( 'WooCommerce has detected that some of your active plugins are incompatible with currently enabled WooCommerce features. Please <a>review the details</a>.', 'woocommerce' )
[1634] Fix | Delete
);
[1635] Fix | Delete
[1636] Fix | Delete
// phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped
[1637] Fix | Delete
?>
[1638] Fix | Delete
<div class="notice notice-error">
[1639] Fix | Delete
<p><?php echo $message; ?></p>
[1640] Fix | Delete
</div>
[1641] Fix | Delete
<?php
[1642] Fix | Delete
// phpcs:enable WordPress.Security.EscapeOutput.OutputNotEscaped
[1643] Fix | Delete
}
[1644] Fix | Delete
[1645] Fix | Delete
/**
[1646] Fix | Delete
* Shows a "You are viewing the plugins that are incompatible with the X feature"
[1647] Fix | Delete
* if we are in the plugins page and the query string of the current request
[1648] Fix | Delete
* looks like '?plugin_status=incompatible_with_feature&feature_id=<feature id>'.
[1649] Fix | Delete
*/
[1650] Fix | Delete
private function maybe_display_current_feature_filter_description(): bool {
[1651] Fix | Delete
if ( 'plugins' !== get_current_screen()->id ) {
[1652] Fix | Delete
return false;
[1653] Fix | Delete
}
[1654] Fix | Delete
[1655] Fix | Delete
// phpcs:disable WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput
[1656] Fix | Delete
$plugin_status = $_GET['plugin_status'] ?? '';
[1657] Fix | Delete
$feature_id = $_GET['feature_id'] ?? '';
[1658] Fix | Delete
// phpcs:enable WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput
[1659] Fix | Delete
[1660] Fix | Delete
if ( 'incompatible_with_feature' !== $plugin_status ) {
[1661] Fix | Delete
return false;
[1662] Fix | Delete
}
[1663] Fix | Delete
[1664] Fix | Delete
$feature_id = ( '' === $feature_id ) ? 'all' : $feature_id;
[1665] Fix | Delete
[1666] Fix | Delete
if ( 'all' !== $feature_id && ! $this->feature_exists( $feature_id ) ) {
[1667] Fix | Delete
return false;
[1668] Fix | Delete
}
[1669] Fix | Delete
[1670] Fix | Delete
$features = $this->get_feature_definitions();
[1671] Fix | Delete
$plugins_page_url = admin_url( 'plugins.php' );
[1672] Fix | Delete
$features_page_url = $this->get_features_page_url();
[1673] Fix | Delete
[1674] Fix | Delete
$message =
[1675] Fix | Delete
'all' === $feature_id
[1676] Fix | Delete
? __( 'You are viewing active plugins that are incompatible with currently enabled WooCommerce features.', 'woocommerce' )
[1677] Fix | Delete
: sprintf(
[1678] Fix | Delete
/* translators: %s is a feature name. */
[1679] Fix | Delete
__( "You are viewing the active plugins that are incompatible with the '%s' feature.", 'woocommerce' ),
[1680] Fix | Delete
$features[ $feature_id ]['name']
[1681] Fix | Delete
);
[1682] Fix | Delete
[1683] Fix | Delete
$message .= '<br />';
[1684] Fix | Delete
$message .= sprintf(
[1685] Fix | Delete
__( "<a href='%1\$s'>View all plugins</a> - <a href='%2\$s'>Manage WooCommerce features</a>", 'woocommerce' ),
[1686] Fix | Delete
$plugins_page_url,
[1687] Fix | Delete
$features_page_url
[1688] Fix | Delete
);
[1689] Fix | Delete
[1690] Fix | Delete
// phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped
[1691] Fix | Delete
?>
[1692] Fix | Delete
<div class="notice notice-info">
[1693] Fix | Delete
<p><?php echo $message; ?></p>
[1694] Fix | Delete
</div>
[1695] Fix | Delete
<?php
[1696] Fix | Delete
// phpcs:enable WordPress.Security.EscapeOutput.OutputNotEscaped
[1697] Fix | Delete
[1698] Fix | Delete
return true;
[1699] Fix | Delete
}
[1700] Fix | Delete
[1701] Fix | Delete
/**
[1702] Fix | Delete
* If the 'incompatible with features' plugin list is being rendered, invalidate existing cached plugin data.
[1703] Fix | Delete
*
[1704] Fix | Delete
* This heads off a problem in which WordPress's `get_plugins()` function may be called much earlier in the request
[1705] Fix | Delete
* (by third party code, for example), the results of which are cached, and before WooCommerce can modify the list
[1706] Fix | Delete
* to inject useful information of its own.
[1707] Fix | Delete
*
[1708] Fix | Delete
* @see https://github.com/woocommerce/woocommerce/issues/37343
[1709] Fix | Delete
*
[1710] Fix | Delete
* @return void
[1711] Fix | Delete
*
[1712] Fix | Delete
* @internal For exclusive usage of WooCommerce core, backwards compatibility not guaranteed.
[1713] Fix | Delete
*/
[1714] Fix | Delete
public function maybe_invalidate_cached_plugin_data(): void {
[1715] Fix | Delete
// phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
[1716] Fix | Delete
if ( ( $_GET['plugin_status'] ?? '' ) === 'incompatible_with_feature' ) {
[1717] Fix | Delete
wp_cache_delete( 'plugins', 'plugins' );
[1718] Fix | Delete
}
[1719] Fix | Delete
}
[1720] Fix | Delete
[1721] Fix | Delete
/**
[1722] Fix | Delete
* Handler for the 'after_plugin_row' action.
[1723] Fix | Delete
* Displays a "This plugin is incompatible with X features" notice if necessary.
[1724] Fix | Delete
*
[1725] Fix | Delete
* @param string $plugin_file The id of the plugin for which a row has been rendered in the plugins page.
[1726] Fix | Delete
* @param array $plugin_data Plugin data, as returned by 'get_plugins'.
[1727] Fix | Delete
*
[1728] Fix | Delete
* @internal For exclusive usage of WooCommerce core, backwards compatibility not guaranteed.
[1729] Fix | Delete
*/
[1730] Fix | Delete
public function handle_plugin_list_rows( $plugin_file, $plugin_data ) {
[1731] Fix | Delete
global $wp_list_table;
[1732] Fix | Delete
[1733] Fix | Delete
if ( in_array( $plugin_file, $this->plugins_excluded_from_compatibility_ui, true ) ) {
[1734] Fix | Delete
return;
[1735] Fix | Delete
}
[1736] Fix | Delete
[1737] Fix | Delete
if ( 'incompatible_with_feature' !== ArrayUtil::get_value_or_default( $_GET, 'plugin_status' ) ) { // phpcs:ignore WordPress.Security.NonceVerification
[1738] Fix | Delete
return;
[1739] Fix | Delete
}
[1740] Fix | Delete
[1741] Fix | Delete
if ( is_null( $wp_list_table ) || ! $this->plugin_util->is_woocommerce_aware_plugin( $plugin_data ) ) {
[1742] Fix | Delete
return;
[1743] Fix | Delete
}
[1744] Fix | Delete
[1745] Fix | Delete
if ( ! $this->proxy->call_function( 'is_plugin_active', $plugin_file ) ) {
[1746] Fix | Delete
return;
[1747] Fix | Delete
}
[1748] Fix | Delete
[1749] Fix | Delete
$features = $this->get_feature_definitions();
[1750] Fix | Delete
$feature_compatibility_info = $this->get_compatible_features_for_plugin( $plugin_file, true, true );
[1751] Fix | Delete
$incompatible_features = $feature_compatibility_info[ FeaturePluginCompatibility::INCOMPATIBLE ];
[1752] Fix | Delete
$incompatible_features = array_values(
[1753] Fix | Delete
array_filter(
[1754] Fix | Delete
$incompatible_features,
[1755] Fix | Delete
function ( $feature_id ) {
[1756] Fix | Delete
return ! $this->should_skip_compatibility_checks( $feature_id );
[1757] Fix | Delete
}
[1758] Fix | Delete
)
[1759] Fix | Delete
);
[1760] Fix | Delete
[1761] Fix | Delete
$incompatible_features_count = count( $incompatible_features );
[1762] Fix | Delete
if ( $incompatible_features_count > 0 ) {
[1763] Fix | Delete
$columns_count = $wp_list_table->get_column_count();
[1764] Fix | Delete
$is_active = true; // For now we are showing active plugins in the "Incompatible with..." view.
[1765] Fix | Delete
$is_active_class = $is_active ? 'active' : 'inactive';
[1766] Fix | Delete
$is_active_td_style = $is_active ? " style='border-left: 4px solid #72aee6;'" : '';
[1767] Fix | Delete
[1768] Fix | Delete
if ( 1 === $incompatible_features_count ) {
[1769] Fix | Delete
$message = sprintf(
[1770] Fix | Delete
/* translators: %s = printable plugin name */
[1771] Fix | Delete
__( "âš  This plugin is incompatible with the enabled WooCommerce feature '%s', it shouldn't be activated.", 'woocommerce' ),
[1772] Fix | Delete
$features[ $incompatible_features[0] ]['name']
[1773] Fix | Delete
);
[1774] Fix | Delete
} elseif ( 2 === $incompatible_features_count ) {
[1775] Fix | Delete
/* translators: %1\$s, %2\$s = printable plugin names */
[1776] Fix | Delete
$message = sprintf(
[1777] Fix | Delete
__( "âš  This plugin is incompatible with the enabled WooCommerce features '%1\$s' and '%2\$s', it shouldn't be activated.", 'woocommerce' ),
[1778] Fix | Delete
$features[ $incompatible_features[0] ]['name'],
[1779] Fix | Delete
$features[ $incompatible_features[1] ]['name']
[1780] Fix | Delete
);
[1781] Fix | Delete
} else {
[1782] Fix | Delete
/* translators: %1\$s, %2\$s = printable plugin names, %3\$d = plugins count */
[1783] Fix | Delete
$message = sprintf(
[1784] Fix | Delete
__( "âš  This plugin is incompatible with the enabled WooCommerce features '%1\$s', '%2\$s' and %3\$d more, it shouldn't be activated.", 'woocommerce' ),
[1785] Fix | Delete
$features[ $incompatible_features[0] ]['name'],
[1786] Fix | Delete
$features[ $incompatible_features[1] ]['name'],
[1787] Fix | Delete
$incompatible_features_count - 2
[1788] Fix | Delete
);
[1789] Fix | Delete
}
[1790] Fix | Delete
$features_page_url = $this->get_features_page_url();
[1791] Fix | Delete
$manage_features_message = __( 'Manage WooCommerce features', 'woocommerce' );
[1792] Fix | Delete
[1793] Fix | Delete
// phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped
[1794] Fix | Delete
?>
[1795] Fix | Delete
<tr class='plugin-update-tr update <?php echo $is_active_class; ?>' data-plugin='<?php echo $plugin_file; ?>' data-plugin-row-type='feature-incomp-warn'>
[1796] Fix | Delete
<td colspan='<?php echo $columns_count; ?>' class='plugin-update'<?php echo $is_active_td_style; ?>>
[1797] Fix | Delete
<div class='notice inline notice-warning notice-alt'>
[1798] Fix | Delete
<p>
[1799] Fix | Delete
<?php echo $message; ?>
[1800] Fix | Delete
<a href="<?php echo $features_page_url; ?>"><?php echo $manage_features_message; ?></a>
[1801] Fix | Delete
</p>
[1802] Fix | Delete
</div>
[1803] Fix | Delete
</td>
[1804] Fix | Delete
</tr>
[1805] Fix | Delete
<?php
[1806] Fix | Delete
// phpcs:enable WordPress.Security.EscapeOutput.OutputNotEscaped
[1807] Fix | Delete
}
[1808] Fix | Delete
}
[1809] Fix | Delete
[1810] Fix | Delete
/**
[1811] Fix | Delete
* Get the URL of the features settings page.
[1812] Fix | Delete
*
[1813] Fix | Delete
* @return string
[1814] Fix | Delete
*/
[1815] Fix | Delete
public function get_features_page_url(): string {
[1816] Fix | Delete
return admin_url( 'admin.php?page=wc-settings&tab=advanced&section=features' );
[1817] Fix | Delete
}
[1818] Fix | Delete
[1819] Fix | Delete
/**
[1820] Fix | Delete
* Fix for the HTML of the plugins list when there are feature-plugin incompatibility warnings.
[1821] Fix | Delete
*
[1822] Fix | Delete
* WordPress renders the plugin information rows in the plugins page in <tr> elements as follows:
[1823] Fix | Delete
*
[1824] Fix | Delete
* - If the plugin needs update, the <tr> will have an "update" class. This will prevent the lower
[1825] Fix | Delete
* border line to be drawn. Later an additional <tr> with an "update available" warning will be rendered,
[1826] Fix | Delete
* it will have a "plugin-update-tr" class which will draw the missing lower border line.
[1827] Fix | Delete
* - Otherwise, the <tr> will be already drawn with the lower border line.
[1828] Fix | Delete
*
[1829] Fix | Delete
* This is a problem for our rendering of the "plugin is incompatible with X features" warning:
[1830] Fix | Delete
*
[1831] Fix | Delete
* - If the plugin info <tr> has "update", our <tr> will render nicely right after it; but then
[1832] Fix | Delete
* our own "plugin-update-tr" class will draw an additional line before the "needs update" warning.
[1833] Fix | Delete
* - If not, the plugin info <tr> will render its lower border line right before our compatibility info <tr>.
[1834] Fix | Delete
*
[1835] Fix | Delete
* This small script fixes this by adding the "update" class to the plugin info <tr> if it doesn't have it
[1836] Fix | Delete
* (so no extra line before our <tr>), or removing 'plugin-update-tr' from our <tr> otherwise
[1837] Fix | Delete
* (and then some extra manual tweaking of margins is needed).
[1838] Fix | Delete
*
[1839] Fix | Delete
* @param string $current_screen The current screen object.
[1840] Fix | Delete
*
[1841] Fix | Delete
* @internal For exclusive usage of WooCommerce core, backwards compatibility not guaranteed.
[1842] Fix | Delete
*/
[1843] Fix | Delete
public function enqueue_script_to_fix_plugin_list_html( $current_screen ): void {
[1844] Fix | Delete
if ( 'plugins' !== $current_screen->id ) {
[1845] Fix | Delete
return;
[1846] Fix | Delete
}
[1847] Fix | Delete
[1848] Fix | Delete
$handle = 'wc-features-fix-plugin-list-html';
[1849] Fix | Delete
wp_register_script( $handle, '', array(), WC_VERSION, array( 'in_footer' => true ) );
[1850] Fix | Delete
wp_enqueue_script( $handle );
[1851] Fix | Delete
wp_add_inline_script(
[1852] Fix | Delete
$handle,
[1853] Fix | Delete
"
[1854] Fix | Delete
const warningRows = document.querySelectorAll('tr[data-plugin-row-type=\"feature-incomp-warn\"]');
[1855] Fix | Delete
for(const warningRow of warningRows) {
[1856] Fix | Delete
const pluginName = warningRow.getAttribute('data-plugin');
[1857] Fix | Delete
const pluginInfoRow = document.querySelector('tr.active[data-plugin=\"' + pluginName + '\"]:not(.plugin-update-tr), tr.inactive[data-plugin=\"' + pluginName + '\"]:not(.plugin-update-tr)');
[1858] Fix | Delete
if(!pluginInfoRow) {
[1859] Fix | Delete
continue;
[1860] Fix | Delete
}
[1861] Fix | Delete
if(pluginInfoRow.classList.contains('update')) {
[1862] Fix | Delete
warningRow.classList.remove('plugin-update-tr');
[1863] Fix | Delete
warningRow.querySelector('.notice').style.margin = '5px 10px 15px 30px';
[1864] Fix | Delete
}
[1865] Fix | Delete
else {
[1866] Fix | Delete
pluginInfoRow.classList.add('update');
[1867] Fix | Delete
}
[1868] Fix | Delete
}
[1869] Fix | Delete
"
[1870] Fix | Delete
);
[1871] Fix | Delete
}
[1872] Fix | Delete
[1873] Fix | Delete
/**
[1874] Fix | Delete
* Handler for the 'views_plugins' hook that shows the links to the different views in the plugins page.
[1875] Fix | Delete
* If we come from a "Manage incompatible plugins" in the features page we'll show just two views:
[1876] Fix | Delete
* "All" (so that it's easy to go back to a known state) and "Incompatible with X".
[1877] Fix | Delete
* We'll skip the rest of the views since the counts are wrong anyway, as we are modifying
[1878] Fix | Delete
* the plugins list via the 'all_plugins' filter.
[1879] Fix | Delete
*
[1880] Fix | Delete
* @param array $views An array of view ids => view links.
[1881] Fix | Delete
* @return string[] The actual views array to use.
[1882] Fix | Delete
*
[1883] Fix | Delete
* @internal For exclusive usage of WooCommerce core, backwards compatibility not guaranteed.
[1884] Fix | Delete
*/
[1885] Fix | Delete
public function handle_plugins_page_views_list( $views ): array {
[1886] Fix | Delete
// phpcs:disable WordPress.Security.NonceVerification, WordPress.Security.ValidatedSanitizedInput
[1887] Fix | Delete
if ( 'incompatible_with_feature' !== ArrayUtil::get_value_or_default( $_GET, 'plugin_status' ) ) {
[1888] Fix | Delete
return $views;
[1889] Fix | Delete
}
[1890] Fix | Delete
[1891] Fix | Delete
$feature_id = $_GET['feature_id'] ?? 'all';
[1892] Fix | Delete
if ( 'all' !== $feature_id && ! $this->feature_exists( $feature_id ) ) {
[1893] Fix | Delete
return $views;
[1894] Fix | Delete
}
[1895] Fix | Delete
// phpcs:enable WordPress.Security.NonceVerification, WordPress.Security.ValidatedSanitizedInput
[1896] Fix | Delete
[1897] Fix | Delete
$all_items = get_plugins();
[1898] Fix | Delete
$features = $this->get_feature_definitions();
[1899] Fix | Delete
[1900] Fix | Delete
$incompatible_plugins_count = count( $this->filter_plugins_list( $all_items ) );
[1901] Fix | Delete
$incompatible_text =
[1902] Fix | Delete
'all' === $feature_id
[1903] Fix | Delete
? __( 'Incompatible with WooCommerce features', 'woocommerce' )
[1904] Fix | Delete
/* translators: %s = name of a WooCommerce feature */
[1905] Fix | Delete
: sprintf( __( "Incompatible with '%s'", 'woocommerce' ), $features[ $feature_id ]['name'] );
[1906] Fix | Delete
$incompatible_link = "<a href='plugins.php?plugin_status=incompatible_with_feature&feature_id={$feature_id}' class='current' aria-current='page'>{$incompatible_text} <span class='count'>({$incompatible_plugins_count})</span></a>";
[1907] Fix | Delete
[1908] Fix | Delete
$all_plugins_count = count( $all_items );
[1909] Fix | Delete
$all_text = __( 'All', 'woocommerce' );
[1910] Fix | Delete
$all_link = "<a href='plugins.php?plugin_status=all'>{$all_text} <span class='count'>({$all_plugins_count})</span></a>";
[1911] Fix | Delete
[1912] Fix | Delete
return array(
[1913] Fix | Delete
'all' => $all_link,
[1914] Fix | Delete
'incompatible_with_feature' => $incompatible_link,
[1915] Fix | Delete
);
[1916] Fix | Delete
}
[1917] Fix | Delete
[1918] Fix | Delete
/**
[1919] Fix | Delete
* Set the feature nonce to be sent from client side.
[1920] Fix | Delete
*
[1921] Fix | Delete
* @param array $settings Component settings.
[1922] Fix | Delete
*
[1923] Fix | Delete
* @return array
[1924] Fix | Delete
*
[1925] Fix | Delete
* @internal For exclusive usage of WooCommerce core, backwards compatibility not guaranteed.
[1926] Fix | Delete
*/
[1927] Fix | Delete
public function set_change_feature_enable_nonce( $settings ) {
[1928] Fix | Delete
$settings['_feature_nonce'] = wp_create_nonce( 'change_feature_enable' );
[1929] Fix | Delete
return $settings;
[1930] Fix | Delete
}
[1931] Fix | Delete
[1932] Fix | Delete
/**
[1933] Fix | Delete
* Changes the feature given it's id, a toggle value and nonce as a query param.
[1934] Fix | Delete
*
[1935] Fix | Delete
* `/wp-admin/post.php?product_block_editor=1&_feature_nonce=1234`, 1 for on
[1936] Fix | Delete
* `/wp-admin/post.php?product_block_editor=0&_feature_nonce=1234`, 0 for off
[1937] Fix | Delete
*
[1938] Fix | Delete
* @internal For exclusive usage of WooCommerce core, backwards compatibility not guaranteed.
[1939] Fix | Delete
*/
[1940] Fix | Delete
public function change_feature_enable_from_query_params(): void {
[1941] Fix | Delete
if ( ! current_user_can( 'manage_woocommerce' ) ) {
[1942] Fix | Delete
return;
[1943] Fix | Delete
}
[1944] Fix | Delete
[1945] Fix | Delete
$is_feature_nonce_invalid = ( ! isset( $_GET['_feature_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_feature_nonce'] ) ), 'change_feature_enable' ) );
[1946] Fix | Delete
[1947] Fix | Delete
$query_params_to_remove = array( '_feature_nonce' );
[1948] Fix | Delete
[1949] Fix | Delete
foreach ( array_keys( $this->get_feature_definitions() ) as $feature_id ) {
[1950] Fix | Delete
if ( isset( $_GET[ $feature_id ] ) && is_numeric( $_GET[ $feature_id ] ) ) {
[1951] Fix | Delete
$value = absint( $_GET[ $feature_id ] );
[1952] Fix | Delete
[1953] Fix | Delete
if ( $is_feature_nonce_invalid ) {
[1954] Fix | Delete
wp_die( esc_html__( 'Action failed. Please refresh the page and retry.', 'woocommerce' ) );
[1955] Fix | Delete
return;
[1956] Fix | Delete
}
[1957] Fix | Delete
[1958] Fix | Delete
if ( 1 === $value ) {
[1959] Fix | Delete
$this->change_feature_enable( $feature_id, true );
[1960] Fix | Delete
} elseif ( 0 === $value ) {
[1961] Fix | Delete
$this->change_feature_enable( $feature_id, false );
[1962] Fix | Delete
}
[1963] Fix | Delete
$query_params_to_remove[] = $feature_id;
[1964] Fix | Delete
}
[1965] Fix | Delete
}
[1966] Fix | Delete
if ( count( $query_params_to_remove ) > 1 && isset( $_SERVER['REQUEST_URI'] ) ) {
[1967] Fix | Delete
// phpcs:disable WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
[1968] Fix | Delete
wp_safe_redirect( remove_query_arg( $query_params_to_remove, $_SERVER['REQUEST_URI'] ) );
[1969] Fix | Delete
}
[1970] Fix | Delete
}
[1971] Fix | Delete
[1972] Fix | Delete
/**
[1973] Fix | Delete
* Display the email improvements feedback notice to render CES modal in.
[1974] Fix | Delete
*
[1975] Fix | Delete
* @param string $feature_id The feature id.
[1976] Fix | Delete
* @param bool $is_enabled Whether the feature is enabled.
[1977] Fix | Delete
*
[1978] Fix | Delete
* @internal For exclusive usage of WooCommerce core, backwards compatibility not guaranteed.
[1979] Fix | Delete
*/
[1980] Fix | Delete
public function display_email_improvements_feedback_notice( $feature_id, $is_enabled ): void {
[1981] Fix | Delete
if ( 'email_improvements' === $feature_id && ! $is_enabled ) {
[1982] Fix | Delete
set_transient( 'wc_settings_email_improvements_reverted', 'yes', 15 );
[1983] Fix | Delete
add_action(
[1984] Fix | Delete
'admin_notices',
[1985] Fix | Delete
function () {
[1986] Fix | Delete
echo '<div id="wc_settings_features_email_feedback_slotfill"></div>';
[1987] Fix | Delete
}
[1988] Fix | Delete
);
[1989] Fix | Delete
}
[1990] Fix | Delete
}
[1991] Fix | Delete
[1992] Fix | Delete
/**
[1993] Fix | Delete
* Check if the email improvements feature is enabled in preview mode in Settings > Emails.
[1994] Fix | Delete
* This is used to force the email improvements feature without affecting shoppers.
[1995] Fix | Delete
*
[1996] Fix | Delete
* @param string $feature_id The feature id.
[1997] Fix | Delete
* @return bool Whether the email improvements feature is enabled in preview mode.
[1998] Fix | Delete
*/
[1999] Fix | Delete
It is recommended that you Edit text format, this type of Fix handles quite a lot in one request
Function