Skip to content

Commit

Permalink
Merge pull request #60 from Automattic/add/file-path-customization
Browse files Browse the repository at this point in the history
Allow customizing file path for multisites and non vip sites
  • Loading branch information
ingeniumed authored Nov 29, 2023
2 parents 635b0f9 + e93e937 commit 0c69750
Show file tree
Hide file tree
Showing 10 changed files with 116 additions and 62 deletions.
64 changes: 32 additions & 32 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@ This plugin is currently developed for use on WordPress sites hosted on the VIP

- [Installation](#installation)
- [Install on WordPress VIP](#install-on-wordpress-vip)
- [Install via `git subtree`](#install-via-git-subtree)
- [Install via ZIP file](#install-via-zip-file)
- [Plugin activation](#plugin-activation)
- [Usage](#usage)
- [Schema Basics](#schema-basics)
- [Quick Start](#quick-start)
Expand All @@ -26,6 +24,7 @@ This plugin is currently developed for use on WordPress sites hosted on the VIP
- [Default and Post Type Rule Set](#default-and-post-type-rule-set)
- [Limitations](#limitations)
- [Code Filters](#code-filters)
- [`vip_governance__governance_file_path`](#vip_governance__governance_file_path)
- [`vip_governance__is_block_allowed_for_insertion`](#vip_governance__is_block_allowed_for_insertion)
- [`vip_governance__is_block_allowed_for_editing`](#vip_governance__is_block_allowed_for_editing)
- [`vip_governance__is_block_allowed_in_hierarchy`](#vip_governance__is_block_allowed_in_hierarchy)
Expand All @@ -39,6 +38,8 @@ This plugin is currently developed for use on WordPress sites hosted on the VIP

## Installation

To use the WordPress VIP Block Governance plugin after activation, skip to [Usage](#usage).

### Install on WordPress VIP

The WordPress VIP Block Governance plugin is authored and maintained by [WordPress VIP][wpvip], and made available to all WordPress sites by [VIP MU plugins][vip-go-mu-plugins]. Customers who host on WordPress VIP or use [`vip dev-env`](https://docs.wpvip.com/how-tos/local-development/use-the-vip-local-development-environment/) to develop locally have access to this plugin automatically. We recommend this activation method for WordPress VIP customers.
Expand All @@ -55,36 +56,6 @@ Create this path in your WordPress VIP site if it does not yet exist.

This will automatically install and activate the latest mu-plugins release of the WordPress VIP Block Governance plugin. Remove this line to deactivate the plugin.

To use the WordPress VIP Block Governance plugin after activation, skip to [Usage](#usage).

### Install via `git subtree`

We recommend this method for non-[WordPress VIP][wpvip] customers.

The latest version of the WordPress VIP Block Governance plugin is available in the default `trunk` branch of this repository.

We recommend installing the latest plugin version [via `git subtree`][wpvip-plugin-subtrees] within your site's repository:

```bash
# Enter your project's root directory:
cd my-site-repo/

# Add a subtree for the trunk branch:
git subtree add --prefix plugins/vip-governance [email protected]:Automattic/vip-governance-plugin.git trunk --squash
```

To deploy the plugin to a remote branch, `git push` the committed subtree.

The `trunk` branch will stay up to date with the latest version of the plugin. Use this command to pull the latest `trunk` branch changes:

```bash
git subtree pull --prefix plugins/vip-governance [email protected]:Automattic/vip-governance-plugin.git trunk --squash
```

Ensure that the plugin is up-to-date by pulling changes often.

Note: We **do not recommend** using `git submodule`. [Submodules on WPVIP that require authentication][wpvip-plugin-submodules] will fail to deploy.

### Install via ZIP file

The latest version of the plugin can be downloaded from the [repository's Releases page][repo-releases]. Unzip the downloaded plugin and add it to the `plugins/` directory of your site's GitHub repository.
Expand Down Expand Up @@ -413,6 +384,35 @@ With this rule set, the following rules will apply:

There are filters in place that can be applied to change the behavior for what's allowed and what's not allowed.

### `vip_governance__governance_file_path`

Change the governance rules file that's used by the plugin, based on a variety of filter options that are available. By default, it is set to the path to `governance-rules.json` in the private directory in a VIP site. For non-vip sites, it is set to the path to `governance-rules.json` in the plugin directory.

```php
/**
* Filter the governance file path, based on the filter options provided.
*
* Currently supported keys:
*
* site_id: The site ID for the current site.
*
* @param string $governance_file_path Path to the governance file.
* @param array $filter_options Options that can be used as a filter for determining the right file.
*/
apply_filters( 'vip_governance__governance_file_path', $governance_file_path, $filter_options );
```

For example, this filter can be used to customize the rules file used for a subsite:

```php
add_filter( 'vip_governance__governance_file_path', function ( $governance_file_path, $filter_options ) {
if ( isset( $filter_options['site_id'] ) && $filter_options['site_id'] === 2 ) {
return WPCOM_VIP_PRIVATE_DIR . '/site' . '/' . '2/' . WPCOMVIP_GOVERNANCE_RULES_FILENAME;
}
return $governance_file_path;
}, 10, 2 );
```

### `vip_governance__is_block_allowed_for_insertion`

Change what blocks are allowed to be inserted in the block editor. By default, root level and children blocks are compared against the governance rules, and then a decision is made to allow or reject them. This filter will allow you to override the default logic for insertion.
Expand Down
2 changes: 1 addition & 1 deletion build/index.asset.php
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<?php return array('dependencies' => array('lodash', 'wp-block-editor', 'wp-components', 'wp-compose', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-notices'), 'version' => 'd6a2dcada46f778b9c93');
<?php return array('dependencies' => array('wp-block-editor', 'wp-components', 'wp-compose', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-notices'), 'version' => 'a6d9b2a606df332a91b2');
2 changes: 1 addition & 1 deletion build/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 25 additions & 4 deletions governance/governance-utilities.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,38 @@ public static function get_governance_rules_json() {
$governance_file_path = WPCOM_VIP_PRIVATE_DIR . '/' . WPCOMVIP_GOVERNANCE_RULES_FILENAME;
}

// Filter options that can be used to customize the governance rules that could be used.
$filter_options = [
'site_id' => get_current_blog_id(),
];

/**
* Filter the governance file path, based on the filter options provided.
*
* Currently supported keys:
*
* site_id: The site ID for the current site.
*
* @param string $governance_file_path Path to the governance file.
* @param array $filter_options Options that can be used as a filter for determining the right file.
*/
$governance_file_path = apply_filters( 'vip_governance__governance_file_path', $governance_file_path, $filter_options );

// Make sure the path is normalized. Note that file_exists() is still.
$governance_file_path = realpath( $governance_file_path );

// Make sure the file exists and is in the wp-content/ directory.
if ( ! file_exists( $governance_file_path ) ) {
/* translators: %s: governance file name */
return new WP_Error( 'governance-file-not-found', sprintf( __( 'Governance rules (%s) could not be found in private or plugin folders.', 'vip-governance' ), WPCOMVIP_GOVERNANCE_RULES_FILENAME ) );
return new WP_Error( 'governance-file-not-found', __( 'Governance rules could not be found.', 'vip-governance' ) );
} elseif ( substr( $governance_file_path, 0, strlen( WP_CONTENT_DIR ) ) !== WP_CONTENT_DIR ) {
return new WP_Error( 'governance-file-not-in-wp-content', __( 'Governance rules must be stored within the wp-content/ directory or a subdirectory.', 'vip-governance' ) );
}

// phpcs:ignore WordPressVIPMinimum.Performance.FetchingRemoteData.FileGetContentsUnknown
$governance_rules_json = file_get_contents( $governance_file_path );

if ( false === $governance_rules_json ) {
/* translators: %s: governance file name */
return new WP_Error( 'governance-file-not-readable', sprintf( __( 'Governance rules (%s) could not be read from private folder.', 'vip-governance' ), WPCOMVIP_GOVERNANCE_RULES_FILENAME ) );
return new WP_Error( 'governance-file-not-readable', __( 'Governance rules could not be read from specified folder.', 'vip-governance' ) );
}

return $governance_rules_json;
Expand Down
30 changes: 16 additions & 14 deletions governance/settings/settings-view.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
defined( 'ABSPATH' ) || die();

$is_governance_error = false !== $governance_error;
$governance_rules_formatted = join("\n", array_map(function ( $line ) {
$governance_rules_formatted = $governance_rules_json ? join("\n", array_map(function ( $line ) {
return sprintf( '<code>%s</code>', esc_html( $line ) );
}, explode( "\n", trim( $governance_rules_json ) )));
}, explode( "\n", trim( $governance_rules_json ) ))) : false;

?>

Expand Down Expand Up @@ -42,20 +42,22 @@
<?php } ?>
</div>

<div class="governance-rules-json">
<?php if ( $is_governance_error ) { ?>
<p><?php esc_html_e( 'From governance rules:' ); ?></p>
<?php // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Lines are individually escaped ?>
<pre><?php echo $governance_rules_formatted; ?></pre>
<?php } else { ?>
<details>
<summary><?php esc_html_e( 'Click to expand governance rules' ); ?></summary>

<?php if ( $governance_rules_json ) { ?>
<div class="governance-rules-json">
<?php if ( $is_governance_error ) { ?>
<p><?php esc_html_e( 'From governance rules:' ); ?></p>
<?php // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Lines are individually escaped ?>
<pre><?php echo $governance_rules_formatted; ?></pre>
</details>
<?php } ?>
</div>
<?php } else { ?>
<details>
<summary><?php esc_html_e( 'Click to expand governance rules' ); ?></summary>

<?php // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Lines are individually escaped ?>
<pre><?php echo $governance_rules_formatted; ?></pre>
</details>
<?php } ?>
</div>
<?php } ?>
</div>

<?php if ( ! $is_governance_error ) { ?>
Expand Down
2 changes: 1 addition & 1 deletion governance/settings/settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ public static function render() {
$governance_error = false;
if ( is_wp_error( $governance_rules_json ) ) {
$governance_error = $governance_rules_json->get_error_message();
$governance_rules_json = '';
$governance_rules_json = false;
} else {
$governance_rules = GovernanceUtilities::get_parsed_governance_rules();

Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "block-editor-governance",
"version": "1.0.2",
"version": "1.0.3",
"description": "This is a plugin adding additional governance capabilities to the block editor.",
"author": "VIP Bistro",
"main": "build/index.js",
Expand Down
37 changes: 34 additions & 3 deletions src/nested-governance-loader.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { get } from 'lodash';

/**
* Find the list of nestedPaths that can be found in the block settings, so that
* it's faster to find out if a deeper nested setting exists or not.
Expand Down Expand Up @@ -76,7 +74,7 @@ export function getNestedSetting(
const blockSettings = settings[ currentBlockName ];

if ( remainingBlockNames.length === 0 ) {
const settingValue = get( blockSettings, normalizedPath );
const settingValue = deepGet( blockSettings, normalizedPath );

if ( settingValue !== undefined && depth >= result.depth ) {
result.depth = depth;
Expand All @@ -99,6 +97,39 @@ export function getNestedSetting(
return getNestedSetting( remainingBlockNames, normalizedPath, settings, result, depth );
}

/**
* Port of lodash's get function from https://gist.github.com/andrewchilds/30a7fb18981d413260c7a36428ed13da?permalink_comment_id=4433741#gistcomment-4433741
* @param {Object} value The value to query.
* @param {String} query The query to run.
* @param {Object} defaultVal The default value to return if the query doesn't exist.
* @returns
*/
function deepGet( value, query, defaultVal = undefined ) {
const splitQuery = Array.isArray( query )
? query
: query
.replace( /(\[(\d)\])/g, '.$2' )
.replace( /^\./, '' )
.split( '.' );

if ( ! splitQuery.length || splitQuery[ 0 ] === undefined ) return value;

const key = splitQuery[ 0 ];

if (
typeof value !== 'object' ||
value === null ||
! ( key in value ) ||
// eslint-disable-next-line security/detect-object-injection
value[ key ] === undefined
) {
return defaultVal;
}

// eslint-disable-next-line security/detect-object-injection
return deepGet( value[ key ], splitQuery.slice( 1 ), defaultVal );
}

/**
* Flatten a nested object into a map of paths.
* @param {Object} settings The settings value that is to be flattened.
Expand Down
Loading

0 comments on commit 0c69750

Please sign in to comment.